Split Synchronizer.applyNewBlocks() into two methods.

If fast syncing is enabled in the settings (by default it's disabled) AND the peer is running at least v1.5.0, then it will route through to a new method which fetches multiple blocks at a time, in a very similar way to Synchronizer.syncToPeerChain().
If fast syncing is disabled in the settings, or we are communicating with a peer on an older version, it will continue to sync blocks individually.
This commit is contained in:
CalDescent 2021-03-27 18:04:47 +00:00
parent 8c3753326f
commit 3e0ff7f43f

View File

@ -572,8 +572,103 @@ public class Synchronizer {
}
private SynchronizationResult applyNewBlocks(Repository repository, BlockData commonBlockData, int ourInitialHeight,
Peer peer, int peerHeight, List<BlockSummaryData> peerBlockSummaries) throws InterruptedException, DataException {
if (Settings.getInstance().isFastSyncEnabled() && peer.getPeersVersion() >= PEER_VERSION_150)
// This peer supports syncing multiple blocks at once via GetBlocksMessage, and it is enabled in the settings
return this.applyNewBlocksUsingFastSync(repository, commonBlockData, ourInitialHeight, peer, peerHeight, peerBlockSummaries);
else
// Older peer version, or fast sync is disabled in the settings - use slow sync
return this.applyNewBlocksUsingSlowSync(repository, commonBlockData, ourInitialHeight, peer, peerHeight, peerBlockSummaries);
}
private SynchronizationResult applyNewBlocksUsingFastSync(Repository repository, BlockData commonBlockData, int ourInitialHeight,
Peer peer, int peerHeight, List<BlockSummaryData> peerBlockSummaries) throws InterruptedException, DataException {
LOGGER.debug(String.format("Fetching new blocks from peer %s using fast sync", peer));
final int commonBlockHeight = commonBlockData.getHeight();
final byte[] commonBlockSig = commonBlockData.getSignature();
byte[] latestPeerSignature = commonBlockSig;
int ourHeight = ourInitialHeight;
// Fetch, and apply, blocks from peer
int maxBatchHeight = commonBlockHeight + SYNC_BATCH_SIZE;
while (ourHeight < peerHeight && ourHeight < maxBatchHeight) {
if (Controller.isStopping())
return SynchronizationResult.SHUTTING_DOWN;
int numberRequested = Math.min(maxBatchHeight - ourHeight, MAXIMUM_REQUEST_SIZE);
LOGGER.trace(String.format("Fetching %d blocks after height %d, sig %.8s from %s", numberRequested, ourHeight, Base58.encode(latestPeerSignature), peer));
List<Block> blocks = this.fetchBlocks(repository, peer, latestPeerSignature, numberRequested);
if (blocks == null || blocks.isEmpty()) {
LOGGER.info(String.format("Peer %s failed to respond with more blocks after height %d, sig %.8s", peer,
ourHeight, Base58.encode(latestPeerSignature)));
}
LOGGER.trace(String.format("Received %d blocks after height %d, sig %.8s from %s", blocks.size(), ourHeight, Base58.encode(latestPeerSignature), peer));
for (Block newBlock : blocks) {
++ourHeight;
if (Controller.isStopping())
return SynchronizationResult.SHUTTING_DOWN;
if (newBlock == null) {
LOGGER.info(String.format("Peer %s failed to respond with block for height %d, sig %.8s", peer,
ourHeight, Base58.encode(latestPeerSignature)));
return SynchronizationResult.NO_REPLY;
}
if (!newBlock.isSignatureValid()) {
LOGGER.info(String.format("Peer %s sent block with invalid signature for height %d, sig %.8s", peer,
ourHeight, Base58.encode(latestPeerSignature)));
return SynchronizationResult.INVALID_DATA;
}
// Set the repository, because we couldn't do that when originally constructing the Block
newBlock.setRepository(repository);
// Transactions are transmitted without approval status so determine that now
for (Transaction transaction : newBlock.getTransactions()) {
transaction.setInitialApprovalStatus();
}
ValidationResult blockResult = newBlock.isValid();
if (blockResult != ValidationResult.OK) {
LOGGER.info(String.format("Peer %s sent invalid block for height %d, sig %.8s: %s", peer,
ourHeight, Base58.encode(latestPeerSignature), blockResult.name()));
return SynchronizationResult.INVALID_DATA;
}
// Save transactions attached to this block
for (Transaction transaction : newBlock.getTransactions()) {
TransactionData transactionData = transaction.getTransactionData();
repository.getTransactionRepository().save(transactionData);
}
newBlock.process();
LOGGER.trace(String.format("Processed block height %d, sig %.8s", newBlock.getBlockData().getHeight(), Base58.encode(newBlock.getBlockData().getSignature())));
repository.saveChanges();
Controller.getInstance().onNewBlock(newBlock.getBlockData());
// Update latestPeerSignature so that subsequent batches start requesting from the correct block
latestPeerSignature = newBlock.getSignature();
}
}
return SynchronizationResult.OK;
}
private SynchronizationResult applyNewBlocksUsingSlowSync(Repository repository, BlockData commonBlockData, int ourInitialHeight,
Peer peer, int peerHeight, List<BlockSummaryData> peerBlockSummaries) throws InterruptedException, DataException {
LOGGER.debug(String.format("Fetching new blocks from peer %s", peer));
LOGGER.debug(String.format("Fetching new blocks from peer %s using slow sync", peer));
final int commonBlockHeight = commonBlockData.getHeight();
final byte[] commonBlockSig = commonBlockData.getSignature();