protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolTxSource, ISealer sealer, ITransactionComparerProvider transactionComparerProvider)
        {
            SealEngine = new MergeSealEngine(SealEngine, PoSSwitcher, SealValidator, LogManager);
            MiningConfig miningConfig = new() { Enabled = true, MinGasPrice = 0 };
            TargetAdjustedGasLimitCalculator targetAdjustedGasLimitCalculator = new(SpecProvider, miningConfig);

            EthSyncingInfo = new EthSyncingInfo(BlockTree);
            PostMergeBlockProducerFactory blockProducerFactory = new(
                SpecProvider,
                SealEngine,
                Timestamper,
                miningConfig,
                LogManager,
                targetAdjustedGasLimitCalculator);

            BlockProducerEnvFactory blockProducerEnvFactory = new(
                DbProvider,
                BlockTree,
                ReadOnlyTrieStore,
                SpecProvider,
                BlockValidator,
                NoBlockRewards.Instance,
                ReceiptStorage,
                BlockPreprocessorStep,
                TxPool,
                transactionComparerProvider,
                miningConfig,
                LogManager);


            BlockProducerEnv       blockProducerEnv       = blockProducerEnvFactory.Create();
            PostMergeBlockProducer postMergeBlockProducer = blockProducerFactory.Create(blockProducerEnv, BlockProductionTrigger);

            PostMergeBlockProducer = postMergeBlockProducer;
            PayloadPreparationService ??= new PayloadPreparationService(
                postMergeBlockProducer,
                new BlockImprovementContextFactory(BlockProductionTrigger, TimeSpan.FromSeconds(MergeConfig.SecondsPerSlot)
                                                   ),
                TimerFactory.Default,
                LogManager,
                TimeSpan.FromSeconds(MergeConfig.SecondsPerSlot)
                );

            IAuRaStepCalculator auraStepCalculator = Substitute.For <IAuRaStepCalculator>();

            auraStepCalculator.TimeToNextStep.Returns(TimeSpan.FromMilliseconds(0));
            FollowOtherMiners gasLimitCalculator    = new(MainnetSpecProvider.Instance);
            AuRaBlockProducer preMergeBlockProducer = new(
                txPoolTxSource,
                blockProducerEnvFactory.Create().ChainProcessor,
                ((TestBlockchain)this).BlockProductionTrigger,
                State,
                sealer,
                BlockTree,
                Timestamper,
                auraStepCalculator,
                NullReportingValidator.Instance,
                new AuRaConfig(),
                gasLimitCalculator,
                SpecProvider,
                LogManager
                );

            return(new MergeBlockProducer(preMergeBlockProducer, postMergeBlockProducer, PoSSwitcher));
        }
    }
        public async Task <IBlockProducer> InitBlockProducer(IConsensusPlugin consensusPlugin)
        {
            if (MergeEnabled)
            {
                if (_api.EngineSigner == null)
                {
                    throw new ArgumentNullException(nameof(_api.EngineSigner));
                }
                if (_api.ChainSpec == null)
                {
                    throw new ArgumentNullException(nameof(_api.ChainSpec));
                }
                if (_api.BlockTree == null)
                {
                    throw new ArgumentNullException(nameof(_api.BlockTree));
                }
                if (_api.BlockProcessingQueue == null)
                {
                    throw new ArgumentNullException(nameof(_api.BlockProcessingQueue));
                }
                if (_api.SpecProvider == null)
                {
                    throw new ArgumentNullException(nameof(_api.SpecProvider));
                }
                if (_api.BlockValidator == null)
                {
                    throw new ArgumentNullException(nameof(_api.BlockValidator));
                }
                if (_api.RewardCalculatorSource == null)
                {
                    throw new ArgumentNullException(nameof(_api.RewardCalculatorSource));
                }
                if (_api.ReceiptStorage == null)
                {
                    throw new ArgumentNullException(nameof(_api.ReceiptStorage));
                }
                if (_api.TxPool == null)
                {
                    throw new ArgumentNullException(nameof(_api.TxPool));
                }
                if (_api.DbProvider == null)
                {
                    throw new ArgumentNullException(nameof(_api.DbProvider));
                }
                if (_api.ReadOnlyTrieStore == null)
                {
                    throw new ArgumentNullException(nameof(_api.ReadOnlyTrieStore));
                }
                if (_api.BlockchainProcessor == null)
                {
                    throw new ArgumentNullException(nameof(_api.BlockchainProcessor));
                }
                if (_api.HeaderValidator == null)
                {
                    throw new ArgumentNullException(nameof(_api.HeaderValidator));
                }
                if (_mergeBlockProductionPolicy == null)
                {
                    throw new ArgumentNullException(nameof(_mergeBlockProductionPolicy));
                }
                if (_api.SealValidator == null)
                {
                    throw new ArgumentNullException(nameof(_api.SealValidator));
                }

                if (_logger.IsInfo)
                {
                    _logger.Info("Starting Merge block producer & sealer");
                }

                IBlockProducer?blockProducer = _mergeBlockProductionPolicy.ShouldInitPreMergeBlockProduction()
                    ? await consensusPlugin.InitBlockProducer()
                    : null;

                _miningConfig = _api.Config <IMiningConfig>();
                _manualTimestamper ??= new ManualTimestamper();
                _blockProductionTrigger = new BuildBlocksWhenRequested();
                BlockProducerEnv blockProducerEnv = _api.BlockProducerEnvFactory.Create();

                _api.SealEngine = new MergeSealEngine(_api.SealEngine, _poSSwitcher, _api.SealValidator, _api.LogManager);
                _api.Sealer     = _api.SealEngine;
                PostMergeBlockProducerFactory blockProducerFactory = new(_api.SpecProvider, _api.SealEngine, _manualTimestamper, _miningConfig, _api.LogManager);
                _postMergeBlockProducer = blockProducerFactory.Create(
                    blockProducerEnv,
                    _blockProductionTrigger,
                    CreateTxSource(blockProducerEnv.ReadOnlyStateProvider)
                    );

                _api.BlockProducer = new MergeBlockProducer(blockProducer, _postMergeBlockProducer, _poSSwitcher);
            }

            return(_api.BlockProducer !);
        }