Beispiel #1
0
        public async Task <ResultWrapper <BlockRequestResult?> > HandleAsync(AssembleBlockRequest request)
        {
            BlockHeader?parentHeader = _blockTree.FindHeader(request.ParentHash);

            if (parentHeader is null)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Parent block {request.ParentHash} cannot be found. New block will not be produced.");
                }
                return(ResultWrapper <BlockRequestResult?> .Success(null));
            }

            _timestamper.Set(DateTimeOffset.FromUnixTimeSeconds((long)request.Timestamp).UtcDateTime);
            using CancellationTokenSource cts = new(_timeout);
            Block?block = await _blockProductionTrigger.BuildBlock(parentHeader, cts.Token);

            if (block == null)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Block production on parent {request.ParentHash} with timestamp {request.Timestamp} failed.");
                }
                return(ResultWrapper <BlockRequestResult?> .Success(null));
            }
            else
            {
                return(ResultWrapper <BlockRequestResult?> .Success(new BlockRequestResult(block)));
            }
        }
Beispiel #2
0
    public override void InitializeFeed()
    {
        _chainMerged = false;

        // First, we assume pivot
        _pivotNumber    = _pivot.PivotNumber;
        _nextHeaderHash = _pivot.PivotHash ?? Keccak.Zero;
        _nextHeaderDiff = _poSSwitcher.FinalTotalDifficulty;

        // This is probably whats going to happen. We probably should just set the pivot directly to the parent of FcU head,
        // but pivot underlying data is a Header, which we may not have. Maybe later we'll clean this up.
        if (_pivot.PivotParentHash != null)
        {
            _pivotNumber    = _pivotNumber - 1;
            _nextHeaderHash = _pivot.PivotParentHash;
        }

        long startNumber = _pivotNumber;

        // In case we already have beacon sync happened before
        BlockHeader?lowestInserted = LowestInsertedBlockHeader;

        if (lowestInserted != null && lowestInserted.Number <= _pivotNumber)
        {
            startNumber     = lowestInserted.Number - 1;
            _nextHeaderHash = lowestInserted.ParentHash ?? Keccak.Zero;
            _nextHeaderDiff = lowestInserted.TotalDifficulty - lowestInserted.Difficulty;
        }

        // the base class with starts with _lowestRequestedHeaderNumber - 1, so we offset it here.
        _lowestRequestedHeaderNumber = startNumber + 1;

        _logger.Info($"Initialized beacon headers sync. lowestRequestedHeaderNumber: {_lowestRequestedHeaderNumber}," +
                     $"lowestInsertedBlockHeader: {lowestInserted?.ToString(BlockHeader.Format.FullHashAndNumber)}, pivotNumber: {_pivotNumber}, pivotDestination: {_pivot.PivotDestinationNumber}");
    }
        public ResultWrapper <Result> Handle(Keccak request)
        {
            BlockHeader?blockHeader = _blockFinder.FindHeader(request, BlockTreeLookupOptions.None);

            if (blockHeader is null)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Block {request} not found for finalization.");
                }
                return(ResultWrapper <Result> .Success(Result.Fail));
            }

            BlockHeader?headHeader = _blockFinder.Head?.Header;

            if (headHeader is null)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Can't finalize block {request}. Head is null.");
                }
                return(ResultWrapper <Result> .Success(Result.Fail));
            }

            _manualBlockFinalizationManager.MarkFinalized(headHeader, blockHeader);
            return(ResultWrapper <Result> .Success(Result.Ok));
        }
Beispiel #4
0
        public Task <Block?> BuildBlock(BlockHeader?parentHeader = null, CancellationToken?cancellationToken = null, IBlockTracer?blockTracer = null)
        {
            BlockProductionEventArgs args = new(parentHeader, cancellationToken, blockTracer);

            TriggerBlockProduction?.Invoke(this, args);
            return(args.BlockProductionTask);
        }
