Search in sources :

Example 71 with Block

use of org.aion.zero.impl.types.Block in project aion by aionnetwork.

the class TransactionCreateSpecificationTests method deployInternalAvmContractOnTopOfAddressWithBalanceUsingAvmVersion1_DeployAndRequireSuccess.

@Test
public void deployInternalAvmContractOnTopOfAddressWithBalanceUsingAvmVersion1_DeployAndRequireSuccess() throws VmFatalException {
    AvmTestConfig.clearConfigurations();
    AvmTestConfig.supportOnlyAvmVersion1();
    // Deploy AVM contract.
    AionTransaction deployTxAvm = BlockchainTestUtils.deployAvmContractTransaction(AvmContract.DEPLOY_INTERNAL, resourceProvider.factoryForVersion1, SENDER_KEY, BigInteger.ZERO);
    AionAddress contract = TxUtil.calculateContractAddress(deployTxAvm);
    Pair<Block, ImportResult> resultImport = BlockchainTestUtils.addMiningBlock(blockchain, blockchain.getBestBlock(), List.of(deployTxAvm));
    assertThat(resultImport.getRight()).isEqualTo(ImportResult.IMPORTED_BEST);
    // Call AVM contract to deploy new internal AVM contract (version with required success).
    long internalLimit = 1_000_000;
    AionTransaction deployInternal = BlockchainTestUtils.callSimpleAvmContractTransaction(resourceProvider.factoryForVersion1, SENDER_KEY, BigInteger.ONE, contract, "deployAndRequireSuccess", deployTxAvm.getData(), internalLimit);
    AionAddress internalContract = new AionAddress(Hex.decode("a0268090998a99666b72cc452b9307438a34341047d9e0d7b92c9207bf413655"));
    assertThat(blockchain.getRepository().hasAccountState(internalContract)).isFalse();
    // Manipulate the repository to have a non-default balance value.
    RepositoryCache cache = blockchain.getRepository().startTracking();
    cache.createAccount(internalContract);
    cache.addBalance(internalContract, BigInteger.TEN);
    cache.flushTo(cache.getParent(), true);
    // Check assumptions about contract state.
    AccountState contractState = (AccountState) blockchain.getRepository().startTracking().getAccountState(internalContract);
    assertThat(contractState.getBalance()).isEqualTo(BigInteger.TEN);
    assertThat(contractState.getNonce()).isEqualTo(BigInteger.ZERO);
    assertThat(contractState.getStateRoot()).isEqualTo(EMPTY_TRIE_HASH);
    assertThat(contractState.getCodeHash()).isEqualTo(EMPTY_DATA_HASH);
    // Next, process the deploy transaction with fork040 enabled.
    AionTxExecSummary result = executeTransaction(deployInternal, true);
    assertThat(result.isFailed()).isFalse();
    assertThat(result.isRejected()).isFalse();
    assertThat(result.getReceipt().getError()).isEmpty();
    assertThat(result.getNrgUsed()).isLessThan(BigInteger.valueOf(deployInternal.getEnergyLimit()));
    assertThat(result.getLogs()).isEmpty();
    InternalTransaction itx = result.getInternalTransactions().get(0);
    assertThat(itx.isCreate).isTrue();
    assertThat(TxUtil.calculateContractAddress(itx)).isEqualTo(internalContract);
    assertThat(itx.isRejected).isFalse();
    assertThat(itx.energyLimit).isEqualTo(internalLimit);
    assertThat(result.getNrgUsed()).isLessThan(BigInteger.valueOf(itx.energyLimit));
    contractState = (AccountState) blockchain.getRepository().startTracking().getAccountState(internalContract);
    assertThat(contractState.getBalance()).isEqualTo(BigInteger.TEN);
    assertThat(contractState.getNonce()).isEqualTo(BigInteger.ZERO);
    assertThat(contractState.getStateRoot()).isNotEqualTo(EMPTY_TRIE_HASH);
    assertThat(contractState.getCodeHash()).isNotEqualTo(EMPTY_DATA_HASH);
}
Also used : AionAddress(org.aion.types.AionAddress) ImportResult(org.aion.zero.impl.core.ImportResult) AionTxExecSummary(org.aion.base.AionTxExecSummary) AionBlockchainImpl.getPostExecutionWorkForGeneratePreBlock(org.aion.zero.impl.blockchain.AionBlockchainImpl.getPostExecutionWorkForGeneratePreBlock) Block(org.aion.zero.impl.types.Block) RepositoryCache(org.aion.base.db.RepositoryCache) AionTransaction(org.aion.base.AionTransaction) AccountState(org.aion.base.AccountState) InternalTransaction(org.aion.types.InternalTransaction) Test(org.junit.Test)

