use of org.aion.zero.impl.types.AionBlock in project aion by aionnetwork.
the class BlockchainDataRecoveryTest method testRecoverWorldStateWithPartialWorldState.
/**
* Test the recovery of the world state in the case where it is missing from the database.
*/
@Test
public void testRecoverWorldStateWithPartialWorldState() {
final int NUMBER_OF_BLOCKS = 10;
// build a blockchain with a few blocks
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").build();
StandaloneBlockchain chain = bundle.bc;
// first half of blocks will be correct
ImportResult result;
for (int i = 0; i < NUMBER_OF_BLOCKS / 2; i++) {
result = chain.tryToConnect(chain.createNewBlock(chain.getBestBlock(), Collections.emptyList(), true));
assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
}
// second half of blocks will miss the state root
List<byte[]> statesToDelete = new ArrayList<>();
for (int i = 0; i < NUMBER_OF_BLOCKS / 2; i++) {
AionBlock next = chain.createNewBlock(chain.getBestBlock(), Collections.emptyList(), true);
result = chain.tryToConnect(next);
assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
statesToDelete.add(next.getStateRoot());
}
AionBlock bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
chain.getRepository().flush();
// delete some world state root entries from the database
TrieImpl trie = (TrieImpl) ((AionRepositoryImpl) chain.getRepository()).getWorldState();
IByteArrayKeyValueDatabase database = (IByteArrayKeyValueDatabase) trie.getCache().getDb();
for (byte[] key : statesToDelete) {
database.delete(key);
assertThat(trie.isValidRoot(key)).isFalse();
}
// ensure that the world state was corrupted
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
// call the recovery functionality
boolean worked = chain.recoverWorldState(chain.getRepository(), bestBlock.getNumber());
// ensure that the blockchain is ok
assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
// ensure that the world state is ok
assertThat(worked).isTrue();
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isTrue();
}
use of org.aion.zero.impl.types.AionBlock in project aion by aionnetwork.
the class BlockchainDataRecoveryTest method testRecoverWorldStateWithoutGenesis.
/**
* Test the recovery of the world state in the case where it is missing from the database.
*/
@Test
public void testRecoverWorldStateWithoutGenesis() {
final int NUMBER_OF_BLOCKS = 10;
// build a blockchain with a few blocks
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").build();
StandaloneBlockchain chain = bundle.bc;
// all blocks will be incorrect
ImportResult result;
for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
AionBlock next = chain.createNewBlock(chain.getBestBlock(), Collections.emptyList(), true);
result = chain.tryToConnect(next);
assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
}
AionBlock bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
chain.getRepository().flush();
// delete some world state root entries from the database
TrieImpl trie = (TrieImpl) ((AionRepositoryImpl) chain.getRepository()).getWorldState();
IByteArrayKeyValueDatabase database = (IByteArrayKeyValueDatabase) trie.getCache().getDb();
List<byte[]> statesToDelete = new ArrayList<>();
statesToDelete.addAll(database.keys());
for (byte[] key : statesToDelete) {
database.delete(key);
assertThat(trie.isValidRoot(key)).isFalse();
}
// ensure that the world state was corrupted
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
// call the recovery functionality
boolean worked = chain.recoverWorldState(chain.getRepository(), bestBlock.getNumber());
// ensure that the blockchain is ok
assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
// ensure that the world state was not recovered
assertThat(worked).isFalse();
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
}
use of org.aion.zero.impl.types.AionBlock in project aion by aionnetwork.
the class BlockchainForkingTest method testSameBlockDifferentNonceAndSolutionSimple.
/*-
* Tests the case where multiple threads submit a single block (content) but
* with different mining nonces and solutions. In this case our rules dictate
* that all subsequent blocks are considered invalid.
*
* (common ancestor)
* / \
* / \
* / \
* (a)o (b)x
*
* Given:
* a.td == b.td
*/
@Test
public void testSameBlockDifferentNonceAndSolutionSimple() {
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle b = builder.withValidatorConfiguration("simple").build();
StandaloneBlockchain bc = b.bc;
AionBlock block = bc.createNewBlock(bc.getBestBlock(), Collections.emptyList(), true);
AionBlock sameBlock = new AionBlock(block.getEncoded());
ImportResult firstRes = bc.tryToConnect(block);
// check that the returned block is the first block
assertThat(bc.getBestBlock() == block).isTrue();
ImportResult secondRes = bc.tryToConnect(sameBlock);
// the second block should get rejected, so check that the reference still refers
// to the first block (we dont change the published reference)
assertThat(bc.getBestBlock() == block).isTrue();
assertThat(firstRes).isEqualTo(ImportResult.IMPORTED_BEST);
assertThat(secondRes).isEqualTo(ImportResult.EXIST);
}
use of org.aion.zero.impl.types.AionBlock in project aion by aionnetwork.
the class BlockchainIntegrationTest method testAppendIncorrectTimestampBlock.
@Test
public void testAppendIncorrectTimestampBlock() {
StandaloneBlockchain.Bundle bundle = (new StandaloneBlockchain.Builder()).withValidatorConfiguration("simple").withDefaultAccounts().build();
StandaloneBlockchain bc = bundle.bc;
AionBlock block = bc.createNewBlock(bc.getBestBlock(), Collections.EMPTY_LIST, true);
// set the block to be created 1 month in the future
block.getHeader().setTimestamp((System.currentTimeMillis() / 1000) + 2592000);
ImportResult result = bc.tryToConnect(block);
assertThat(result.isSuccessful()).isFalse();
}
use of org.aion.zero.impl.types.AionBlock in project aion by aionnetwork.
the class BlockchainIntegrationTest method testBlockchainDifficultyOnBranching.
@Test
public void testBlockchainDifficultyOnBranching() {
StandaloneBlockchain.Bundle bundle = (new StandaloneBlockchain.Builder()).withValidatorConfiguration("simple").withDefaultAccounts().build();
StandaloneBlockchain bc = bundle.bc;
BigInteger initialTD = bc.getTotalDifficulty();
// these two should have different hashes
AionBlock block1 = bc.createNewBlock(bc.getGenesis(), new ArrayList<>(), true);
assertThat(bc.tryToConnect(block1)).isEqualTo(ImportResult.IMPORTED_BEST);
BigInteger postConnectTD = bc.getTotalDifficulty();
assertThat(postConnectTD).isEqualTo(bc.getGenesis().getDifficultyBI().add(block1.getDifficultyBI()));
// first scenario is a one level branch, where both branches are of same height
// but one branch (lighter) comes first, and the second (heavier) comes second
AionBlock block2 = bc.createNewBlock(block1, new ArrayList<>(), true);
AionBlock heavyBlock = bc.createNewBlock(block1, new ArrayList<>(), true);
heavyBlock.getHeader().setDifficulty(BigInteger.valueOf(10000000L).toByteArray());
assertThat(bc.tryToConnect(block2)).isEqualTo(ImportResult.IMPORTED_BEST);
BigInteger postBlock2TD = bc.getTotalDifficulty();
assertThat(postBlock2TD).isEqualTo(postConnectTD.add(block2.getDifficultyBI()));
assertThat(bc.tryToConnect(heavyBlock)).isEqualTo(ImportResult.IMPORTED_BEST);
BigInteger postHeavyBlockTD = bc.getTotalDifficulty();
assertThat(postHeavyBlockTD).isEqualTo(postConnectTD.add(heavyBlock.getDifficultyBI()));
assertThat(bc.getBlockStore().getBestBlock().getHash()).isEqualTo(heavyBlock.getHash());
assertThat(bc.getBlockStore().getTotalDifficulty()).isEqualTo(postHeavyBlockTD);
}
Aggregations