Search in sources :

Example 31 with ImportResult

use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.

the class PendingStateTest method alreadySealed.

@Test
public void alreadySealed() {
    AionTransaction tx = AionTransaction.create(deployerKey, BigInteger.ZERO.toByteArray(), new AionAddress(new byte[32]), ByteUtils.fromHexString("1"), ByteUtils.fromHexString("1"), 1000_000L, energyPrice, TransactionTypes.DEFAULT, null);
    AionTransaction tx2 = AionTransaction.create(deployerKey, BigInteger.ZERO.toByteArray(), new AionAddress(new byte[32]), ByteUtils.fromHexString("2"), ByteUtils.fromHexString("2"), 1000_000L, energyPrice * 2, TransactionTypes.DEFAULT, null);
    assertEquals(pendingState.addTransactionFromApiServer(tx), TxResponse.SUCCESS);
    MiningBlock block = blockchain.createNewMiningBlock(blockchain.getBestBlock(), pendingState.getPendingTransactions(), false);
    Pair<ImportResult, AionBlockSummary> connectResult = blockchain.tryToConnectAndFetchSummary(block);
    assertEquals(connectResult.getLeft(), ImportResult.IMPORTED_BEST);
    assertEquals(pendingState.addTransactionFromApiServer(tx), TxResponse.ALREADY_SEALED);
    assertEquals(pendingState.addTransactionFromApiServer(tx2), TxResponse.ALREADY_SEALED);
}
Also used : AionAddress(org.aion.types.AionAddress) ImportResult(org.aion.zero.impl.core.ImportResult) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) AionTransaction(org.aion.base.AionTransaction) MiningBlock(org.aion.zero.impl.types.MiningBlock) Test(org.junit.Test)

Example 32 with ImportResult

use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.

the class PendingStateTest method replayTransactionThatThatInvalidatesMiddleTx.

@Test
public void replayTransactionThatThatInvalidatesMiddleTx() {
    BigInteger balance = blockchain.getRepository().getBalance(new AionAddress(deployerKey.getAddress()));
    BigInteger value = balance.subtract(BigInteger.valueOf(21000 * 7).multiply(BigInteger.valueOf(energyPrice)));
    AionTransaction tx1 = AionTransaction.create(deployerKey, BigInteger.ZERO.toByteArray(), new AionAddress(new byte[32]), value.toByteArray(), new byte[0], 21000, energyPrice, TransactionTypes.DEFAULT, null);
    AionTransaction tx2 = AionTransaction.create(deployerKey, BigInteger.ONE.toByteArray(), new AionAddress(new byte[32]), BigInteger.ZERO.toByteArray(), new byte[0], 21000, energyPrice, TransactionTypes.DEFAULT, null);
    /* tx1 and tx3 should use the entire balance. If tx2 is removed properly, tx3 should be
         * able to replace it in the pending state */
    AionTransaction tx3 = AionTransaction.create(deployerKey, BigInteger.ONE.toByteArray(), new AionAddress(new byte[32]), BigInteger.ZERO.toByteArray(), new byte[0], 21000, energyPrice * 4, TransactionTypes.DEFAULT, null);
    // This would execute fine on top of tx2, but should have insufficient balance on top of tx3
    AionTransaction tx4 = AionTransaction.create(deployerKey, BigInteger.TWO.toByteArray(), new AionAddress(new byte[32]), BigInteger.ZERO.toByteArray(), new byte[0], 21000, energyPrice * 4, TransactionTypes.DEFAULT, null);
    AionTransaction tx5 = AionTransaction.create(deployerKey, BigInteger.valueOf(3).toByteArray(), new AionAddress(new byte[32]), BigInteger.ZERO.toByteArray(), new byte[0], 21000, energyPrice, TransactionTypes.DEFAULT, null);
    assertEquals(TxResponse.SUCCESS, pendingState.addTransactionFromApiServer(tx1));
    assertEquals(TxResponse.SUCCESS, pendingState.addTransactionFromApiServer(tx2));
    assertEquals(TxResponse.REPAID, pendingState.addTransactionFromApiServer(tx3));
    assertEquals(TxResponse.SUCCESS, pendingState.addTransactionFromApiServer(tx4));
    assertEquals(TxResponse.SUCCESS, pendingState.addTransactionFromApiServer(tx5));
    assertEquals(4, pendingState.getPendingTxSize());
    MiningBlock block = blockchain.createNewMiningBlock(blockchain.getBestBlock(), Collections.emptyList(), false);
    Pair<ImportResult, AionBlockSummary> connectResult = blockchain.tryToConnectAndFetchSummary(block);
    assertEquals(connectResult.getLeft(), ImportResult.IMPORTED_BEST);
    pendingState.applyBlockUpdate(block, connectResult.getRight().getReceipts());
    // tx3 should replace tx2, and tx4 will now have insufficient funds so it will get dropped
    assertEquals(2, pendingState.getPendingTxSize());
    assertEquals(pendingState.getPendingTransactions().get(1), tx3);
}
Also used : AionAddress(org.aion.types.AionAddress) ImportResult(org.aion.zero.impl.core.ImportResult) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) BigInteger(java.math.BigInteger) AionTransaction(org.aion.base.AionTransaction) MiningBlock(org.aion.zero.impl.types.MiningBlock) Test(org.junit.Test)

