From 1081f92e972b809ecd31efb32b1b6c4f95b11456 Mon Sep 17 00:00:00 2001 From: HashEngineering Date: Fri, 4 Oct 2024 14:46:52 -0700 Subject: [PATCH 1/2] fix: if keys are updated, save later to avoid deadlocks --- core/src/main/java/org/bitcoinj/wallet/Wallet.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/wallet/Wallet.java b/core/src/main/java/org/bitcoinj/wallet/Wallet.java index 7aae6a2c1..77730c791 100644 --- a/core/src/main/java/org/bitcoinj/wallet/Wallet.java +++ b/core/src/main/java/org/bitcoinj/wallet/Wallet.java @@ -5946,7 +5946,7 @@ public void addReceivingFromFriendKeyChain(FriendKeyChain chain) { receivingFromFriendsGroup = FriendKeyChainGroup.friendlybuilder(params).build(); } receivingFromFriendsGroup.addAndActivateHDChain(chain); - saveNow(); + saveLater(); } finally { keyChainGroupLock.unlock(); } @@ -5966,7 +5966,7 @@ public void addSendingToFriendKeyChain(FriendKeyChain chain) { sendingToFriendsGroup = FriendKeyChainGroup.friendlybuilder(params).build(); } sendingToFriendsGroup.addAndActivateHDChain(chain); - saveNow(); + saveLater(); } finally { keyChainGroupLock.unlock(); } From eed75391d606484d8126491b16dadaa005097b77 Mon Sep 17 00:00:00 2001 From: HashEngineering Date: Mon, 7 Oct 2024 12:57:55 -0700 Subject: [PATCH 2/2] fix(coinjoin): MasternodeGroup should not sync blockchain --- .../coinjoin/utils/MasternodeGroup.java | 2 +- .../java/org/bitcoinj/core/PeerGroup.java | 34 ++++++++++++++++--- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/coinjoin/utils/MasternodeGroup.java b/core/src/main/java/org/bitcoinj/coinjoin/utils/MasternodeGroup.java index 9b61ffbf5..dc3a653e0 100644 --- a/core/src/main/java/org/bitcoinj/coinjoin/utils/MasternodeGroup.java +++ b/core/src/main/java/org/bitcoinj/coinjoin/utils/MasternodeGroup.java @@ -147,7 +147,7 @@ public MasternodeGroup(NetworkParameters params, @Nullable AbstractBlockChain ch * @param chain */ public MasternodeGroup(Context context, @Nullable AbstractBlockChain chain) { - super(context, chain); + super(context, chain, false); init(); } diff --git a/core/src/main/java/org/bitcoinj/core/PeerGroup.java b/core/src/main/java/org/bitcoinj/core/PeerGroup.java index fa7376508..0b72fbcd9 100644 --- a/core/src/main/java/org/bitcoinj/core/PeerGroup.java +++ b/core/src/main/java/org/bitcoinj/core/PeerGroup.java @@ -364,9 +364,14 @@ public PeerGroup(Context context) { this(context, null); } + /** See {@link #PeerGroup(Context, AbstractBlockChain)} */ + public PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain, boolean syncBlockchain) { + this(Context.getOrCreate(params), chain, null, new NioClientManager(), syncBlockchain); + } + /** See {@link #PeerGroup(Context, AbstractBlockChain)} */ public PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain) { - this(Context.getOrCreate(params), chain, null, new NioClientManager()); + this(Context.getOrCreate(params), chain, null, new NioClientManager(), true); } /** See {@link #PeerGroup(Context, AbstractBlockChain)} */ @@ -382,6 +387,14 @@ public PeerGroup(Context context, @Nullable AbstractBlockChain chain) { this(context, chain, null, new NioClientManager()); } + /** + * Creates a PeerGroup for the given context and chain. Blocks will be passed to the chain as they are broadcast + * and downloaded. This is probably the constructor you want to use. + */ + public PeerGroup(Context context, @Nullable AbstractBlockChain chain, boolean syncsBlockchain) { + this(context, chain, null, new NioClientManager(), syncsBlockchain); + } + /** See {@link #PeerGroup(Context, AbstractBlockChain, AbstractBlockChain, ClientConnectionManager)} */ public PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain, ClientConnectionManager connectionManager) { this(Context.getOrCreate(params), chain, null, connectionManager); @@ -389,9 +402,17 @@ public PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain, C /** * Creates a new PeerGroup allowing you to specify the {@link ClientConnectionManager} which is used to create new - * connections and keep track of existing ones. + * connections and keep track of existing ones. This peer group will initialize headerChain if null */ private PeerGroup(Context context, @Nullable AbstractBlockChain chain, @Nullable AbstractBlockChain headerChain, ClientConnectionManager connectionManager) { + this(context, chain, headerChain, connectionManager, true); + } + + /** + * Creates a new PeerGroup allowing you to specify the {@link ClientConnectionManager} which is used to create new + * connections and keep track of existing ones. + */ + private PeerGroup(Context context, @Nullable AbstractBlockChain chain, @Nullable AbstractBlockChain headerChain, ClientConnectionManager connectionManager, boolean syncsBlockchain) { checkNotNull(context); this.context = context; this.params = context.getParams(); @@ -438,15 +459,18 @@ public int compare(PeerAddress a, PeerAddress b) { vMinRequiredProtocolVersion = params.getProtocolVersionNum(NetworkParameters.ProtocolVersion.MINIMUM); runningVoteBroadcasts = Collections.synchronizedSet(new HashSet()); - //DashSpecific - if (headerChain == null) { + // Dash Specific - if this PeerGroup does not sync the blockchain, then syncsBlockchain should be false + // otherwise, if headerChain is null, then copy the last 100 headers over to it + if (headerChain == null && syncsBlockchain) { if (context.getSyncFlags().contains(MasternodeSync.SYNC_FLAGS.SYNC_HEADERS_MN_LIST_FIRST)) { try { this.headerChain = new BlockChain(params, new MemoryBlockStore(params)); StoredBlock cursor = chain.getChainHead(); - while (cursor != null && !cursor.getHeader().equals(params.getGenesisBlock())) { + int headers = 0; // limit headers to 100, enough to sync + while (cursor != null && !cursor.getHeader().equals(params.getGenesisBlock()) && headers < 100) { this.headerChain.getBlockStore().put(cursor); cursor = cursor.getPrev(chain.getBlockStore()); + headers++; } } catch (BlockStoreException x) { // swallow