Example #1
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;
        }