use of org.aion.zero.types.IAionBlock in project aion by aionnetwork.
the class AionBlockStore method revert.
@Override
public void revert(long previousLevel) {
IAionBlock bestBlock = getBestBlock();
long currentLevel = bestBlock.getNumber();
// ensure that the given level is lower than current
if (previousLevel >= currentLevel) {
return;
}
// walk back removing blocks greater than the given level value
IAionBlock bestLine = bestBlock;
while (currentLevel > previousLevel) {
// remove all the blocks at that level
List<BlockInfo> currentLevelBlocks = getBlockInfoForLevel(currentLevel);
if (currentLevelBlocks == null || currentLevelBlocks.size() == 0) {
blocks.delete(bestLine.getHash());
LOG.error("Null block information found at " + currentLevel + " when information should exist.");
} else {
for (BlockInfo bk_info : currentLevelBlocks) {
blocks.delete(bk_info.getHash());
}
}
// remove the level
index.remove(currentLevel);
if (bestLine != null) {
bestLine = getBlockByHash(bestLine.getParentHash());
} else {
// attempt to find another block at the parent level
bestLine = getChainBlockByNumber(currentLevel - 1);
}
--currentLevel;
}
if (bestLine == null) {
LOG.error("Block at level #" + previousLevel + " is null. Reverting further back may be required.");
} else {
// update the main chain based on difficulty, if needed
List<BlockInfo> blocks = getBlockInfoForLevel(previousLevel);
BlockInfo blockInfo = getBlockInfoForHash(blocks, bestLine.getHash());
// no side chains at this level
if (blocks.size() == 1 && blockInfo != null) {
if (!blockInfo.isMainChain()) {
blockInfo.setMainChain(true);
setBlockInfoForLevel(previousLevel, blocks);
}
} else {
if (blockInfo == null) {
LOG.error("Null block information found at " + previousLevel + " when information should exist. " + "Rebuilding information.");
// recreate missing block info
blockInfo = new BlockInfo();
blockInfo.setCummDifficulty(getTotalDifficultyForHash(bestLine.getParentHash()).add(bestLine.getHeader().getDifficultyBI()));
blockInfo.setHash(bestLine.getHash());
blocks.add(blockInfo);
}
// check for max total difficulty
BlockInfo maxTDInfo = blockInfo;
for (BlockInfo info : blocks) {
if (info.getCummDifficulty().compareTo(maxTDInfo.getCummDifficulty()) > 0) {
maxTDInfo = info;
}
}
// 2. Loop back on each level until common block
IAionBlock forkLine = getBlockByHash(maxTDInfo.getHash());
loopBackToCommonBlock(bestLine, forkLine);
}
}
}
use of org.aion.zero.types.IAionBlock in project aion by aionnetwork.
the class AionBlockStore method reBranch.
@Override
public void reBranch(AionBlock forkBlock) {
IAionBlock bestBlock = getBestBlock();
long currentLevel = Math.max(bestBlock.getNumber(), forkBlock.getNumber());
// 1. First ensure that you are one the save level
IAionBlock 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);
} else {
LOG.error("Null block information found at " + currentLevel + " when information should exist.");
}
forkLine = getBlockByHash(forkLine.getParentHash());
--currentLevel;
}
}
IAionBlock 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);
} else {
LOG.error("Null block information found at " + currentLevel + " when information should exist.");
}
bestLine = getBlockByHash(bestLine.getParentHash());
--currentLevel;
}
}
// 2. Loop back on each level until common block
loopBackToCommonBlock(bestLine, forkLine);
}
use of org.aion.zero.types.IAionBlock in project aion by aionnetwork.
the class AionBlockStore method getListHeadersEndWith.
@Override
public List<A0BlockHeader> getListHeadersEndWith(byte[] hash, long qty) {
List<AionBlock> blocks = getListBlocksEndWith(hash, qty);
List<A0BlockHeader> headers = new ArrayList<>(blocks.size());
for (IAionBlock b : blocks) {
headers.add(b.getHeader());
}
return headers;
}
use of org.aion.zero.types.IAionBlock in project aion by aionnetwork.
the class AionBlockStore method getTotalDifficultyForHash.
@Override
public BigInteger getTotalDifficultyForHash(byte[] hash) {
IAionBlock 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 (Arrays.equals(blockInfo.getHash(), hash)) {
return blockInfo.cummDifficulty;
}
}
return ZERO;
}
use of org.aion.zero.types.IAionBlock in project aion by aionnetwork.
the class AionBlockStore method pruneAndCorrect.
@Override
public void pruneAndCorrect() {
IAionBlock block = getBestBlock();
long initialLevel = block.getNumber();
long level = initialLevel;
// top down pruning of nodes on side chains
while (level > 0) {
pruneSideChains(block);
block = getBlockByHash(block.getParentHash());
if (block == null) {
LOG.error("Block #" + (level - 1) + " missing from the database. " + "Cannot proceed with block pruning and total difficulty updates.");
return;
}
level = block.getNumber();
}
// prune genesis
pruneSideChains(block);
// bottom up repair of information
BigInteger parentTotalDifficulty = block.getCumulativeDifficulty();
level = 1;
while (level <= initialLevel) {
parentTotalDifficulty = correctTotalDifficulty(level, parentTotalDifficulty);
LOG.info("Updated total difficulty on level " + level + " to " + parentTotalDifficulty + ".");
level++;
}
}
Aggregations