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 Jan 30, 2020
1 parent e5f8416 commit 1a38c17
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 27 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,10 @@ 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 = getTwoGenParents(parentHdr);

parentMiningBlock = blockFamily[0].getHeader();
parentMiningBlocksParent = blockFamily[1].getHeader();
diffCalculator = chainConfiguration.getUnityDifficultyCalculator();
}
} else {
Expand Down Expand Up @@ -1289,8 +1291,10 @@ private StakingBlock createNewStakingBlock(
parentSeed = GENESIS_SEED;
newDiff = calculateFirstPoSDifficultyAtBlock(parent);
} else {
BlockHeader parentStakingBlock = getParent(parentHdr).getHeader();
BlockHeader parentStakingBlocksParent = getParent(parentStakingBlock).getHeader();
Block[] blockFamily = getTwoGenParents(parentHdr);

BlockHeader parentStakingBlock = blockFamily[0].getHeader();
BlockHeader parentStakingBlocksParent = blockFamily[1].getHeader();
parentSeed = ((StakingBlockHeader) parentStakingBlock).getSeed();
newDiff = chainConfiguration.getUnityDifficultyCalculator().calculateDifficulty(parentStakingBlock, parentStakingBlocksParent);
}
Expand Down Expand Up @@ -1589,6 +1593,14 @@ private Block getParent(BlockHeader header) {
return getBlockStore().getBlockByHashWithInfo(header.getParentHash());
}

private Block[] getTwoGenParents(BlockHeader header) {
return getBlockStore().getTwoGenParentsByHashWithInfo(header.getParentHash());
}

private Block[] getThreeGenParents(BlockHeader header) {
return getBlockStore().getThreeGenParentsByHashWithInfo(header.getParentHash());
}

public boolean isValid(BlockHeader header) {
/*
* The block header should already be validated at this point by P2P or mining,
Expand All @@ -1597,62 +1609,58 @@ public boolean isValid(BlockHeader header) {
if (!this.headerValidator.validate(header, LOG)) {
return false;
}
/*
* threeGenParents[0] = parentBlock, threeGenParents[1] = grandParent, threeGenParents[2] greatGrandParent.
* if threeGenParents is not equal to null, the threeGenParents[0] must have block data.
*/
Block[] threeGenParents = getThreeGenParents(header);

Block parent = getParent(header);
if (parent == null) {
if (threeGenParents == null) {
return false;
}

Block grandParent = getParent(parent.getHeader());
if (header.getSealType() == BlockSealType.SEAL_POW_BLOCK) {
if (forkUtility.isUnityForkActive(header.getNumber())) {
if (grandParent == null) {
return false;
}

Block greatGrandParent = getParent(grandParent.getHeader());
if (greatGrandParent == null) {
if (threeGenParents[1] == null || threeGenParents[2] == null) {
return false;
}

return unityParentBlockHeaderValidator.validate(header, parent.getHeader(), LOG, null) &&
unityGreatGrandParentBlockHeaderValidator.validate(grandParent.getHeader(), greatGrandParent.getHeader(), header, LOG);
return unityParentBlockHeaderValidator.validate(header, threeGenParents[0].getHeader(), LOG, null) &&
unityGreatGrandParentBlockHeaderValidator.validate(threeGenParents[1].getHeader(), threeGenParents[2].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, threeGenParents[0].getHeader(), LOG, null) &&
preUnityGrandParentBlockHeaderValidator.validate(threeGenParents[0].getHeader(), threeGenParents[1] == null ? null : threeGenParents[1].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 (threeGenParents[1] == 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(threeGenParents[0].getNumber())) {
BigInteger expectedDiff = calculateFirstPoSDifficultyAtBlock(threeGenParents[0]);
if (!expectedDiff.equals(header.getDifficultyBI())) {
return false;
}
grandParent = new GenesisStakingBlock(expectedDiff);
threeGenParents[1] = 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(), threeGenParents[0]);
} 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, threeGenParents[0].getHeader(), LOG, stake) &&
unityGreatGrandParentBlockHeaderValidator.validate(threeGenParents[1].getHeader(), threeGenParents[2].getHeader(), header, LOG);

} else {
LOG.debug("Invalid header seal type!");
Expand Down
125 changes: 125 additions & 0 deletions modAionImpl/src/org/aion/zero/impl/db/AionBlockStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,131 @@ 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[] getThreeGenParentsByHashWithInfo(byte[] hash) {
if (hash == null) {
return null;
}

lock.lock();

try {
Block block = blocks.get(hash);
if (block == null) {
return null;
} else {
Block[] blockFamily = new Block[] { null, null, null};
BlockInfo blockInfo = getBlockInfoForHash(hash, block.getNumber());
if (blockInfo != null) {
if (blockInfo.isMainChain()) {
block.setMainChain();
}

block.setTotalDifficulty(blockInfo.getTotalDifficulty());
}

blockFamily[0] = block;

Block parent = blocks.get(block.getParentHash());
if (parent == null) {
return blockFamily;
} else {
blockInfo = getBlockInfoForHash(parent.getHash(), parent.getNumber());
if (blockInfo != null) {
if (blockInfo.isMainChain()) {
parent.setMainChain();
}

parent.setTotalDifficulty(blockInfo.getTotalDifficulty());
}

blockFamily[1] = parent;
}

Block grandParent = blocks.get(parent.getParentHash());
if (grandParent == null) {
return blockFamily;
} else {
blockInfo = getBlockInfoForHash(grandParent.getHash(), grandParent.getNumber());
if (blockInfo != null) {
if (blockInfo.isMainChain()) {
grandParent.setMainChain();
}

grandParent.setTotalDifficulty(blockInfo.getTotalDifficulty());
}

blockFamily[2] = grandParent;
}

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[] getTwoGenParentsByHashWithInfo(byte[] hash) {
if (hash == null) {
return null;
}

lock.lock();

try {
Block block = blocks.get(hash);
if (block == null) {
return null;
} else {
Block[] blockFamily = new Block[] { null, null};
BlockInfo blockInfo = getBlockInfoForHash(hash, block.getNumber());
if (blockInfo != null) {
if (blockInfo.isMainChain()) {
block.setMainChain();
}

block.setTotalDifficulty(blockInfo.getTotalDifficulty());
}

blockFamily[0] = block;

Block parent = blocks.get(block.getParentHash());
if (parent == null) {
return blockFamily;
} else {
blockInfo = getBlockInfoForHash(parent.getHash(), parent.getNumber());
if (blockInfo != null) {
if (blockInfo.isMainChain()) {
parent.setMainChain();
}

parent.setTotalDifficulty(blockInfo.getTotalDifficulty());
}

blockFamily[1] = parent;
}

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

public static class BlockInfo {

/**
Expand Down

0 comments on commit 1a38c17

Please sign in to comment.