use of org.aion.zero.impl.types.BlockContext in project aion by aionnetwork.
the class BlockchainForkingTest method testSecondBlockHigherDifficultyFork_wExceptionOnFasterBlockAdd.
/**
* Test fork with exception.
*/
@Test
public void testSecondBlockHigherDifficultyFork_wExceptionOnFasterBlockAdd() {
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").withDefaultAccounts().build();
long time = System.currentTimeMillis();
StandaloneBlockchain bc = bundle.bc;
// generate three blocks, on the third block we get flexibility
// for what difficulties can occur
BlockContext firstBlock = bc.createNewMiningBlockInternal(bc.getGenesis(), Collections.emptyList(), true, time / 1000L);
assertThat(bc.tryToConnect(firstBlock.block)).isEqualTo(ImportResult.IMPORTED_BEST);
// now connect the second block
BlockContext secondBlock = bc.createNewMiningBlockInternal(firstBlock.block, Collections.emptyList(), true, time / 1000L);
assertThat(bc.tryToConnect(secondBlock.block)).isEqualTo(ImportResult.IMPORTED_BEST);
// now on the third block, we diverge with one block having higher TD than the other
BlockContext fasterSecondBlock = bc.createNewMiningBlockInternal(secondBlock.block, Collections.emptyList(), true, time / 1000L);
MiningBlock slowerSecondBlock = new MiningBlock(fasterSecondBlock.block);
MiningBlockHeader newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader(slowerSecondBlock.getHeader()).withTimestamp(time / 1000L + 100).build();
slowerSecondBlock.updateHeader(newBlockHeader);
assertThat(bc.tryToConnect(fasterSecondBlock.block)).isEqualTo(ImportResult.IMPORTED_BEST);
assertThat(bc.tryToConnect(slowerSecondBlock)).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
time += 100;
BlockContext fastBlockDescendant = bc.createNewMiningBlockInternal(fasterSecondBlock.block, Collections.emptyList(), true, time / 1000L);
BlockContext slowerBlockDescendant = bc.createNewMiningBlockInternal(slowerSecondBlock, Collections.emptyList(), true, time / 1000L + 100 + 1);
assertThat(fastBlockDescendant.block.getDifficultyBI()).isGreaterThan(slowerBlockDescendant.block.getDifficultyBI());
System.out.println("faster block descendant TD: " + fastBlockDescendant.block.getDifficultyBI());
System.out.println("slower block descendant TD: " + slowerBlockDescendant.block.getDifficultyBI());
assertThat(bc.tryToConnect(slowerBlockDescendant.block)).isEqualTo(ImportResult.IMPORTED_BEST);
// corrupt the parent for the fast block descendant
((MockDB) bc.getRepository().getStateDatabase()).deleteAndCommit(fasterSecondBlock.block.getStateRoot());
assertThat(bc.getRepository().isValidRoot(fasterSecondBlock.block.getStateRoot())).isFalse();
// attempt adding the fastBlockDescendant
assertThat(bc.tryToConnect(fastBlockDescendant.block)).isEqualTo(ImportResult.INVALID_BLOCK);
// check for correct state rollback
assertThat(bc.getBestBlock()).isEqualTo(slowerBlockDescendant.block);
assertThat(bc.getRepository().getRoot()).isEqualTo(slowerBlockDescendant.block.getStateRoot());
assertThat(bc.getTotalDifficulty()).isEqualTo(bc.getTotalDifficultyForHash(slowerBlockDescendant.block.getHash()));
}
use of org.aion.zero.impl.types.BlockContext 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.types.BlockContext 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();
}
use of org.aion.zero.impl.types.BlockContext in project aion by aionnetwork.
the class TxRecptLgTest method TestTxRecptLg.
@Test
public void TestTxRecptLg() throws InterruptedException, IOException {
StandaloneBlockchain.Bundle bundle = new StandaloneBlockchain.Builder().withValidatorConfiguration("simple").withDefaultAccounts().build();
StandaloneBlockchain bc = bundle.bc;
ECKey deployerAccount = bundle.privateKeys.get(0);
// ======================
// DEPLOY contract A & B
// ======================
Compiler.Result r = Compiler.getInstance().compile(readContract("contract/contract.sol"), Compiler.Options.ABI, Compiler.Options.BIN);
CompilationResult cr = CompilationResult.parse(r.output);
String contractA = cr.contracts.get("A").bin;
String contractB = cr.contracts.get("B").bin;
BigInteger nonce = BigInteger.ZERO;
AionTransaction tx1 = AionTransaction.create(deployerAccount, nonce.toByteArray(), null, new byte[0], ByteUtil.hexStringToBytes(contractA), 1_000_000L, energyPrice, TransactionTypes.DEFAULT, null);
nonce = nonce.add(BigInteger.ONE);
AionTransaction tx2 = AionTransaction.create(deployerAccount, nonce.toByteArray(), null, new byte[0], ByteUtil.hexStringToBytes(contractB), 1_000_000L, energyPrice, TransactionTypes.DEFAULT, null);
BlockContext context = bc.createNewMiningBlockContext(bc.getBestBlock(), List.of(tx1, tx2), false);
ImportResult result = bc.tryToConnect(context.block);
assertEquals(result, ImportResult.IMPORTED_BEST);
AionAddress addressA = TxUtil.calculateContractAddress(tx1);
System.out.println("contract A address = " + addressA);
AionAddress addressB = TxUtil.calculateContractAddress(tx2);
System.out.println("contract B address = " + addressB);
Thread.sleep(1000);
// ======================
// CALL function A.AA
// ======================
nonce = nonce.add(BigInteger.ONE);
byte[] functionAA = new byte[4];
System.arraycopy(HashUtil.keccak256("AA(address)".getBytes()), 0, functionAA, 0, 4);
AionTransaction tx3 = AionTransaction.create(deployerAccount, nonce.toByteArray(), addressA, new byte[0], ByteUtil.merge(functionAA, addressB.toByteArray()), 1_000_000L, energyPrice, TransactionTypes.DEFAULT, null);
context = bc.createNewMiningBlockContext(bc.getBestBlock(), List.of(tx3), false);
result = bc.tryToConnect(context.block);
assertEquals(result, ImportResult.IMPORTED_BEST);
AionTxInfo info = bc.getTransactionInfo(tx3.getTransactionHash());
AionTxReceipt receipt = info.getReceipt();
System.out.println(receipt);
assertEquals(4, receipt.getLogInfoList().size());
// ======================
// Test
// ======================
TxRecptLg[] logs = new TxRecptLg[receipt.getLogInfoList().size()];
for (int i = 0; i < logs.length; i++) {
Log logInfo = receipt.getLogInfoList().get(i);
logs[i] = new TxRecptLg(logInfo, context.block, info.getIndex(), receipt.getTransaction(), i, true);
}
String ctAddrA = "0x" + addressA.toString();
String ctAddrB = "0x" + addressB.toString();
// AE
assertEquals(ctAddrA, logs[0].address);
// AEA
assertEquals(ctAddrA, logs[1].address);
// b.BB
assertEquals(ctAddrB, logs[2].address);
// AEB
assertEquals(ctAddrA, logs[3].address);
}
Aggregations