コード例 #1
0
        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;
            }
        }
コード例 #2
0
 // 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);
     }
 }
コード例 #3
0
        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();
        }
コード例 #4
0
 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);
         }
     }
 }
コード例 #5
0
        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)}].");
                }
            }
        }
コード例 #6
0
        // 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);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        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;
        }
コード例 #9
0
        // 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;
            }
        }