Beispiel #5
0
        private GethLikeTxTrace[] TraceBlock(Block?block, GethTraceOptions options, CancellationToken cancellationToken, Keccak?txHash = null)
        {
            if (block == null)
            {
                throw new InvalidOperationException("Only canonical, historical blocks supported");
            }

            if (!block.IsGenesis)
            {
                BlockHeader?parent = _blockTree.FindParentHeader(block.Header, BlockTreeLookupOptions.None);
                if (parent?.Hash is null)
                {
                    throw new InvalidOperationException("Cannot trace blocks with invalid parents");
                }

                if (!_blockTree.IsMainChain(parent.Hash))
                {
                    throw new InvalidOperationException("Cannot trace orphaned blocks");
                }
            }

            GethLikeBlockTracer listener = txHash == null ? new GethLikeBlockTracer(options) : new GethLikeBlockTracer(txHash, options);

            _processor.Process(block, ProcessingOptions.Trace, listener.WithCancellation(cancellationToken));
            return(listener.BuildResult().ToArray());
        }
Beispiel #6
0
        public static SearchResult <Block> SearchForBlock(this IBlockFinder blockFinder, BlockParameter blockParameter, bool allowNulls = false)
        {
            Block block;

            if (blockParameter.RequireCanonical)
            {
                block = blockFinder.FindBlock(blockParameter.BlockHash, BlockTreeLookupOptions.RequireCanonical);
                if (block == null && !allowNulls)
                {
                    BlockHeader?header = blockFinder.FindHeader(blockParameter.BlockHash);
                    if (header != null)
                    {
                        return(new SearchResult <Block>($"{blockParameter.BlockHash} block is not canonical", ErrorCodes.InvalidInput));
                    }
                }
            }
            else
            {
                block = blockFinder.FindBlock(blockParameter);
            }

            return(block == null && !allowNulls
                ? new SearchResult <Block>($"Block {blockParameter.BlockHash?.ToString() ?? blockParameter.BlockNumber?.ToString() ?? blockParameter.Type.ToString()} could not be found", ErrorCodes.ResourceNotFound)
                : new SearchResult <Block>(block));
        }
Beispiel #7
0
    private async void BuildAndProcessHeaderSyncBatches(
        Context ctx,
        BlockTree blockTree,
        BlockTree syncedBlockTree,
        IBeaconPivot pivot,
        long bestPointer,
        long endLowestBeaconHeader)
    {
        ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeTrue();
        blockTree.BestKnownNumber.Should().Be(bestPointer);
        BlockHeader?startBestHeader = syncedBlockTree.FindHeader(bestPointer, BlockTreeLookupOptions.None);

        blockTree.BestSuggestedHeader.Should().BeEquivalentTo(startBestHeader);
        blockTree.LowestInsertedBeaconHeader.Should().BeEquivalentTo(syncedBlockTree.FindHeader(pivot.PivotNumber, BlockTreeLookupOptions.None));

        BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, endLowestBeaconHeader);

        HeadersSyncBatch result = await ctx.Feed.PrepareRequest();

        result.Should().BeNull();
        // check headers are inserted into block tree during sync
        blockTree.FindHeader(pivot.PivotNumber - 1, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Should().NotBeNull();
        blockTree.LowestInsertedBeaconHeader?.Hash.Should().BeEquivalentTo(syncedBlockTree.FindHeader(endLowestBeaconHeader, BlockTreeLookupOptions.None)?.Hash);
        blockTree.BestKnownNumber.Should().Be(bestPointer);
        blockTree.BestSuggestedHeader.Should().BeEquivalentTo(startBestHeader);
        ctx.Feed.CurrentState.Should().Be(SyncFeedState.Dormant);
        ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeFalse();
    }
Beispiel #8
0
    private async void BuildHeadersSyncBatches(
        Context ctx,
        BlockTree blockTree,
        BlockTree syncedBlockTree,
        IBeaconPivot pivot,
        long endLowestBeaconHeader)
    {
        ctx.Feed.InitializeFeed();
        long lowestHeaderNumber = pivot.PivotNumber;

        while (lowestHeaderNumber > endLowestBeaconHeader)
        {
            HeadersSyncBatch batch = await ctx.Feed.PrepareRequest();

            batch.Should().NotBeNull();
            BuildHeadersSyncBatchResponse(batch, syncedBlockTree);
            ctx.Feed.HandleResponse(batch);
            lowestHeaderNumber = lowestHeaderNumber - batch.RequestSize < endLowestBeaconHeader
                ? endLowestBeaconHeader
                : lowestHeaderNumber - batch.RequestSize;

            BlockHeader?lowestHeader = syncedBlockTree.FindHeader(lowestHeaderNumber, BlockTreeLookupOptions.None);
            blockTree.LowestInsertedBeaconHeader?.Hash.Should().BeEquivalentTo(lowestHeader?.Hash);
        }
    }
