use of org.aion.zero.impl.types.MiningBlock in project aion by aionnetwork.
the class BlockchainConcurrentImportTest method generateBlocks.
private static void generateBlocks() {
System.out.format("%nGenerating %d input blocks...%n", CONCURRENT_THREADS_PER_TYPE);
Random rand = new Random();
MiningBlock parent, block, mainChain;
mainChain = sourceChain.getGenesis();
knownBlocks.add(mainChain);
List<AionTransaction> txs;
AionRepositoryImpl sourceRepo = sourceChain.getRepository();
long time = System.currentTimeMillis();
for (int i = 0; i < CONCURRENT_THREADS_PER_TYPE; i++) {
// ensuring that we add to the main chain at least every MAIN_CHAIN_FREQUENCY block
if (i % MAIN_CHAIN_FREQUENCY == 0) {
// the parent will be the main chain
parent = mainChain;
} else {
// the parent is a random already imported block
parent = knownBlocks.get(rand.nextInt(knownBlocks.size()));
}
// generate transactions for correct root
byte[] originalRoot = sourceRepo.getRoot();
sourceRepo.syncToRoot(parent.getStateRoot());
txs = generateTransactions(MAX_TX_PER_BLOCK, accounts, sourceRepo);
sourceRepo.syncToRoot(originalRoot);
block = sourceChain.createNewMiningBlockInternal(parent, txs, true, time / 10000L).block;
MiningBlockHeader newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader(block.getHeader()).withExtraData(String.valueOf(i).getBytes()).build();
block.updateHeader(newBlockHeader);
ImportResult result = sourceChain.tryToConnect(block);
knownBlocks.add(block);
if (result == ImportResult.IMPORTED_BEST) {
mainChain = block;
}
if (DISPLAY_MESSAGES) {
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());
}
}
// all blocks except the genesis will be imported by the other chain
knownBlocks.remove(sourceChain.getGenesis());
}
use of org.aion.zero.impl.types.MiningBlock in project aion by aionnetwork.
the class BlockchainConcurrentImportTest method addThread_tryToConnect.
/**
* Adds a new thread for importing an already known block.
*
* @param _threads list of threads to be executed; the current thread will be added to this list
* @param _chain the blockchain where the blocks will be imported
* @param _block the block to import
*/
private void addThread_tryToConnect(List<Runnable> _threads, StandaloneBlockchain _chain, MiningBlock _block) {
_threads.add(() -> {
testChain.assertEqualTotalDifficulty();
// importing the given block
ImportResult result = _chain.tryToConnect(_block);
testChain.assertEqualTotalDifficulty();
if (DISPLAY_MESSAGES) {
System.out.format("Import block with hash: %s, number: %6d, extra data: %6s, txs: %3d, status: %20s in thread: %20s %n", _block.getShortHash(), _block.getNumber(), new String(_block.getExtraData()), _block.getTransactionsList().size(), result.toString(), Thread.currentThread().getName());
}
// checking total difficulty
if (result == ImportResult.IMPORTED_BEST || result == ImportResult.IMPORTED_NOT_BEST) {
AionBlockStore store = _chain.getRepository().getBlockStore();
BigInteger tdFromStore = _chain.getTotalDifficultyForHash(_block.getHash());
BigInteger tdCalculated = _chain.getTotalDifficultyForHash(_block.getParentHash()).add(_block.getDifficultyBI());
assertThat(tdFromStore).isEqualTo(tdCalculated);
assertThat(tdCalculated).isEqualTo(_chain.getTotalDifficultyForHash(_block.getHash()));
if (result == ImportResult.IMPORTED_BEST) {
// can't check for equality since other blocks may have already been
// imported
Block bestBlock = store.getBestBlock();
assertNotNull(bestBlock);
assertThat(bestBlock.getTotalDifficulty()).isAtLeast(tdFromStore);
}
}
});
}
use of org.aion.zero.impl.types.MiningBlock 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.types.MiningBlock 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.types.MiningBlock 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