use of org.aion.zero.impl.trie.TrieImpl in project aion by aionnetwork.
the class BlockUtil method calcReceiptsTrie.
public static byte[] calcReceiptsTrie(List<AionTxReceipt> receipts) {
Objects.requireNonNull(receipts);
if (receipts.isEmpty()) {
return ConstantUtil.EMPTY_TRIE_HASH;
}
Trie receiptsTrie = new TrieImpl(null);
for (int i = 0; i < receipts.size(); i++) {
receiptsTrie.update(RLP.encodeInt(i), receipts.get(i).getReceiptTrieEncoded());
}
return receiptsTrie.getRootHash();
}
use of org.aion.zero.impl.trie.TrieImpl in project aion by aionnetwork.
the class BlockchainDataRecoveryTest method testRecoverWorldStateWithPartialWorldState.
/**
* Test the recovery of the world state with start from the state of an ancestor block.
*/
@Test
public void testRecoverWorldStateWithPartialWorldState() {
// build a blockchain with a few blocks
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).build();
StandaloneBlockchain chain = bundle.bc;
AionRepositoryImpl repo = chain.getRepository();
BlockContext context;
List<AionTransaction> txs;
// first half of blocks will be correct
long time = System.currentTimeMillis();
for (int i = 0; i < NUMBER_OF_BLOCKS / 2; i++) {
txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, accounts, repo);
context = chain.createNewMiningBlockInternal(chain.getBestBlock(), txs, true, time / 10000L);
assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
}
// second half of blocks will miss the state root
List<byte[]> statesToDelete = new ArrayList<>();
List<MiningBlock> blocksToImport = new ArrayList<>();
for (int i = 0; i < NUMBER_OF_BLOCKS / 2; i++) {
txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, accounts, repo);
context = chain.createNewMiningBlockInternal(chain.getBestBlock(), txs, true, time / 10000L);
assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
statesToDelete.add(context.block.getStateRoot());
blocksToImport.add(context.block);
}
Block bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
// delete some world state root entries from the database
TrieImpl trie = (TrieImpl) repo.getWorldState();
MockDB database = (MockDB) repo.getStateDatabase();
// 1: direct recovery call
repo.flush();
for (byte[] key : statesToDelete) {
database.deleteAndCommit(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(repo, bestBlock);
// 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();
// 2: recovery at import
repo.flush();
for (byte[] key : statesToDelete) {
database.deleteAndCommit(key);
assertThat(trie.isValidRoot(key)).isFalse();
}
// ensure that the world state was corrupted
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
// call the recovery functionality indirectly
for (MiningBlock block : blocksToImport) {
// state missing before import
assertThat(trie.isValidRoot(block.getStateRoot())).isFalse();
assertThat(chain.tryToConnect(block)).isEqualTo(ImportResult.EXIST);
// state present after import
assertThat(trie.isValidRoot(block.getStateRoot())).isTrue();
}
// ensure that the blockchain is ok
assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
// ensure that the world state is ok
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isTrue();
}
use of org.aion.zero.impl.trie.TrieImpl in project aion by aionnetwork.
the class AionHubTest method MockHubInst_wStartRollback.
@Test
public void MockHubInst_wStartRollback() {
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").withDefaultAccounts().build();
int NUMBER_OF_BLOCKS = 10, MAX_TX_PER_BLOCK = 60;
StandaloneBlockchain chain = bundle.bc;
AionRepositoryImpl repo = chain.getRepository();
BlockContext context;
List<AionTransaction> txs;
// first half of blocks will be correct
long time = System.currentTimeMillis();
for (int i = 0; i < NUMBER_OF_BLOCKS / 2; i++) {
txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, bundle.privateKeys, repo);
context = chain.createNewMiningBlockInternal(chain.getBestBlock(), txs, true, time / 10000L);
assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
}
BigInteger td6 = BigInteger.ZERO;
// second half of blocks will miss the state root
List<byte[]> statesToDelete = new ArrayList<>();
List<MiningBlock> blocksToImport = new ArrayList<>();
for (int i = 0; i < NUMBER_OF_BLOCKS / 2; i++) {
txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, bundle.privateKeys, repo);
context = chain.createNewMiningBlockInternal(chain.getBestBlock(), txs, true, time / 10000L);
assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
statesToDelete.add(context.block.getStateRoot());
blocksToImport.add(context.block);
if (context.block.getNumber() == 6) {
td6 = context.block.getTotalDifficulty();
}
}
Block bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
BigInteger td2 = chain.getTotalDifficulty();
assertTrue(td2.longValue() > td6.longValue());
// delete some world state root entries from the database
TrieImpl trie = (TrieImpl) repo.getWorldState();
MockDB database = (MockDB) repo.getStateDatabase();
repo.flush();
for (byte[] key : statesToDelete) {
database.deleteAndCommit(key);
assertThat(trie.isValidRoot(key)).isFalse();
}
// ensure that the world state was corrupted
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
assertNotEquals(td6, chain.getTotalDifficulty());
// Also, missing the block DB
blocksToImport.remove(0);
database = (MockDB) repo.getBlockDatabase();
for (MiningBlock b : blocksToImport) {
database.deleteAndCommit(b.getHash());
}
repo.flush();
// recovery should be called by loadBlockchain()
AionHub hub = AionHub.createForTesting(CfgAion.inst(), chain, new PendingTxCallback(new ArrayList<>()), new NetworkBestBlockCallback(AionImpl.inst()), new TransactionBroadcastCallback(AionImpl.inst()));
checkHubNullity(hub);
assertEquals(td6, chain.getTotalDifficulty());
Block blk = hub.getStartingBlock();
assertThat(blk).isNotNull();
assertThat(blk.getNumber()).isEqualTo(6);
// ensure that the world state is ok
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isTrue();
hub.close();
assertThat(hub.isRunning()).isFalse();
}
use of org.aion.zero.impl.trie.TrieImpl in project aion by aionnetwork.
the class AionHubTest method MockHubInst_wStartRecovery.
@Test
public void MockHubInst_wStartRecovery() {
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").withDefaultAccounts().build();
int NUMBER_OF_BLOCKS = 10, MAX_TX_PER_BLOCK = 60;
StandaloneBlockchain chain = bundle.bc;
AionRepositoryImpl repo = chain.getRepository();
BlockContext context;
List<AionTransaction> txs;
// first half of blocks will be correct
long time = System.currentTimeMillis();
for (int i = 0; i < NUMBER_OF_BLOCKS / 2; i++) {
txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, bundle.privateKeys, repo);
context = chain.createNewMiningBlockInternal(chain.getBestBlock(), txs, true, time / 10000L);
assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
}
// second half of blocks will miss the state root
List<byte[]> statesToDelete = new ArrayList<>();
List<MiningBlock> blocksToImport = new ArrayList<>();
for (int i = 0; i < NUMBER_OF_BLOCKS / 2; i++) {
txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, bundle.privateKeys, repo);
context = chain.createNewMiningBlockInternal(chain.getBestBlock(), txs, true, time / 10000L);
assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
statesToDelete.add(context.block.getStateRoot());
blocksToImport.add(context.block);
}
Block bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
// delete some world state root entries from the database
TrieImpl trie = (TrieImpl) repo.getWorldState();
MockDB database = (MockDB) repo.getStateDatabase();
repo.flush();
for (byte[] key : statesToDelete) {
database.deleteAndCommit(key);
assertThat(trie.isValidRoot(key)).isFalse();
}
// ensure that the world state was corrupted
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
// recovery should be called by loadBlockchain()
AionHub hub = AionHub.createForTesting(CfgAion.inst(), chain, new PendingTxCallback(new ArrayList<>()), new NetworkBestBlockCallback(AionImpl.inst()), new TransactionBroadcastCallback(AionImpl.inst()));
checkHubNullity(hub);
Block blk = hub.getStartingBlock();
assertThat(blk).isNotNull();
assertThat(blk.getNumber()).isEqualTo((long) NUMBER_OF_BLOCKS);
// ensure that the blockchain is ok
assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
// ensure that the world state is ok
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isTrue();
hub.close();
assertThat(hub.isRunning()).isFalse();
}
Aggregations