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; }