Search in sources :

Example 21 with MiningBlockHeader

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

the class ApiWeb3Aion method stratum_getHeaderByBlockNumber.

public RpcMsg stratum_getHeaderByBlockNumber(Object _params) {
    Object _blockNum;
    if (_params instanceof JSONArray) {
        _blockNum = ((JSONArray) _params).opt(0);
    } else {
        return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid parameters");
    }
    JSONObject obj = new JSONObject();
    if (!JSONObject.NULL.equals(_blockNum)) {
        String bnStr = _blockNum + "";
        try {
            int bnInt = Integer.decode(bnStr);
            Block block = getBlockRaw(bnInt);
            if (block != null && isPowBlock(block)) {
                MiningBlockHeader header = (MiningBlockHeader) block.getHeader();
                // 0 = success
                obj.put("code", 0);
                obj.put("nonce", toHexString(header.getNonce()));
                obj.put("solution", toHexString(header.getSolution()));
                obj.put("headerHash", toHexString(header.getMineHash()));
                obj.putOpt("blockHeader", header.toJSON());
            } else {
                obj.put("message", "Fail - Unable to find block" + bnStr);
                obj.put("code", -2);
            }
        } catch (Exception e) {
            obj.put("message", bnStr + " must be an integer value");
            obj.put("code", -3);
        }
    } else {
        obj.put("message", "Missing block number");
        obj.put("code", -1);
    }
    return new RpcMsg(obj);
}
Also used : MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) JSONObject(org.json.JSONObject) JSONArray(org.json.JSONArray) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) StakingBlock(org.aion.zero.impl.types.StakingBlock) JSONObject(org.json.JSONObject) Hex.toHexString(org.aion.util.conversions.Hex.toHexString)

Example 22 with MiningBlockHeader

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

the class BlockchainTestUtils method generateNewBlock.

/**
 * @param chain blockchain implementation to be populated
 * @param parent the parent block for the newly generated block
 * @param accounts existing accounts
 * @param txCount maximum number of transactions per block
 * @implNote returns {@code null} if the parent block is not part of the chain
 */
public static Block generateNewBlock(StandaloneBlockchain chain, Block parent, List<ECKey> accounts, int txCount) {
    if (!chain.isBlockStored(parent.getHash(), parent.getNumber()))
        return null;
    Block block;
    AionRepositoryImpl repo = chain.getRepository();
    List<AionTransaction> txs;
    // generate transactions for correct root
    byte[] originalRoot = repo.getRoot();
    repo.syncToRoot(parent.getStateRoot());
    txs = generateTransactions(txCount, accounts, repo);
    repo.syncToRoot(originalRoot);
    long time = System.currentTimeMillis();
    block = chain.createNewMiningBlockInternal(parent, txs, true, time / TEN_THOUSAND_MS).block;
    MiningBlockHeader newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader((MiningBlockHeader) block.getHeader()).withExtraData(String.valueOf(time).getBytes()).build();
    block.updateHeader(newBlockHeader);
    return block;
}
Also used : MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) StakingBlock(org.aion.zero.impl.types.StakingBlock) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) AionRepositoryImpl(org.aion.zero.impl.db.AionRepositoryImpl) AionTransaction(org.aion.base.AionTransaction)

Example 23 with MiningBlockHeader

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

the class BlockchainIndexIntegrityTest method testIndexIntegrityWithRecovery.

/**
 * Test the index integrity check and recovery when the index database is incorrect.
 */
