Browse Source

Apply blocks in syncToPeerChain() if the latest received block is newer than our latest, and we started from an out of date chain.

This solves a common problem that is mostly seen when starting a node that has been switched off for some time, or when starting from a bootstrap. In these cases, it can be difficult get synced to the latest if you are starting from a small fork. This is because it required that the node was brought up to date via a single peer, and there wasn't much room for error if it failed to retrieve a block a couple of times. This generally caused the blocks to be thrown away and it would try the same process over and over.

The solution is to apply new blocks if the most recently received block is newer than our current latest block. This gets the node back on to the main fork where it can then sync using the regular applyNewBlocks() method.
chain-weight-consensus
CalDescent 3 years ago
parent
commit
c0c5bf1591
  1. 20
      src/main/java/org/qortal/controller/Synchronizer.java

20
src/main/java/org/qortal/controller/Synchronizer.java

@ -771,15 +771,33 @@ public class Synchronizer {
if (cachedCommonBlockData != null)
cachedCommonBlockData.setBlockSummariesAfterCommonBlock(null);
// If we have already received RECENT blocks from this peer, go ahead and apply them
// If we have already received recent or newer blocks from this peer, go ahead and apply them
if (peerBlocks.size() > 0) {
final Block peerLatestBlock = peerBlocks.get(peerBlocks.size() - 1);
final Long minLatestBlockTimestamp = Controller.getMinimumLatestBlockTimestamp();
// If we have received at least one recent block, we can apply them
if (peerLatestBlock != null && minLatestBlockTimestamp != null
&& peerLatestBlock.getBlockData().getTimestamp() > minLatestBlockTimestamp) {
LOGGER.debug("Newly received blocks are recent, so we will apply them");
break;
}
// If our latest block is very old....
final BlockData ourLatestBlockData = repository.getBlockRepository().getLastBlock();
if (minLatestBlockTimestamp != null && ourLatestBlockData.getTimestamp() < minLatestBlockTimestamp) {
// ... and we have received a block that is more recent than our latest block ...
if (peerLatestBlock.getBlockData().getTimestamp() > ourLatestBlockData.getTimestamp()) {
// ... then apply the blocks, as it takes us a step forward.
// This is particularly useful when starting up a node that was on a small fork when it was last shut down.
// In these cases, we now allow the node to sync forward, and get onto the main chain again.
// Without this, we would require that the node syncs ENTIRELY with this peer,
// and any problems downloading a block would cause all progress to be lost.
LOGGER.debug(String.format("Newly received blocks are %d ms newer than our latest block - so we will apply them", peerLatestBlock.getBlockData().getTimestamp() - ourLatestBlockData.getTimestamp()));
break;
}
}
}
// Otherwise, give up and move on to the next peer, to avoid putting our chain into an outdated state
return SynchronizationResult.NO_REPLY;

Loading…
Cancel
Save