Example 72 with Block

use of org.aion.zero.impl.types.Block in project aion by aionnetwork.

the class TransactionCreateSpecificationTests method deployInternalAvmContractOnTopOfAddressWithNonceUsingAvmVersion1_DeployAndRequireSuccess.

@Test
public void deployInternalAvmContractOnTopOfAddressWithNonceUsingAvmVersion1_DeployAndRequireSuccess() throws VmFatalException {
    AvmTestConfig.clearConfigurations();
    AvmTestConfig.supportOnlyAvmVersion1();
    // Deploy AVM contract.
    AionTransaction deployTxAvm = BlockchainTestUtils.deployAvmContractTransaction(AvmContract.DEPLOY_INTERNAL, resourceProvider.factoryForVersion1, SENDER_KEY, BigInteger.ZERO);
    AionAddress contract = TxUtil.calculateContractAddress(deployTxAvm);
    Pair<Block, ImportResult> resultImport = BlockchainTestUtils.addMiningBlock(blockchain, blockchain.getBestBlock(), List.of(deployTxAvm));
    assertThat(resultImport.getRight()).isEqualTo(ImportResult.IMPORTED_BEST);
    // Call AVM contract to deploy new internal AVM contract (version with required success).
    long internalLimit = 1_000_000;
    AionTransaction deployInternal = BlockchainTestUtils.callSimpleAvmContractTransaction(resourceProvider.factoryForVersion1, SENDER_KEY, BigInteger.ONE, contract, "deployAndRequireSuccess", deployTxAvm.getData(), internalLimit);
    AionAddress internalContract = new AionAddress(Hex.decode("a0268090998a99666b72cc452b9307438a34341047d9e0d7b92c9207bf413655"));
    assertThat(blockchain.getRepository().hasAccountState(internalContract)).isFalse();
    // Manipulate the repository to have a non-default nonce value.
    RepositoryCache cache = blockchain.getRepository().startTracking();
    cache.createAccount(internalContract);
    cache.setNonce(internalContract, BigInteger.TEN);
    cache.flushTo(cache.getParent(), true);
    // Check assumptions about contract state.
    AccountState contractState = (AccountState) blockchain.getRepository().startTracking().getAccountState(internalContract);
    assertThat(contractState.getBalance()).isEqualTo(BigInteger.ZERO);
    assertThat(contractState.getNonce()).isEqualTo(BigInteger.TEN);
    assertThat(contractState.getStateRoot()).isEqualTo(EMPTY_TRIE_HASH);
    assertThat(contractState.getCodeHash()).isEqualTo(EMPTY_DATA_HASH);
    // Next, process the deploy transaction with fork040 enabled.
    AionTxExecSummary result = executeTransaction(deployInternal, true);
    assertThat(result.isFailed()).isFalse();
    assertThat(result.isRejected()).isFalse();
    assertThat(result.getReceipt().getError()).isEmpty();
    assertThat(result.getNrgUsed()).isLessThan(BigInteger.valueOf(deployInternal.getEnergyLimit()));
    assertThat(result.getLogs()).isEmpty();
    InternalTransaction itx = result.getInternalTransactions().get(0);
    assertThat(itx.isCreate).isTrue();
    assertThat(TxUtil.calculateContractAddress(itx)).isEqualTo(internalContract);
    assertThat(itx.isRejected).isFalse();
    assertThat(itx.energyLimit).isEqualTo(internalLimit);
    assertThat(result.getNrgUsed()).isLessThan(BigInteger.valueOf(itx.energyLimit));
    contractState = (AccountState) blockchain.getRepository().startTracking().getAccountState(internalContract);
    assertThat(contractState.getBalance()).isEqualTo(BigInteger.ZERO);
    assertThat(contractState.getNonce()).isEqualTo(BigInteger.TEN);
    assertThat(contractState.getStateRoot()).isNotEqualTo(EMPTY_TRIE_HASH);
    assertThat(contractState.getCodeHash()).isNotEqualTo(EMPTY_DATA_HASH);
}
Also used : AionAddress(org.aion.types.AionAddress) ImportResult(org.aion.zero.impl.core.ImportResult) AionTxExecSummary(org.aion.base.AionTxExecSummary) AionBlockchainImpl.getPostExecutionWorkForGeneratePreBlock(org.aion.zero.impl.blockchain.AionBlockchainImpl.getPostExecutionWorkForGeneratePreBlock) Block(org.aion.zero.impl.types.Block) RepositoryCache(org.aion.base.db.RepositoryCache) AionTransaction(org.aion.base.AionTransaction) AccountState(org.aion.base.AccountState) InternalTransaction(org.aion.types.InternalTransaction) Test(org.junit.Test)

