private Block PrepareBlock(BlockHeader parentHeader) { Block parent = _blockTree.FindBlock(parentHeader.Hash, BlockTreeLookupOptions.None); UInt256 timestamp = _timestamper.EpochSeconds; BlockHeader header = new BlockHeader( parent.Hash, Keccak.OfAnEmptySequenceRlp, _nodeAddress, _difficultyCalculator.CalculateDifficulty(parent.Header), parent.Number + 1, parent.GasLimit, timestamp > parent.Timestamp ? timestamp : parent.Timestamp + 1, Encoding.UTF8.GetBytes("Nethermind")) { AuRaStep = (long)_auRaStepCalculator.CurrentStep, }; header.TotalDifficulty = parent.TotalDifficulty + header.Difficulty; if (_logger.IsDebug) { _logger.Debug($"Setting total difficulty to {parent.TotalDifficulty} + {header.Difficulty}."); } var transactions = _txPool.GetPendingTransactions().OrderBy(t => t?.Nonce); // by nonce in case there are two transactions for the same account var selectedTxs = new List <Transaction>(); BigInteger gasRemaining = header.GasLimit; if (_logger.IsDebug) { _logger.Debug($"Collecting pending transactions at min gas price {MinGasPriceForMining} and block gas limit {gasRemaining}."); } int total = 0; foreach (Transaction transaction in transactions) { total++; if (transaction == null) { throw new InvalidOperationException("Block transaction is null"); } if (transaction.GasPrice < MinGasPriceForMining) { if (_logger.IsTrace) { _logger.Trace($"Rejecting transaction - gas price ({transaction.GasPrice}) too low (min gas price: {MinGasPriceForMining}."); } continue; } if (transaction.GasLimit > gasRemaining) { if (_logger.IsTrace) { _logger.Trace($"Rejecting transaction - gas limit ({transaction.GasPrice}) more than remaining gas ({gasRemaining})."); } break; } selectedTxs.Add(transaction); gasRemaining -= transaction.GasLimit; } if (_logger.IsDebug) { _logger.Debug($"Collected {selectedTxs.Count} out of {total} pending transactions."); } Block block = new Block(header, selectedTxs, new BlockHeader[0]); header.TxRoot = block.CalculateTxRoot(); return(block); }
public bool ValidateParams(BlockHeader parent, BlockHeader header) { const long rejectedStepDrift = 4; if (header.AuRaSignature == null) { if (_logger.IsError) { _logger.Error($"Block {header.Number}, hash {header.Hash} is missing signature."); } return(false); } // Ensure header is from the step after parent. if (header.AuRaStep == null) { if (_logger.IsError) { _logger.Error($"Block {header.Number}, hash {header.Hash} is missing step value."); } return(false); } else if (header.AuRaStep == parent.AuRaStep) { if (_logger.IsWarn) { _logger.Warn($"Multiple blocks proposed for step {header.AuRaStep}. Block {header.Number}, hash {header.Hash} is duplicate."); } return(false); } else if (header.AuRaStep < parent.AuRaStep && header.Number >= _parameters.ValidateStepTransition) { if (_logger.IsError) { _logger.Error($"Block {header.Number}, hash {header.Hash} step {header.AuRaStep} is lesser than parents step {parent.AuRaStep}."); } return(false); } var currentStep = _stepCalculator.CurrentStep; if (header.AuRaStep > currentStep + rejectedStepDrift) { if (_logger.IsError) { _logger.Error($"Block {header.Number}, hash {header.Hash} step {header.AuRaStep} is from the future. Current step is {currentStep}."); } return(false); } if (header.AuRaStep > currentStep) { if (_logger.IsWarn) { _logger.Warn($"Block {header.Number}, hash {header.Hash} step {header.AuRaStep} is too early. Current step is {currentStep}."); } } if (header.AuRaStep - parent.AuRaStep != 1) { // report_skipped } // Report malice if the validator produced other sibling blocks in the same step. if (_receivedSteps.ContainsOrInsert(header, _validator.CurrentSealersCount)) { if (_logger.IsDebug) { _logger.Debug($"Validator {header.Beneficiary} produced sibling blocks in the same step {header.AuRaStep} in block {header.Number}."); } // report malicious } if (header.Number >= _parameters.ValidateScoreTransition) { if (header.Difficulty >= AuraDifficultyCalculator.MaxDifficulty) { if (_logger.IsError) { _logger.Error($"Difficulty out of bounds for block {header.Number}, hash {header.Hash}, Max value {AuraDifficultyCalculator.MaxDifficulty}, but found {header.Difficulty}."); } return(false); } var expectedDifficulty = AuraDifficultyCalculator.CalculateDifficulty(parent.AuRaStep.Value, header.AuRaStep.Value, 0); if (header.Difficulty != expectedDifficulty) { if (_logger.IsError) { _logger.Error($"Invalid difficulty for block {header.Number}, hash {header.Hash}, expected value {expectedDifficulty}, but found {header.Difficulty}."); } return(false); } } return(true); }