Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: chainlock and islock issues #260

Merged
merged 5 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion core/src/main/java/org/bitcoinj/core/AbstractManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,10 @@ protected void saveNow() {
/** Requests an asynchronous save on a background thread */
protected void saveLater() {
ManagerFiles files = vFileManager;
if (files != null)
if (files != null) {
Context.propagate(context);
files.saveLater();
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.nio.ByteBuffer;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.lang.Math.min;
Expand Down Expand Up @@ -338,6 +339,12 @@ public Masternode getMNByAddress(InetSocketAddress socketAddress) {
return null;
}

public List<Masternode> getMasternodesByVotingKey(KeyId votingKeyId) {
return mnMap.values().stream()
.filter(simplifiedMasternodeListEntry -> simplifiedMasternodeListEntry.keyIdVoting.equals(votingKeyId))
.collect(Collectors.toList());
}

public interface ForeachMNCallback {
void processMN(SimplifiedMasternodeListEntry mn);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,11 @@ public ChainLocksHandler(Context context) {
public void setBlockChain(AbstractBlockChain blockChain, AbstractBlockChain headerChain) {
this.blockChain = blockChain;
this.headerChain = headerChain;
this.blockChain.addNewBestBlockListener(this.newBestBlockListener);
this.quorumSigningManager = context.signingManager;
}

@Override
public void close() {
if (blockChain != null) {
blockChain.removeNewBestBlockListener(this.newBestBlockListener);
}
blockChain = null;
super.close();
}
Expand Down Expand Up @@ -477,8 +473,6 @@ void cleanup() {

}

private final NewBestBlockListener newBestBlockListener = block -> updatedBlockTip(block, null);

private final CopyOnWriteArrayList<ListenerRegistration<ChainLockListener>> chainLockListeners;

/**
Expand Down
29 changes: 27 additions & 2 deletions core/src/main/java/org/bitcoinj/quorums/InstantSendManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.bitcoinj.store.BlockStore;
import org.bitcoinj.store.BlockStoreException;
import org.bitcoinj.store.FullPrunedBlockStore;
import org.bitcoinj.utils.ContextPropagatingThreadFactory;
import org.bitcoinj.utils.Pair;
import org.bitcoinj.utils.Threading;
import org.slf4j.Logger;
Expand All @@ -26,6 +27,9 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class InstantSendManager implements RecoveredSignatureListener {
Expand All @@ -36,8 +40,11 @@ public class InstantSendManager implements RecoveredSignatureListener {
private static final Logger log = LoggerFactory.getLogger(InstantSendManager.class);
ReentrantLock lock = Threading.lock("InstantSendManager");
InstantSendDatabase db;
@Deprecated
Thread workThread;
@Deprecated
private boolean runWithoutThread = true;
private ScheduledExecutorService scheduledExecutorService;
AbstractBlockChain blockChain;

//Keep track of when the ISLOCK arrived
Expand All @@ -52,6 +59,11 @@ public InstantSendManager(Context context, InstantSendDatabase db) {
this.quorumSigningManager = context.signingManager;
pendingInstantSendLocks = new HashMap<>();
invalidInstantSendLocks = new HashMap<>();
scheduledExecutorService = createScheduledExecutorService();
}

private ScheduledExecutorService createScheduledExecutorService() {
return Executors.newScheduledThreadPool(1, new ContextPropagatingThreadFactory("instantsend"));
}

@Override
Expand All @@ -72,6 +84,8 @@ public void setBlockChain(AbstractBlockChain blockChain, @Nullable PeerGroup pee
peerGroup.addOnTransactionBroadcastListener(this.transactionBroadcastListener);
}
context.chainLockHandler.addChainLockListener(this.chainLockListener);
if (scheduledExecutorService == null)
scheduledExecutorService = createScheduledExecutorService();
}

public void close(PeerGroup peerGroup) {
Expand All @@ -84,6 +98,15 @@ public void close(PeerGroup peerGroup) {
peerGroup.removeOnTransactionBroadcastListener(this.transactionBroadcastListener);
}
context.chainLockHandler.removeChainLockListener(this.chainLockListener);
try {
if (!scheduledExecutorService.awaitTermination(3000, TimeUnit.MILLISECONDS)) {
log.warn("scheduled threads still remain");
}
scheduledExecutorService = null;
} catch (InterruptedException e) {
log.warn("thread termination interrupted");
// swallow
}
}

private boolean isInitialized() {
Expand Down Expand Up @@ -713,8 +736,10 @@ void processInstantSendLock(long from, Sha256Hash hash, InstantSendLock islock)
void updateWalletTransaction(Sha256Hash txid, Transaction tx) {
TransactionConfidence confidence = tx != null ? tx.getConfidence() : context.getConfidenceTable().get(txid);
if(confidence != null) {
confidence.setIXType(TransactionConfidence.IXType.IX_LOCKED);
confidence.queueListeners(TransactionConfidence.Listener.ChangeReason.IX_TYPE);
scheduledExecutorService.schedule(() -> {
confidence.setIXType(TransactionConfidence.IXType.IX_LOCKED);
confidence.queueListeners(TransactionConfidence.Listener.ChangeReason.IX_TYPE);
}, 250, TimeUnit.MILLISECONDS);
} else {
log.info("Can't find {} in mempool", txid);
}
Expand Down
14 changes: 12 additions & 2 deletions core/src/main/java/org/bitcoinj/wallet/CoinJoinExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@

public class CoinJoinExtension extends AbstractKeyChainGroupExtension {
private static final Logger log = LoggerFactory.getLogger(CoinJoinExtension.class);
private static final int COINJOIN_LOOKADHEAD = 400;
private static final int COINJOIN_LOOKADHEAD_THRESHOLD = COINJOIN_LOOKADHEAD - 1;

protected AnyKeyChainGroup coinJoinKeyChainGroup;

Expand Down Expand Up @@ -154,11 +156,19 @@ public void deserializeWalletExtension(Wallet containingWallet, byte[] data) thr
coinJoinKeyChainGroup = AnyKeyChainGroup.fromProtobufUnencrypted(containingWallet.params,
coinJoinProto.getKeyList(), ECKeyFactory.get(), false);
}
if (coinJoinKeyChainGroup.hasKeyChains()) {
setLookaheadSize();
}
rounds = coinJoinProto.getRounds();
CoinJoinClientOptions.setRounds(rounds);
loadedKeys = true;
}

private void setLookaheadSize() {
coinJoinKeyChainGroup.getActiveKeyChain().setLookaheadSize(COINJOIN_LOOKADHEAD);
coinJoinKeyChainGroup.getActiveKeyChain().setLookaheadThreshold(COINJOIN_LOOKADHEAD_THRESHOLD);
}

public boolean hasKeyChain(ImmutableList<ChildNumber> path) {
if (coinJoinKeyChainGroup == null)
return false;
Expand All @@ -179,7 +189,7 @@ public void addKeyChain(DeterministicSeed seed, ImmutableList<ChildNumber> path)
coinJoinKeyChainGroup = AnyKeyChainGroup.builder(wallet.getParams(), ECKeyFactory.get()).build();
}
coinJoinKeyChainGroup.addAndActivateHDChain(AnyDeterministicKeyChain.builder().seed(seed).accountPath(path).build());
coinJoinKeyChainGroup.getActiveKeyChain().setLookaheadSize(300);
setLookaheadSize();
}
}

Expand All @@ -196,7 +206,7 @@ public void addEncryptedKeyChain(DeterministicSeed seed, ImmutableList<ChildNumb
AnyDeterministicKeyChain chain = AnyDeterministicKeyChain.builder().seed(seed).accountPath(path).build();
AnyDeterministicKeyChain encryptedChain = chain.toEncrypted(wallet.getKeyCrypter(), keyParameter);
coinJoinKeyChainGroup.addAndActivateHDChain(encryptedChain);
coinJoinKeyChainGroup.getActiveKeyChain().setLookaheadSize(300);
setLookaheadSize();
}
}

Expand Down
Loading