use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.
the class BlockchainIndexIntegrityTest method testIndexIntegrityWithoutLevel.
/**
* Test the index integrity check and recovery when the index database is missing a level
* information.
*
* <p>Under these circumstances the recovery process will fail.
*/
@Test
public void testIndexIntegrityWithoutLevel() {
final int NUMBER_OF_BLOCKS = 5;
// build a blockchain with a few blocks
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").build();
StandaloneBlockchain chain = bundle.bc;
ImportResult result;
for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
Block next = chain.createNewMiningBlock(chain.getBestBlock(), Collections.emptyList(), true);
result = chain.tryToConnect(next);
assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
}
Block bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
chain.getRepository().flush();
AionRepositoryImpl repo = chain.getRepository();
MockDB indexDatabase = (MockDB) repo.getIndexDatabase();
// deleting the level 2 index
indexDatabase.deleteAndCommit(ByteUtil.intToBytes(2));
AionBlockStore blockStore = repo.getBlockStore();
// check that the index recovery failed
assertThat(blockStore.indexIntegrityCheck()).isEqualTo(AionBlockStore.IntegrityCheckResult.MISSING_LEVEL);
}
use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.
the class BlockchainIndexIntegrityTest method testIndexIntegrityWithCorrectData.
/**
* Test the index integrity check and recovery when the index database is correct.
*/
@Test
public void testIndexIntegrityWithCorrectData() {
final int NUMBER_OF_BLOCKS = 5;
// build a blockchain with a few blocks
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").build();
StandaloneBlockchain chain = bundle.bc;
Block bestBlock;
ImportResult result;
for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
bestBlock = chain.getBestBlock();
MiningBlock next = chain.createNewMiningBlock(bestBlock, Collections.emptyList(), true);
result = chain.tryToConnect(next);
assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
// adding side chain
next = chain.createNewMiningBlock(bestBlock, Collections.emptyList(), true);
MiningBlockHeader newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader(next.getHeader()).withExtraData("other".getBytes()).build();
next.updateHeader(newBlockHeader);
result = chain.tryToConnect(next);
assertThat(result).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
}
bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
chain.getRepository().flush();
AionRepositoryImpl repo = chain.getRepository();
AionBlockStore blockStore = repo.getBlockStore();
// check that the index recovery succeeded
assertThat(blockStore.indexIntegrityCheck()).isEqualTo(AionBlockStore.IntegrityCheckResult.CORRECT);
}
use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.
the class BlockchainPruningTest method testTopPruningWithoutSideChains.
@Test
public void testTopPruningWithoutSideChains() throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
// Setup used accounts.
assertThat(accounts.size()).isAtLeast(12);
ECKey stakingRegistryOwner = accounts.get(0);
// Lists of stakers.
List<ECKey> allStakes = List.of(accounts.get(1), accounts.get(2), accounts.get(3), accounts.get(4), accounts.get(5), accounts.get(6));
List<ECKey> mainStakers = List.of(accounts.get(1), accounts.get(2), accounts.get(3));
List<ECKey> otherStakers = List.of(accounts.get(4), accounts.get(5), accounts.get(6));
// Lists of users.
List<ECKey> mainUsers = List.of(accounts.get(1), accounts.get(2), accounts.get(3), accounts.get(7), accounts.get(8), accounts.get(9));
List<ECKey> otherUsers = List.of(accounts.get(4), accounts.get(5), accounts.get(6), accounts.get(10), accounts.get(11), accounts.get(0));
// Setup the blockchain.
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain chain = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).withAvmEnabled().build().bc;
chain.forkUtility.enableUnityFork(unityForkBlock);
// Setup TOP pruning for the repository.
AionRepositoryImpl repository = chain.getRepository();
repository.setupTopPruning(1);
// Setup the first block in the chain with the staker registry deployment.
Block nextBlock = BlockchainTestUtils.generateNextMiningBlockWithStakerRegistry(chain, chain.getGenesis(), resourceProvider, stakingRegistryOwner);
Pair<ImportResult, AionBlockSummary> result = chain.tryToConnectAndFetchSummary(nextBlock);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
assertThat(result.getRight().getReceipts().get(0).isSuccessful()).isTrue();
assertThat(result.getRight().getReceipts().get(0).getLogInfoList()).isNotEmpty();
assertThat(result.getRight().getReceipts().get(0).getEnergyUsed()).isEqualTo(1_225_655L);
// Ensure the current state was not pruned after the import.
verifyFullState(repository, nextBlock);
// Set the staking contract address in the staking genesis.
AionTransaction deploy = nextBlock.getTransactionsList().get(0);
AionAddress contract = TxUtil.calculateContractAddress(deploy.getSenderAddress().toByteArray(), deploy.getNonceBI());
chain.getGenesis().setStakingContractAddress(contract);
// Create block to register all stakers.
nextBlock = BlockchainTestUtils.generateNextMiningBlockWithStakers(chain, chain.getBestBlock(), resourceProvider, allStakes, MIN_SELF_STAKE);
result = chain.tryToConnectAndFetchSummary(nextBlock);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// Ensure the current state was not pruned after the import.
verifyFullState(repository, nextBlock);
// Verify that all stakers were registered.
verifyReceipts(result.getRight().getReceipts(), allStakes.size(), true);
verifyEffectiveSelfStake(otherStakers, chain, nextBlock, MIN_SELF_STAKE);
// Generate random transactions for all accounts to add them to the state.
List<AionTransaction> txs = BlockchainTestUtils.generateTransactions(1_000, accounts, chain.getRepository());
nextBlock = BlockchainTestUtils.generateNextStakingBlock(chain, nextBlock, txs, otherStakers.get(0));
result = chain.tryToConnectAndFetchSummary(nextBlock);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// Ensure the current state was not pruned after the import.
verifyFullState(repository, nextBlock);
BigInteger expectedStake = MIN_SELF_STAKE;
for (int i = 0; i < 6; i++) {
// Add blocks with transactions for mainStakers and mainUsers.
for (int j = 0; j < 6; j++) {
// Add transactions for frequent users.
txs = BlockchainTestUtils.generateTransactions(1_000, mainUsers, chain.getRepository());
// Seal the block with a frequent staker.
ECKey staker = mainStakers.get((i + j) % mainStakers.size());
if (nextBlock instanceof MiningBlock) {
nextBlock = BlockchainTestUtils.generateNextStakingBlock(chain, nextBlock, txs, staker);
} else {
nextBlock = BlockchainTestUtils.generateNextMiningBlock(chain, nextBlock, txs);
}
result = chain.tryToConnectAndFetchSummary(nextBlock);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// Ensure the current state was not pruned after the import.
verifyFullState(repository, nextBlock);
}
// Increase stake of mainStakes.
txs = BlockchainTestUtils.generateIncreaseStakeTransactions(chain, nextBlock, resourceProvider, mainStakers, MIN_SELF_STAKE);
assertThat(txs.size()).isEqualTo(mainStakers.size());
nextBlock = BlockchainTestUtils.generateNextMiningBlock(chain, nextBlock, txs);
result = chain.tryToConnectAndFetchSummary(nextBlock);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
verifyReceipts(result.getRight().getReceipts(), mainStakers.size(), false);
// Ensure the current state was not pruned after the import.
verifyFullState(repository, nextBlock);
// Verify stakers effective stake update.
expectedStake = expectedStake.add(MIN_SELF_STAKE);
verifyEffectiveSelfStake(mainStakers, chain, nextBlock, expectedStake);
// Add transactions for infrequent users.
txs = BlockchainTestUtils.generateTransactions(10, otherUsers, chain.getRepository());
// Seal the block with an infrequent staker.
ECKey staker = otherStakers.get(i % otherStakers.size());
nextBlock = BlockchainTestUtils.generateNextStakingBlock(chain, nextBlock, txs, staker);
result = chain.tryToConnectAndFetchSummary(nextBlock);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// Ensure the current state was not pruned after the import.
verifyFullState(repository, nextBlock);
}
}
use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.
the class BlockchainTestUtils method addStakingBlock.
public static Pair<Block, ImportResult> addStakingBlock(StandaloneBlockchain chain, Block parent, List<AionTransaction> txs, ECKey key) {
byte[] parentSeed = chain.forkUtility.isUnityForkBlock(parent.getNumber()) ? StakingBlockHeader.GENESIS_SEED : ((StakingBlock) chain.getBlockByHash(parent.getParentHash())).getSeed();
byte[] newSeed = key.sign(parentSeed).getSignature();
StakingBlock block = chain.createStakingBlockTemplate(parent, txs, key.getPubKey(), newSeed, new AionAddress(key.getAddress()).toByteArray());
if (block == null) {
return null;
}
byte[] mineHashSig = key.sign(block.getHeader().getMineHash()).getSignature();
block.seal(mineHashSig, key.getPubKey());
ImportResult result = chain.tryToConnect(block);
System.out.format("Created block with hash: %s, number: %6d, extra data: %6s, txs: %3d, import status: %20s %n", block.getShortHash(), block.getNumber(), new String(block.getExtraData()), block.getTransactionsList().size(), result.toString());
return Pair.of(block, result);
}
use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.
the class AionBlockchainImplTest method testBlockTemplateClearWhenChainBranched.
@Test
public /**
* we only test the mining block template has been cleared. The method call in the AionBlockchainImpl
* also proved the staking block template will be cleaned at the same time.
*/
void testBlockTemplateClearWhenChainBranched() {
CfgAion cfg = CfgAion.inst();
Properties p = new Properties();
p.put("fork1.0", "4");
cfg.getFork().setProtocolUpgradeSettings(p, null);
StandaloneBlockchain.Bundle bundle = new StandaloneBlockchain.Builder().withDefaultAccounts().withValidatorConfiguration("simple").build();
this.blockchain = bundle.bc;
assertNotNull(blockchain);
MiningBlock block1a = blockchain.createBlockAndBlockTemplate(blockchain.genesis, new ArrayList<>(), false, blockchain.genesis.getTimestamp() + 10);
Pair<ImportResult, AionBlockSummary> connectResult = blockchain.tryToConnectAndFetchSummary(block1a);
assertEquals(ImportResult.IMPORTED_BEST, connectResult.getLeft());
assertEquals(1, blockchain.miningBlockTemplate.size());
MiningBlock block2a = blockchain.createBlockAndBlockTemplate(blockchain.getBestBlock(), new ArrayList<>(), false, blockchain.getBestBlock().getTimestamp() + 1000);
connectResult = blockchain.tryToConnectAndFetchSummary(block2a);
assertEquals(ImportResult.IMPORTED_BEST, connectResult.getLeft());
assertEquals(2, blockchain.miningBlockTemplate.size());
// create a side chain block 2b first
MiningBlock block2b = blockchain.createBlockAndBlockTemplate(block1a, new ArrayList<>(), false, block1a.getTimestamp() + 1);
connectResult = blockchain.tryToConnectAndFetchSummary(block2b);
assertEquals(ImportResult.IMPORTED_NOT_BEST, connectResult.getLeft());
assertEquals(3, blockchain.miningBlockTemplate.size());
MiningBlock block3a = blockchain.createBlockAndBlockTemplate(blockchain.getBestBlock(), new ArrayList<>(), false, block2a.getTimestamp() + 10);
connectResult = blockchain.tryToConnectAndFetchSummary(block3a);
assertEquals(ImportResult.IMPORTED_BEST, connectResult.getLeft());
assertEquals(3, blockchain.miningBlockTemplate.size());
// Chain will be branched after import the block3b and the template will be cleaned.
MiningBlock block3b = blockchain.createBlockAndBlockTemplate(block2b, new ArrayList<>(), false, block2b.getTimestamp() + 1);
connectResult = blockchain.tryToConnectAndFetchSummary(block3b);
assertEquals(ImportResult.IMPORTED_BEST, connectResult.getLeft());
assertEquals(0, blockchain.miningBlockTemplate.size());
}
Aggregations