Search in sources :

Example 21 with BlockHeader

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

the class AionBlockchainImpl method createNewMiningBlockInternal.

BlockContext createNewMiningBlockInternal(Block parent, List<AionTransaction> txs, boolean waitUntilBlockTime, long currTimeSeconds) {
    BlockHeader parentHdr = parent.getHeader();
    long time = currTimeSeconds;
    if (parentHdr.getTimestamp() >= time) {
        time = parentHdr.getTimestamp() + 1;
        while (waitUntilBlockTime && TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) <= time) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                break;
            }
        }
    }
    long energyLimit = this.energyLimitStrategy.getEnergyLimit(parentHdr);
    MiningBlock block;
    try {
        MiningBlockHeader.Builder headerBuilder = MiningBlockHeader.Builder.newInstance().withParentHash(parent.getHash()).withCoinbase(minerCoinbase).withNumber(parentHdr.getNumber() + 1).withTimestamp(time).withExtraData(minerExtraData).withTxTrieRoot(calcTxTrieRoot(txs)).withEnergyLimit(energyLimit).withDefaultStateRoot().withDefaultReceiptTrieRoot().withDefaultLogsBloom().withDefaultDifficulty().withDefaultNonce().withDefaultSolution();
        block = new MiningBlock(headerBuilder.build(), txs);
    } catch (Exception e) {
        LOG.error("Construct new mining block header exception:", e);
        return null;
    }
    BlockHeader parentMiningBlock;
    BlockHeader parentMiningBlocksParent = null;
    byte[] newDiff;
    IDifficultyCalculator diffCalculator;
    // so we use a strict greater than here
    if (forkUtility.isUnityForkActive(block.getNumber())) {
        if (parentHdr.getSealType() == Seal.PROOF_OF_WORK) {
            LOG.warn("Tried to create 2 PoW blocks in a row");
            return null;
        } else {
            Block[] blockFamily = repository.getBlockStore().getTwoGenerationBlocksByHashWithInfo(parentHdr.getParentHash());
            Objects.requireNonNull(blockFamily[0]);
            parentMiningBlock = blockFamily[0].getHeader();
            parentMiningBlocksParent = blockFamily[1].getHeader();
            diffCalculator = chainConfiguration.getUnityDifficultyCalculator();
        }
    } else {
        parentMiningBlock = parentHdr;
        if (!parentMiningBlock.isGenesis()) {
            parentMiningBlocksParent = getParent(parentMiningBlock).getHeader();
        }
        diffCalculator = chainConfiguration.getPreUnityDifficultyCalculator();
    }
    newDiff = ByteUtil.bigIntegerToBytes(diffCalculator.calculateDifficulty(parentMiningBlock, parentMiningBlocksParent), DIFFICULTY_BYTES);
    block.updateHeaderDifficulty(newDiff);
    BigInteger totalTransactionFee = blockPreSeal(parentHdr, block);
    if (totalTransactionFee == null) {
        return null;
    }
    // derive base block reward
    BigInteger baseBlockReward;
    if (forkUtility.isSignatureSwapForkActive(block.getNumber())) {
        baseBlockReward = TimeVaryingRewardsCalculator.calculateReward(block.getTimestamp() - parentHdr.getTimestamp());
    } else {
        baseBlockReward = this.chainConfiguration.getRewardsCalculatorBeforeSignatureSchemeSwap(forkUtility.isUnityForkActive(block.getNumber())).calculateReward(block.getNumber());
    }
    return new BlockContext(block, baseBlockReward, totalTransactionFee);
}
Also used : BlockContext(org.aion.zero.impl.types.BlockContext) MiningBlock(org.aion.zero.impl.types.MiningBlock) IDifficultyCalculator(org.aion.zero.impl.core.IDifficultyCalculator) VmFatalException(org.aion.zero.impl.vm.common.VmFatalException) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) 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) BigInteger(java.math.BigInteger) BlockHeader(org.aion.zero.impl.types.BlockHeader) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) StakingBlockHeader(org.aion.zero.impl.types.StakingBlockHeader)

Example 22 with BlockHeader

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

the class TaskValidateAndAddBlocks method run.

