Search in sources :

Example 46 with BlockContext

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()));
}
Also used : MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) BlockContext(org.aion.zero.impl.types.BlockContext) MockDB(org.aion.db.impl.mockdb.MockDB) MiningBlock(org.aion.zero.impl.types.MiningBlock) Test(org.junit.Test)

Example 47 with BlockContext

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();
}
Also used : TransactionBroadcastCallback(org.aion.zero.impl.blockchain.AionImpl.TransactionBroadcastCallback) NetworkBestBlockCallback(org.aion.zero.impl.blockchain.AionImpl.NetworkBestBlockCallback) BlockContext(org.aion.zero.impl.types.BlockContext) PendingTxCallback(org.aion.zero.impl.blockchain.AionImpl.PendingTxCallback) MockDB(org.aion.db.impl.mockdb.MockDB) ArrayList(java.util.ArrayList) AionRepositoryImpl(org.aion.zero.impl.db.AionRepositoryImpl) AionTransaction(org.aion.base.AionTransaction) MiningBlock(org.aion.zero.impl.types.MiningBlock) TrieImpl(org.aion.zero.impl.trie.TrieImpl) BigInteger(java.math.BigInteger) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) Test(org.junit.Test)

Example 48 with BlockContext

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();
}
Also used : TransactionBroadcastCallback(org.aion.zero.impl.blockchain.AionImpl.TransactionBroadcastCallback) NetworkBestBlockCallback(org.aion.zero.impl.blockchain.AionImpl.NetworkBestBlockCallback) BlockContext(org.aion.zero.impl.types.BlockContext) PendingTxCallback(org.aion.zero.impl.blockchain.AionImpl.PendingTxCallback) MockDB(org.aion.db.impl.mockdb.MockDB) ArrayList(java.util.ArrayList) AionRepositoryImpl(org.aion.zero.impl.db.AionRepositoryImpl) AionTransaction(org.aion.base.AionTransaction) MiningBlock(org.aion.zero.impl.types.MiningBlock) TrieImpl(org.aion.zero.impl.trie.TrieImpl) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) Test(org.junit.Test)

Example 49 with BlockContext

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);
}
Also used : Compiler(org.aion.solidity.Compiler) ImportResult(org.aion.zero.impl.core.ImportResult) AionAddress(org.aion.types.AionAddress) AionTxInfo(org.aion.zero.impl.types.AionTxInfo) Log(org.aion.types.Log) BlockContext(org.aion.zero.impl.types.BlockContext) StandaloneBlockchain(org.aion.zero.impl.blockchain.StandaloneBlockchain) ECKey(org.aion.crypto.ECKey) AionTransaction(org.aion.base.AionTransaction) TxRecptLg(org.aion.api.server.types.TxRecptLg) BigInteger(java.math.BigInteger) CompilationResult(org.aion.solidity.CompilationResult) AionTxReceipt(org.aion.base.AionTxReceipt) Test(org.junit.Test)

Aggregations

BlockContext (org.aion.zero.impl.types.BlockContext)49 AionTransaction (org.aion.base.AionTransaction)42 Test (org.junit.Test)42 BigInteger (java.math.BigInteger)27 AionAddress (org.aion.types.AionAddress)25 AionTxExecSummary (org.aion.base.AionTxExecSummary)19 MiningBlock (org.aion.zero.impl.types.MiningBlock)18 AionRepositoryImpl (org.aion.zero.impl.db.AionRepositoryImpl)16 RepositoryCache (org.aion.base.db.RepositoryCache)15 Block (org.aion.zero.impl.types.Block)15 ArrayList (java.util.ArrayList)13 MockDB (org.aion.db.impl.mockdb.MockDB)12 DataWord (org.aion.util.types.DataWord)11 ImportResult (org.aion.zero.impl.core.ImportResult)9 ECKey (org.aion.crypto.ECKey)8 StandaloneBlockchain (org.aion.zero.impl.blockchain.StandaloneBlockchain)8 TrieImpl (org.aion.zero.impl.trie.TrieImpl)6 HashMap (java.util.HashMap)5 Map (java.util.Map)5 Log (org.aion.types.Log)5