@Override public BigInteger getTotalDifficultyForHash(byte[] hash) { Block block = this.getBlockByHash(hash); if (block == null) return ZERO; Long level = block.getNumber(); List<BlockInfo> blockInfos = index.get(level.intValue()); for (BlockInfo blockInfo : blockInfos) if (areEqual(blockInfo.getHash(), hash)) { return blockInfo.cummDifficulty; } return ZERO; }
public void printChain() { Long number = getMaxNumber(); for (int i = 0; i < number; ++i) { List<BlockInfo> levelInfos = index.get(i); if (levelInfos != null) { System.out.print(i); for (BlockInfo blockInfo : levelInfos) { if (blockInfo.isMainChain()) System.out.print(" [" + shortHash(blockInfo.getHash()) + "] "); else System.out.print(" " + shortHash(blockInfo.getHash()) + " "); } System.out.println(); } } }
private void addInternalBlock(Block block, BigInteger cummDifficulty, boolean mainChain) { List<BlockInfo> blockInfos = block.getNumber() >= index.size() ? new ArrayList<BlockInfo>() : index.get((int) block.getNumber()); BlockInfo blockInfo = new BlockInfo(); blockInfo.setCummDifficulty(cummDifficulty); blockInfo.setHash(block.getHash()); blockInfo.setMainChain( mainChain); // FIXME:maybe here I should force reset main chain for all uncles on that level blockInfos.add(blockInfo); index.set((int) block.getNumber(), blockInfos); blocks.put(block.getHash(), block); }
@Override public Block getChainBlockByNumber(long number) { if (number >= index.size()) { return null; } List<BlockInfo> blockInfos = index.get((int) number); for (BlockInfo blockInfo : blockInfos) { if (blockInfo.isMainChain()) { byte[] hash = blockInfo.getHash(); return blocks.get(hash); } } return null; }
public List<Block> getBlocksByNumber(long number) { List<Block> result = new ArrayList<>(); if (number >= index.size()) { return result; } List<BlockInfo> blockInfos = index.get((int) number); for (BlockInfo blockInfo : blockInfos) { byte[] hash = blockInfo.getHash(); Block block = blocks.get(hash); result.add(block); } return result; }
public List<byte[]> getListHashesStartWith(long number, long maxBlocks) { List<byte[]> result = new ArrayList<>(); int i; for (i = 0; i < maxBlocks; ++i) { List<BlockInfo> blockInfos = index.get((int) number); if (blockInfos == null) break; for (BlockInfo blockInfo : blockInfos) if (blockInfo.isMainChain()) { result.add(blockInfo.getHash()); break; } ++number; } maxBlocks -= i; return result; }
@Override public BigInteger getTotalDifficulty() { long maxNumber = getMaxNumber(); List<BlockInfo> blockInfos = index.get((int) maxNumber); for (BlockInfo blockInfo : blockInfos) { if (blockInfo.isMainChain()) { return blockInfo.getCummDifficulty(); } } while (true) { --maxNumber; List<BlockInfo> infos = getBlockInfoForLevel(maxNumber); for (BlockInfo blockInfo : infos) { if (blockInfo.isMainChain()) { return blockInfo.getCummDifficulty(); } } } }
private static BlockInfo getBlockInfoForHash(List<BlockInfo> blocks, byte[] hash) { for (BlockInfo blockInfo : blocks) if (areEqual(hash, blockInfo.getHash())) return blockInfo; return null; }
@Override public void reBranch(Block forkBlock) { Block bestBlock = getBestBlock(); long maxLevel = Math.max(bestBlock.getNumber(), forkBlock.getNumber()); // 1. First ensure that you are one the save level long currentLevel = maxLevel; Block forkLine = forkBlock; if (forkBlock.getNumber() > bestBlock.getNumber()) { while (currentLevel > bestBlock.getNumber()) { List<BlockInfo> blocks = getBlockInfoForLevel(currentLevel); BlockInfo blockInfo = getBlockInfoForHash(blocks, forkLine.getHash()); if (blockInfo != null) { blockInfo.setMainChain(true); setBlockInfoForLevel(currentLevel, blocks); } forkLine = getBlockByHash(forkLine.getParentHash()); --currentLevel; } } Block bestLine = bestBlock; if (bestBlock.getNumber() > forkBlock.getNumber()) { while (currentLevel > forkBlock.getNumber()) { List<BlockInfo> blocks = getBlockInfoForLevel(currentLevel); BlockInfo blockInfo = getBlockInfoForHash(blocks, bestLine.getHash()); if (blockInfo != null) { blockInfo.setMainChain(false); setBlockInfoForLevel(currentLevel, blocks); } bestLine = getBlockByHash(bestLine.getParentHash()); --currentLevel; } } // 2. Loop back on each level until common block while (!bestLine.isEqual(forkLine)) { List<BlockInfo> levelBlocks = getBlockInfoForLevel(currentLevel); BlockInfo bestInfo = getBlockInfoForHash(levelBlocks, bestLine.getHash()); if (bestInfo != null) { bestInfo.setMainChain(false); setBlockInfoForLevel(currentLevel, levelBlocks); } BlockInfo forkInfo = getBlockInfoForHash(levelBlocks, forkLine.getHash()); if (forkInfo != null) { forkInfo.setMainChain(true); setBlockInfoForLevel(currentLevel, levelBlocks); } bestLine = getBlockByHash(bestLine.getParentHash()); forkLine = getBlockByHash(forkLine.getParentHash()); --currentLevel; } }