Example 73 with Block

use of org.aion.zero.impl.types.Block in project aion by aionnetwork.

the class BlockchainConcurrencyTest method testPublishBestBlockSafely.

@Test
public void testPublishBestBlockSafely() {
    ExecutorService blockCreationService = Executors.newSingleThreadExecutor();
    ExecutorService getBlockService = Executors.newSingleThreadExecutor();
    StandaloneBlockchain.Bundle bundle = new StandaloneBlockchain.Builder().withDefaultAccounts().withValidatorConfiguration("simple").build();
    StandaloneBlockchain bc = bundle.bc;
    final int MAX_COUNT = 100000;
    final CountDownLatch endLatch = new CountDownLatch(2);
    // this will not definitively prove
    try {
        blockCreationService.submit(() -> {
            int count = 0;
            List<AionTransaction> txList = Collections.emptyList();
            MiningBlock block = null;
            try {
                block = bc.createNewMiningBlock(bc.genesis, Collections.emptyList(), false);
            } catch (Exception e) {
                e.printStackTrace();
            }
            while (!Thread.currentThread().isInterrupted() && count < MAX_COUNT) {
                try {
                    block = bc.createNewMiningBlock(block, txList, false);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                count++;
            }
            System.out.println("completed block creation");
            endLatch.countDown();
        });
        getBlockService.submit(() -> {
            int count = 0;
            long prevNumber = bc.getBestBlock().getNumber();
            while (!Thread.currentThread().isInterrupted() && count < MAX_COUNT) {
                // all three of these methods use {@link
                // AionBlockchainImpl#pubBestBlock}
                assertThat(bc.getBestBlockHash()).isNotNull();
                bc.getSize();
                Block block = bc.getBestBlock();
                assertThat(block).isNotNull();
                assertThat(block.getNumber()).isAtLeast(prevNumber);
                prevNumber = block.getNumber();
                count++;
            }
            endLatch.countDown();
        });
    } finally {
        blockCreationService.shutdown();
        getBlockService.shutdown();
    }
}
Also used : ExecutorService(java.util.concurrent.ExecutorService) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) AionTransaction(org.aion.base.AionTransaction) CountDownLatch(java.util.concurrent.CountDownLatch) MiningBlock(org.aion.zero.impl.types.MiningBlock) Test(org.junit.Test)

Example 74 with Block

use of org.aion.zero.impl.types.Block in project aion by aionnetwork.

the class BlockchainDataRecoveryTest method testRecoverIndex_wDeletedBlock.

