diff --git a/src/main/java/org/qortal/controller/Synchronizer.java b/src/main/java/org/qortal/controller/Synchronizer.java index 1609979e..dd279a3c 100644 --- a/src/main/java/org/qortal/controller/Synchronizer.java +++ b/src/main/java/org/qortal/controller/Synchronizer.java @@ -118,17 +118,9 @@ public class Synchronizer { return SynchronizationResult.SHUTTING_DOWN; // Check if we can use the cached common block data, by comparing the peer's current chain tip against the peer's chain tip when we last found our common block - PeerChainTipData peerChainTipData = peer.getChainTipData(); - CommonBlockData commonBlockData = peer.getCommonBlockData(); - - if (peerChainTipData != null && commonBlockData != null) { - PeerChainTipData commonBlockChainTipData = commonBlockData.getChainTipData(); - if (peerChainTipData.getLastBlockSignature() != null && commonBlockChainTipData != null && commonBlockChainTipData.getLastBlockSignature() != null) { - if (Arrays.equals(peerChainTipData.getLastBlockSignature(), commonBlockChainTipData.getLastBlockSignature())) { - LOGGER.debug(String.format("Skipping peer %s because we already have the latest common block data in our cache. Cached common block sig is %.08s", peer, Base58.encode(commonBlockData.getCommonBlockSummary().getSignature()))); - continue; - } - } + if (peer.canUseCachedCommonBlockData()) { + LOGGER.debug(String.format("Skipping peer %s because we already have the latest common block data in our cache. Cached common block sig is %.08s", peer, Base58.encode(peer.getCommonBlockData().getCommonBlockSummary().getSignature()))); + continue; } // Cached data is stale, so clear it and repopulate @@ -288,31 +280,43 @@ public class Synchronizer { final int peerHeight = peer.getChainTipData().getLastHeight(); final int peerAdditionalBlocksAfterCommonBlock = peerHeight - commonBlockSummary.getHeight(); // Limit the number of blocks we are comparing. FUTURE: we could request more in batches, but there may not be a case when this is needed - final int summariesRequired = Math.min(peerAdditionalBlocksAfterCommonBlock, MAXIMUM_REQUEST_SIZE); + int summariesRequired = Math.min(peerAdditionalBlocksAfterCommonBlock, MAXIMUM_REQUEST_SIZE); - if (summariesRequired > 0) { - LOGGER.trace(String.format("Requesting %d block summar%s from peer %s after common block %.8s. Peer height: %d", summariesRequired, (summariesRequired != 1 ? "ies" : "y"), peer, Base58.encode(commonBlockSummary.getSignature()), peerHeight)); - - List blockSummaries = this.getBlockSummaries(peer, commonBlockSummary.getSignature(), summariesRequired); - peer.getCommonBlockData().setBlockSummariesAfterCommonBlock(blockSummaries); - - if (blockSummaries != null) { - LOGGER.trace(String.format("Peer %s returned %d block summar%s", peer, blockSummaries.size(), (blockSummaries.size() != 1 ? "ies" : "y"))); - - // We need to adjust minChainLength if peers fail to return all expected block summaries - if (blockSummaries.size() < summariesRequired) { - // This could mean that the peer has re-orged. But we still have the same common block, so it's safe to proceed with this set of signatures instead. - LOGGER.debug(String.format("Peer %s returned %d block summar%s instead of expected %d", peer, blockSummaries.size(), (blockSummaries.size() != 1 ? "ies" : "y"), summariesRequired)); - - // Update minChainLength if we have at least 1 block for this peer. If we don't have any blocks, this peer will be excluded from chain weight comparisons later in the process, so we shouldn't update minChainLength - if (blockSummaries.size() > 0) - minChainLength = blockSummaries.size(); + // Check if we can use the cached common block summaries, by comparing the peer's current chain tip against the peer's chain tip when we last found our common block + boolean useCachedSummaries = false; + if (peer.canUseCachedCommonBlockData()) { + if (peer.getCommonBlockData().getBlockSummariesAfterCommonBlock() != null) { + if (peer.getCommonBlockData().getBlockSummariesAfterCommonBlock().size() == summariesRequired) { + LOGGER.debug(String.format("Using cached block summaries for peer %s", peer)); + useCachedSummaries = true; } } } - else { - // There are no block summaries after this common block - peer.getCommonBlockData().setBlockSummariesAfterCommonBlock(null); + + if (useCachedSummaries == false) { + if (summariesRequired > 0) { + LOGGER.trace(String.format("Requesting %d block summar%s from peer %s after common block %.8s. Peer height: %d", summariesRequired, (summariesRequired != 1 ? "ies" : "y"), peer, Base58.encode(commonBlockSummary.getSignature()), peerHeight)); + + List blockSummaries = this.getBlockSummaries(peer, commonBlockSummary.getSignature(), summariesRequired); + peer.getCommonBlockData().setBlockSummariesAfterCommonBlock(blockSummaries); + + if (blockSummaries != null) { + LOGGER.trace(String.format("Peer %s returned %d block summar%s", peer, blockSummaries.size(), (blockSummaries.size() != 1 ? "ies" : "y"))); + + // We need to adjust minChainLength if peers fail to return all expected block summaries + if (blockSummaries.size() < summariesRequired) { + // This could mean that the peer has re-orged. But we still have the same common block, so it's safe to proceed with this set of signatures instead. + LOGGER.debug(String.format("Peer %s returned %d block summar%s instead of expected %d", peer, blockSummaries.size(), (blockSummaries.size() != 1 ? "ies" : "y"), summariesRequired)); + + // Update minChainLength if we have at least 1 block for this peer. If we don't have any blocks, this peer will be excluded from chain weight comparisons later in the process, so we shouldn't update minChainLength + if (blockSummaries.size() > 0) + minChainLength = blockSummaries.size(); + } + } + } else { + // There are no block summaries after this common block + peer.getCommonBlockData().setBlockSummariesAfterCommonBlock(null); + } } } diff --git a/src/main/java/org/qortal/network/Peer.java b/src/main/java/org/qortal/network/Peer.java index ef6fb88a..08db0dd9 100644 --- a/src/main/java/org/qortal/network/Peer.java +++ b/src/main/java/org/qortal/network/Peer.java @@ -15,6 +15,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Random; +import java.util.Arrays; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; @@ -632,6 +633,25 @@ public class Peer { } } + + // Common block data + + public boolean canUseCachedCommonBlockData() { + PeerChainTipData peerChainTipData = this.getChainTipData(); + CommonBlockData commonBlockData = this.getCommonBlockData(); + + if (peerChainTipData != null && commonBlockData != null) { + PeerChainTipData commonBlockChainTipData = commonBlockData.getChainTipData(); + if (peerChainTipData.getLastBlockSignature() != null && commonBlockChainTipData != null && commonBlockChainTipData.getLastBlockSignature() != null) { + if (Arrays.equals(peerChainTipData.getLastBlockSignature(), commonBlockChainTipData.getLastBlockSignature())) { + return true; + } + } + } + return false; + } + + // Utility methods /** Returns true if ports and addresses (or hostnames) match */