@Test
public void testIndexIntegrityWithRecovery() {
    final int NUMBER_OF_BLOCKS = 5;
    // build a blockchain with a few blocks
    StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
    StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").build();
    StandaloneBlockchain chain = bundle.bc;
    Block bestBlock;
    ImportResult result;
    for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
        bestBlock = chain.getBestBlock();
        MiningBlock next = chain.createNewMiningBlock(bestBlock, Collections.emptyList(), true);
        result = chain.tryToConnect(next);
        assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
        // adding side chain
        next = chain.createNewMiningBlock(bestBlock, Collections.emptyList(), true);
        MiningBlockHeader newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader(next.getHeader()).withExtraData("other".getBytes()).build();
        next.updateHeader(newBlockHeader);
        result = chain.tryToConnect(next);
        assertThat(result).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
    }
    bestBlock = chain.getBestBlock();
    assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
    chain.getRepository().flush();
    AionRepositoryImpl repo = chain.getRepository();
    ByteArrayKeyValueDatabase indexDatabase = repo.getIndexDatabase();
    // corrupting the index at level 2
    ArrayStore<List<BlockInfo>> index = Stores.newArrayStore(indexDatabase, BLOCK_INFO_SERIALIZER);
    List<BlockInfo> infos = index.get(2);
    assertThat(infos.size()).isEqualTo(2);
    for (BlockInfo bi : infos) {
        bi.setTotalDifficulty(bi.getTotalDifficulty().add(BigInteger.TEN));
    }
    index.set(2, infos);
    AionBlockStore blockStore = repo.getBlockStore();
    // check that the index recovery succeeded
    assertThat(blockStore.indexIntegrityCheck()).isEqualTo(AionBlockStore.IntegrityCheckResult.FIXED);
}
Also used : ImportResult(org.aion.zero.impl.core.ImportResult) AionRepositoryImpl(org.aion.zero.impl.db.AionRepositoryImpl) AionBlockStore(org.aion.zero.impl.db.AionBlockStore) MiningBlock(org.aion.zero.impl.types.MiningBlock) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) ByteArrayKeyValueDatabase(org.aion.db.impl.ByteArrayKeyValueDatabase) BlockInfo(org.aion.zero.impl.db.AionBlockStore.BlockInfo) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) List(java.util.List) Test(org.junit.Test)

Example 24 with MiningBlockHeader

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

the class BlockchainTestUtils method addMiningBlock.

private static Pair<Block, ImportResult> addMiningBlock(StandaloneBlockchain chain, Block parent, List<AionTransaction> txs, long time, byte[] extraData) {
    MiningBlock block = chain.createNewMiningBlockInternal(parent, txs, true, time / TEN_THOUSAND_MS).block;
    MiningBlockHeader newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader(block.getHeader()).withExtraData(extraData).build();
    block.updateHeader(newBlockHeader);
    ImportResult result = chain.tryToConnect(block);
    System.out.format("Created block with hash: %s, number: %6d, extra data: %6s, txs: %3d, import status: %20s %n", block.getShortHash(), block.getNumber(), new String(block.getExtraData()), block.getTransactionsList().size(), result.toString());
    return Pair.of(block, result);
}
Also used : MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) ImportResult(org.aion.zero.impl.core.ImportResult) MiningBlock(org.aion.zero.impl.types.MiningBlock)

Example 25 with MiningBlockHeader

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

the class BlockchainDataRecoveryTest method testRecoverIndexWithPartialIndex_ShorterSideChain.

/**
 * Test the recovery of the index with start from the index of an ancestor block.
 */
