In syncToPeerChain(), only apply a partial set of peer's blocks if they are recent.

If a peer fails to reply with all requested blocks, we will now only apply the blocks we have received so far if at least one of them is recent. This should prevent or greatly reduce the scenario where our chain is taken from a recent to an outdated state due to only partially syncing with a peer. It is best to keep our chain "recent" if possible, as this ensures that the peer selection code always runs, and therefore avoids unnecessarily syncing to a random peer on an inferior chain.
This commit is contained in:
CalDescent 2021-04-24 20:12:11 +01:00
parent 1e491dd8fb
commit 476731a2c3

View File

@ -759,11 +759,17 @@ public class Synchronizer {
LOGGER.info(String.format("Peer %s failed to respond with more block signatures after height %d, sig %.8s", peer, LOGGER.info(String.format("Peer %s failed to respond with more block signatures after height %d, sig %.8s", peer,
height, Base58.encode(latestPeerSignature))); height, Base58.encode(latestPeerSignature)));
// If we have already received blocks from this peer, go ahead and apply them // If we have already received RECENT blocks from this peer, go ahead and apply them
if (peerBlocks.size() > 0) { if (peerBlocks.size() > 0) {
final Block peerLatestBlock = peerBlocks.get(peerBlocks.size() - 1);
final Long minLatestBlockTimestamp = Controller.getMinimumLatestBlockTimestamp();
if (peerLatestBlock != null && minLatestBlockTimestamp != null
&& peerLatestBlock.getBlockData().getTimestamp() > minLatestBlockTimestamp) {
LOGGER.debug("Newly received blocks are recent, so we will apply them");
break; break;
} }
// Otherwise, give up and move on to the next peer }
// Otherwise, give up and move on to the next peer, to avoid putting our chain into an outdated state
return SynchronizationResult.NO_REPLY; return SynchronizationResult.NO_REPLY;
} }
@ -788,11 +794,17 @@ public class Synchronizer {
if (retryCount >= MAXIMUM_RETRIES) { if (retryCount >= MAXIMUM_RETRIES) {
// If we have already received blocks from this peer, go ahead and apply them // If we have already received RECENT blocks from this peer, go ahead and apply them
if (peerBlocks.size() > 0) { if (peerBlocks.size() > 0) {
final Block peerLatestBlock = peerBlocks.get(peerBlocks.size() - 1);
final Long minLatestBlockTimestamp = Controller.getMinimumLatestBlockTimestamp();
if (peerLatestBlock != null && minLatestBlockTimestamp != null
&& peerLatestBlock.getBlockData().getTimestamp() > minLatestBlockTimestamp) {
LOGGER.debug("Newly received blocks are recent, so we will apply them");
break; break;
} }
// Otherwise, give up and move on to the next peer }
// Otherwise, give up and move on to the next peer, to avoid putting our chain into an outdated state
return SynchronizationResult.NO_REPLY; return SynchronizationResult.NO_REPLY;
} else { } else {