Beispiel #9
0
    public async Task Feed_able_to_sync_when_new_pivot_is_set()
    {
        BlockTree syncedBlockTree = Build.A.BlockTree().OfChainLength(1000).TestObject;
        Block     genesisBlock    = syncedBlockTree.FindBlock(syncedBlockTree.GenesisHash, BlockTreeLookupOptions.None) !;
        BlockTree blockTree       = Build.A.BlockTree().TestObject;

        blockTree.SuggestBlock(genesisBlock);
        ISyncConfig syncConfig = new SyncConfig
        {
            FastSync             = true,
            FastBlocks           = true,
            PivotNumber          = "500",
            PivotHash            = Keccak.Zero.ToString(),
            PivotTotalDifficulty = "1000000" // default difficulty in block tree builder
        };
        BlockHeader? pivotHeader = syncedBlockTree.FindHeader(700, BlockTreeLookupOptions.None);
        IBeaconPivot pivot       = PreparePivot(700, syncConfig, blockTree, pivotHeader);
        Context      ctx         = new (blockTree, syncConfig, pivot);

        BuildAndProcessHeaderSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 0, 501);

        // move best pointers forward as proxy for chain merge
        Block highestBlock = syncedBlockTree.FindBlock(700, BlockTreeLookupOptions.None) !;

        blockTree.Insert(highestBlock, BlockTreeInsertBlockOptions.SaveHeader);

        pivot.EnsurePivot(syncedBlockTree.FindHeader(900, BlockTreeLookupOptions.None));
        BuildAndProcessHeaderSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 700, 701);

        highestBlock = syncedBlockTree.FindBlock(900, BlockTreeLookupOptions.None) !;
        blockTree.Insert(highestBlock, BlockTreeInsertBlockOptions.SaveHeader);
        pivot.EnsurePivot(syncedBlockTree.FindHeader(999, BlockTreeLookupOptions.None));
        BuildAndProcessHeaderSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 900, 901);
    }
Beispiel #10
0
    public async Task Feed_able_to_connect_to_existing_chain_through_block_hash()
    {
        BlockTree syncedBlockTree = Build.A.BlockTree().OfChainLength(600).TestObject;
        Block     genesisBlock    = syncedBlockTree.FindBlock(syncedBlockTree.GenesisHash, BlockTreeLookupOptions.None) !;
        BlockTree blockTree       = Build.A.BlockTree().TestObject;

        blockTree.SuggestBlock(genesisBlock);
        Block?firstBlock = syncedBlockTree.FindBlock(1, BlockTreeLookupOptions.None);

        blockTree.SuggestBlock(firstBlock);
        BlockHeader? pivotHeader = syncedBlockTree.FindHeader(500, BlockTreeLookupOptions.None);
        IBeaconPivot pivot       = PreparePivot(500, new SyncConfig(), blockTree, pivotHeader);
        Context      ctx         = new (blockTree, new SyncConfig(), pivot);
        // fork in chain
        Block parent = firstBlock;

        for (int i = 0; i < 5; i++)
        {
            Block block = Build.A.Block.WithParent(parent).WithNonce(1).TestObject;
            blockTree.SuggestBlock(block);
            parent = block;
        }

        ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeTrue();
        blockTree.BestKnownNumber.Should().Be(6);
        BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 2);
        HeadersSyncBatch result = await ctx.Feed.PrepareRequest();

        result.Should().BeNull();
        blockTree.BestKnownNumber.Should().Be(6);
        ctx.Feed.CurrentState.Should().Be(SyncFeedState.Dormant);
        ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeFalse();
    }
        private Address GetContractAddress(BlockHeader?header)
        {
            bool needUpdate = false;

            lock (_currentHashAddress)
            {
                needUpdate = header != null && _currentHashAddress != header.Hash;
            }

            if (needUpdate)
            {
                if (_registerContract.TryGetAddress(header, _registryKey, out Address contractAddress))
                {
                    lock (_currentHashAddress)
                    {
                        ContractAddress     = contractAddress;
                        _currentHashAddress = header.Hash !;
                    }
                }

                return(contractAddress);
            }

            return(ContractAddress);
        }
