Search in sources :

Example 1 with MiningBlockHeader

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

the class EnergyLimitRuleTest method testEnergyLimitLowerBound.

@Test
public void testEnergyLimitLowerBound() {
    final long INITIAL_VAL = 0l;
    MiningBlockHeader parentHeader = MiningBlockHeader.Builder.newInstance().withEnergyLimit(0l).withDefaultExtraData().withDefaultCoinbase().withDefaultParentHash().withDefaultNonce().withDefaultLogsBloom().withDefaultSolution().withDefaultDifficulty().withDefaultStateRoot().withDefaultReceiptTrieRoot().withDefaultTxTrieRoot().withTimestamp(0).withEnergyConsumed(21000).withNumber(1).build();
    MiningBlockHeader currentHeader = MiningBlockHeader.Builder.newInstance().withEnergyLimit(1l).withDefaultExtraData().withDefaultCoinbase().withDefaultParentHash().withDefaultNonce().withDefaultLogsBloom().withDefaultSolution().withDefaultDifficulty().withDefaultStateRoot().withDefaultReceiptTrieRoot().withDefaultTxTrieRoot().withTimestamp(1).withEnergyConsumed(21000).withNumber(2).build();
    List<RuleError> errors = new ArrayList<>();
    EnergyLimitRule rule = new EnergyLimitRule(constants.getEnergyDivisorLimitLong(), constants.getEnergyLowerBoundLong());
    boolean res = rule.validate(currentHeader, parentHeader, errors);
    assertThat(res).isEqualTo(false);
    assertThat(errors).isNotEmpty();
}
Also used : MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) ArrayList(java.util.ArrayList) Test(org.junit.Test)

Example 2 with MiningBlockHeader

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

the class EnergyLimitRuleTest method testEnergyLimitBounds.

@Test
public void testEnergyLimitBounds() {
    final long INITIAL_VAL = 2000000L;
    final long DIVISOR = 1024;
    EnergyLimitRule rule = new EnergyLimitRule(constants.getEnergyDivisorLimitLong(), constants.getEnergyLowerBoundLong());
    MiningBlockHeader parentHeader = MiningBlockHeader.Builder.newInstance().withEnergyLimit(INITIAL_VAL).withNumber(1).withDefaultParentHash().withDefaultCoinbase().withDefaultLogsBloom().withDifficulty(ByteUtil.intToBytes(1)).withDefaultExtraData().withEnergyConsumed(1).withTimestamp(1).withDefaultNonce().withDefaultSolution().withDefaultStateRoot().withDefaultTxTrieRoot().withDefaultReceiptTrieRoot().build();
    long boundShiftLimit = INITIAL_VAL / DIVISOR;
    MiningBlockHeader upperCurrentBlock = MiningBlockHeader.Builder.newInstance().withEnergyLimit(INITIAL_VAL + boundShiftLimit).withNumber(1).withDefaultParentHash().withDefaultCoinbase().withDefaultLogsBloom().withDifficulty(ByteUtil.intToBytes(1)).withDefaultExtraData().withEnergyConsumed(1).withTimestamp(1).withDefaultNonce().withDefaultSolution().withDefaultStateRoot().withDefaultTxTrieRoot().withDefaultReceiptTrieRoot().build();
    List<RuleError> errors = new ArrayList<>();
    // upper bound
    boolean res = rule.validate(upperCurrentBlock, parentHeader, errors);
    assertThat(res).isEqualTo(true);
    assertThat(errors).isEmpty();
    errors.clear();
    MiningBlockHeader invalidCurrentHeader = MiningBlockHeader.Builder.newInstance().withEnergyLimit(INITIAL_VAL + boundShiftLimit + 1).withNumber(1).withDefaultParentHash().withDefaultCoinbase().withDefaultLogsBloom().withDifficulty(ByteUtil.intToBytes(1)).withDefaultExtraData().withEnergyConsumed(1).withTimestamp(1).withDefaultNonce().withDefaultSolution().withDefaultStateRoot().withDefaultTxTrieRoot().withDefaultReceiptTrieRoot().build();
    res = rule.validate(invalidCurrentHeader, parentHeader, errors);
    assertThat(res).isEqualTo(false);
    assertThat(errors).isNotEmpty();
    errors.clear();
    // lower bound
    MiningBlockHeader lowerCurrentHeader = MiningBlockHeader.Builder.newInstance().withEnergyLimit(INITIAL_VAL - boundShiftLimit).withNumber(1).withDefaultParentHash().withDefaultCoinbase().withDefaultLogsBloom().withDifficulty(ByteUtil.intToBytes(1)).withDefaultExtraData().withEnergyConsumed(1).withTimestamp(1).withDefaultNonce().withDefaultSolution().withDefaultStateRoot().withDefaultTxTrieRoot().withDefaultReceiptTrieRoot().build();
    res = rule.validate(lowerCurrentHeader, parentHeader, errors);
    assertThat(res).isEqualTo(true);
    assertThat(errors).isEmpty();
    errors.clear();
    MiningBlockHeader invalidLowerCurrentHeader = MiningBlockHeader.Builder.newInstance().withEnergyLimit(INITIAL_VAL - boundShiftLimit - 1).withNumber(1).withDefaultParentHash().withDefaultCoinbase().withDefaultLogsBloom().withDifficulty(ByteUtil.intToBytes(1)).withDefaultExtraData().withEnergyConsumed(1).withTimestamp(1).withDefaultNonce().withDefaultSolution().withDefaultStateRoot().withDefaultTxTrieRoot().withDefaultReceiptTrieRoot().build();
    res = rule.validate(invalidLowerCurrentHeader, parentHeader, errors);
    assertThat(res).isEqualTo(false);
    assertThat(errors).isNotEmpty();
    errors.clear();
}
Also used : MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) ArrayList(java.util.ArrayList) Test(org.junit.Test)

