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.IsProducingBlock(); 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.GetLastLevelFinalizedBy(block.ParentHash); canSetValidatorAsCurrent = finalizedAtBlockNumber >= validatorInfo.Key; } if (canSetValidatorAsCurrent) { SetCurrentValidator(finalizedAtBlockNumber ?? validatorInfo.Key, validatorInfo.Value, parentHeader); } } } } } _currentValidator?.OnBlockProcessingStart(block, options); }
private PendingValidators TryGetInitChangeFromPastBlocks(Keccak blockHash) { PendingValidators pendingValidators = null; var lastFinalized = _blockFinalizationManager.GetLastLevelFinalizedBy(blockHash); var toBlock = Math.Max(lastFinalized, InitBlockNumber); var block = _blockTree.FindBlock(blockHash, BlockTreeLookupOptions.None); while (block?.Number >= toBlock) { var receipts = _receiptFinder.Get(block) ?? Array.Empty <TxReceipt>(); if (ValidatorContract.CheckInitiateChangeEvent(block.Header, receipts, out var potentialValidators)) { if (Validators.SequenceEqual(potentialValidators)) { break; } pendingValidators = new PendingValidators(block.Number, block.Hash, potentialValidators); } block = _blockTree.FindBlock(block.ParentHash, BlockTreeLookupOptions.None); } return(pendingValidators); }
public override void OnBlockProcessingStart(Block block, ProcessingOptions options = ProcessingOptions.None) { if (block.IsGenesis) { return; } var isProducingBlock = options.IsProducingBlock(); 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; }