diff --git a/modAionImpl/src/org/aion/zero/impl/db/AionBlockStore.java b/modAionImpl/src/org/aion/zero/impl/db/AionBlockStore.java index bd64463d31..81623fe27e 100644 --- a/modAionImpl/src/org/aion/zero/impl/db/AionBlockStore.java +++ b/modAionImpl/src/org/aion/zero/impl/db/AionBlockStore.java @@ -558,9 +558,10 @@ boolean isBlockStored(byte[] hash, long number) { } /** - * Retrieve block with unity protocol info - * @param hash given hash of the block - * @return the block data has matched hash with unity protocol info + * Retrieve a block with unity protocol info. + * + * @param hash the hash of the requested block + * @return the block data for the given hash with unity protocol info */ public Block getBlockByHashWithInfo(byte[] hash) { if (hash == null) { diff --git a/modAionImpl/src/org/aion/zero/impl/types/AbstractBlock.java b/modAionImpl/src/org/aion/zero/impl/types/AbstractBlock.java index 9bff8a8c2b..c8e039685f 100644 --- a/modAionImpl/src/org/aion/zero/impl/types/AbstractBlock.java +++ b/modAionImpl/src/org/aion/zero/impl/types/AbstractBlock.java @@ -14,7 +14,7 @@ public abstract class AbstractBlock implements Block { /** use for cli tooling */ - Boolean mainChain; + boolean mainChain = false; // set from BlockInfos in index database protected BigInteger totalDifficulty; @@ -93,7 +93,7 @@ public void setTotalDifficulty(BigInteger totalDifficulty) { @Override public boolean isMainChain() { - return mainChain == null ? true : mainChain; + return mainChain; } @Override diff --git a/modAionImpl/src/org/aion/zero/impl/types/AionBlock.java b/modAionImpl/src/org/aion/zero/impl/types/AionBlock.java index 8368430afb..6aed5896bc 100644 --- a/modAionImpl/src/org/aion/zero/impl/types/AionBlock.java +++ b/modAionImpl/src/org/aion/zero/impl/types/AionBlock.java @@ -338,9 +338,7 @@ public String toString() { toStringBuff.append(" total difficulty=").append(totalDifficulty).append("\n"); } - if (mainChain != null) { - toStringBuff.append(" mainChain=").append(mainChain ? "yes" : "no").append("\n"); - } + toStringBuff.append(" mainChain=").append(mainChain ? "yes" : "no").append("\n"); if (!getTransactionsList().isEmpty()) { toStringBuff diff --git a/modAionImpl/src/org/aion/zero/impl/types/StakingBlock.java b/modAionImpl/src/org/aion/zero/impl/types/StakingBlock.java index 58fbf62a0b..eaa4d031db 100644 --- a/modAionImpl/src/org/aion/zero/impl/types/StakingBlock.java +++ b/modAionImpl/src/org/aion/zero/impl/types/StakingBlock.java @@ -325,9 +325,7 @@ public String toString() { toStringBuff.append(" total difficulty=").append(totalDifficulty).append("\n"); } - if (mainChain != null) { - toStringBuff.append(" mainChain=").append(mainChain ? "yes" : "no").append("\n"); - } + toStringBuff.append(" mainChain=").append(mainChain ? "yes" : "no").append("\n"); if (!getTransactionsList().isEmpty()) { toStringBuff.append("Txs [\n"); diff --git a/modAionImpl/test/org/aion/zero/impl/db/AionBlockStoreTest.java b/modAionImpl/test/org/aion/zero/impl/db/AionBlockStoreTest.java index 5f68f786ee..a778ce3d77 100644 --- a/modAionImpl/test/org/aion/zero/impl/db/AionBlockStoreTest.java +++ b/modAionImpl/test/org/aion/zero/impl/db/AionBlockStoreTest.java @@ -21,6 +21,8 @@ import org.aion.util.TestResources; import org.aion.util.types.AddressUtils; import org.aion.zero.impl.types.AionBlock; +import org.aion.zero.impl.types.BlockUtil; +import org.apache.commons.lang3.RandomUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -229,6 +231,62 @@ public void testGetBlocksByRange_withAscendingOrderAndIncorrectHeight() { assertThat(store.getBlocksByRange(first.getNumber(), last.getNumber())).isNull(); } + @Test + public void testGetBlockByHashWithInfo_withNullInput() { + AionBlockStore store = new AionBlockStore(index, blocks, false); + Block block = store.getBlockByHashWithInfo(null); + assertThat(block).isNull(); + } + + @Test + public void testGetBlockByHashWithInfo_withMissingBlock() { + byte[] blockHash = RandomUtils.nextBytes(32); + + AionBlockStore store = new AionBlockStore(index, blocks, false); + assertThat(index.isEmpty()).isTrue(); + assertThat(blocks.isEmpty()).isTrue(); + + Block block = store.getBlockByHashWithInfo(blockHash); + assertThat(block).isNull(); + } + + @Test + public void testGetBlockByHashWithInfo() { + Block givenBlock = consecutiveBlocks.get(0); + BigInteger totalDifficulty = BigInteger.TEN; + + AionBlockStore store = new AionBlockStore(index, blocks, false); + // does not require accurate total difficulty + store.saveBlock(givenBlock, totalDifficulty, true); + + Block block = store.getBlockByHashWithInfo(givenBlock.getHash()); + assertThat(block).isEqualTo(givenBlock); + assertThat(block.getTotalDifficulty()).isEqualTo(totalDifficulty); + assertThat(block.isMainChain()).isTrue(); + } + + @Test + public void testGetBlockByHashWithInfo_withSideChain() { + Block givenBlock = consecutiveBlocks.get(0); + BigInteger totalDifficulty = BigInteger.TWO; + + BigInteger sideTotalDifficulty = BigInteger.TEN; + Block sideBlock = BlockUtil.newBlockFromRlp(givenBlock.getEncoded()); + sideBlock.updateHeaderDifficulty(sideTotalDifficulty.toByteArray()); + assertThat(givenBlock.getHash()).isNotEqualTo(sideBlock.getHash()); + assertThat(givenBlock.getEncoded()).isNotEqualTo(sideBlock.getEncoded()); + + AionBlockStore store = new AionBlockStore(index, blocks, false); + // does not require accurate total difficulty + store.saveBlock(givenBlock, totalDifficulty, false); + store.saveBlock(sideBlock, sideTotalDifficulty, true); + + Block block = store.getBlockByHashWithInfo(givenBlock.getHash()); + assertThat(block).isEqualTo(givenBlock); + assertThat(block.getTotalDifficulty()).isEqualTo(totalDifficulty); + assertThat(block.isMainChain()).isFalse(); + } + @Test public void testRollback() {