@Test
public void testRecoverIndexWithPartialIndex_ShorterSideChain() {
    final int EVEN_NUMBER_OF_BLOCKS = NUMBER_OF_BLOCKS % 2 == 0 ? NUMBER_OF_BLOCKS : NUMBER_OF_BLOCKS + 1;
    // 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;
    // adding common blocks
    long time = System.currentTimeMillis();
    for (int i = 0; i < EVEN_NUMBER_OF_BLOCKS / 2 - 1; 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);
    }
    // splitting chains
    Block mainChainBlock, sideChainBlock;
    mainChainBlock = chain.getBestBlock();
    sideChainBlock = mainChainBlock;
    txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, accounts, repo);
    context = chain.createNewMiningBlockInternal(mainChainBlock, txs, true, time / 10000L);
    assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
    mainChainBlock = context.block;
    // starting side chain
    txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, accounts, repo);
    context = chain.createNewMiningBlockInternal(sideChainBlock, txs, true, time / 10000L);
    MiningBlockHeader newHeader = MiningBlockHeader.Builder.newInstance().withHeader(context.block.getHeader()).withExtraData("other".getBytes()).build();
    context.block.updateHeader(newHeader);
    assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
    sideChainBlock = context.block;
    // building chains; sidechain will have missing index
    Map<Long, byte[]> blocksToDelete = new HashMap<>();
    List<MiningBlock> blocksToImportMainChain = new ArrayList<>();
    List<MiningBlock> blocksToImportSideChain = new ArrayList<>();
    for (int i = 0; i < EVEN_NUMBER_OF_BLOCKS / 2 - 1; i++) {
        txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, accounts, repo);
        context = chain.createNewMiningBlockInternal(mainChainBlock, txs, true, time / 10000L);
        assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
        mainChainBlock = context.block;
        blocksToImportMainChain.add(context.block);
        // adding side chain
        txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, accounts, repo);
        context = chain.createNewMiningBlockInternal(sideChainBlock, txs, true, time / 10000L);
        assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
        sideChainBlock = context.block;
        blocksToDelete.put(sideChainBlock.getNumber(), sideChainBlock.getHash());
        blocksToImportSideChain.add(context.block);
    }
    // making the main chain longer
    txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, accounts, repo);
    context = chain.createNewMiningBlockInternal(mainChainBlock, txs, true, time / 10000L);
    assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
    mainChainBlock = context.block;
    Block bestBlock = chain.getBestBlock();
    assertThat(bestBlock.getNumber()).isEqualTo(EVEN_NUMBER_OF_BLOCKS);
    assertThat(bestBlock.getHash()).isEqualTo(mainChainBlock.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();
    }
    // call the recovery functionality for the main chain subsection
    boolean worked = chain.recoverIndexEntry(repo, chain.getBlockByHash(mainChainBlock.getParentHash()));
    // ensure that the index was corrupted only for the side chain
    assertThat(repo.isIndexed(sideChainBlock.getHash(), sideChainBlock.getNumber())).isFalse();
    assertThat(repo.isIndexed(mainChainBlock.getHash(), mainChainBlock.getNumber())).isTrue();
    assertThat(worked).isTrue();
    // call the recovery functionality
    worked = chain.recoverIndexEntry(repo, sideChainBlock);
    // ensure that the blockchain is ok
    assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
    // ensure that the index was recovered
    assertThat(worked).isTrue();
    assertThat(repo.isIndexed(sideChainBlock.getHash(), sideChainBlock.getNumber())).isTrue();
    // check that the index information is correct
    for (Map.Entry<Long, byte[]> entry : blocksToDelete.entrySet()) {
        long level = entry.getKey();
        byte[] hash = entry.getValue();
        // checking at block store level
        assertThat(repo.isIndexed(hash, level)).isTrue();
        // checking at database level
        byte[] indexKey = ByteUtil.intToBytes(entry.getKey().intValue());
        // NOTE: this checks the correction of both main chain and side chain recovery
        assertThat(deletedInfo.get(level)).isEqualTo(indexDatabase.get(indexKey).get());
    }
    // 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();
    }
    // call the recovery functionality indirectly for main chain
    for (MiningBlock block : blocksToImportMainChain) {
        // 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 index was corrupted only for the side chain
    assertThat(repo.isIndexed(sideChainBlock.getHash(), sideChainBlock.getNumber())).isFalse();
    assertThat(repo.isIndexed(mainChainBlock.getHash(), mainChainBlock.getNumber())).isTrue();
    // call the recovery functionality indirectly for side chain
    for (MiningBlock block : blocksToImportSideChain) {
        // 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 index was corrupted only for the side chain
    assertThat(repo.isIndexed(sideChainBlock.getHash(), sideChainBlock.getNumber())).isTrue();
    assertThat(repo.isIndexed(mainChainBlock.getHash(), mainChainBlock.getNumber())).isTrue();
    // ensure that the blockchain is ok
    assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
    // 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());
        // NOTE: this checks the correction of both main chain and side chain recovery
        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) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) 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)

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