Skip to content

Commit

Permalink
AKI-655 Implemented a blockStore call for querying multi-layer parent…
Browse files Browse the repository at this point in the history
… blocks
  • Loading branch information
AionJayT committed Feb 12, 2020
1 parent 65a3cf9 commit 2f2f57a
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 42 deletions.
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

0 comments on commit 2f2f57a

Please sign in to comment.