Beispiel #12
0
        public uint GetNextWorkRequired(HeaderNode previousHeaderNode, BlockHeader header)
        {
            if (previousHeaderNode == null)
            {
                ThrowHelper.ThrowArgumentNullException(nameof(previousHeaderNode));
            }

            if (!_blockHeaderRepository.TryGet(previousHeaderNode.Hash, out BlockHeader? previousHeader))
            {
                //this should never happens, if it happens means we have consistency problem (we lost an header)
                ThrowHelper.ThrowArgumentNullException(nameof(previousHeaderNode));
            }

            uint proofOfWorkLimit             = _consensusParameters.PowLimit.ToCompact();
            int  difficultyAdjustmentInterval = (int)GetDifficultyAdjustmentInterval();

            // Only change once per difficulty adjustment interval
            if ((previousHeaderNode.Height + 1) % difficultyAdjustmentInterval != 0)
            {
                if (_consensusParameters.PowAllowMinDifficultyBlocks)
                {
                    /// Special difficulty rule for test networks:
                    /// if the new block's timestamp is more than 2 times the PoWTargetSpacing then allow mining of a min-difficulty block.
                    if (header.TimeStamp > (previousHeader.TimeStamp + (_consensusParameters.PowTargetSpacing * 2)))
                    {
                        return(proofOfWorkLimit);
                    }
                    else
                    {
                        // Return the last non-special-min-difficulty-rules-block.
                        HeaderNode  currentHeaderNode = previousHeaderNode;
                        BlockHeader currentHeader     = previousHeader;
                        while (currentHeaderNode.Previous != null &&
                               (currentHeaderNode.Height % difficultyAdjustmentInterval) != 0 &&
                               _blockHeaderRepository.TryGet(currentHeaderNode.Hash, out currentHeader !) && currentHeader.Bits == proofOfWorkLimit
                               )
                        {
                            currentHeaderNode = currentHeaderNode.Previous;
                        }

                        return(currentHeader.Bits);
                    }
                }

                return(previousHeader.Bits);
            }

            // Go back by what we want to be 14 days worth of blocks
            int        heightReference     = previousHeaderNode.Height - (difficultyAdjustmentInterval - 1);
            HeaderNode?headerNodeReference = previousHeaderNode.GetAncestor(heightReference);

            BlockHeader?headerReference = null;

            if (headerNodeReference == null || !_blockHeaderRepository.TryGet(headerNodeReference.Hash, out headerReference))
            {
                ThrowHelper.ThrowNotSupportedException("Header ancestor not found, PoW required work computation requires a full chain.");
            }

            return(CalculateNextWorkRequired(previousHeader, headerReference.TimeStamp));
        }
        private bool TryPrepareReceipts(BlockInfo blockInfo, TxReceipt[] receipts, out TxReceipt[]?preparedReceipts)
        {
            BlockHeader?header = _blockTree.FindHeader(blockInfo.BlockHash);

            if (header == null)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn("Could not find header for requested blockhash.");
                }
                preparedReceipts = null;
            }
            else
            {
                if (header.ReceiptsRoot == Keccak.EmptyTreeHash)
                {
                    preparedReceipts = receipts.Length == 0 ? receipts : null;
                }
                else
                {
                    Keccak receiptsRoot = new ReceiptTrie(blockInfo.BlockNumber, _specProvider, receipts).RootHash;
                    if (receiptsRoot != header.ReceiptsRoot)
                    {
                        preparedReceipts = null;
                    }
                    else
                    {
                        preparedReceipts = receipts;
                    }
                }
            }

            return(preparedReceipts != null);
        }
Beispiel #14
0
        private bool TryPrepareReceipts(BlockInfo blockInfo, TxReceipt[] receipts, out TxReceipt[]?preparedReceipts)
        {
            BlockHeader?header = _blockTree.FindHeader(blockInfo.BlockHash);

            if (header == null)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn("Could not find header for requested blockhash.");
                }
                preparedReceipts = null;
            }
            else
            {
                if (header.ReceiptsRoot == Keccak.EmptyTreeHash)
                {
                    preparedReceipts = receipts.Length == 0 ? receipts : null;
                }
                else
                {
                    IReleaseSpec releaseSpec = _specProvider.GetSpec(blockInfo.BlockNumber);
                    preparedReceipts = receipts.GetReceiptsRoot(releaseSpec, header.ReceiptsRoot) != header.ReceiptsRoot
                        ? null
                        : receipts;
                }
            }

            return(preparedReceipts != null);
        }
