Exemplo n.º 1
0
        /// <summary>
        /// Suggested block validation runs basic checks that can be executed before going through the expensive EVM processing.
        /// </summary>
        /// <param name="block">A block to validate</param>
        /// <returns><value>True</value> if the <paramref name="block"/> is valid, otherwise <value>False</value></returns>
        public bool ValidateSuggestedBlock(Block block)
        {
            Transaction[] txs  = block.Transactions;
            IReleaseSpec  spec = _specProvider.GetSpec(block.Number);

            for (int i = 0; i < txs.Length; i++)
            {
                if (!_txValidator.IsWellFormed(txs[i], spec))
                {
                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - invalid transaction ({txs[i].Hash})");
                    }
                    return(false);
                }
            }

            if (spec.MaximumUncleCount < block.Ommers.Length)
            {
                _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - uncle count is {block.Ommers.Length} (MAX: {spec.MaximumUncleCount})");
                return(false);
            }

            if (block.Header.OmmersHash != OmmersHash.Calculate(block))
            {
                _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - invalid uncles hash");
                return(false);
            }

            if (!_ommersValidator.Validate(block.Header, block.Ommers))
            {
                _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - invalid uncles");
                return(false);
            }

            bool blockHeaderValid = _headerValidator.Validate(block.Header);

            if (!blockHeaderValid)
            {
                if (_logger.IsDebug)
                {
                    _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - invalid header");
                }
                return(false);
            }

            Keccak txRoot = new TxTrie(block.Transactions).RootHash;

            if (txRoot != block.Header.TxRoot)
            {
                if (_logger.IsDebug)
                {
                    _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) tx root {txRoot} != stated tx root {block.Header.TxRoot}");
                }
                return(false);
            }

            return(true);
        }
Exemplo n.º 2
0
        private bool TryPrepareBlock(BlockInfo blockInfo, BlockBody blockBody, out Block?block)
        {
            BlockHeader header            = _blockTree.FindHeader(blockInfo.BlockHash);
            bool        txRootIsValid     = new TxTrie(blockBody.Transactions).RootHash == header.TxRoot;
            bool        ommersHashIsValid = OmmersHash.Calculate(blockBody.Ommers) == header.OmmersHash;

            if (txRootIsValid && ommersHashIsValid)
            {
                block = new Block(header, blockBody);
            }
            else
            {
                block = null;
            }

            return(block != null);
        }
Exemplo n.º 3
0
        private int InsertBodies(BodiesSyncBatch batch)
        {
            List <Block> validResponses = new List <Block>();

            for (int i = 0; i < batch.Response.Length; i++)
            {
                BlockBody blockBody = batch.Response[i];
                if (blockBody == null)
                {
                    break;
                }

                Block block = new Block(batch.Headers[i], blockBody.Transactions, blockBody.Ommers);
                if (new TxTrie(block.Transactions).RootHash != block.TxRoot ||
                    OmmersHash.Calculate(block) != block.OmmersHash)
                {
                    if (_logger.IsWarn)
                    {
                        _logger.Warn($"{batch} - reporting INVALID - tx or ommers");
                    }
                    _syncPeerPool.ReportBreachOfProtocol(batch.ResponseSourcePeer, $"invalid tx or ommers root");
                    break;
                }

                validResponses.Add(block);
            }

            int validResponsesCount = validResponses.Count;

            if (validResponses.Count < batch.Request.Length)
            {
                BodiesSyncBatch fillerBatch = new BodiesSyncBatch();
                fillerBatch.MinNumber = batch.MinNumber;

                int originalLength = batch.Request.Length;
                fillerBatch.Request = new Keccak[originalLength - validResponsesCount];
                fillerBatch.Headers = new BlockHeader[originalLength - validResponsesCount];

                for (int i = validResponsesCount; i < originalLength; i++)
                {
                    fillerBatch.Request[i - validResponsesCount] = batch.Request[i];
                    fillerBatch.Headers[i - validResponsesCount] = batch.Headers[i];
                }

                if (_logger.IsDebug)
                {
                    _logger.Debug($"{batch} -> FILLER {fillerBatch}");
                }
                _pending.Enqueue(fillerBatch);
            }

            if (validResponses.Any())
            {
                long expectedNumber = _blockTree.LowestInsertedBody?.Number - 1 ?? LongConverter.FromString(_syncConfig.PivotNumber ?? "0");
                if (validResponses.Last().Number != expectedNumber)
                {
                    _dependencies.TryAdd(validResponses.Last().Number, validResponses);
                }
                else
                {
                    validResponses.Reverse();
                    InsertBlocks(validResponses);
                }

                if (_blockTree.LowestInsertedBody != null)
                {
                    _syncReport.FastBlocksBodies.Update(_pivotNumber - _blockTree.LowestInsertedBody.Number + 1);
                }
            }

            if (_logger.IsDebug)
            {
                _logger.Debug($"LOWEST_INSERTED {_blockTree.LowestInsertedBody?.Number} | HANDLED {batch}");
            }

            _syncReport.BodiesInQueue.Update(BodiesInQueue);
            return(validResponsesCount);
        }