Example 33 with ImportResult

use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.

the class BlockchainConcurrentImportTest method addThread_tryToConnect.

/**
 * Adds a new thread for importing a block from the given queue.
 *
 * @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 _queue a queue containing new blocks
 * @param _imported a list of blocks that have been imported; blocks successfully imported are
 *     added to this list
 */
private void addThread_tryToConnect(List<Runnable> _threads, StandaloneBlockchain _chain, ConcurrentLinkedQueue<MiningBlock> _queue, ConcurrentLinkedQueue<MiningBlock> _imported) {
    _threads.add(() -> {
        // get next block from queue
        MiningBlock _block = _queue.poll();
        if (_block != null) {
            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 (from queue)%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
                    assertThat(store.getBestBlock().getTotalDifficulty()).isAtLeast(tdFromStore);
                }
                // save the block for later comparison
                _imported.add(_block);
            }
        } else {
            if (DISPLAY_MESSAGES) {
                System.out.format("%62sNo block in queue. Skipping import in thread: %20s %n", " ", Thread.currentThread().getName());
            }
        }
    });
}
Also used : ImportResult(org.aion.zero.impl.core.ImportResult) BigInteger(java.math.BigInteger) AionBlockStore(org.aion.zero.impl.db.AionBlockStore) MiningBlock(org.aion.zero.impl.types.MiningBlock)

Example 34 with ImportResult

use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.

the class BlockchainConcurrentImportTest method testConcurrent.

@Test
public void testConcurrent() throws InterruptedException {
    List<Runnable> threads = new ArrayList<>();
    int start = (int) sourceChain.getBestBlock().getNumber() - 1;
    ConcurrentLinkedQueue<MiningBlock> queue = new ConcurrentLinkedQueue<>();
    ConcurrentLinkedQueue<MiningBlock> imported = new ConcurrentLinkedQueue<>();
    int blockCount = CONCURRENT_THREADS_PER_TYPE + 1;
    for (MiningBlock blk : knownBlocks) {
        // connect to known blocks
        addThread_tryToConnect(threads, testChain, blk);
        // add new blocks with known parent
        addThread_createNewBlock(threads, testChain, blk, blockCount, queue);
        blockCount++;
        // add new blocks with best block parent
        addThread_createNewBlock(threads, testChain, blockCount, queue, start);
        blockCount++;
        // connect to new blocks
        addThread_tryToConnect(threads, testChain, queue, imported);
    }
    // run threads while not at minimum height
    long height, targetHeight = sourceChain.getBestBlock().getNumber() + MAIN_CHAIN_FREQUENCY;
    boolean done = false;
    while (!done) {
        System.out.format("%nRunning the %d generated threads...%n", threads.size());
        assertConcurrent("Testing tryToConnect(...) ", threads, TIME_OUT);
        // checking height
        height = testChain.getBestBlock().getNumber();
        done = height >= targetHeight;
        System.out.format("Current height = %d. Target height = %d.%n", height, targetHeight);
    }
    // adding new blocks to source chain
    System.out.format("%nAdding new blocks to source chain for testing...%n");
    MiningBlock block = imported.poll();
    while (block != null) {
        ImportResult result = sourceChain.tryToConnect(block);
        knownBlocks.add(block);
        if (DISPLAY_MESSAGES) {
            System.out.format("Importing block with hash: %s, number: %6d, extra data: %6s, txs: %3d, status: %20s%n", block.getShortHash(), block.getNumber(), new String(block.getExtraData()), block.getTransactionsList().size(), result.toString());
        }
        block = imported.poll();
    }
    // comparing total diff for the two chains
    assertThat(testChain.getTotalDifficulty()).isEqualTo(sourceChain.getTotalDifficulty());
    assertThat(testChain.getCachedTotalDifficulty()).isEqualTo(sourceChain.getCachedTotalDifficulty());
    testChain.assertEqualTotalDifficulty();
    // comparing total diff for each block of the two chains
    for (MiningBlock blk : knownBlocks) {
        assertThat(testChain.getTotalDifficultyForHash(blk.getHash())).isEqualTo(sourceChain.getTotalDifficultyForHash(blk.getHash()));
        byte[] hash = blk.getHash();
        assertThat(testChain.getTotalDifficultyForHash(hash)).isEqualTo(sourceChain.getTotalDifficultyForHash(hash));
    }
}
Also used : ImportResult(org.aion.zero.impl.core.ImportResult) ArrayList(java.util.ArrayList) MiningBlock(org.aion.zero.impl.types.MiningBlock) ConcurrentLinkedQueue(java.util.concurrent.ConcurrentLinkedQueue) Test(org.junit.Test)