@Override
public void run() {
    // TODO: re-evaluate priority when full functionality is implemented
    Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
    Block firstBlock = response.getBlocks().get(0);
    Thread.currentThread().setName("check-" + displayId + "-" + firstBlock.getShortHash());
    // log start of operation
    if (log.isDebugEnabled()) {
        log.debug("Starting block validation from peer={}, start-block={}, batch-size={}.", displayId, firstBlock.getShortHash(), response.getBlocks().size());
    }
    List<Block> filtered = new ArrayList<>();
    List<ByteArrayWrapper> batchHashes = new ArrayList<>();
    BlockHeader currentHeader, previousHeader = null;
    for (Block currentBlock : response.getBlocks()) {
        ByteArrayWrapper hash = currentBlock.getHashWrapper();
        if (// exclude imported
        importedBlockHashes.containsKey(hash) || receivedBlockHashes.containsKey(hash)) {
            // exclude known hashes
            previousHeader = currentBlock.getHeader();
            continue;
        }
        currentHeader = currentBlock.getHeader();
        // TODO: we could do partial evaluations here (as per fast sync specs)
        if (!this.blockHeaderValidator.validate(currentHeader, log)) {
            if (log.isDebugEnabled()) {
                log.debug("<invalid-header num={} hash={} from peer={}/{}>", currentHeader.getNumber(), currentHeader.getHash(), displayId, peerId);
            }
            if (log.isTraceEnabled()) {
                log.debug("<invalid-header: {}>", currentHeader.toString());
            }
            return;
        }
        // ignore batch if not ordered correctly
        if (previousHeader != null && (currentHeader.getNumber() != (previousHeader.getNumber() - 1) || !Arrays.equals(previousHeader.getParentHash(), currentHeader.getHash()))) {
            log.debug("<inconsistent-block-headers num={}, prev-1={}, p_hash={}, prev={} from peer={}/{}>", currentHeader.getNumber(), previousHeader.getNumber() - 1, ByteUtil.toHexString(previousHeader.getParentHash()), ByteUtil.toHexString(currentHeader.getHash()), displayId, peerId);
            return;
        }
        filtered.add(currentBlock);
        previousHeader = currentHeader;
        batchHashes.add(hash);
    }
    if (!filtered.isEmpty()) {
        ByteArrayWrapper first = batchHashes.get(0);
        downloadedBlocks.offer(new BlocksWrapper(peerId, displayId, filtered));
        batchHashes.forEach(k -> receivedBlockHashes.put(k, first));
    }
    // log end of operation
    if (log.isDebugEnabled()) {
        log.debug("Completed block validation from peer={}, start-block={}, batch-size={} with filtered-size={}.", displayId, firstBlock.getShortHash(), response.getBlocks().size(), filtered.size());
    }
}
Also used : ByteArrayWrapper(org.aion.util.types.ByteArrayWrapper) ArrayList(java.util.ArrayList) Block(org.aion.zero.impl.types.Block) BlockHeader(org.aion.zero.impl.types.BlockHeader)

Example 23 with BlockHeader

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

the class ReqBlocksHeadersHandler method receive.

@Override
public void receive(int _nodeIdHashcode, String _displayId, final byte[] _msgBytes) {
    if (isSyncOnlyNode) {
        return;
    }
    ReqBlocksHeaders reqHeaders = ReqBlocksHeaders.decode(_msgBytes);
    if (reqHeaders != null) {
        long fromBlock = reqHeaders.getFromBlock();
        int take = reqHeaders.getTake();
        if (log.isDebugEnabled()) {
            this.log.debug("<req-headers from-number={} size={} node={}>", fromBlock, take, _displayId);
        }
        List<BlockHeader> headers = this.blockchain.getListOfHeadersStartFrom(fromBlock, Math.min(take, MAX_NUM_OF_BLOCKS));
        ResBlocksHeaders rbhs = new ResBlocksHeaders(headers);
        this.p2pMgr.send(_nodeIdHashcode, _displayId, rbhs);
    } else {
        this.log.error("<req-headers decode-error msg-bytes={} node={}>", _msgBytes == null ? 0 : _msgBytes.length, _nodeIdHashcode);
    }
}
Also used : ResBlocksHeaders(org.aion.zero.impl.sync.msg.ResBlocksHeaders) ReqBlocksHeaders(org.aion.zero.impl.sync.msg.ReqBlocksHeaders) BlockHeader(org.aion.zero.impl.types.BlockHeader)

Example 24 with BlockHeader

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

the class SyncMgr method validateAndAddBlocks.

/**
 * @param _nodeIdHashcode int
 * @param _displayId String
 * @param _bodies List<byte[]> Assemble and validate blocks batch and add batch to import queue
 *     from network response blocks bodies
 */
