Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AKI-655 Added multi-layer parent block query in the blockstore #1111

Merged
merged 1 commit into from
Feb 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1221,7 +1221,7 @@ BlockContext createNewMiningBlockInternal(
return null;
}

BlockHeader parentMiningBlock = null;
BlockHeader parentMiningBlock;
BlockHeader parentMiningBlocksParent = null;
byte[] newDiff;
IDifficultyCalculator diffCalculator;
Expand All @@ -1233,8 +1233,9 @@ BlockContext createNewMiningBlockInternal(
LOG.warn("Tried to create 2 PoW blocks in a row");
return null;
} else {
parentMiningBlock = getParent(parentHdr).getHeader();
parentMiningBlocksParent = getParent(parentMiningBlock).getHeader();
Block[] blockFamily = getBlockStore().getTwoGenerationBlocksByHashWithInfo(parentHdr.getParentHash());
parentMiningBlock = blockFamily[0].getHeader();
parentMiningBlocksParent = blockFamily[1].getHeader();
diffCalculator = chainConfiguration.getUnityDifficultyCalculator();
}
} else {
Expand Down Expand Up @@ -1289,8 +1290,10 @@ private StakingBlock createNewStakingBlock(
parentSeed = GENESIS_SEED;
newDiff = calculateFirstPoSDifficultyAtBlock(parent);
} else {
BlockHeader parentStakingBlock = getParent(parentHdr).getHeader();
BlockHeader parentStakingBlocksParent = getParent(parentStakingBlock).getHeader();
Block[] blockFamily = getBlockStore().getTwoGenerationBlocksByHashWithInfo(parentHdr.getParentHash());

BlockHeader parentStakingBlock = blockFamily[0].getHeader();
BlockHeader parentStakingBlocksParent = blockFamily[1].getHeader();
parentSeed = ((StakingBlockHeader) parentStakingBlock).getSeed();
newDiff = chainConfiguration.getUnityDifficultyCalculator().calculateDifficulty(parentStakingBlock, parentStakingBlocksParent);
}
Expand Down Expand Up @@ -1598,61 +1601,58 @@ public boolean isValid(BlockHeader header) {
return false;
}

Block parent = getParent(header);
if (parent == null) {
Block[] threeGenParents = getBlockStore().getThreeGenerationBlocksByHashWithInfo(header.getParentHash());

if (threeGenParents == null) {
return false;
}

Block grandParent = getParent(parent.getHeader());
Block parentBlock = threeGenParents[0];
Block grandparentBlock = threeGenParents[1];
Block greatGrandparentBlock = threeGenParents[2];

if (header.getSealType() == BlockSealType.SEAL_POW_BLOCK) {
if (forkUtility.isUnityForkActive(header.getNumber())) {
if (grandParent == null) {
if (grandparentBlock == null || greatGrandparentBlock == null) {
return false;
}

Block greatGrandParent = getParent(grandParent.getHeader());
if (greatGrandParent == null) {
return false;
}

return unityParentBlockHeaderValidator.validate(header, parent.getHeader(), LOG, null) &&
unityGreatGrandParentBlockHeaderValidator.validate(grandParent.getHeader(), greatGrandParent.getHeader(), header, LOG);
return unityParentBlockHeaderValidator.validate(header, parentBlock.getHeader(), LOG, null) &&
unityGreatGrandParentBlockHeaderValidator.validate(grandparentBlock.getHeader(), greatGrandparentBlock.getHeader(), header, LOG);
} else {
return preUnityParentBlockHeaderValidator.validate(header, parent.getHeader(), LOG, null) &&
preUnityGrandParentBlockHeaderValidator.validate(parent.getHeader(), grandParent == null ? null : grandParent.getHeader(), header, LOG);
return preUnityParentBlockHeaderValidator.validate(header, parentBlock.getHeader(), LOG, null) &&
preUnityGrandParentBlockHeaderValidator.validate(parentBlock.getHeader(), grandparentBlock == null ? null : grandparentBlock.getHeader(), header, LOG);
}
} else if (header.getSealType() == BlockSealType.SEAL_POS_BLOCK) {
if (!forkUtility.isUnityForkActive(header.getNumber())) {
LOG.warn("Trying to import a Staking block when the Unity fork is not active.");
return false;
}

if (grandParent == null) {
if (grandparentBlock == null) {
LOG.warn("Staking block {} cannot find its grandparent", header.getNumber());
return false;
}

Block greatGrandParent = getParent(grandParent.getHeader());

if (forkUtility.isUnityForkBlock(parent.getNumber())) {
BigInteger expectedDiff = calculateFirstPoSDifficultyAtBlock(parent);
if (forkUtility.isUnityForkBlock(parentBlock.getNumber())) {
BigInteger expectedDiff = calculateFirstPoSDifficultyAtBlock(parentBlock);
if (!expectedDiff.equals(header.getDifficultyBI())) {
return false;
}
grandParent = new GenesisStakingBlock(expectedDiff);
grandparentBlock = new GenesisStakingBlock(expectedDiff);
}

BigInteger stake = null;

try {
stake = getStakingContractHelper().getEffectiveStake(new AionAddress(AddressSpecs.computeA0Address(((StakingBlockHeader) header).getSigningPublicKey())), ((StakingBlockHeader) header).getCoinbase(), parent);
stake = getStakingContractHelper().getEffectiveStake(new AionAddress(AddressSpecs.computeA0Address(((StakingBlockHeader) header).getSigningPublicKey())), ((StakingBlockHeader) header).getCoinbase(), parentBlock);
} catch (Exception e) {
LOG.error("Shutdown due to a fatal error encountered while getting the effective stake.", e);
System.exit(SystemExitCodes.FATAL_VM_ERROR);
}

return unityParentBlockHeaderValidator.validate(header, parent.getHeader(), LOG, stake) &&
unityGreatGrandParentBlockHeaderValidator.validate(grandParent.getHeader(), greatGrandParent.getHeader(), header, LOG);
return unityParentBlockHeaderValidator.validate(header, parentBlock.getHeader(), LOG, stake) &&
unityGreatGrandParentBlockHeaderValidator.validate(grandparentBlock.getHeader(), greatGrandparentBlock.getHeader(), header, LOG);

} else {
LOG.debug("Invalid header seal type!");
Expand Down
109 changes: 94 additions & 15 deletions modAionImpl/src/org/aion/zero/impl/db/AionBlockStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public Block getBestBlockWithInfo() {
bestBlock = getChainBlockByNumber(maxLevel);
}

BlockInfo bestBlockInfo = getBlockInfoForHash(bestBlock.getHash(), bestBlock.getNumber());
BlockInfo bestBlockInfo = getBlockInfoWithHashAndNumber(bestBlock.getHash(), bestBlock.getNumber());
if (bestBlockInfo == null) {
LOG.error(
"Encountered a kernel database corruption: cannot find blockInfos at level {} in index data store. "
Expand Down Expand Up @@ -573,22 +573,31 @@ public Block getBlockByHashWithInfo(byte[] hash) {
lock.lock();

try {
Block retBlock = blocks.get(hash);
if (retBlock == null) {
return null;
} else {
BlockInfo blockInfo = getBlockInfoForHash(hash, retBlock.getNumber());
if (blockInfo != null) {
if (blockInfo.isMainChain()) {
retBlock.setMainChain();
}
return getBlockWithInfo(hash);
} finally {
lock.unlock();
}
}

retBlock.setTotalDifficulty(blockInfo.getTotalDifficulty());
/**
* Retrieve block with unity protocol info for the inner call
* @param hash given hash of the block
* @return the block data has matched hash with unity protocol info
*/
private Block getBlockWithInfo(byte[] hash) {
Block returnBlock = blocks.get(hash);
if (returnBlock == null) {
return null;
} else {
BlockInfo blockInfo = getBlockInfoWithHashAndNumber(hash, returnBlock.getNumber());
if (blockInfo != null) {
if (blockInfo.isMainChain()) {
returnBlock.setMainChain();
}
return retBlock;

returnBlock.setTotalDifficulty(blockInfo.getTotalDifficulty());
}
} finally {
lock.unlock();
return returnBlock;
}
}

Expand Down Expand Up @@ -619,7 +628,7 @@ public BigInteger getTotalDifficultyForHash(byte[] hash) {
* @return null when the hash info is not matched or database corruption. Otherwise, return the
* BlockInfoV1 stored in the index database.
*/
private BlockInfo getBlockInfoForHash(byte[] hash, long blockNumber) {
private BlockInfo getBlockInfoWithHashAndNumber(byte[] hash, long blockNumber) {
List<BlockInfo> blockInfos = index.get(blockNumber);
if (blockInfos == null) {
LOG.error(
Expand Down Expand Up @@ -1384,6 +1393,76 @@ void redoIndexWithoutSideChains(Block block) {
}
}

/**
* Retrieve three generation blocks with unity protocol info with one lock.
* @param hash given hash of the block
* @return the 3 generation block data have matched hash with unity protocol info. Block[0] is the parent block,
* Block[1] is the grandParent block, and Block[2] is the greatParentBlock. The return might only contain the parent
* block and still return the 3-elements array.
*/
public final Block[] getThreeGenerationBlocksByHashWithInfo(byte[] hash) {
if (hash == null) {
return null;
}

Block[] blockFamily = new Block[] { null, null, null};
lock.lock();

try {
Block block = getBlockWithInfo(hash);
if (block != null) {
blockFamily[0] = block;

Block parentBlock = getBlockWithInfo(block.getParentHash());
if (parentBlock != null) {
blockFamily[1] = parentBlock;

Block grandParentBlock = getBlockWithInfo(parentBlock.getParentHash());
if (grandParentBlock != null) {
blockFamily[2] = grandParentBlock;
}
}
}

return blockFamily;
} finally {
lock.unlock();
}
}

/**
* Retrieve two generation blocks with unity protocol info with one lock.
*
* @param hash given hash of the block
* @return the 2 generation block data have matched hash with unity protocol info. Block[0] is
* the parent block, Block[1] is the grandParent block. The return might only contain the
* parent block and still return the 2-elements array.
*/
public final Block[] getTwoGenerationBlocksByHashWithInfo(byte[] hash) {
if (hash == null) {
return null;
}
Block[] blockFamily = new Block[] { null, null};

lock.lock();

try {
Block block = getBlockWithInfo(hash);
if (block != null) {
blockFamily[0] = block;

Block parentBlock = getBlockWithInfo(block.getParentHash());
if (parentBlock != null) {
blockFamily[1] = parentBlock;
}
}

return blockFamily;
} finally {
lock.unlock();
}
}

public static class BlockInfo {

/**
Expand Down