Example 3 with MiningBlockHeader

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

the class AionBlockchainImpl method getListOfHeadersStartFrom.

/**
 * Returns up to limit headers found with following search parameters
 *
 * @param blockNumber Identifier of start block, by number
 * @param limit Maximum number of headers in return
 * @return {@link MiningBlockHeader}'s list or empty list if none found
 */
@Override
public List<BlockHeader> getListOfHeadersStartFrom(long blockNumber, int limit) {
    if (limit <= 0) {
        return emptyList();
    }
    // identifying block we'll move from
    Block startBlock = getBlockByNumber(blockNumber);
    // if nothing found on main chain, return empty array
    if (startBlock == null) {
        return emptyList();
    }
    List<BlockHeader> headers;
    long bestNumber = bestBlock.getNumber();
    headers = getContinuousHeaders(bestNumber, blockNumber, limit);
    return headers;
}
Also used : Block(org.aion.zero.impl.types.Block) BlockDetailsValidator.isValidBlock(org.aion.zero.impl.valid.BlockDetailsValidator.isValidBlock) GenesisStakingBlock(org.aion.zero.impl.types.GenesisStakingBlock) RetValidPreBlock(org.aion.zero.impl.types.RetValidPreBlock) MiningBlock(org.aion.zero.impl.types.MiningBlock) EventBlock(org.aion.evtmgr.impl.evt.EventBlock) StakingBlock(org.aion.zero.impl.types.StakingBlock) BlockHeader(org.aion.zero.impl.types.BlockHeader) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) StakingBlockHeader(org.aion.zero.impl.types.StakingBlockHeader)

Example 4 with MiningBlockHeader

use of org.aion.zero.impl.types.MiningBlockHeader 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)

Example 5 with MiningBlockHeader

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

the class BlockchainForkingTest method testForkWithRevertOnSmallContractStorage.

/**
 * Test the fork case when the block being replaced had contract storage changes that differ
 * from the previous block and are replaced by new changes in the updated block.
 *
 * <p>Ensures that the output of applying the block after the fork is the same as applying the
 * block first.
 */