@Test
public void testRecoverIndex_wDeletedBlock() {
    // build a blockchain with a few blocks
    StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
    StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).build();
    StandaloneBlockchain chain = bundle.bc;
    AionRepositoryImpl repo = chain.getRepository();
    BlockContext context;
    List<AionTransaction> txs;
    // all blocks will be incorrect
    long time = System.currentTimeMillis();
    Map<Long, byte[]> blocksToDelete = new HashMap<>();
    List<MiningBlock> blocksToImport = new ArrayList<>();
    for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
        txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, accounts, repo);
        context = chain.createNewMiningBlockInternal(chain.getBestBlock(), txs, true, time / 10000L);
        assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
        blocksToDelete.put(context.block.getNumber(), context.block.getHash());
        // skipping middle block
        if (context.block.getNumber() != NUMBER_OF_BLOCKS / 2) {
            blocksToImport.add(context.block);
        }
    }
    Block bestBlock = chain.getBestBlock();
    assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
    // delete middle block from db
    Block middle = chain.getBlockByNumber(NUMBER_OF_BLOCKS / 2);
    MockDB database = (MockDB) repo.getBlockDatabase();
    database.deleteAndCommit(middle.getHash());
    // delete index entries from the database
    MockDB indexDatabase = (MockDB) repo.getIndexDatabase();
    // 1: direct recovery call
    repo.flush();
    Map<Long, byte[]> deletedInfo = new HashMap<>();
    for (Map.Entry<Long, byte[]> entry : blocksToDelete.entrySet()) {
        byte[] indexKey = ByteUtil.intToBytes(entry.getKey().intValue());
        // saving the data for checking recovery
        deletedInfo.put(entry.getKey(), indexDatabase.get(indexKey).get());
        // deleting the block info
        indexDatabase.deleteAndCommit(indexKey);
        // ensure that the index was corrupted
        assertThat(repo.isIndexed(entry.getValue(), entry.getKey())).isFalse();
    }
    // ensure that the index was corrupted
    assertThat(repo.isIndexed(bestBlock.getHash(), bestBlock.getNumber())).isFalse();
    // call the recovery functionality
    assertThat(chain.recoverIndexEntry(repo, bestBlock)).isFalse();
    // ensure that the blockchain is ok
    assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
    // ensure that the index was recovered
    assertThat(repo.isIndexed(bestBlock.getHash(), bestBlock.getNumber())).isFalse();
    // 2: recovery at import
    repo.flush();
    for (Map.Entry<Long, byte[]> entry : blocksToDelete.entrySet()) {
        byte[] indexKey = ByteUtil.intToBytes(entry.getKey().intValue());
        // deleting the block info
        indexDatabase.deleteAndCommit(indexKey);
        // ensure that the index was corrupted
        assertThat(repo.isIndexed(entry.getValue(), entry.getKey())).isFalse();
    }
    // ensure that the index was corrupted
    assertThat(repo.isIndexed(bestBlock.getHash(), bestBlock.getNumber())).isFalse();
    // call the recovery functionality indirectly
    for (MiningBlock block : blocksToImport) {
        // index missing before import
        assertThat(repo.isIndexed(block.getHash(), block.getNumber())).isFalse();
        assertThat(chain.tryToConnect(block)).isEqualTo(ImportResult.EXIST);
        if (block.getNumber() < middle.getNumber()) {
            // index present after import
            assertThat(repo.isIndexed(block.getHash(), block.getNumber())).isTrue();
        } else {
            // blocks after missing one cannot be recovered
            assertThat(repo.isIndexed(block.getHash(), block.getNumber())).isFalse();
        }
    }
    // ensure that the blockchain is ok
    assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
    // ensure that the index was recovered
    assertThat(repo.isIndexed(bestBlock.getHash(), bestBlock.getNumber())).isFalse();
    // importing middle block
    assertThat(chain.tryToConnect(middle)).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
    // call the recovery functionality indirectly
    for (MiningBlock block : blocksToImport) {
        // checking only failed blocks from before
        if (block.getNumber() > middle.getNumber()) {
            // index missing before import
            assertThat(repo.isIndexed(block.getHash(), block.getNumber())).isFalse();
            assertThat(chain.tryToConnect(block)).isEqualTo(ImportResult.EXIST);
            // index present after import
            assertThat(repo.isIndexed(block.getHash(), block.getNumber())).isTrue();
        }
    }
    // ensure that the blockchain is ok
    assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
    // ensure that the index was recovered
    assertThat(repo.isIndexed(bestBlock.getHash(), bestBlock.getNumber())).isTrue();
    // check that the index information is correct at database level
    for (Long key : blocksToDelete.keySet()) {
        // checking at database level
        byte[] indexKey = ByteUtil.intToBytes(key.intValue());
        assertThat(deletedInfo.get(key)).isEqualTo(indexDatabase.get(indexKey).get());
    }
}
Also used : HashMap(java.util.HashMap) BlockContext(org.aion.zero.impl.types.BlockContext) 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) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) HashMap(java.util.HashMap) Map(java.util.Map) Test(org.junit.Test)