Beispiel #15
0
 public Block With(BlockHeader?Header = null, ImmutableArray <Transaction>?Transactions = null)
 {
     return(new Block
            (
                Header ?? this.Header,
                Transactions ?? this.Transactions
            ));
 }
 public BlockProductionEventArgs(
     BlockHeader?parentHeader            = null,
     CancellationToken?cancellationToken = null,
     IBlockTracer?blockTracer            = null)
 {
     ParentHeader      = parentHeader;
     BlockTracer       = blockTracer;
     CancellationToken = cancellationToken ?? CancellationToken.None;
 }
Beispiel #17
0
        /// <summary>
        /// Rough header memory size estimator
        /// </summary>
        /// <param name="header"></param>
        /// <returns></returns>
        public static long EstimateSize(BlockHeader?header)
        {
            if (header == null)
            {
                return(8);
            }

            return(1212 + (header.ExtraData?.Length ?? 0));
        }
Beispiel #18
0
    public static int Compare(this IBetterPeerStrategy peerStrategy, BlockHeader?header, ISyncPeer?peerInfo)
    {
        UInt256 headerDifficulty = header?.TotalDifficulty ?? UInt256.Zero;
        long    headerNumber     = header?.Number ?? 0;

        UInt256 peerDifficulty     = peerInfo?.TotalDifficulty ?? UInt256.Zero;
        long    peerInfoHeadNumber = peerInfo?.HeadNumber ?? 0;

        return(peerStrategy.Compare((headerDifficulty, headerNumber), (peerDifficulty, peerInfoHeadNumber)));
    }
Beispiel #19
0
 public BlockProductionEventArgs(
     BlockHeader?parentHeader            = null,
     CancellationToken?cancellationToken = null,
     IBlockTracer?blockTracer            = null,
     PayloadAttributes?payloadAttributes = null)
 {
     ParentHeader      = parentHeader;
     BlockTracer       = blockTracer;
     PayloadAttributes = payloadAttributes;
     CancellationToken = cancellationToken ?? CancellationToken.None;
 }
Beispiel #20
0
        /// <summary>
        /// The consumer that perform validation.
        /// </summary>
        /// <param name="cancellation">The cancellation.</param>
        private async Task ValidationWorkAsync(CancellationToken cancellation)
        {
            await foreach (HeadersToValidate request in _headersToValidate.Reader.ReadAllAsync(cancellation))
            {
                if (request.Headers.Count == 0)
                {
                    continue;                         //if there aren't headers to validate, ignore the request
                }
                _logger.LogDebug("Validating {HeadersCount} headers", request.Headers.Count);

                var newValidatedHeaderNodes = new List <HeaderNode>();

                HeaderNode?          lastValidatedHeaderNode  = null;
                BlockHeader?         lastValidatedBlockHeader = null;
                BlockValidationState?state = null;
                BlockHeader?         invalidBlockHeader = null;

                /// If during validation a new header is found, this will be set to true.
                /// Once a new header is found, every other new header is expected to be new too
                /// because we don't store unconnecting headers.
                //bool hasNewHeaders = false;

                int validatedHeaders = 0;

                using (await GlobalLocks.WriteOnMainAsync())
                {
                    foreach (BlockHeader header in request.Headers)
                    {
                        using (_logger.BeginScope("Validating header {ValidationRuleType}", header !.Hash))
                        {
                            if (!AcceptBlockHeaderLocked(header, out state, out HeaderNode? validatedHeaderNode, out bool newHeaderFound))
                            {
                                invalidBlockHeader = header;
                                break;
                            }

                            validatedHeaders++;
                            lastValidatedBlockHeader = header;
                            lastValidatedHeaderNode  = validatedHeaderNode;
                            if (newHeaderFound)
                            {
                                //hasNewHeaders = true;
                                newValidatedHeaderNodes.Add(validatedHeaderNode);
                            }
                        }
                    }
                }

                // publish events out of lock
                if (state !.IsInvalid())
                {
                    // signal header validation failed
                    _eventBus.Publish(new BlockHeaderValidationFailed(invalidBlockHeader !, state, request.Peer));
                }
        public Rlp Encode(BlockHeader?item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (item == null)
            {
                return(Rlp.OfEmptySequence);
            }

            RlpStream rlpStream = new(GetLength(item, rlpBehaviors));

            Encode(rlpStream, item, rlpBehaviors);

            return(new Rlp(rlpStream.Data));
        }
Beispiel #22
0
    private void BuildHeadersSyncBatchResponse(HeadersSyncBatch batch, IBlockTree blockTree)
    {
        batch.MarkSent();
        BlockHeader?startHeader = blockTree.FindHeader(batch.StartNumber);

        if (startHeader == null)
        {
            return;
        }

        BlockHeader[] headers = blockTree.FindHeaders(startHeader.Hash !, batch.RequestSize, 0, true);
        batch.Response = headers;
    }
Beispiel #23
0
    public void Can_insert_beacon_headers()
    {
        (BlockTree notSyncedTree, BlockTree syncedTree) = BuildBlockTrees(10, 20);

        Block?beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None);
        BlockTreeInsertHeaderOptions headerOptions = BlockTreeInsertHeaderOptions.BeaconBlockInsert;
        AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock, BlockTreeInsertBlockOptions.SaveHeader, headerOptions);

        for (int i = 13; i > 9; --i)
        {
            BlockHeader?   beaconHeader  = syncedTree.FindHeader(i, BlockTreeLookupOptions.None);
            AddBlockResult insertOutcome = notSyncedTree.Insert(beaconHeader !, headerOptions);
            Assert.AreEqual(insertOutcome, insertResult);
        }
    }