@Test
public void testForkWithRevertOnSmallContractStorage() {
    // ****** setup ******
    // build a blockchain with CONCURRENT_THREADS_PER_TYPE blocks
    List<ECKey> accounts = generateAccounts(10);
    StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
    StandaloneBlockchain sourceChain = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).build().bc;
    StandaloneBlockchain testChain = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).build().bc;
    assertThat(testChain).isNotEqualTo(sourceChain);
    assertThat(testChain.genesis).isEqualTo(sourceChain.genesis);
    long time = System.currentTimeMillis();
    // add a block with contract deploy
    ECKey sender = accounts.remove(0);
    AionTransaction deployTx = deployContract(sender);
    MiningBlock block = sourceChain.createNewMiningBlockInternal(sourceChain.genesis, Arrays.asList(deployTx), true, time / 10_000L).block;
    Pair<ImportResult, AionBlockSummary> connectResult = sourceChain.tryToConnectAndFetchSummary(block);
    AionTxReceipt receipt = connectResult.getRight().getReceipts().get(0);
    assertThat(receipt.isSuccessful()).isTrue();
    ImportResult result = connectResult.getLeft();
    assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
    result = testChain.tryToConnect(block);
    assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
    assertThat(testChain.getRepository().getRoot()).isEqualTo(sourceChain.getRepository().getRoot());
    AionAddress contract = TxUtil.calculateContractAddress(receipt.getTransaction());
    // add a block with transactions to both
    List<AionTransaction> txs = generateTransactions(20, accounts, sourceChain.getRepository());
    block = sourceChain.createNewMiningBlockInternal(sourceChain.getBestBlock(), txs, true, time / 10_000L).block;
    result = sourceChain.tryToConnect(block);
    assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
    result = testChain.tryToConnect(block);
    assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
    assertThat(testChain.getRepository().getRoot()).isEqualTo(sourceChain.getRepository().getRoot());
    // create a slow / fast block distinction
    AionTransaction callTx = callSetValue2(sender, contract, 5, 6, BigInteger.ONE);
    MiningBlock fastBlock = sourceChain.createNewMiningBlockInternal(sourceChain.getBestBlock(), Arrays.asList(callTx), true, time / 10_000L).block;
    callTx = callSetValue2(sender, contract, 1, 9, BigInteger.ONE);
    MiningBlock slowBlock = new MiningBlock(sourceChain.createNewMiningBlockInternal(sourceChain.getBestBlock(), Arrays.asList(callTx), true, time / 10_000L).block);
    MiningBlockHeader newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader(slowBlock.getHeader()).withTimestamp(time / 10_000L + 100).build();
    slowBlock.updateHeader(newBlockHeader);
    time += 100;
    // sourceChain imports only fast block
    assertThat(sourceChain.tryToConnect(fastBlock)).isEqualTo(ImportResult.IMPORTED_BEST);
    // testChain imports both blocks
    assertThat(testChain.tryToConnect(fastBlock)).isEqualTo(ImportResult.IMPORTED_BEST);
    assertThat(testChain.tryToConnect(slowBlock)).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
    // build two blocks with different contract storage calls
    // the second block gets a higher total difficulty
    callTx = callSetValue(sender, contract, 5, BigInteger.TWO);
    MiningBlock lowBlock = testChain.createNewMiningBlockInternal(slowBlock, Arrays.asList(callTx), true, time / 10_000L + 101).block;
    callTx = callSetValue(sender, contract, 9, BigInteger.TWO);
    MiningBlock highBlock = sourceChain.createNewMiningBlockInternal(fastBlock, Arrays.asList(callTx), true, time / 10_000L).block;
    // System.out.println("***highBlock TD: " + highBlock.getDifficultyBI());
    // System.out.println("***lowBlock TD: " + lowBlock.getDifficultyBI());
    assertThat(highBlock.getDifficultyBI()).isGreaterThan(lowBlock.getDifficultyBI());
    // build first chain with highBlock applied directly
    connectResult = sourceChain.tryToConnectAndFetchSummary(highBlock);
    receipt = connectResult.getRight().getReceipts().get(0);
    assertThat(receipt.isSuccessful()).isTrue();
    result = connectResult.getLeft();
    assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
    // collect the consensus information from the block & receipt
    AionBlockSummary blockSummary = connectResult.getRight();
    byte[] stateRoot = blockSummary.getBlock().getStateRoot();
    byte[] blockReceiptsRoot = blockSummary.getBlock().getReceiptsRoot();
    byte[] receiptTrieEncoded = receipt.getReceiptTrieEncoded();
    // ****** test fork behavior ******
    // first import lowBlock
    assertThat(testChain.tryToConnect(lowBlock)).isEqualTo(ImportResult.IMPORTED_BEST);
    // next import highBlock causing the fork
    connectResult = testChain.tryToConnectAndFetchSummary(highBlock);
    receipt = connectResult.getRight().getReceipts().get(0);
    assertThat(receipt.isSuccessful()).isTrue();
    System.out.println(receipt);
    result = connectResult.getLeft();
    assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
    // collect the consensus information from the block & receipt
    blockSummary = connectResult.getRight();
    assertThat(testChain.getBestBlock()).isEqualTo(sourceChain.getBestBlock());
    assertThat(blockSummary.getBlock().getStateRoot()).isEqualTo(stateRoot);
    assertThat(blockSummary.getBlock().getReceiptsRoot()).isEqualTo(blockReceiptsRoot);
    assertThat(receipt.getReceiptTrieEncoded()).isEqualTo(receiptTrieEncoded);
}
Also used : ImportResult(org.aion.zero.impl.core.ImportResult) AionAddress(org.aion.types.AionAddress) ECKey(org.aion.crypto.ECKey) AionTransaction(org.aion.base.AionTransaction) MiningBlock(org.aion.zero.impl.types.MiningBlock) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) AionTxReceipt(org.aion.base.AionTxReceipt) Test(org.junit.Test)

Aggregations

MiningBlockHeader (org.aion.zero.impl.types.MiningBlockHeader)29 MiningBlock (org.aion.zero.impl.types.MiningBlock)23 Test (org.junit.Test)20 Block (org.aion.zero.impl.types.Block)14 AionTransaction (org.aion.base.AionTransaction)9 ImportResult (org.aion.zero.impl.core.ImportResult)9 ArrayList (java.util.ArrayList)8 AionRepositoryImpl (org.aion.zero.impl.db.AionRepositoryImpl)8 List (java.util.List)5 IOException (java.io.IOException)4 Properties (java.util.Properties)4 ByteArrayWrapper (org.aion.util.types.ByteArrayWrapper)4 StakingBlock (org.aion.zero.impl.types.StakingBlock)4 BigInteger (java.math.BigInteger)3 ECKey (org.aion.crypto.ECKey)3 AionAddress (org.aion.types.AionAddress)3 BlockContext (org.aion.zero.impl.types.BlockContext)3 AionTxReceipt (org.aion.base.AionTxReceipt)2 MockDB (org.aion.db.impl.mockdb.MockDB)2 AionBlockStore (org.aion.zero.impl.db.AionBlockStore)2