/// <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.Uncles.Length) { _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - uncle count is {block.Uncles.Length} (MAX: {spec.MaximumUncleCount})"); return(false); } if (block.Header.UnclesHash != UnclesHash.Calculate(block)) { _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - invalid uncles hash"); return(false); } if (!_unclesValidator.Validate(block.Header, block.Uncles)) { _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); }
public bool Validate(BlockHeader header, BlockHeader[] uncles) { if (_poSSwitcher.IsPostMerge(header)) { return(true); } return(_preMergeUnclesValidator.Validate(header, uncles)); }