Beispiel #24
0
        public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader?parentHeader, UInt256 minGasPriceFloor)
        {
            UInt256      gasPrice    = tx.GasPrice;
            long         blockNumber = (parentHeader?.Number ?? 0) + 1;
            IReleaseSpec spec        = _specProvider.GetSpec(blockNumber);

            if (spec.IsEip1559Enabled && tx.IsEip1559)
            {
                UInt256 baseFee = BlockHeader.CalculateBaseFee(parentHeader, spec);
                gasPrice = tx.CalculateEffectiveGasPrice(true, baseFee);
            }

            bool allowed = gasPrice >= minGasPriceFloor;

            return(allowed, allowed ? string.Empty : $"gas price too low {gasPrice} < {minGasPriceFloor}");
        }
Beispiel #25
0
        public ResultWrapper <Address?> clique_getBlockSigner(Keccak?hash)
        {
            if (hash is null)
            {
                return(ResultWrapper <Address> .Fail($"Hash parameter cannot be null"));
            }

            BlockHeader?header = _blockTree.FindHeader(hash);

            if (header == null)
            {
                return(ResultWrapper <Address> .Fail($"Could not find block with hash {hash}"));
            }

            header.Author ??= _snapshotManager.GetBlockSealer(header);
            return(ResultWrapper <Address> .Success(header.Author));
        }
        public void Encode(RlpStream rlpStream, BlockHeader?header, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (header is null)
            {
                rlpStream.EncodeNullObject();
                return;
            }

            bool notForSealing = (rlpBehaviors & RlpBehaviors.ForSealing) != RlpBehaviors.ForSealing;

            rlpStream.StartSequence(GetContentLength(header, rlpBehaviors));
            rlpStream.Encode(header.ParentHash);
            rlpStream.Encode(header.UnclesHash);
            rlpStream.Encode(header.Beneficiary);
            rlpStream.Encode(header.StateRoot);
            rlpStream.Encode(header.TxRoot);
            rlpStream.Encode(header.ReceiptsRoot);
            rlpStream.Encode(header.Bloom);
            rlpStream.Encode(header.Difficulty);
            rlpStream.Encode(header.Number);
            rlpStream.Encode(header.GasLimit);
            rlpStream.Encode(header.GasUsed);
            rlpStream.Encode(header.Timestamp);
            rlpStream.Encode(header.ExtraData);

            if (notForSealing)
            {
                bool isAuRa = header.AuRaSignature != null;
                if (isAuRa)
                {
                    rlpStream.Encode(header.AuRaStep !.Value);
                    rlpStream.Encode(header.AuRaSignature);
                }
                else
                {
                    rlpStream.Encode(header.MixHash);
                    rlpStream.EncodeNonce(header.Nonce);
                }
            }

            if (header.Number >= Eip1559TransitionBlock)
            {
                rlpStream.Encode(header.BaseFeePerGas);
            }
        }
        protected virtual bool ValidateExtraData(BlockHeader header, BlockHeader?parent, IReleaseSpec spec, bool isUncle = false)
        {
            bool extraDataValid = header.ExtraData.Length <= spec.MaximumExtraDataSize &&
                                  (isUncle ||
                                   _daoBlockNumber == null ||
                                   header.Number < _daoBlockNumber ||
                                   header.Number >= _daoBlockNumber + 10 ||
                                   Bytes.AreEqual(header.ExtraData, DaoExtraData));

            if (!extraDataValid)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Invalid block header ({header.Hash}) - DAO extra data not valid. MaximumExtraDataSize {spec.MaximumExtraDataSize}, ExtraDataLength {header.ExtraData.Length}, DaoBlockNumber: {_daoBlockNumber}");
                }
            }
            return(extraDataValid);
        }
        protected override bool ValidateExtraData(BlockHeader header, BlockHeader?parent, IReleaseSpec spec, bool isUncle = false)
        {
            if (_poSSwitcher.IsPostMerge(header))
            {
                if (header.ExtraData.Length > MaxExtraDataBytes)
                {
                    if (_logger.IsWarn)
                    {
                        _logger.Warn($"Invalid block header {header.ToString(BlockHeader.Format.Short)} - the {nameof(header.ExtraData)} exceeded max length of {MaxExtraDataBytes}.");
                    }
                    return(false);
                }

                return(true);
            }

            return(base.ValidateExtraData(header, parent, spec, isUncle));
        }
        private void OnBlockProcessed(object?sender, BlockProcessedEventArgs e)
        {
            if (_logger.IsWarn)
            {
                _logger.Warn($"Tree tracker for {_baselineTree} processing block {e.Block.ToString(Block.Format.Short)}");
            }

            if (_currentBlockHeader != null && _currentBlockHeader.Hash != e.Block.ParentHash && _currentBlockHeader.Number < e.Block.Number)
            {
                // what is this - not covered by any test?
                // why do we build tree here?
                _baselineTreeHelper.BuildTree(_baselineTree, _address, new BlockParameter(_currentBlockHeader.Hash), new BlockParameter(e.Block.Hash));
                _currentBlockHeader = e.Block.Header;

                // TODO: why this is here
                _baselineTree.MemorizeCurrentCount(_baselineTree.LastBlockDbHash, _baselineTree.LastBlockWithLeaves, _baselineTree.Count);
                return;
            }

            uint removedItemsCount = 0;
            bool reorganized       = _currentBlockHeader != null && _currentBlockHeader.Hash != e.Block.ParentHash;

            if (reorganized)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn(
                        $"Tree tracker for {_baselineTree} reorganizes from branching point at {e.Block.ToString(Block.Format.Short)}");
                }
                removedItemsCount = Revert(e.Block.Number);
            }

            _currentBlockHeader = e.Block.Header;
            uint treeStartingCount = _baselineTree.Count;
            uint newLeavesCount    = AddFromCurrentBlock(e.TxReceipts);

            _baselineTree.CalculateHashes(treeStartingCount - removedItemsCount);
            if (newLeavesCount != 0 || removedItemsCount != 0 || reorganized)
            {
                uint currentTreeCount = treeStartingCount + newLeavesCount - removedItemsCount;
                _baselineTree.MemorizeCurrentCount(e.Block.Hash, e.Block.Number, currentTreeCount);
            }
        }
Beispiel #30
0
        private bool CanSuggestBlocks(Block block)
        {
            _firstBlockVisited = false;
            if (block?.ParentHash != null)
            {
                BlockHeader?parentHeader = _blockTree.FindParentHeader(block.Header, BlockTreeLookupOptions.TotalDifficultyNotNeeded);
                if (parentHeader == null || parentHeader.StateRoot == null ||
                    _stateDb.Get(parentHeader.StateRoot) == null)
                {
                    return(false);
                }
            }
            else
            {
                return(false);
            }

            return(true);
        }