use of org.aion.zero.impl.types.AionBlock in project aion by aionnetwork.
the class BlockchainDataRecoveryTest method testRecoverWorldStateWithStartFromGenesis.
/**
* Test the recovery of the world state in the case where it is missing from the database.
*/
@Test
public void testRecoverWorldStateWithStartFromGenesis() {
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;
List<byte[]> statesToDelete = new ArrayList<>();
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);
statesToDelete.add(next.getStateRoot());
}
AionBlock bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
chain.getRepository().flush();
// System.out.println(Hex.toHexString(chain.getRepository().getRoot()));
// 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();
}
// System.out.println(Hex.toHexString(chain.getRepository().getRoot()));
// 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 BlockchainDifficultyTest method difficultySetTest.
@Test
public void difficultySetTest() {
final long TIME_DIFFERENCE = 10l;
StandaloneBlockchain.Bundle bundle = new StandaloneBlockchain.Builder().withDefaultAccounts().withValidatorConfiguration("simple").build();
StandaloneBlockchain bc = bundle.bc;
AionBlock block = bc.createNewBlock(bc.getBestBlock(), Collections.EMPTY_LIST, true);
assertThat(block.getDifficultyBI()).isLessThan(bc.getGenesis().getDifficultyBI());
}
use of org.aion.zero.impl.types.AionBlock in project aion by aionnetwork.
the class BlockchainEnergyTest method testConsistentEnergyUsage.
@Test
public void testConsistentEnergyUsage() {
StandaloneBlockchain.Bundle bundle = new StandaloneBlockchain.Builder().withValidatorConfiguration("simple").withDefaultAccounts().build();
StandaloneBlockchain bc = bundle.bc;
// in cases where no transactions are included (no energy usage)
// the default energy limit should persist (it should not degrade)
AionBlock block = bc.createNewBlock(bc.getBestBlock(), Collections.EMPTY_LIST, true);
assertThat(block.getNrgLimit()).isEqualTo(bc.getGenesis().getNrgLimit());
}
use of org.aion.zero.impl.types.AionBlock in project aion by aionnetwork.
the class BlockchainEnergyTest method testEnergyUsageRecorded.
@Test
public void testEnergyUsageRecorded() {
final int DEFAULT_TX_AMOUNT = 21000;
final Address RECEIPT_ADDR = Address.wrap("CAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE");
StandaloneBlockchain.Bundle bundle = new StandaloneBlockchain.Builder().withDefaultAccounts().withValidatorConfiguration("simple").build();
StandaloneBlockchain bc = bundle.bc;
// TODO: where is the 21000 defined? bad to define magic variables
int amount = (int) (bc.getGenesis().getNrgLimit() / DEFAULT_TX_AMOUNT);
// (byte[] nonce, byte[] from, byte[] to, byte[] value, byte[] data, byte[] nrg, byte[] nrgPrice)
List<AionTransaction> txs = new ArrayList<>();
for (int i = 0; i < amount; i++) {
// this transaction should send one (1) AION coin from acc[0] to RECEIPT_ADDR
AionTransaction atx = new AionTransaction(ByteUtil.intToBytes(i), RECEIPT_ADDR, BigInteger.ONE.toByteArray(), ByteUtil.EMPTY_BYTE_ARRAY, 21000L, BigInteger.valueOf(5).multiply(BigInteger.TEN.pow(9)).longValue());
atx.sign(bundle.privateKeys.get(0));
txs.add(atx);
}
AionBlock block = bc.createNewBlock(bc.getBestBlock(), txs, true);
ImportResult result = bc.tryToConnect(block);
assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
// proceed with connecting the next block, should observe an increase in energyLimit
AionBlock secondBlock = bc.createNewBlock(bc.getBestBlock(), Collections.EMPTY_LIST, true);
assertThat(secondBlock.getNrgLimit()).isEqualTo(block.getNrgLimit());
System.out.println(String.format("%d > %d", secondBlock.getNrgLimit(), block.getNrgLimit()));
}
use of org.aion.zero.impl.types.AionBlock in project aion by aionnetwork.
the class BlockchainForkingTest method testHigherDifficultyBlockFork.
/*-
* Test the general forking case, where an incoming block (b) has a greater total
* difficulty than our current block. In this scenario, we should switch to
* the branch (sub-tree) that has (b) at its tip.
*
* This is the simplest case, where the distance between (a) (our current head) and
* (b) is 2. This implies that the common ancestor is directly adjacent to both blocks.
*
* (common ancestor)
* / \
* / \
* / \
* (a)x(low td) (b)o(higher td)
*
* In this simple case:
* b.td > a.td
* a_worldState === b_worldState
*
*/
@Test
public void testHigherDifficultyBlockFork() {
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle b = builder.withValidatorConfiguration("simple").build();
StandaloneBlockchain bc = b.bc;
AionBlock bestBlock = bc.getBestBlock();
AionBlock standardBlock = bc.createNewBlock(bc.getBestBlock(), Collections.emptyList(), true);
ChainConfiguration cc = new ChainConfiguration();
AionBlock higherDifficultyBlock = new AionBlock(standardBlock);
higherDifficultyBlock.getHeader().setTimestamp(bestBlock.getTimestamp() + 1);
BigInteger difficulty = cc.getDifficultyCalculator().calculateDifficulty(higherDifficultyBlock.getHeader(), bestBlock.getHeader());
assertThat(difficulty).isGreaterThan(standardBlock.getDifficultyBI());
higherDifficultyBlock.getHeader().setDifficulty(difficulty.toByteArray());
System.out.println("before any processing: " + new ByteArrayWrapper(bc.getRepository().getRoot()));
System.out.println("trie: " + ((AionRepositoryImpl) bc.getRepository()).getWorldState().getTrieDump());
ImportResult result = bc.tryToConnect(standardBlock);
assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
// assert that the block we just inserted (best) is the instance that is returned
assertThat(bc.getBestBlock() == standardBlock).isTrue();
System.out.println(new ByteArrayWrapper(bc.getRepository().getRoot()));
ImportResult higherDifficultyResult = bc.tryToConnect(higherDifficultyBlock);
assertThat(higherDifficultyResult).isEqualTo(ImportResult.IMPORTED_BEST);
assertThat(bc.getBestBlockHash()).isEqualTo(higherDifficultyBlock.getHash());
// the object reference here is intentional
assertThat(bc.getBestBlock() == higherDifficultyBlock).isTrue();
}
Aggregations