Document BlockQueue
This commit is contained in:
parent
8ae2e9a3a4
commit
8b381635e3
|
@ -11,6 +11,10 @@ import java.util.concurrent.ConcurrentLinkedDeque;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
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
|
* @author Roman Mandeleil
|
||||||
* Created on: 27/07/2014 11:28
|
* Created on: 27/07/2014 11:28
|
||||||
*/
|
*/
|
||||||
|
@ -18,9 +22,17 @@ public class BlockQueue {
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger("blockchain");
|
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<byte[]> blockHashQueue = new ConcurrentLinkedDeque<>();
|
private Deque<byte[]> blockHashQueue = new ConcurrentLinkedDeque<>();
|
||||||
|
|
||||||
|
/** Queue with blocks to be validated and added to the blockchain */
|
||||||
private Queue<Block> blockReceivedQueue = new ConcurrentLinkedQueue<>();
|
private Queue<Block> blockReceivedQueue = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
|
/** Highest known total difficulty, representing the heaviest chain on the network */
|
||||||
private BigInteger highestTotalDifficulty;
|
private BigInteger highestTotalDifficulty;
|
||||||
|
|
||||||
|
/** Last block in the queue to be processed */
|
||||||
private Block lastBlock;
|
private Block lastBlock;
|
||||||
|
|
||||||
private Timer timer = new Timer("BlockQueueTimer");
|
private Timer timer = new Timer("BlockQueueTimer");
|
||||||
|
@ -33,6 +45,9 @@ public class BlockQueue {
|
||||||
}, 10, 10);
|
}, 10, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processing the queue adding blocks to the chain.
|
||||||
|
*/
|
||||||
private void nudgeQueue() {
|
private void nudgeQueue() {
|
||||||
if (blockReceivedQueue.isEmpty())
|
if (blockReceivedQueue.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
@ -41,18 +56,28 @@ public class BlockQueue {
|
||||||
WorldManager.getInstance().getBlockchain().add(block);
|
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<Block> blockList) {
|
public void addBlocks(List<Block> blockList) {
|
||||||
|
|
||||||
Block lastReceivedBlock = blockList.get(blockList.size() - 1);
|
Block lastReceivedBlock = blockList.get(0);
|
||||||
if (lastReceivedBlock.getNumber() != getLastBlock().getNumber() + 1)
|
if (lastReceivedBlock.getNumber() != getLastBlock().getNumber() + 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = blockList.size() - 1; i >= 0; --i) {
|
for (Block block : blockList) {
|
||||||
|
|
||||||
if (blockReceivedQueue.size() > SystemProperties.CONFIG.maxBlocksQueued())
|
if (blockReceivedQueue.size() > SystemProperties.CONFIG.maxBlocksQueued())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.lastBlock = blockList.get(i);
|
this.lastBlock = block;
|
||||||
logger.trace("Last block now index: [{}]", lastBlock.getNumber());
|
logger.trace("Last block now index: [{}]", lastBlock.getNumber());
|
||||||
blockReceivedQueue.add(lastBlock);
|
blockReceivedQueue.add(lastBlock);
|
||||||
}
|
}
|
||||||
|
@ -60,25 +85,35 @@ public class BlockQueue {
|
||||||
blockReceivedQueue.size());
|
blockReceivedQueue.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigInteger getHighestTotalDifficulty() {
|
/**
|
||||||
return highestTotalDifficulty;
|
* Returns the last block in the queue. If the queue is empty,
|
||||||
}
|
* this will return the last block added to the blockchain.
|
||||||
|
*
|
||||||
public void setHighestTotalDifficulty(BigInteger highestTotalDifficulty) {
|
* @return The last known block this client on the network
|
||||||
this.highestTotalDifficulty = highestTotalDifficulty;
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
public Block getLastBlock() {
|
public Block getLastBlock() {
|
||||||
if (blockReceivedQueue.isEmpty())
|
if (blockReceivedQueue.isEmpty())
|
||||||
return WorldManager.getInstance().getBlockchain().getLastBlock();
|
return WorldManager.getInstance().getBlockchain().getLastBlock();
|
||||||
return lastBlock;
|
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) {
|
public void setBestHash(byte[] hash) {
|
||||||
blockHashQueue.clear();
|
blockHashQueue.clear();
|
||||||
blockHashQueue.addLast(hash);
|
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() {
|
public byte[] getBestHash() {
|
||||||
return blockHashQueue.peekLast();
|
return blockHashQueue.peekLast();
|
||||||
}
|
}
|
||||||
|
@ -87,6 +122,12 @@ public class BlockQueue {
|
||||||
blockHashQueue.addLast(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<byte[]> getHashes(int amount) {
|
public List<byte[]> getHashes(int amount) {
|
||||||
List<byte[]> hashes = new ArrayList<>();
|
List<byte[]> hashes = new ArrayList<>();
|
||||||
for (int i = 0; i < amount; i++) {
|
for (int i = 0; i < amount; i++) {
|
||||||
|
@ -114,10 +155,27 @@ public class BlockQueue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
public int size() {
|
||||||
return blockReceivedQueue.size();
|
return blockReceivedQueue.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel and purge the timer-thread that
|
||||||
|
* processes the blocks in the queue
|
||||||
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
timer.purge();
|
timer.purge();
|
||||||
|
|
Loading…
Reference in New Issue