From 08f3d653ccbdce11f77a28311f32f5dca39207bb Mon Sep 17 00:00:00 2001 From: CalDescent Date: Sun, 28 Mar 2021 17:27:04 +0100 Subject: [PATCH] Added new settings "maxBlocksPerRequest" and "maxBlocksPerResponse", to control the number of blocks requested and returned by nodes when using GetBlocksMessage and BlocksMessage. --- .../java/org/qortal/controller/Controller.java | 12 +++++++++--- .../java/org/qortal/controller/Synchronizer.java | 14 +++++++++----- src/main/java/org/qortal/network/Network.java | 1 - .../org/qortal/network/message/BlocksMessage.java | 1 + src/main/java/org/qortal/settings/Settings.java | 8 ++++++++ 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/qortal/controller/Controller.java b/src/main/java/org/qortal/controller/Controller.java index 40c25d84..d988f24d 100644 --- a/src/main/java/org/qortal/controller/Controller.java +++ b/src/main/java/org/qortal/controller/Controller.java @@ -1245,6 +1245,10 @@ public class Controller extends Thread { return; } + // Ensure that we don't serve more blocks than the amount specified in the settings + // Serializing multiple blocks is very slow, so by default we are using a low limit + int blockLimitPerRequest = Settings.getInstance().getMaxBlocksPerResponse(); + List blockDataList = new ArrayList<>(); // Attempt to serve from our cache of latest blocks @@ -1256,7 +1260,7 @@ public class Controller extends Thread { } if (blockDataList.isEmpty()) { - int numberRequested = Math.min(Network.MAX_BLOCKS_PER_REPLY, getBlocksMessage.getNumberRequested()); + int numberRequested = Math.min(blockLimitPerRequest, getBlocksMessage.getNumberRequested()); BlockData blockData = repository.getBlockRepository().fromReference(parentSignature); @@ -1274,8 +1278,10 @@ public class Controller extends Thread { List blocks = new ArrayList<>(); for (BlockData blockData : blockDataList) { - Block block = new Block(repository, blockData); - blocks.add(block); + if (blocks.size() < blockLimitPerRequest) { + Block block = new Block(repository, blockData); + blocks.add(block); + } } Message blocksMessage = new BlocksMessage(blocks); diff --git a/src/main/java/org/qortal/controller/Synchronizer.java b/src/main/java/org/qortal/controller/Synchronizer.java index ade6fb88..c72d18da 100644 --- a/src/main/java/org/qortal/controller/Synchronizer.java +++ b/src/main/java/org/qortal/controller/Synchronizer.java @@ -56,9 +56,6 @@ public class Synchronizer { /** Maximum number of block signatures we ask from peer in one go */ private static final int MAXIMUM_REQUEST_SIZE = 200; // XXX move to Settings? - /** Maximum number of blocks we ask from peer in one go */ - private static final int MAXIMUM_BLOCKS_REQUEST_SIZE = 1; // XXX move to Settings? - /** Number of retry attempts if a peer fails to respond with the requested data */ private static final int MAXIMUM_RETRIES = 1; // XXX move to Settings? @@ -380,13 +377,17 @@ public class Synchronizer { if (Settings.getInstance().isFastSyncEnabledWhenResolvingFork() && peer.getPeersVersion() >= PEER_VERSION_150) { // This peer supports syncing multiple blocks at once via GetBlocksMessage, and it is enabled in the settings int numberBlocksRequired = additionalPeerBlocksAfterCommonBlock - peerBlocks.size(); + + // Ensure that we don't request more blocks than specified in the settings + int maxBlocksPerRequest = Settings.getInstance().getMaxBlocksPerRequest(); + while (numberBlocksRequired > 0) { if (Controller.isStopping()) return SynchronizationResult.SHUTTING_DOWN; byte[] latestPeerSignature = peerBlocks.isEmpty() ? commonBlockSig : peerBlocks.get(peerBlocks.size() - 1).getSignature(); int lastPeerHeight = commonBlockHeight + peerBlocks.size(); - int numberOfBlocksToRequest = Math.min(numberBlocksRequired, MAXIMUM_BLOCKS_REQUEST_SIZE); + int numberOfBlocksToRequest = Math.min(numberBlocksRequired, maxBlocksPerRequest); LOGGER.trace(String.format("Requesting %d block%s after height %d, sig %.8s", numberOfBlocksToRequest, (numberOfBlocksToRequest != 1 ? "s" : ""), lastPeerHeight, Base58.encode(latestPeerSignature))); @@ -600,11 +601,14 @@ public class Synchronizer { // Fetch, and apply, blocks from peer int maxBatchHeight = commonBlockHeight + SYNC_BATCH_SIZE; + // Ensure that we don't request more blocks than specified in the settings + int maxBlocksPerRequest = Settings.getInstance().getMaxBlocksPerRequest(); + while (ourHeight < peerHeight && ourHeight < maxBatchHeight) { if (Controller.isStopping()) return SynchronizationResult.SHUTTING_DOWN; - int numberRequested = Math.min(maxBatchHeight - ourHeight, MAXIMUM_BLOCKS_REQUEST_SIZE); + int numberRequested = Math.min(maxBatchHeight - ourHeight, maxBlocksPerRequest); LOGGER.trace(String.format("Fetching %d blocks after height %d, sig %.8s from %s", numberRequested, ourHeight, Base58.encode(latestPeerSignature), peer)); List blocks = this.fetchBlocks(repository, peer, latestPeerSignature, numberRequested); diff --git a/src/main/java/org/qortal/network/Network.java b/src/main/java/org/qortal/network/Network.java index 7a234c7a..0e9ac32b 100644 --- a/src/main/java/org/qortal/network/Network.java +++ b/src/main/java/org/qortal/network/Network.java @@ -89,7 +89,6 @@ public class Network { public static final int MAX_SIGNATURES_PER_REPLY = 500; public static final int MAX_BLOCK_SUMMARIES_PER_REPLY = 500; - public static final int MAX_BLOCKS_PER_REPLY = 500; // Generate our node keys / ID private final Ed25519PrivateKeyParameters edPrivateKeyParams = new Ed25519PrivateKeyParameters(new SecureRandom()); diff --git a/src/main/java/org/qortal/network/message/BlocksMessage.java b/src/main/java/org/qortal/network/message/BlocksMessage.java index f53de301..b997ead5 100644 --- a/src/main/java/org/qortal/network/message/BlocksMessage.java +++ b/src/main/java/org/qortal/network/message/BlocksMessage.java @@ -78,6 +78,7 @@ public class BlocksMessage extends Message { bytes.write(Ints.toByteArray(block.getBlockData().getHeight())); bytes.write(BlockTransformer.toBytes(block)); } + LOGGER.trace(String.format("Total length of %d blocks is %d bytes", this.blocks.size(), bytes.size())); return bytes.toByteArray(); } catch (IOException e) { diff --git a/src/main/java/org/qortal/settings/Settings.java b/src/main/java/org/qortal/settings/Settings.java index d15a4ab9..3070bf96 100644 --- a/src/main/java/org/qortal/settings/Settings.java +++ b/src/main/java/org/qortal/settings/Settings.java @@ -127,6 +127,10 @@ public class Settings { private boolean fastSyncEnabled = false; /** Whether to sync multiple blocks at once when the peer has a different chain */ private boolean fastSyncEnabledWhenResolvingFork = true; + /** Maximum number of blocks to request at once */ + private int maxBlocksPerRequest = 1; + /** Maximum number of blocks this node will serve in a single response */ + private int maxBlocksPerResponse = 5; // Which blockchains this node is running private String blockchainConfig = null; // use default from resources @@ -449,6 +453,10 @@ public class Settings { return this.fastSyncEnabledWhenResolvingFork; } + public int getMaxBlocksPerRequest() { return this.maxBlocksPerRequest; } + + public int getMaxBlocksPerResponse() { return this.maxBlocksPerResponse; } + public boolean isAutoUpdateEnabled() { return this.autoUpdateEnabled; }