protected override void InitSealEngine()
        {
            if (_api.DbProvider == null)
            {
                throw new StepDependencyException(nameof(_api.DbProvider));
            }
            if (_api.ChainSpec == null)
            {
                throw new StepDependencyException(nameof(_api.ChainSpec));
            }
            if (_api.EthereumEcdsa == null)
            {
                throw new StepDependencyException(nameof(_api.EthereumEcdsa));
            }
            if (_api.BlockTree == null)
            {
                throw new StepDependencyException(nameof(_api.BlockTree));
            }

            _api.ValidatorStore = new ValidatorStore(_api.DbProvider.BlockInfosDb);

            ValidSealerStrategy validSealerStrategy = new ValidSealerStrategy();
            AuRaStepCalculator  auRaStepCalculator  = new AuRaStepCalculator(_api.ChainSpec.AuRa.StepDuration, _api.Timestamper, _api.LogManager);

            _api.SealValidator          = _sealValidator = new AuRaSealValidator(_api.ChainSpec.AuRa, auRaStepCalculator, _api.BlockTree, _api.ValidatorStore, validSealerStrategy, _api.EthereumEcdsa, _api.LogManager);
            _api.RewardCalculatorSource = AuRaRewardCalculator.GetSource(_api.ChainSpec.AuRa, _api.AbiEncoder);
            _api.Sealer         = new AuRaSealer(_api.BlockTree, _api.ValidatorStore, auRaStepCalculator, _api.EngineSigner, validSealerStrategy, _api.LogManager);
            _auRaStepCalculator = auRaStepCalculator;
        }
        public IAuRaValidator CreateValidatorProcessor(AuRaParameters.Validator validator, BlockHeader parentHeader = null, long?startBlock = null)
        {
            IValidatorContract GetValidatorContract() => new ValidatorContract(_transactionProcessor, _abiEncoder, validator.GetContractAddress(), _stateProvider, _readOnlyTxProcessorSource, _signer);
            IReportingValidatorContract GetReportingValidatorContract() => new ReportingValidatorContract(_abiEncoder, validator.GetContractAddress(), _signer);

            var  validSealerStrategy = new ValidSealerStrategy();
            long startBlockNumber    = startBlock ?? AuRaValidatorBase.DefaultStartBlockNumber;

            ContractBasedValidator GetContractBasedValidator() =>
            new ContractBasedValidator(
                GetValidatorContract(),
                _blockTree,
                _receiptFinder,
                _validatorStore,
                validSealerStrategy,
                _finalizationManager,
                parentHeader,
                _logManager,
                startBlockNumber,
                _posdaoTransition,
                _forSealing);

            return(validator.ValidatorType switch
            {
                AuRaParameters.ValidatorType.List =>
                new ListBasedValidator(
                    validator,
                    validSealerStrategy,
                    _validatorStore,
                    _logManager,
                    startBlockNumber,
                    _forSealing),

                AuRaParameters.ValidatorType.Contract => GetContractBasedValidator(),

                AuRaParameters.ValidatorType.ReportingContract =>
                new ReportingContractBasedValidator(
                    GetContractBasedValidator(),
                    GetReportingValidatorContract(),
                    _posdaoTransition,
                    _txSender,
                    _txPool,
                    _miningConfig,
                    _stateProvider,
                    _reportingValidatorCache,
                    _logManager),

                AuRaParameters.ValidatorType.Multi =>
                new MultiValidator(
                    validator,
                    this,
                    _blockTree,
                    _validatorStore,
                    _finalizationManager,
                    parentHeader,
                    _logManager,
                    _forSealing),

                _ => throw new ArgumentOutOfRangeException()
            });
        public IAuRaValidatorProcessorExtension CreateValidatorProcessor(AuRaParameters.Validator validator, long?startBlock = null)
        {
            var  auRaSealerValidator = new ValidSealerStrategy();
            long startBlockNumber    = startBlock ?? DefaultStartBlockNumber;

            return(validator.ValidatorType switch
            {
                AuRaParameters.ValidatorType.List => (IAuRaValidatorProcessorExtension) new ListBasedValidator(validator, auRaSealerValidator, _logManager),
                AuRaParameters.ValidatorType.Contract => new ContractBasedValidator(validator, _stateProvider, _abiEncoder, _transactionProcessor, _readOnlyReadOnlyTransactionProcessorSource, _blockTree, _receiptStorage, _validatorStore, auRaSealerValidator, _logManager, startBlockNumber),
                AuRaParameters.ValidatorType.ReportingContract => new ReportingContractBasedValidator(validator, _stateProvider, _abiEncoder, _transactionProcessor, _readOnlyReadOnlyTransactionProcessorSource, _blockTree, _receiptStorage, _validatorStore, auRaSealerValidator, _logManager, startBlockNumber),
                AuRaParameters.ValidatorType.Multi => new MultiValidator(validator, this, _blockTree, _validatorStore, _logManager),
                _ => throw new ArgumentOutOfRangeException()
            });
        private ListBasedValidator GetListValidator(params Address[] address)
        {
            var logManager = LimboLogs.Instance;

            _validSealerStrategy = new ValidSealerStrategy();
            var validator = new ListBasedValidator(
                new AuRaParameters.Validator()
            {
                ValidatorType = AuRaParameters.ValidatorType.List,
                Addresses     = address
            }, _validSealerStrategy, Substitute.For <IValidatorStore>(), logManager, 1);

            return(validator);
        }