diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockQueue.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockQueue.java index 379b32ef..c1490231 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockQueue.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockQueue.java @@ -11,6 +11,10 @@ import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedQueue; /** + * The processing queue for blocks to be validated and added to the blockchain. + * This class also maintains the list of hashes from the peer with the heaviest sub-tree. + * Based on these hashes, blocks are added to the queue. + * * @author Roman Mandeleil * Created on: 27/07/2014 11:28 */ @@ -18,9 +22,17 @@ public class BlockQueue { private static Logger logger = LoggerFactory.getLogger("blockchain"); + /** The list of hashes of the heaviest chain on the network, + * for which this client doesn't have the blocks yet */ private Deque blockHashQueue = new ConcurrentLinkedDeque<>(); + + /** Queue with blocks to be validated and added to the blockchain */ private Queue blockReceivedQueue = new ConcurrentLinkedQueue<>(); + + /** Highest known total difficulty, representing the heaviest chain on the network */ private BigInteger highestTotalDifficulty; + + /** Last block in the queue to be processed */ private Block lastBlock; private Timer timer = new Timer("BlockQueueTimer"); @@ -33,6 +45,9 @@ public class BlockQueue { }, 10, 10); } + /** + * Processing the queue adding blocks to the chain. + */ private void nudgeQueue() { if (blockReceivedQueue.isEmpty()) return; @@ -41,18 +56,28 @@ public class BlockQueue { WorldManager.getInstance().getBlockchain().add(block); } + /** + * Add a list of blocks to the processing queue. + * The list is validated by making sure the first block in the received list of blocks + * is the next expected block number of the queue. + * + * The queue is configured to contain a maximum number of blocks to avoid memory issues + * If the list exceeds that, the rest of the received blocks in the list are discarded. + * + * @param blockList - the blocks received from a peer to be added to the queue + */ public void addBlocks(List blockList) { - Block lastReceivedBlock = blockList.get(blockList.size() - 1); + Block lastReceivedBlock = blockList.get(0); if (lastReceivedBlock.getNumber() != getLastBlock().getNumber() + 1) return; - for (int i = blockList.size() - 1; i >= 0; --i) { - + for (Block block : blockList) { + if (blockReceivedQueue.size() > SystemProperties.CONFIG.maxBlocksQueued()) return; - this.lastBlock = blockList.get(i); + this.lastBlock = block; logger.trace("Last block now index: [{}]", lastBlock.getNumber()); blockReceivedQueue.add(lastBlock); } @@ -60,25 +85,35 @@ public class BlockQueue { blockReceivedQueue.size()); } - public BigInteger getHighestTotalDifficulty() { - return highestTotalDifficulty; - } - - public void setHighestTotalDifficulty(BigInteger highestTotalDifficulty) { - this.highestTotalDifficulty = highestTotalDifficulty; - } - + /** + * Returns the last block in the queue. If the queue is empty, + * this will return the last block added to the blockchain. + * + * @return The last known block this client on the network + */ public Block getLastBlock() { if (blockReceivedQueue.isEmpty()) return WorldManager.getInstance().getBlockchain().getLastBlock(); return lastBlock; } + /** + * Reset the queue of hashes of blocks to be retrieved + * and add the best hash to the top of the queue + * + * @param hash - the best hash + */ public void setBestHash(byte[] hash) { blockHashQueue.clear(); blockHashQueue.addLast(hash); } + /** + * Returns the last added hash to the queue representing + * the latest known block on the network + * + * @return The best hash on the network known to the client + */ public byte[] getBestHash() { return blockHashQueue.peekLast(); } @@ -86,7 +121,13 @@ public class BlockQueue { public void addHash(byte[] hash) { blockHashQueue.addLast(hash); } - + + /** + * Return a list of hashes from blocks that still need to be downloaded. + * + * @param amount - the number of hashes to return + * @return A list of hashes for which blocks need to be retrieved. + */ public List getHashes(int amount) { List hashes = new ArrayList<>(); for (int i = 0; i < amount; i++) { @@ -113,11 +154,28 @@ public class BlockQueue { return 0; } } + + public BigInteger getHighestTotalDifficulty() { + return highestTotalDifficulty; + } + public void setHighestTotalDifficulty(BigInteger highestTotalDifficulty) { + this.highestTotalDifficulty = highestTotalDifficulty; + } + + /** + * Returns the current number of blocks in the queue + * + * @return the current number of blocks in the queue + */ public int size() { return blockReceivedQueue.size(); } + /** + * Cancel and purge the timer-thread that + * processes the blocks in the queue + */ public void close() { timer.cancel(); timer.purge();