Search in sources :

Example 16 with BlockContext

use of org.aion.zero.impl.types.BlockContext 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 17 with BlockContext

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

Example 18 with BlockContext

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

the class BlockchainDataRecoveryTest method testRecoverWorldState_wDeletedBlock.

@Test
public void testRecoverWorldState_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();
    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());
        // 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 some world state root entries from the database
    TrieImpl trie = (TrieImpl) repo.getWorldState();
    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
    assertThat(chain.recoverWorldState(repo, bestBlock)).isFalse();
    // ensure that the blockchain is ok
    assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
    // ensure that the world state could not be recovered
    assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
    // 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);
        if (block.getNumber() < middle.getNumber()) {
            // state present after import
            assertThat(trie.isValidRoot(block.getStateRoot())).isTrue();
        } else {
            // block after missing one cannot be recovered
            assertThat(trie.isValidRoot(block.getStateRoot())).isFalse();
        }
    }
    // 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())).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()) {
            // 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)

Example 19 with BlockContext

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

the class BlockchainDataRecoveryTest method testRecoverWorldStateWithoutGenesis.

/**
 * Test the recovery of the world state when missing the genesis block state.
 *
 * <p>Under these circumstances the recovery will fail.
 */
@Test
public void testRecoverWorldStateWithoutGenesis() {
    // 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<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);
        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();
    List<byte[]> statesToDelete = new ArrayList<>();
    Iterator<byte[]> iterator = database.keys();
    while (iterator.hasNext()) {
        statesToDelete.add(iterator.next());
    }
    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 was not recovered
    assertThat(worked).isFalse();
    assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
    // 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 missing after import (because there is not genesis to recover from)
        assertThat(trie.isValidRoot(block.getStateRoot())).isFalse();
    }
    // 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())).isFalse();
}
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)

Example 20 with BlockContext

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

the class ApiWeb3Aion method stratum_getwork.

public RpcMsg stratum_getwork() {
    if (isSeedMode) {
        return new RpcMsg(null, RpcError.NOT_ALLOWED, "SeedNodeIsOpened");
    }
    BlockContext bestBlock;
    try {
        bestBlock = getBlockTemplate();
        if (bestBlock == null) {
            LOG.debug("Couldn't create a mining block template");
            JSONObject obj = new JSONObject();
            obj.put("message", "no mining block template ");
            obj.put("code", -1);
            return new RpcMsg(obj);
        }
    } catch (Exception e) {
        LOG.error("get mining block template failed!", e);
        JSONObject obj = new JSONObject();
        obj.put("message", "failed: " + e.toString());
        obj.put("code", -1);
        return new RpcMsg(obj);
    }
    JSONObject obj = new JSONObject();
    obj.put("previousblockhash", toHexString(bestBlock.block.getParentHash()));
    obj.put("height", bestBlock.block.getNumber());
    obj.put("target", toHexString(bestBlock.block.getHeader().getPowBoundary()));
    obj.put("headerHash", toHexString(bestBlock.block.getHeader().getMineHash()));
    obj.put("blockBaseReward", toHexString(bestBlock.baseBlockReward.toByteArray()));
    obj.put("blockTxFee", toHexString(bestBlock.transactionFee.toByteArray()));
    return new RpcMsg(obj);
}
Also used : JSONObject(org.json.JSONObject) BlockContext(org.aion.zero.impl.types.BlockContext)

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