Example 75 with Block

use of org.aion.zero.impl.types.Block in project aion by aionnetwork.

the class BlockchainDataRecoveryTest method testRecoverWorldStateWithStartFromGenesis.

/**
 * Test the recovery of the world state with start from the state of the genesis block.
 */
@Test
public void testRecoverWorldStateWithStartFromGenesis() {
    // build a blockchain with a few blocks
    StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
    StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).build();
    StandaloneBlockchain chain = bundle.bc;
    AionRepositoryImpl repo = chain.getRepository();
    BlockContext context;
    List<AionTransaction> txs;
    // all blocks will be incorrect
    long time = System.currentTimeMillis();
    List<byte[]> statesToDelete = new ArrayList<>();
    List<MiningBlock> blocksToImport = new ArrayList<>();
    for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
        txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, accounts, 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();
    // 1: direct recovery call
    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();
    // call the recovery functionality
    boolean worked = chain.recoverWorldState(repo, bestBlock);
    // 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();
    // 2: recovery at import
    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();
    // call the recovery functionality indirectly
    for (MiningBlock block : blocksToImport) {
        // state missing before import
        assertThat(trie.isValidRoot(block.getStateRoot())).isFalse();
        assertThat(chain.tryToConnect(block)).isEqualTo(ImportResult.EXIST);
        // state present after import
        assertThat(trie.isValidRoot(block.getStateRoot())).isTrue();
    }
    // 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();
}
Also used : BlockContext(org.aion.zero.impl.types.BlockContext) 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)

Aggregations

Block (org.aion.zero.impl.types.Block)283 MiningBlock (org.aion.zero.impl.types.MiningBlock)155 Test (org.junit.Test)148 AionTransaction (org.aion.base.AionTransaction)106 ImportResult (org.aion.zero.impl.core.ImportResult)86 ArrayList (java.util.ArrayList)63 AionAddress (org.aion.types.AionAddress)61 StakingBlock (org.aion.zero.impl.types.StakingBlock)58 AionBlockSummary (org.aion.zero.impl.types.AionBlockSummary)57 BigInteger (java.math.BigInteger)55 AionRepositoryImpl (org.aion.zero.impl.db.AionRepositoryImpl)34 ByteArrayWrapper (org.aion.util.types.ByteArrayWrapper)30 AionTxReceipt (org.aion.base.AionTxReceipt)29 Hex.toHexString (org.aion.util.conversions.Hex.toHexString)28 AccountState (org.aion.base.AccountState)26 EventBlock (org.aion.evtmgr.impl.evt.EventBlock)26 JSONArray (org.json.JSONArray)26 JSONObject (org.json.JSONObject)26 MiningBlockHeader (org.aion.zero.impl.types.MiningBlockHeader)22 AionTxExecSummary (org.aion.base.AionTxExecSummary)20