public AuRaSealValidator(AuRaParameters parameters, IAuRaStepCalculator stepCalculator, IAuRaValidator validator, IEthereumEcdsa ecdsa, ILogManager logManager) { _parameters = parameters ?? throw new ArgumentNullException(nameof(parameters)); _stepCalculator = stepCalculator ?? throw new ArgumentNullException(nameof(stepCalculator)); _validator = validator ?? throw new ArgumentNullException(nameof(validator)); _ecdsa = ecdsa ?? throw new ArgumentNullException(nameof(ecdsa)); _logger = logManager.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _auraDifficultyCalculator = new AuraDifficultyCalculator(stepCalculator); }
public AuRaBlockProducer(ITxPool txPool, IBlockchainProcessor blockchainProcessor, IBlockTree blockTree, ITimestamper timestamper, IAuRaStepCalculator auRaStepCalculator, Address nodeAddress, ISealer sealer, IStateProvider stateProvider, IAuraConfig config, ILogManager logManager) { _txPool = txPool ?? throw new ArgumentNullException(nameof(txPool)); _processor = blockchainProcessor ?? throw new ArgumentNullException(nameof(blockchainProcessor)); _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); _timestamper = timestamper ?? throw new ArgumentNullException(nameof(timestamper)); _auRaStepCalculator = auRaStepCalculator ?? throw new ArgumentNullException(nameof(auRaStepCalculator)); _nodeAddress = nodeAddress ?? throw new ArgumentNullException(nameof(nodeAddress)); _sealer = sealer ?? throw new ArgumentNullException(nameof(sealer)); _stateProvider = stateProvider ?? throw new ArgumentNullException(nameof(stateProvider)); _config = config ?? throw new ArgumentNullException(nameof(config)); _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _difficultyCalculator = new AuraDifficultyCalculator(_auRaStepCalculator); }
private Block PrepareBlock(BlockHeader parentHeader) { UInt256 timestamp = _timestamper.EpochSeconds; BlockHeader header = new BlockHeader( parentHeader.Hash, Keccak.OfAnEmptySequenceRlp, _nodeAddress, AuraDifficultyCalculator.CalculateDifficulty(parentHeader.AuRaStep.Value, _auRaStepCalculator.CurrentStep, 0), parentHeader.Number + 1, parentHeader.GasLimit, timestamp > parentHeader.Timestamp ? timestamp : parentHeader.Timestamp + 1, Encoding.UTF8.GetBytes("Nethermind")) { AuRaStep = (long)_auRaStepCalculator.CurrentStep, }; header.TotalDifficulty = parentHeader.TotalDifficulty + header.Difficulty; if (_logger.IsDebug) { _logger.Debug($"Setting total difficulty to {parentHeader.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); }