private async Task <MevBlockProducer.MevBlockProducerInfo> CreateProducer( IConsensusPlugin consensusPlugin, int bundleLimit = 0, ITxSource?additionalTxSource = null) { bool BundleLimitTriggerCondition(BlockProductionEventArgs e) { // TODO: why we are checking parent and not the currently produced block...? BlockHeader?parent = _nethermindApi.BlockTree !.GetProducedBlockParent(e.ParentHeader); if (parent is not null) { IEnumerable <MevBundle> bundles = BundlePool.GetBundles(parent, _nethermindApi.Timestamper); return(bundles.Count() >= bundleLimit); } return(false); } IManualBlockProductionTrigger manualTrigger = new BuildBlocksWhenRequested(); IBlockProductionTrigger trigger = manualTrigger; if (bundleLimit != 0) { trigger = new TriggerWithCondition(manualTrigger, BundleLimitTriggerCondition); } IBlockProducer producer = await consensusPlugin.InitBlockProducer(trigger, additionalTxSource); return(new MevBlockProducer.MevBlockProducerInfo(producer, manualTrigger, new BeneficiaryTracer())); }
public void CheckHealth_returns_expected_results([ValueSource(nameof(CheckHealthTestCases))] CheckHealthTest test) { IBlockFinder blockFinder = Substitute.For <IBlockFinder>(); ISyncServer syncServer = Substitute.For <ISyncServer>(); IBlockchainProcessor blockchainProcessor = Substitute.For <IBlockchainProcessor>(); IBlockProducer blockProducer = Substitute.For <IBlockProducer>(); IHealthHintService healthHintService = Substitute.For <IHealthHintService>(); blockchainProcessor.IsProcessingBlocks(Arg.Any <ulong?>()).Returns(test.IsProcessingBlocks); blockProducer.IsProducingBlocks(Arg.Any <ulong?>()).Returns(test.IsProducingBlocks); syncServer.GetPeerCount().Returns(test.PeerCount); BlockHeaderBuilder GetBlockHeader(int blockNumber) => Build.A.BlockHeader.WithNumber(blockNumber); blockFinder.Head.Returns(new Block(GetBlockHeader(4).TestObject)); if (test.IsSyncing) { blockFinder.FindBestSuggestedHeader().Returns(GetBlockHeader(15).TestObject); } else { blockFinder.FindBestSuggestedHeader().Returns(GetBlockHeader(2).TestObject); } IEthSyncingInfo ethSyncingInfo = new EthSyncingInfo(blockFinder); NodeHealthService nodeHealthService = new(syncServer, blockFinder, blockchainProcessor, blockProducer, new HealthChecksConfig(), healthHintService, ethSyncingInfo, test.IsMining); CheckHealthResult result = nodeHealthService.CheckHealth(); Assert.AreEqual(test.ExpectedHealthy, result.Healthy); Assert.AreEqual(test.ExpectedMessage, FormatMessages(result.Messages.Select(x => x.Message))); Assert.AreEqual(test.ExpectedLongMessage, FormatMessages(result.Messages.Select(x => x.LongMessage))); }
public void Start() { for (int index = 0; index < _blockProducers.Length; index++) { IBlockProducer blockProducer = _blockProducers[index].BlockProducer; blockProducer.Start(); } _blockProductionTrigger.TriggerBlockProduction += OnBlockProduction; }
public Task Start() { for (int index = 0; index < _blockProducers.Length; index++) { IBlockProducer blockProducer = _blockProducers[index].BlockProducer; blockProducer.Start(); } _blockProductionTrigger.TriggerBlockProduction += OnBlockProduction; return(Task.CompletedTask); }
public MergeBlockProducer(IBlockProducer?preMergeProducer, IBlockProducer?postMergeBlockProducer, IPoSSwitcher?poSSwitcher) { _preMergeProducer = preMergeProducer; _eth2BlockProducer = postMergeBlockProducer ?? throw new ArgumentNullException(nameof(postMergeBlockProducer)); _poSSwitcher = poSSwitcher ?? throw new ArgumentNullException(nameof(poSSwitcher)); _poSSwitcher.TerminalBlockReached += OnSwitchHappened; if (HasPreMergeProducer) { _preMergeProducer !.BlockProduced += OnBlockProduced; } postMergeBlockProducer.BlockProduced += OnBlockProduced; }
public bool IsProducingBlocks(ulong?maxProducingInterval) { for (int index = 0; index < _blockProducers.Length; index++) { IBlockProducer blockProducer = _blockProducers[index].BlockProducer; if (blockProducer.IsProducingBlocks(maxProducingInterval)) { return(true); } } return(false); }
private async Task AssertIsProducingBlocks(IBlockProducer blockProducer) { Assert.AreEqual(false, blockProducer.IsProducingBlocks(null)); blockProducer.Start(); Assert.AreEqual(true, blockProducer.IsProducingBlocks(null)); Thread.Sleep(5000); Assert.AreEqual(false, blockProducer.IsProducingBlocks(1)); Assert.AreEqual(true, blockProducer.IsProducingBlocks(1000)); Assert.AreEqual(true, blockProducer.IsProducingBlocks(null)); await blockProducer.StopAsync(); Assert.AreEqual(false, blockProducer.IsProducingBlocks(null)); }
public Task StopAsync() { _blockProductionTrigger.TriggerBlockProduction -= OnBlockProduction; IList <Task> stopTasks = new List <Task>(); for (int index = 0; index < _blockProducers.Length; index++) { IBlockProducer blockProducer = _blockProducers[index].BlockProducer; stopTasks.Add(blockProducer.StopAsync()); } return(Task.WhenAll(stopTasks)); }
protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolTxSource, ISealer sealer, ITransactionComparerProvider transactionComparerProvider) { MiningConfig miningConfig = new() { MinGasPrice = UInt256.One }; SpecProvider.UpdateMergeTransitionInfo(1, 0); BlockProducerEnvFactory blockProducerEnvFactory = new BlockProducerEnvFactory( DbProvider, BlockTree, ReadOnlyTrieStore, SpecProvider, BlockValidator, NoBlockRewards.Instance, ReceiptStorage, BlockPreprocessorStep, TxPool, transactionComparerProvider, miningConfig, LogManager) { TransactionsExecutorFactory = new AABlockProducerTransactionsExecutorFactory( SpecProvider, LogManager, Signer, EntryPointAddresses) }; UserOperationTxSource = new(UserOperationTxBuilder, UserOperationPool, UserOperationSimulator, SpecProvider, State, Signer, LogManager.GetClassLogger()); PostMergeBlockProducer CreatePostMergeBlockProducer(IBlockProductionTrigger blockProductionTrigger, ITxSource?txSource = null) { var blockProducerEnv = blockProducerEnvFactory.Create(txSource); return(new PostMergeBlockProducerFactory(SpecProvider, SealEngine, Timestamper, miningConfig, LogManager, GasLimitCalculator).Create( blockProducerEnv, blockProductionTrigger)); } IBlockProducer blockProducer = CreatePostMergeBlockProducer(BlockProductionTrigger, UserOperationTxSource); blockProducer.BlockProduced += OnBlockProduced; return(blockProducer); }
protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolTxSource, ISealer sealer, ITransactionComparerProvider transactionComparerProvider) { SealEngine = new MergeSealEngine(SealEngine, PoSSwitcher, SealValidator, LogManager); IBlockProducer preMergeBlockProducer = base.CreateTestBlockProducer(txPoolTxSource, sealer, transactionComparerProvider); 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)); return(new MergeBlockProducer(preMergeBlockProducer, postMergeBlockProducer, PoSSwitcher)); }
private void InitBlockProducers() { if (_initConfig.IsMining) { IReadOnlyDbProvider minerDbProvider = new ReadOnlyDbProvider(_dbProvider, false); ReadOnlyBlockTree readOnlyBlockTree = new ReadOnlyBlockTree(_blockTree); ReadOnlyChain producerChain = new ReadOnlyChain(readOnlyBlockTree, _blockValidator, _rewardCalculator, _specProvider, minerDbProvider, _recoveryStep, _logManager, _txPool, _receiptStorage); switch (_chainSpec.SealEngineType) { case SealEngineType.Clique: { if (_logger.IsWarn) { _logger.Warn("Starting Clique block producer & sealer"); } CliqueConfig cliqueConfig = new CliqueConfig(); cliqueConfig.BlockPeriod = _chainSpec.Clique.Period; cliqueConfig.Epoch = _chainSpec.Clique.Epoch; _blockProducer = new CliqueBlockProducer(_txPool, producerChain.Processor, _blockTree, _timestamper, _cryptoRandom, producerChain.ReadOnlyStateProvider, _snapshotManager, (CliqueSealer)_sealer, _nodeKey.Address, cliqueConfig, _logManager); break; } case SealEngineType.NethDev: { if (_logger.IsWarn) { _logger.Warn("Starting Dev block producer & sealer"); } _blockProducer = new DevBlockProducer(_txPool, producerChain.Processor, _blockTree, _timestamper, _logManager); break; } default: throw new NotSupportedException($"Mining in {_chainSpec.SealEngineType} mode is not supported"); } _blockProducer.Start(); } }
private async Task InitBlockchain() { /* spec */ if (_chainSpec.ChainId == RopstenSpecProvider.Instance.ChainId) { _specProvider = RopstenSpecProvider.Instance; } else if (_chainSpec.ChainId == MainNetSpecProvider.Instance.ChainId) { _specProvider = MainNetSpecProvider.Instance; } else if (_chainSpec.ChainId == RinkebySpecProvider.Instance.ChainId) { _specProvider = RinkebySpecProvider.Instance; } else if (_chainSpec.ChainId == GoerliSpecProvider.Instance.ChainId) { _specProvider = GoerliSpecProvider.Instance; } else if (_chainSpec.ChainId == SturebySpecProvider.Instance.ChainId) { _specProvider = SturebySpecProvider.Instance; } else { _specProvider = new SingleReleaseSpecProvider(LatestRelease.Instance, _chainSpec.ChainId); } /* sync */ IDbConfig dbConfig = _configProvider.GetConfig <IDbConfig>(); foreach (PropertyInfo propertyInfo in typeof(IDbConfig).GetProperties()) { if (_logger.IsDebug) { _logger.Debug($"DB {propertyInfo.Name}: {propertyInfo.GetValue(dbConfig)}"); } } _dbProvider = HiveEnabled ? (IDbProvider) new MemDbProvider() : new RocksDbProvider(_initConfig.BaseDbPath, dbConfig, _logManager, _initConfig.StoreTraces, _initConfig.StoreReceipts); _ethereumEcdsa = new EthereumEcdsa(_specProvider, _logManager); _transactionPool = new TransactionPool( new PersistentTransactionStorage(_dbProvider.PendingTxsDb, _specProvider), new PendingTransactionThresholdValidator(_initConfig.ObsoletePendingTransactionInterval, _initConfig.RemovePendingTransactionInterval), new Timestamp(), _ethereumEcdsa, _specProvider, _logManager, _initConfig.RemovePendingTransactionInterval, _initConfig.PeerNotificationThreshold); _receiptStorage = new PersistentReceiptStorage(_dbProvider.ReceiptsDb, _specProvider); // IDbProvider debugRecorder = new RocksDbProvider(Path.Combine(_dbBasePath, "debug"), dbConfig); // _dbProvider = new RpcDbProvider(_jsonSerializer, new BasicJsonRpcClient(KnownRpcUris.NethVm1, _jsonSerializer, _logManager), _logManager, debugRecorder); // IDbProvider debugReader = new ReadOnlyDbProvider(new RocksDbProvider(Path.Combine(_dbBasePath, "debug"), dbConfig)); // _dbProvider = debugReader; _blockTree = new BlockTree( _dbProvider.BlocksDb, _dbProvider.BlockInfosDb, _specProvider, _transactionPool, _logManager); _recoveryStep = new TxSignaturesRecoveryStep(_ethereumEcdsa, _transactionPool); CliqueConfig cliqueConfig = null; _snapshotManager = null; switch (_chainSpec.SealEngineType) { case SealEngineType.None: _sealer = NullSealEngine.Instance; _sealValidator = NullSealEngine.Instance; _rewardCalculator = NoBlockRewards.Instance; break; case SealEngineType.Clique: _rewardCalculator = NoBlockRewards.Instance; cliqueConfig = new CliqueConfig(); cliqueConfig.BlockPeriod = _chainSpec.CliquePeriod; cliqueConfig.Epoch = _chainSpec.CliqueEpoch; _snapshotManager = new SnapshotManager(cliqueConfig, _dbProvider.BlocksDb, _blockTree, _ethereumEcdsa, _logManager); _sealValidator = new CliqueSealValidator(cliqueConfig, _snapshotManager, _logManager); _recoveryStep = new CompositeDataRecoveryStep(_recoveryStep, new AuthorRecoveryStep(_snapshotManager)); if (_initConfig.IsMining) { _sealer = new CliqueSealer(new BasicWallet(_nodeKey), cliqueConfig, _snapshotManager, _nodeKey.Address, _logManager); } else { _sealer = NullSealEngine.Instance; } break; case SealEngineType.NethDev: _sealer = NullSealEngine.Instance; _sealValidator = NullSealEngine.Instance; _rewardCalculator = NoBlockRewards.Instance; break; case SealEngineType.Ethash: _rewardCalculator = new RewardCalculator(_specProvider); var difficultyCalculator = new DifficultyCalculator(_specProvider); if (_initConfig.IsMining) { _sealer = new EthashSealer(new Ethash(_logManager), _logManager); } else { _sealer = NullSealEngine.Instance; } _sealValidator = new EthashSealValidator(_logManager, difficultyCalculator, new Ethash(_logManager)); break; default: throw new NotSupportedException($"Seal engine type {_chainSpec.SealEngineType} is not supported in Nethermind"); } /* validation */ var headerValidator = new HeaderValidator( _blockTree, _sealValidator, _specProvider, _logManager); var ommersValidator = new OmmersValidator( _blockTree, headerValidator, _logManager); var txValidator = new TransactionValidator( new SignatureValidator(_specProvider.ChainId)); _blockValidator = new BlockValidator( txValidator, headerValidator, ommersValidator, _specProvider, _logManager); var stateTree = new StateTree(_dbProvider.StateDb); var stateProvider = new StateProvider( stateTree, _dbProvider.CodeDb, _logManager); _stateProvider = stateProvider; var storageProvider = new StorageProvider( _dbProvider.StateDb, stateProvider, _logManager); _transactionPoolInfoProvider = new TransactionPoolInfoProvider(stateProvider); /* blockchain processing */ var blockhashProvider = new BlockhashProvider( _blockTree); var virtualMachine = new VirtualMachine( stateProvider, storageProvider, blockhashProvider, _logManager); var transactionProcessor = new TransactionProcessor( _specProvider, stateProvider, storageProvider, virtualMachine, _logManager); _blockProcessor = new BlockProcessor( _specProvider, _blockValidator, _rewardCalculator, transactionProcessor, _dbProvider.StateDb, _dbProvider.CodeDb, _dbProvider.TraceDb, stateProvider, storageProvider, _transactionPool, _receiptStorage, _logManager); _blockchainProcessor = new BlockchainProcessor( _blockTree, _blockProcessor, _recoveryStep, _logManager, _initConfig.StoreReceipts, _initConfig.StoreTraces); // create shared objects between discovery and peer manager IStatsConfig statsConfig = _configProvider.GetConfig <IStatsConfig>(); _nodeStatsManager = new NodeStatsManager(statsConfig, _logManager, !statsConfig.CaptureNodeStatsEventHistory); if (_initConfig.IsMining) { IReadOnlyDbProvider minerDbProvider = new ReadOnlyDbProvider(_dbProvider, false); AlternativeChain producerChain = new AlternativeChain(_blockTree, _blockValidator, _rewardCalculator, _specProvider, minerDbProvider, _recoveryStep, _logManager, _transactionPool, _receiptStorage); switch (_chainSpec.SealEngineType) { case SealEngineType.Clique: { // TODO: need to introduce snapshot provider for clique and pass it here instead of CliqueSealEngine if (_logger.IsWarn) { _logger.Warn("Starting Clique block producer & sealer"); } _blockProducer = new CliqueBlockProducer(_transactionPool, producerChain.Processor, _blockTree, _timestamp, _cryptoRandom, producerChain.StateProvider, _snapshotManager, (CliqueSealer)_sealer, _nodeKey.Address, cliqueConfig, _logManager); break; } case SealEngineType.NethDev: { if (_logger.IsWarn) { _logger.Warn("Starting Dev block producer & sealer"); } _blockProducer = new DevBlockProducer(_transactionPool, producerChain.Processor, _blockTree, _timestamp, _logManager); break; } default: throw new NotSupportedException($"Mining in {_chainSpec.SealEngineType} mode is not supported"); } _blockProducer.Start(); } if (!HiveEnabled) { _blockchainProcessor.Start(); LoadGenesisBlock(_chainSpec, string.IsNullOrWhiteSpace(_initConfig.GenesisHash) ? null : new Keccak(_initConfig.GenesisHash), _blockTree, stateProvider, _specProvider); if (_initConfig.ProcessingEnabled) { #pragma warning disable 4014 LoadBlocksFromDb(); #pragma warning restore 4014 } else { if (_logger.IsWarn) { _logger.Warn($"Shutting down processor due to {nameof(InitConfig)}.{nameof(InitConfig.ProcessingEnabled)} set to false"); } await _blockchainProcessor.StopAsync(); } } await InitializeNetwork( _receiptStorage, _sealValidator, txValidator); }
protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolTxSource, ISealer sealer, ITransactionComparerProvider transactionComparerProvider) { MiningConfig miningConfig = new() { MinGasPrice = UInt256.One }; SpecProvider.UpdateMergeTransitionInfo(1, 0); BlockProducerEnvFactory blockProducerEnvFactory = new( DbProvider, BlockTree, ReadOnlyTrieStore, SpecProvider, BlockValidator, NoBlockRewards.Instance, ReceiptStorage, BlockPreprocessorStep, TxPool, transactionComparerProvider, miningConfig, LogManager) { TransactionsExecutorFactory = new MevBlockProducerTransactionsExecutorFactory(SpecProvider, LogManager) }; PostMergeBlockProducer CreatePostMergeBlockProducer(IBlockProductionTrigger blockProductionTrigger, ITxSource?txSource = null) { BlockProducerEnv blockProducerEnv = blockProducerEnvFactory.Create(txSource); return(new PostMergeBlockProducerFactory(SpecProvider, SealEngine, Timestamper, miningConfig, LogManager).Create( blockProducerEnv, blockProductionTrigger, txSource)); } MevBlockProducer.MevBlockProducerInfo CreateProducer(int bundleLimit = 0, ITxSource?additionalTxSource = null) { // TODO: this could be simplified a lot of the parent was not retrieved, not sure why do we need the parent here bool BundleLimitTriggerCondition(BlockProductionEventArgs e) { // TODO: why do we need this parent? later we use only the current block number BlockHeader?parent = BlockTree.GetProducedBlockParent(e.ParentHeader); if (parent is not null) { // ToDo resolved conflict parent.Timestamp? IEnumerable <MevBundle> bundles = BundlePool.GetBundles(parent.Number + 1, parent.Timestamp); return(bundles.Count() >= bundleLimit); } return(false); } IManualBlockProductionTrigger manualTrigger = new BuildBlocksWhenRequested(); IBlockProductionTrigger trigger = manualTrigger; if (bundleLimit != 0) { trigger = new TriggerWithCondition(manualTrigger, BundleLimitTriggerCondition); } IBlockProducer producer = CreatePostMergeBlockProducer(trigger, additionalTxSource); return(new MevBlockProducer.MevBlockProducerInfo(producer, manualTrigger, new BeneficiaryTracer())); } int megabundleProducerCount = _relayAddresses.Any() ? 1 : 0; List <MevBlockProducer.MevBlockProducerInfo> blockProducers = new(_maxMergedBundles + megabundleProducerCount + 1); // Add non-mev block MevBlockProducer.MevBlockProducerInfo standardProducer = CreateProducer(); blockProducers.Add(standardProducer); // Try blocks with all bundle numbers <= maxMergedBundles for (int bundleLimit = 1; bundleLimit <= _maxMergedBundles; bundleLimit++) { BundleSelector bundleSelector = new(BundlePool, bundleLimit); BundleTxSource bundleTxSource = new(bundleSelector, Timestamper); MevBlockProducer.MevBlockProducerInfo bundleProducer = CreateProducer(bundleLimit, bundleTxSource); blockProducers.Add(bundleProducer); } if (megabundleProducerCount > 0) { MegabundleSelector megabundleSelector = new(BundlePool); BundleTxSource megabundleTxSource = new(megabundleSelector, Timestamper); MevBlockProducer.MevBlockProducerInfo bundleProducer = CreateProducer(0, megabundleTxSource); blockProducers.Add(bundleProducer); } MevBlockProducer blockProducer = new MevBlockProducer(BlockProductionTrigger, LogManager, blockProducers.ToArray()); blockProducer.BlockProduced += OnBlockProduced; return(blockProducer); }
protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolTxSource, ISealer sealer, ITransactionComparerProvider transactionComparerProvider) { MiningConfig miningConfig = new() { MinGasPrice = UInt256.One }; BlockProducerEnvFactory blockProducerEnvFactory = new( DbProvider, BlockTree, ReadOnlyTrieStore, SpecProvider, BlockValidator, NoBlockRewards.Instance, ReceiptStorage, BlockPreprocessorStep, TxPool, transactionComparerProvider, miningConfig, LogManager) { TransactionsExecutorFactory = new MevBlockProducerTransactionsExecutorFactory(SpecProvider, LogManager) }; Eth2BlockProducer CreateEth2BlockProducer(IBlockProductionTrigger blockProductionTrigger, ITxSource?txSource = null) => new Eth2TestBlockProducerFactory(GasLimitCalculator, txSource).Create( blockProducerEnvFactory, BlockTree, blockProductionTrigger, SpecProvider, Signer, Timestamper, miningConfig, LogManager); MevBlockProducer.MevBlockProducerInfo CreateProducer(int bundleLimit = 0, ITxSource?additionalTxSource = null) { bool BundleLimitTriggerCondition(BlockProductionEventArgs e) { BlockHeader?parent = BlockTree.GetProducedBlockParent(e.ParentHeader); if (parent is not null) { IEnumerable <MevBundle> bundles = BundlePool.GetBundles(parent, Timestamper); return(bundles.Count() >= bundleLimit); } return(false); } IManualBlockProductionTrigger manualTrigger = new BuildBlocksWhenRequested(); IBlockProductionTrigger trigger = manualTrigger; if (bundleLimit != 0) { trigger = new TriggerWithCondition(manualTrigger, BundleLimitTriggerCondition); } IBlockProducer producer = CreateEth2BlockProducer(trigger, additionalTxSource); return(new MevBlockProducer.MevBlockProducerInfo(producer, manualTrigger, new BeneficiaryTracer())); } int megabundleProducerCount = _relayAddresses.Any() ? 1 : 0; List <MevBlockProducer.MevBlockProducerInfo> blockProducers = new(_maxMergedBundles + megabundleProducerCount + 1); // Add non-mev block MevBlockProducer.MevBlockProducerInfo standardProducer = CreateProducer(); blockProducers.Add(standardProducer); // Try blocks with all bundle numbers <= maxMergedBundles for (int bundleLimit = 1; bundleLimit <= _maxMergedBundles; bundleLimit++) { BundleSelector bundleSelector = new(BundlePool, bundleLimit); BundleTxSource bundleTxSource = new(bundleSelector, Timestamper); MevBlockProducer.MevBlockProducerInfo bundleProducer = CreateProducer(bundleLimit, bundleTxSource); blockProducers.Add(bundleProducer); } if (megabundleProducerCount > 0) { MegabundleSelector megabundleSelector = new(BundlePool); BundleTxSource megabundleTxSource = new(megabundleSelector, Timestamper); MevBlockProducer.MevBlockProducerInfo bundleProducer = CreateProducer(0, megabundleTxSource); blockProducers.Add(bundleProducer); } return(new MevBlockProducer(BlockProductionTrigger, LogManager, blockProducers.ToArray())); }
private async Task InitBlockchain() { /* spec */ if (_chainSpec.ChainId == RopstenSpecProvider.Instance.ChainId) { _specProvider = RopstenSpecProvider.Instance; } else if (_chainSpec.ChainId == MainNetSpecProvider.Instance.ChainId) { _specProvider = MainNetSpecProvider.Instance; } else if (_chainSpec.ChainId == RinkebySpecProvider.Instance.ChainId) { _specProvider = RinkebySpecProvider.Instance; } else if (_chainSpec.ChainId == GoerliSpecProvider.Instance.ChainId) { _specProvider = GoerliSpecProvider.Instance; } else if (_chainSpec.ChainId == SturebySpecProvider.Instance.ChainId) { _specProvider = SturebySpecProvider.Instance; } else { _specProvider = new SingleReleaseSpecProvider(LatestRelease.Instance, _chainSpec.ChainId); } /* sync */ IDbConfig dbConfig = _configProvider.GetConfig <IDbConfig>(); foreach (PropertyInfo propertyInfo in typeof(IDbConfig).GetProperties()) { _logger.Info($"DB {propertyInfo.Name}: {propertyInfo.GetValue(dbConfig)}"); } _dbProvider = HiveEnabled ? (IDbProvider) new MemDbProvider() : new RocksDbProvider(_initConfig.BaseDbPath, dbConfig, _logManager); _ethereumSigner = new EthereumSigner(_specProvider, _logManager); _transactionPool = new TransactionPool( new PersistentTransactionStorage(_dbProvider.PendingTxsDb, _specProvider), new PendingTransactionThresholdValidator(_initConfig.ObsoletePendingTransactionInterval, _initConfig.RemovePendingTransactionInterval), new Timestamp(), _ethereumSigner, _logManager, _initConfig.RemovePendingTransactionInterval, _initConfig.PeerNotificationThreshold); _receiptStorage = new PersistentReceiptStorage(_dbProvider.ReceiptsDb, _specProvider); // IDbProvider debugRecorder = new RocksDbProvider(Path.Combine(_dbBasePath, "debug"), dbConfig); // _dbProvider = new RpcDbProvider(_jsonSerializer, new BasicJsonRpcClient(KnownRpcUris.NethVm1, _jsonSerializer, _logManager), _logManager, debugRecorder); // IDbProvider debugReader = new ReadOnlyDbProvider(new RocksDbProvider(Path.Combine(_dbBasePath, "debug"), dbConfig)); // _dbProvider = debugReader; /* blockchain */ _blockTree = new BlockTree( _dbProvider.BlocksDb, _dbProvider.BlockInfosDb, _specProvider, _transactionPool, _logManager); var cliqueConfig = new CliqueConfig(15, 30000); var clique = new CliqueSealEngine(cliqueConfig, _ethereumSigner, _nodeKey, _dbProvider.BlocksDb, _blockTree, _logManager); clique.CanSeal = _initConfig.IsMining; // TODO: read seal engine from ChainSpec _sealEngine = (_specProvider is MainNetSpecProvider) ? ConfigureSealEngine() : (_specProvider is RopstenSpecProvider) ? ConfigureSealEngine() : (_specProvider is SturebySpecProvider) ? ConfigureSealEngine() : (_specProvider is RinkebySpecProvider) ? clique : (_specProvider is GoerliSpecProvider) ? (ISealEngine)clique : NullSealEngine.Instance; _rewardCalculator = (_sealEngine is CliqueSealEngine) ? (IRewardCalculator) new NoBlockRewards() : new RewardCalculator(_specProvider); /* validation */ var headerValidator = new HeaderValidator( _blockTree, _sealEngine, _specProvider, _logManager); var ommersValidator = new OmmersValidator( _blockTree, headerValidator, _logManager); var txValidator = new TransactionValidator( new SignatureValidator(_specProvider.ChainId)); _blockValidator = new BlockValidator( txValidator, headerValidator, ommersValidator, _specProvider, _logManager); var stateTree = new StateTree(_dbProvider.StateDb); var stateProvider = new StateProvider( stateTree, _dbProvider.CodeDb, _logManager); _stateProvider = stateProvider; var storageProvider = new StorageProvider( _dbProvider.StateDb, stateProvider, _logManager); _transactionPoolInfoProvider = new TransactionPoolInfoProvider(stateProvider); /* blockchain processing */ var blockhashProvider = new BlockhashProvider( _blockTree); var virtualMachine = new VirtualMachine( stateProvider, storageProvider, blockhashProvider, _logManager); var transactionProcessor = new TransactionProcessor( _specProvider, stateProvider, storageProvider, virtualMachine, _logManager); var txRecoveryStep = new TxSignaturesRecoveryStep(_ethereumSigner, _transactionPool); _recoveryStep = _sealEngine is CliqueSealEngine ? new CompositeDataRecoveryStep(txRecoveryStep, new AuthorRecoveryStep(clique)) : (IBlockDataRecoveryStep)txRecoveryStep; _blockProcessor = new BlockProcessor( _specProvider, _blockValidator, _rewardCalculator, transactionProcessor, _dbProvider.StateDb, _dbProvider.CodeDb, _dbProvider.TraceDb, stateProvider, storageProvider, _transactionPool, _receiptStorage, _logManager); _blockchainProcessor = new BlockchainProcessor( _blockTree, _blockProcessor, _recoveryStep, _logManager, true, true); // create shared objects between discovery and peer manager _nodeFactory = new NodeFactory(_logManager); _nodeStatsProvider = new NodeStatsProvider(_configProvider.GetConfig <IStatsConfig>(), _nodeFactory, _logManager); var jsonSerializer = new JsonSerializer( _logManager); var encrypter = new AesEncrypter( _configProvider, _logManager); _keyStore = new FileKeyStore( _configProvider, jsonSerializer, encrypter, _cryptoRandom, _logManager); if (_initConfig.IsMining) { IReadOnlyDbProvider minerDbProvider = new ReadOnlyDbProvider(_dbProvider, false); AlternativeChain producerChain = new AlternativeChain(_blockTree, _blockValidator, _rewardCalculator, _specProvider, minerDbProvider, _recoveryStep, _logManager, _transactionPool, _receiptStorage); if (_sealEngine is CliqueSealEngine engine) { // TODO: need to introduce snapshot provider for clique and pass it here instead of CliqueSealEngine if (_logger.IsWarn) { _logger.Warn("Starting Clique block producer & sealer"); } _blockProducer = new CliqueBlockProducer(_transactionPool, producerChain.Processor, _blockTree, producerChain.StateProvider, _timestamp, _cryptoRandom, engine, cliqueConfig, _nodeKey.Address, _logManager); } else { if (_logger.IsWarn) { _logger.Warn("Starting Dev block producer & sealer"); } _blockProducer = new DevBlockProducer(_transactionPool, producerChain.Processor, _blockTree, _timestamp, _logManager); } _blockProducer.Start(); } if (!HiveEnabled) { _blockchainProcessor.Start(); LoadGenesisBlock(_chainSpec, string.IsNullOrWhiteSpace(_initConfig.GenesisHash) ? null : new Keccak(_initConfig.GenesisHash), _blockTree, stateProvider, _specProvider); if (_initConfig.ProcessingEnabled) { #pragma warning disable 4014 LoadBlocksFromDb(); #pragma warning restore 4014 } else { if (_logger.IsWarn) { _logger.Warn($"Shutting down processor due to {nameof(InitConfig)}.{nameof(InitConfig.ProcessingEnabled)} set to false"); } await _blockchainProcessor.StopAsync(); } } await InitializeNetwork( _receiptStorage, headerValidator, txValidator); }
public ProducedBlockSuggester(IBlockTree blockTree, IBlockProducer blockProducer) { _blockTree = blockTree; _blockProducer = blockProducer; _blockProducer.BlockProduced += OnBlockProduced; }
private async Task InitBlockchain() { _specProvider = new ChainSpecBasedSpecProvider(_chainSpec); Account.AccountStartNonce = _chainSpec.Parameters.AccountStartNonce; /* sync */ IDbConfig dbConfig = _configProvider.GetConfig <IDbConfig>(); _syncConfig = _configProvider.GetConfig <ISyncConfig>(); foreach (PropertyInfo propertyInfo in typeof(IDbConfig).GetProperties()) { if (_logger.IsDebug) { _logger.Debug($"DB {propertyInfo.Name}: {propertyInfo.GetValue(dbConfig)}"); } } _dbProvider = HiveEnabled ? (IDbProvider) new MemDbProvider() : new RocksDbProvider(_initConfig.BaseDbPath, dbConfig, _logManager, _initConfig.StoreTraces, _initConfig.StoreReceipts || _syncConfig.DownloadReceiptsInFastSync); _ethereumEcdsa = new EthereumEcdsa(_specProvider, _logManager); _txPool = new TxPool( new PersistentTxStorage(_dbProvider.PendingTxsDb, _specProvider), Timestamp.Default, _ethereumEcdsa, _specProvider, _txPoolConfig, _logManager); var _rc7FixDb = _initConfig.EnableRc7Fix ? _dbProvider.HeadersDb : NullDb.Instance; _receiptStorage = new PersistentReceiptStorage(_dbProvider.ReceiptsDb, _rc7FixDb, _specProvider, _logManager); // IDbProvider debugRecorder = new RocksDbProvider(Path.Combine(_dbBasePath, "debug"), dbConfig); // _dbProvider = new RpcDbProvider(_jsonSerializer, new BasicJsonRpcClient(KnownRpcUris.NethVm1, _jsonSerializer, _logManager), _logManager, debugRecorder); // IDbProvider debugReader = new ReadOnlyDbProvider(new RocksDbProvider(Path.Combine(_dbBasePath, "debug"), dbConfig)); // _dbProvider = debugReader; _blockTree = new BlockTree( _dbProvider.BlocksDb, _dbProvider.HeadersDb, _dbProvider.BlockInfosDb, _specProvider, _txPool, _syncConfig, _logManager); _recoveryStep = new TxSignaturesRecoveryStep(_ethereumEcdsa, _txPool, _logManager); CliqueConfig cliqueConfig = null; _snapshotManager = null; switch (_chainSpec.SealEngineType) { case SealEngineType.None: _sealer = NullSealEngine.Instance; _sealValidator = NullSealEngine.Instance; _rewardCalculator = NoBlockRewards.Instance; break; case SealEngineType.Clique: _rewardCalculator = NoBlockRewards.Instance; cliqueConfig = new CliqueConfig(); cliqueConfig.BlockPeriod = _chainSpec.Clique.Period; cliqueConfig.Epoch = _chainSpec.Clique.Epoch; _snapshotManager = new SnapshotManager(cliqueConfig, _dbProvider.BlocksDb, _blockTree, _ethereumEcdsa, _logManager); _sealValidator = new CliqueSealValidator(cliqueConfig, _snapshotManager, _logManager); _recoveryStep = new CompositeDataRecoveryStep(_recoveryStep, new AuthorRecoveryStep(_snapshotManager)); if (_initConfig.IsMining) { _sealer = new CliqueSealer(new BasicWallet(_nodeKey), cliqueConfig, _snapshotManager, _nodeKey.Address, _logManager); } else { _sealer = NullSealEngine.Instance; } break; case SealEngineType.NethDev: _sealer = NullSealEngine.Instance; _sealValidator = NullSealEngine.Instance; _rewardCalculator = NoBlockRewards.Instance; break; case SealEngineType.Ethash: _rewardCalculator = new RewardCalculator(_specProvider); var difficultyCalculator = new DifficultyCalculator(_specProvider); if (_initConfig.IsMining) { _sealer = new EthashSealer(new Ethash(_logManager), _logManager); } else { _sealer = NullSealEngine.Instance; } _sealValidator = new EthashSealValidator(_logManager, difficultyCalculator, new Ethash(_logManager)); break; default: throw new NotSupportedException($"Seal engine type {_chainSpec.SealEngineType} is not supported in Nethermind"); } /* validation */ _headerValidator = new HeaderValidator( _blockTree, _sealValidator, _specProvider, _logManager); var ommersValidator = new OmmersValidator( _blockTree, _headerValidator, _logManager); var txValidator = new TxValidator(_specProvider.ChainId); _blockValidator = new BlockValidator( txValidator, _headerValidator, ommersValidator, _specProvider, _logManager); var stateProvider = new StateProvider( _dbProvider.StateDb, _dbProvider.CodeDb, _logManager); _stateProvider = stateProvider; var storageProvider = new StorageProvider( _dbProvider.StateDb, stateProvider, _logManager); _txPoolInfoProvider = new TxPoolInfoProvider(stateProvider); _transactionPoolInfoProvider = new TxPoolInfoProvider(stateProvider); /* blockchain processing */ var blockhashProvider = new BlockhashProvider( _blockTree, _logManager); var virtualMachine = new VirtualMachine( stateProvider, storageProvider, blockhashProvider, _logManager); var transactionProcessor = new TransactionProcessor( _specProvider, stateProvider, storageProvider, virtualMachine, _logManager); _blockProcessor = new BlockProcessor( _specProvider, _blockValidator, _rewardCalculator, transactionProcessor, _dbProvider.StateDb, _dbProvider.CodeDb, _dbProvider.TraceDb, stateProvider, storageProvider, _txPool, _receiptStorage, _logManager); _blockchainProcessor = new BlockchainProcessor( _blockTree, _blockProcessor, _recoveryStep, _logManager, _initConfig.StoreReceipts, _initConfig.StoreTraces); // create shared objects between discovery and peer manager IStatsConfig statsConfig = _configProvider.GetConfig <IStatsConfig>(); _nodeStatsManager = new NodeStatsManager(statsConfig, _logManager); if (_initConfig.IsMining) { IReadOnlyDbProvider minerDbProvider = new ReadOnlyDbProvider(_dbProvider, false); AlternativeChain producerChain = new AlternativeChain(_blockTree, _blockValidator, _rewardCalculator, _specProvider, minerDbProvider, _recoveryStep, _logManager, _txPool, _receiptStorage); switch (_chainSpec.SealEngineType) { case SealEngineType.Clique: { if (_logger.IsWarn) { _logger.Warn("Starting Clique block producer & sealer"); } _blockProducer = new CliqueBlockProducer(_txPool, producerChain.Processor, _blockTree, _timestamp, _cryptoRandom, producerChain.StateProvider, _snapshotManager, (CliqueSealer)_sealer, _nodeKey.Address, cliqueConfig, _logManager); break; } case SealEngineType.NethDev: { if (_logger.IsWarn) { _logger.Warn("Starting Dev block producer & sealer"); } _blockProducer = new DevBlockProducer(_txPool, producerChain.Processor, _blockTree, _timestamp, _logManager); break; } default: throw new NotSupportedException($"Mining in {_chainSpec.SealEngineType} mode is not supported"); } _blockProducer.Start(); } _blockchainProcessor.Start(); LoadGenesisBlock(_chainSpec, string.IsNullOrWhiteSpace(_initConfig.GenesisHash) ? null : new Keccak(_initConfig.GenesisHash), _blockTree, stateProvider, _specProvider); if (_initConfig.ProcessingEnabled) { #pragma warning disable 4014 LoadBlocksFromDb(); #pragma warning restore 4014 } else { if (_logger.IsWarn) { _logger.Warn($"Shutting down the blockchain processor due to {nameof(InitConfig)}.{nameof(InitConfig.ProcessingEnabled)} set to false"); } await _blockchainProcessor.StopAsync(); } if (HiveEnabled) { await InitHive(); } if (HiveEnabled) { await InitHive(); } var producers = new List <IProducer>(); if (_initConfig.PubSubEnabled) { var kafkaProducer = await PrepareKafkaProducer(_blockTree, _configProvider.GetConfig <IKafkaConfig>()); producers.Add(kafkaProducer); } var grpcClientConfig = _configProvider.GetConfig <IGrpcClientConfig>(); if (grpcClientConfig.Enabled) { var grpcProducer = new GrpcProducer(_grpcClient, _logManager); producers.Add(grpcProducer); } ISubscription subscription; if (producers.Any()) { subscription = new Subscription(producers, _blockProcessor, _logManager); } else { subscription = new EmptySubscription(); } _disposeStack.Push(subscription); _dataBridge = new DataBridge(subscription, _receiptStorage, _blockTree, _logManager); _dataBridge.Start(); await InitializeNetwork(); }