public void OnBlockProcessingEnd(Block block, TxReceipt[] receipts, ProcessingOptions options = ProcessingOptions.None) { _currentValidator?.OnBlockProcessingEnd(block, receipts, options); if (!block.IsGenesis) { bool notProducing = !options.ContainsFlag(ProcessingOptions.ProducingBlock); if (TryGetValidator(block.Number, out var validator)) { if (validator.ValidatorType.CanChangeImmediately()) { SetCurrentValidator(block.Number, validator, _blockTree.FindParentHeader(block.Header, BlockTreeLookupOptions.None)); if (_logger.IsInfo && notProducing) { _logger.Info($"Immediately applying chainspec validator change signalled at block {block.ToString(Block.Format.Short)} to {validator.ValidatorType}."); } } else if (_logger.IsInfo && notProducing) { _logger.Info($"Signal for switch to chainspec {validator.ValidatorType} based validator set at block {block.ToString(Block.Format.Short)}."); } } _lastProcessedBlock = block.Number; } }
// TODO: block processor pipeline private void ValidateProcessedBlock(Block suggestedBlock, ProcessingOptions options, Block block, TxReceipt[] receipts) { if (!options.ContainsFlag(ProcessingOptions.NoValidation) && !_blockValidator.ValidateProcessedBlock(block, receipts, suggestedBlock)) { if (_logger.IsError) { _logger.Error($"Processed block is not valid {suggestedBlock.ToString(Block.Format.FullHashAndNumber)}"); } if (_logger.IsError) { _logger.Error($"Suggested block TD: {suggestedBlock.TotalDifficulty}, Suggested block IsPostMerge {suggestedBlock.IsPostMerge}, Block TD: {block.TotalDifficulty}, Block IsPostMerge {block.IsPostMerge}"); } throw new InvalidBlockException(suggestedBlock); } }
public static void ProcessTransaction(this ITransactionProcessorAdapter transactionProcessor, Block block, Transaction currentTx, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions, IStateProvider stateProvider) { if (processingOptions.ContainsFlag(ProcessingOptions.DoNotVerifyNonce)) { currentTx.Nonce = stateProvider.GetNonce(currentTx.SenderAddress); } receiptsTracer.StartNewTxTrace(currentTx); transactionProcessor.Execute(currentTx, block.Header, receiptsTracer); receiptsTracer.EndTxTrace(); }
public virtual void OnBlockProcessingStart(Block block, ProcessingOptions options = ProcessingOptions.None) { if (!options.ContainsFlag(ProcessingOptions.ProducingBlock) && !block.IsGenesis) { var auRaStep = block.Header.AuRaStep.Value; if (!_validSealerStrategy.IsValidSealer(Validators, block.Beneficiary, auRaStep)) { if (_logger.IsError) { _logger.Error($"Block from incorrect proposer at block {block.ToString(Block.Format.FullHashAndNumber)}, step {auRaStep} from author {block.Beneficiary}."); } this.GetReportingValidator().ReportBenign(block.Beneficiary, block.Number, IReportingValidator.BenignCause.IncorrectProposer); throw new InvalidBlockException(block); } } }
public override void OnBlockProcessingEnd(Block block, TxReceipt[] receipts, ProcessingOptions options = ProcessingOptions.None) { base.OnBlockProcessingEnd(block, receipts, options); if (block.IsGenesis) { ValidatorStore.SetValidators(block.Number, LoadValidatorsFromContract(block.Header)); } if (ValidatorContract.CheckInitiateChangeEvent(block.Header, receipts, out var potentialValidators)) { bool isProcessingBlock = !options.ContainsFlag(ProcessingOptions.ProducingBlock); InitiateChange(block, potentialValidators, isProcessingBlock, Validators.Length == 1); if (_logger.IsInfo && isProcessingBlock) { _logger.Info($"Signal for transition within contract at block {block.ToString(Block.Format.Short)}. New list of {potentialValidators.Length} : [{string.Join<Address>(", ", potentialValidators)}]."); } } }
// TODO: block processor pipeline private (Block Block, TxReceipt[] Receipts) ProcessOne(Block suggestedBlock, ProcessingOptions options, IBlockTracer blockTracer) { if (_logger.IsTrace) { _logger.Trace($"Processing block {suggestedBlock.ToString(Block.Format.Short)} ({options})"); } ApplyDaoTransition(suggestedBlock); Block block = PrepareBlockForProcessing(suggestedBlock); TxReceipt[] receipts = ProcessBlock(block, blockTracer, options); ValidateProcessedBlock(suggestedBlock, options, block, receipts); if (options.ContainsFlag(ProcessingOptions.StoreReceipts)) { StoreTxReceipts(block, receipts); } return(block, receipts); }
public void OnBlockProcessingStart(Block block, ProcessingOptions options = ProcessingOptions.None) { if (!block.IsGenesis) { bool ValidatorWasAlreadyFinalized(KeyValuePair <long, AuRaParameters.Validator> validatorInfo) => _blockFinalizationManager.LastFinalizedBlockLevel >= validatorInfo.Key; bool isProducingBlock = options.ContainsFlag(ProcessingOptions.ProducingBlock); long previousBlockNumber = block.Number - 1; bool isNotConsecutive = previousBlockNumber != _lastProcessedBlock; if (isProducingBlock || isNotConsecutive) { if (TryGetLastValidator(previousBlockNumber, out var validatorInfo)) { var parentHeader = _blockTree.FindParentHeader(block.Header, BlockTreeLookupOptions.None); if (validatorInfo.Value.ValidatorType.CanChangeImmediately() || ValidatorWasAlreadyFinalized(validatorInfo)) { SetCurrentValidator(validatorInfo, parentHeader); } else if (!isProducingBlock) { bool canSetValidatorAsCurrent = !TryGetLastValidator(validatorInfo.Key - 1, out var previousValidatorInfo); long?finalizedAtBlockNumber = null; if (!canSetValidatorAsCurrent) { SetCurrentValidator(previousValidatorInfo, parentHeader); finalizedAtBlockNumber = _blockFinalizationManager.GetFinalizationLevel(validatorInfo.Key); canSetValidatorAsCurrent = finalizedAtBlockNumber != null; } if (canSetValidatorAsCurrent) { SetCurrentValidator(finalizedAtBlockNumber ?? validatorInfo.Key, validatorInfo.Value, parentHeader); } } } } } _currentValidator?.OnBlockProcessingStart(block, options); }
public override void OnBlockProcessingStart(Block block, ProcessingOptions options = ProcessingOptions.None) { if (block.IsGenesis) { return; } var isProducingBlock = options.ContainsFlag(ProcessingOptions.ProducingBlock); var isProcessingBlock = !isProducingBlock; var isInitBlock = InitBlockNumber == block.Number; var notConsecutiveBlock = block.Number - 1 > _lastProcessedBlockNumber || _lastProcessedBlockNumber == 0; var shouldLoadValidators = Validators == null || notConsecutiveBlock || isProducingBlock; var mainChainProcessing = !ForSealing && isProcessingBlock; if (shouldLoadValidators) { Validators = isInitBlock || notConsecutiveBlock ? LoadValidatorsFromContract(BlockTree.FindParentHeader(block.Header, BlockTreeLookupOptions.None)) : ValidatorStore.GetValidators(); if (mainChainProcessing) { if (_logger.IsInfo) { _logger.Info($"{(isInitBlock ? "Initial" : "Current")} contract validators ({Validators.Length}): [{string.Join<Address>(", ", Validators)}]."); } } } if (isInitBlock) { if (mainChainProcessing) { ValidatorStore.SetValidators(InitBlockNumber, Validators); } InitiateChange(block, Validators.ToArray(), isProcessingBlock, true); } else { if (mainChainProcessing && notConsecutiveBlock) { bool loadedValidatorsAreSameInStore = (ValidatorStore.GetValidators()?.SequenceEqual(Validators) == true); if (!loadedValidatorsAreSameInStore) { ValidatorStore.SetValidators(_blockFinalizationManager.GetLastLevelFinalizedBy(block.ParentHash), Validators); } } if (isProcessingBlock) { bool reorganisationHappened = block.Number <= _lastProcessedBlockNumber; if (reorganisationHappened) { var reorganisationToBlockBeforePendingValidatorsInitChange = block.Number <= CurrentPendingValidators?.BlockNumber; SetPendingValidators(reorganisationToBlockBeforePendingValidatorsInitChange ? null : LoadPendingValidators(), reorganisationToBlockBeforePendingValidatorsInitChange); } else if (block.Number > _lastProcessedBlockNumber + 1) // blocks skipped, like fast sync { SetPendingValidators(TryGetInitChangeFromPastBlocks(block.ParentHash), true); } } else { // if we are not processing blocks we are not on consecutive blocks. // We need to initialize pending validators from db on each block being produced. SetPendingValidators(LoadPendingValidators()); } } base.OnBlockProcessingStart(block, options); FinalizePendingValidatorsIfNeeded(block.Header, isProcessingBlock); _lastProcessedBlockNumber = block.Number; }
// TODO: move to branch processor public Block[] Process(Keccak newBranchStateRoot, List <Block> suggestedBlocks, ProcessingOptions options, IBlockTracer blockTracer) { if (suggestedBlocks.Count == 0) { return(Array.Empty <Block>()); } BlocksProcessing?.Invoke(this, new BlocksProcessingEventArgs(suggestedBlocks)); /* We need to save the snapshot state root before reorganization in case the new branch has invalid blocks. * In case of invalid blocks on the new branch we will discard the entire branch and come back to * the previous head state.*/ Keccak previousBranchStateRoot = CreateCheckpoint(); InitBranch(newBranchStateRoot); bool notReadOnly = !options.ContainsFlag(ProcessingOptions.ReadOnlyChain); int blocksCount = suggestedBlocks.Count; Block[] processedBlocks = new Block[blocksCount]; using IDisposable tracker = _witnessCollector.TrackOnThisThread(); try { for (int i = 0; i < blocksCount; i++) { if (blocksCount > 64 && i % 8 == 0) { if (_logger.IsInfo) { _logger.Info($"Processing part of a long blocks branch {i}/{blocksCount}. Block: {suggestedBlocks[i]}"); } } _witnessCollector.Reset(); (Block processedBlock, TxReceipt[] receipts) = ProcessOne(suggestedBlocks[i], options, blockTracer); processedBlocks[i] = processedBlock; // be cautious here as AuRa depends on processing PreCommitBlock(newBranchStateRoot, suggestedBlocks[i].Number); if (notReadOnly) { _witnessCollector.Persist(processedBlock.Hash !); BlockProcessed?.Invoke(this, new BlockProcessedEventArgs(processedBlock, receipts)); } // CommitBranch in parts if we have long running branch bool isFirstInBatch = i == 0; bool isLastInBatch = i == blocksCount - 1; bool isNotAtTheEdge = !isFirstInBatch && !isLastInBatch; bool isCommitPoint = i % MaxUncommittedBlocks == 0 && isNotAtTheEdge; if (isCommitPoint && notReadOnly) { if (_logger.IsInfo) { _logger.Info($"Commit part of a long blocks branch {i}/{blocksCount}"); } previousBranchStateRoot = CreateCheckpoint(); Keccak?newStateRoot = suggestedBlocks[i].StateRoot; InitBranch(newStateRoot, false); } } if (options.ContainsFlag(ProcessingOptions.DoNotUpdateHead)) { RestoreBranch(previousBranchStateRoot); } return(processedBlocks); } catch (Exception ex) // try to restore for all cost { _logger.Trace($"Encountered exception {ex} while processing blocks."); RestoreBranch(previousBranchStateRoot); throw; } }