public void validateAndAddBlocks(int _nodeIdHashcode, String _displayId, final List<SharedRLPList> _bodies) {
    if (_bodies == null)
        return;
    log.debug("<received-bodies size={} node={}>", _bodies.size(), _displayId);
    // the requests are made such that the size varies to better map headers to bodies
    ByteArrayWrapper firstNodeRoot = ByteArrayWrapper.wrap(BlockUtil.getTxTrieRootFromUnsafeSource(_bodies.get(0)));
    List<BlockHeader> headers = syncHeaderRequestManager.matchAndDropHeaders(_nodeIdHashcode, _bodies.size(), firstNodeRoot);
    if (headers == null) {
        log.debug("<assemble-and-validate-blocks could not match headers for node={} size={} txTrieRoot={}>", _displayId, _bodies.size(), firstNodeRoot);
        return;
    }
    // assemble batch
    List<Block> blocks = new ArrayList<>(_bodies.size());
    Iterator<BlockHeader> headerIt = headers.iterator();
    Iterator<SharedRLPList> bodyIt = _bodies.iterator();
    while (headerIt.hasNext() && bodyIt.hasNext()) {
        Block block = BlockUtil.newBlockWithHeaderFromUnsafeSource(headerIt.next(), (SharedRLPList) bodyIt.next().get(0));
        if (block == null) {
            log.debug("<assemble-and-validate-blocks node={} size={}>", _displayId, _bodies.size());
            break;
        } else {
            blocks.add(block);
        }
    }
    int m = blocks.size();
    if (m == 0) {
        return;
    }
    log.debug("<assembled-blocks from={} size={} node={}>", blocks.get(0).getNumber(), blocks.size(), _displayId);
    // add batch
    syncExecutors.execute(() -> filterBlocks(new BlocksWrapper(_nodeIdHashcode, _displayId, blocks)));
}
Also used : ByteArrayWrapper(org.aion.util.types.ByteArrayWrapper) ArrayList(java.util.ArrayList) Block(org.aion.zero.impl.types.Block) BlockHeader(org.aion.zero.impl.types.BlockHeader) SharedRLPList(org.aion.rlp.SharedRLPList)

Example 25 with BlockHeader

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

the class ResBlocksHeaders method decode.

public static ResBlocksHeaders decode(final byte[] _msgBytes, Logger logger) {
    if (_msgBytes == null || _msgBytes.length == 0)
        return null;
    else {
        try {
            SharedRLPList list = (SharedRLPList) RLP.decode2SharedList(_msgBytes).get(0);
            List<BlockHeader> blockHeaders = new ArrayList<>();
            for (RLPElement aList : list) {
                blockHeaders.add(BlockUtil.newHeaderFromUnsafeSource((SharedRLPList) aList));
            }
            return new ResBlocksHeaders(blockHeaders);
        } catch (Exception ex) {
            if (logger != null) {
                logger.debug("ResBlocksHeaders decode failed!", ex);
            }
            return null;
        }
    }
}
Also used : RLPElement(org.aion.rlp.RLPElement) ArrayList(java.util.ArrayList) BlockHeader(org.aion.zero.impl.types.BlockHeader) SharedRLPList(org.aion.rlp.SharedRLPList)

Aggregations

BlockHeader (org.aion.zero.impl.types.BlockHeader)29 Test (org.junit.Test)18 ArrayList (java.util.ArrayList)17 MiningBlockHeader (org.aion.zero.impl.types.MiningBlockHeader)14 ReqBlocksBodies (org.aion.zero.impl.sync.msg.ReqBlocksBodies)8 Block (org.aion.zero.impl.types.Block)7 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)4 BigInteger (java.math.BigInteger)3 EventBlock (org.aion.evtmgr.impl.evt.EventBlock)3 INode (org.aion.p2p.INode)3 SharedRLPList (org.aion.rlp.SharedRLPList)3 GenesisStakingBlock (org.aion.zero.impl.types.GenesisStakingBlock)3 MiningBlock (org.aion.zero.impl.types.MiningBlock)3 RetValidPreBlock (org.aion.zero.impl.types.RetValidPreBlock)3 StakingBlock (org.aion.zero.impl.types.StakingBlock)3 StakingBlockHeader (org.aion.zero.impl.types.StakingBlockHeader)3 BlockDetailsValidator.isValidBlock (org.aion.zero.impl.valid.BlockDetailsValidator.isValidBlock)3 List (java.util.List)2 ByteArrayWrapper (org.aion.util.types.ByteArrayWrapper)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1