Example 35 with ImportResult

use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.

the class BlockchainForkingTest method testInvalidFirstBlockDifficulty.

/*-
     * 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 testInvalidFirstBlockDifficulty() {
    StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
    StandaloneBlockchain.Bundle b = builder.withValidatorConfiguration("simple").build();
    StandaloneBlockchain bc = b.bc;
    Block bestBlock = bc.getBestBlock();
    MiningBlock standardBlock = bc.createNewMiningBlock(bc.getBestBlock(), Collections.emptyList(), true);
    ChainConfiguration cc = new ChainConfiguration();
    MiningBlock higherDifficultyBlock = new MiningBlock(standardBlock);
    MiningBlockHeader newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader(higherDifficultyBlock.getHeader()).withTimestamp(bestBlock.getTimestamp() + 1).build();
    higherDifficultyBlock.updateHeader(newBlockHeader);
    BigInteger difficulty = cc.getPreUnityDifficultyCalculator().calculateDifficulty(higherDifficultyBlock.getHeader(), bestBlock.getHeader());
    assertThat(difficulty).isGreaterThan(standardBlock.getDifficultyBI());
    newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader(higherDifficultyBlock.getHeader()).withDifficulty(difficulty.toByteArray()).build();
    higherDifficultyBlock.updateHeader(newBlockHeader);
    System.out.println("before any processing: " + Hex.toHexString(bc.getRepository().getRoot()));
    System.out.println("trie: " + bc.getRepository().getWorldState().getTrieDump());
    ImportResult result = bc.tryToConnect(standardBlock);
    assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
    // check that the correct caching context was used
    Pair<Long, BlockCachingContext> cacheContext = bc.getAvmCachingContext();
    assertThat(cacheContext.getLeft()).isEqualTo(standardBlock.getNumber() - 1);
    assertThat(cacheContext.getRight()).isEqualTo(BlockCachingContext.MAINCHAIN);
    // assert that the block we just inserted (best) is the instance that is returned
    assertThat(bc.getBestBlock() == standardBlock).isTrue();
    System.out.println(Hex.toHexString(bc.getRepository().getRoot()));
    ImportResult higherDifficultyResult = bc.tryToConnect(higherDifficultyBlock);
    /**
     * With our updates to difficulty verification and calculation, this block is now invalid
     */
    assertThat(higherDifficultyResult).isEqualTo(ImportResult.INVALID_BLOCK);
    assertThat(bc.getBestBlockHash()).isEqualTo(standardBlock.getHash());
    // since the block is second for that height, it is assumed as sidechain
    cacheContext = bc.getAvmCachingContext();
    assertThat(cacheContext.getLeft()).isEqualTo(standardBlock.getNumber() - 1);
    assertThat(cacheContext.getRight()).isEqualTo(BlockCachingContext.SIDECHAIN);
    // the object reference here is intentional
    assertThat(bc.getBestBlock() == standardBlock).isTrue();
    // check for correct state rollback
    assertThat(bc.getRepository().getRoot()).isEqualTo(standardBlock.getStateRoot());
    assertThat(bc.getTotalDifficulty()).isEqualTo(bc.getTotalDifficultyForHash(standardBlock.getHash()));
}
Also used : ImportResult(org.aion.zero.impl.core.ImportResult) BlockCachingContext(org.aion.zero.impl.vm.common.BlockCachingContext) MiningBlock(org.aion.zero.impl.types.MiningBlock) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) BigInteger(java.math.BigInteger) Test(org.junit.Test)

Aggregations

ImportResult (org.aion.zero.impl.core.ImportResult)166 Test (org.junit.Test)127 AionTransaction (org.aion.base.AionTransaction)114 AionAddress (org.aion.types.AionAddress)106 AionBlockSummary (org.aion.zero.impl.types.AionBlockSummary)95 MiningBlock (org.aion.zero.impl.types.MiningBlock)90 Block (org.aion.zero.impl.types.Block)80 BigInteger (java.math.BigInteger)75 AionTxReceipt (org.aion.base.AionTxReceipt)50 AionTxExecSummary (org.aion.base.AionTxExecSummary)31 ECKey (org.aion.crypto.ECKey)28 RepositoryCache (org.aion.base.db.RepositoryCache)22 StandaloneBlockchain (org.aion.zero.impl.blockchain.StandaloneBlockchain)22 InternalTransaction (org.aion.types.InternalTransaction)20 AccountState (org.aion.base.AccountState)18 ArrayList (java.util.ArrayList)17 AionBlockchainImpl.getPostExecutionWorkForGeneratePreBlock (org.aion.zero.impl.blockchain.AionBlockchainImpl.getPostExecutionWorkForGeneratePreBlock)16 Builder (org.aion.zero.impl.blockchain.StandaloneBlockchain.Builder)14 AionRepositoryImpl (org.aion.zero.impl.db.AionRepositoryImpl)10 BlockContext (org.aion.zero.impl.types.BlockContext)9