public Task <IBlockProducer> InitBlockProducer(IConsensusPlugin consensusPlugin)
        {
            if (!Enabled)
            {
                throw new InvalidOperationException("Account Abstraction plugin is disabled");
            }

            UInt256 minerBalance = _nethermindApi.StateProvider !.GetBalance(_nethermindApi.EngineSigner !.Address);

            if (minerBalance < 1.Ether())
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn(
                        $"Account Abstraction Plugin: Miner ({_nethermindApi.EngineSigner!.Address}) Ether balance low - {minerBalance / 1.Ether()} Ether < 1 Ether. Increasing balance is recommended");
                }
                else
                {
                    if (_logger.IsInfo)
                    {
                        _logger.Info(
                            $"Account Abstraction Plugin: Miner ({_nethermindApi.EngineSigner!.Address}) Ether balance adequate - {minerBalance / 1.Ether()} Ether");
                    }
                }
            }

            IManualBlockProductionTrigger trigger = new BuildBlocksWhenRequested();

            return(consensusPlugin.InitBlockProducer(trigger, UserOperationTxSource));
        }
Esempio n. 2
0
        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 Manual_trigger_works()
        {
            bool triggered = false;
            BuildBlocksWhenRequested trigger = new BuildBlocksWhenRequested();

            trigger.TriggerBlockProduction += (s, e) => triggered = true;
            trigger.BuildBlock();
            triggered.Should().BeTrue();
        }
Esempio n. 4
0
 public Context()
 {
     MainBlockProductionTrigger = new BuildBlocksWhenRequested();
     BlockProcessingQueue       = Substitute.For <IBlockProcessingQueue>();
     BlockTree    = Substitute.For <IBlockTree>();
     Trigger      = new BuildBlocksOnlyWhenNotProcessing(MainBlockProductionTrigger, BlockProcessingQueue, BlockTree, LimboLogs.Instance, false);
     DefaultBlock = Build.A.Block.TestObject;
     Trigger.TriggerBlockProduction += OnTriggerBlockProduction;
 }
        public void Does_not_trigger_when_empty(int txCount, bool shouldTrigger)
        {
            var pool = Substitute.For <ITxPool>();

            pool.GetPendingTransactions().Returns(new Transaction[txCount]);
            bool triggered = false;
            BuildBlocksWhenRequested trigger       = new BuildBlocksWhenRequested();
            IBlockProductionTrigger  withCondition = trigger.IfPoolIsNotEmpty(pool);

            withCondition.TriggerBlockProduction += (s, e) => triggered = true;
            trigger.BuildBlock();
            triggered.Should().Be(shouldTrigger);
        }
        public void On_pending_trigger_works()
        {
            int triggered = 0;
            BuildBlocksWhenRequested trigger1  = new BuildBlocksWhenRequested();
            BuildBlocksWhenRequested trigger2  = new BuildBlocksWhenRequested();
            IBlockProductionTrigger  composite = trigger1.Or(trigger2);

            composite.TriggerBlockProduction += (s, e) => triggered++;
            trigger1.BuildBlock();
            trigger2.BuildBlock();
            trigger1.BuildBlock();
            trigger2.BuildBlock();

            triggered.Should().Be(4);
        }
        public Task <IBlockProducer> InitBlockProducer(IConsensusPlugin consensusPlugin)
        {
            if (!Enabled)
            {
                throw new InvalidOperationException("Account Abstraction plugin is disabled");
            }

            // init all relevant objects if not already initted
            foreach (Address entryPoint in _entryPointContractAddresses)
            {
                UserOperationPool(entryPoint);
                UserOperationSimulator(entryPoint);
                UserOperationTxBuilder(entryPoint);
            }

            _nethermindApi.BlockProducerEnvFactory.TransactionsExecutorFactory =
                new AABlockProducerTransactionsExecutorFactory(
                    _nethermindApi.SpecProvider !,
                    _nethermindApi.LogManager !,
                    _nethermindApi.EngineSigner !,
                    _entryPointContractAddresses.ToArray());

            UInt256 minerBalance = _nethermindApi.ChainHeadStateProvider !.GetBalance(_nethermindApi.EngineSigner !.Address);

            if (minerBalance < 1.Ether())
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn(
                        $"Account Abstraction Plugin: Miner ({_nethermindApi.EngineSigner!.Address}) Ether balance low - {minerBalance / 1.Ether()} Ether < 1 Ether. Increasing balance is recommended");
                }
                else
                {
                    if (_logger.IsInfo)
                    {
                        _logger.Info(
                            $"Account Abstraction Plugin: Miner ({_nethermindApi.EngineSigner!.Address}) Ether balance adequate - {minerBalance / 1.Ether()} Ether");
                    }
                }
            }

            IManualBlockProductionTrigger trigger = new BuildBlocksWhenRequested();

            return(consensusPlugin.InitBlockProducer(trigger, UserOperationTxSource));
        }
            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()));
            }
Esempio n. 10
0
        public void Test()
        {
            ISpecProvider specProvider = MainnetSpecProvider.Instance;
            DbProvider    dbProvider   = new DbProvider(DbModeHint.Mem);

            dbProvider.RegisterDb(DbNames.BlockInfos, new MemDb());
            dbProvider.RegisterDb(DbNames.Blocks, new MemDb());
            dbProvider.RegisterDb(DbNames.Headers, new MemDb());
            dbProvider.RegisterDb(DbNames.State, new MemDb());
            dbProvider.RegisterDb(DbNames.Code, new MemDb());

            BlockTree blockTree = new BlockTree(
                dbProvider,
                new ChainLevelInfoRepository(dbProvider),
                specProvider,
                NullBloomStorage.Instance,
                LimboLogs.Instance);
            TrieStore trieStore = new TrieStore(
                dbProvider.RegisteredDbs[DbNames.State],
                NoPruning.Instance,
                Archive.Instance,
                LimboLogs.Instance);
            StateProvider stateProvider = new StateProvider(
                trieStore,
                dbProvider.RegisteredDbs[DbNames.Code],
                LimboLogs.Instance);
            StorageProvider   storageProvider   = new StorageProvider(trieStore, stateProvider, LimboLogs.Instance);
            BlockhashProvider blockhashProvider = new BlockhashProvider(blockTree, LimboLogs.Instance);
            VirtualMachine    virtualMachine    = new VirtualMachine(
                stateProvider,
                storageProvider,
                blockhashProvider,
                specProvider,
                LimboLogs.Instance);
            TransactionProcessor txProcessor = new TransactionProcessor(
                specProvider,
                stateProvider,
                storageProvider,
                virtualMachine,
                LimboLogs.Instance);
            BlockProcessor blockProcessor = new BlockProcessor(
                specProvider,
                Always.Valid,
                NoBlockRewards.Instance,
                txProcessor,
                stateProvider,
                storageProvider,
                NullTxPool.Instance,
                NullReceiptStorage.Instance,
                NullWitnessCollector.Instance,
                LimboLogs.Instance);
            BlockchainProcessor blockchainProcessor = new BlockchainProcessor(
                blockTree,
                blockProcessor,
                NullRecoveryStep.Instance,
                LimboLogs.Instance,
                BlockchainProcessor.Options.Default);
            BuildBlocksWhenRequested trigger = new BuildBlocksWhenRequested();
            var timestamper = new ManualTimestamper();
            DevBlockProducer devBlockProducer = new DevBlockProducer(
                EmptyTxSource.Instance,
                blockchainProcessor,
                stateProvider,
                blockTree,
                blockchainProcessor,
                trigger,
                timestamper,
                specProvider,
                new MiningConfig {
                Enabled = true
            },
                LimboLogs.Instance);

            blockchainProcessor.Start();
            devBlockProducer.Start();

            AutoResetEvent autoResetEvent = new AutoResetEvent(false);

            blockTree.NewHeadBlock += (s, e) => autoResetEvent.Set();
            blockTree.SuggestBlock(Build.A.Block.Genesis.TestObject);

            autoResetEvent.WaitOne(1000).Should().BeTrue("genesis");

            trigger.BuildBlock();
            autoResetEvent.WaitOne(1000).Should().BeTrue("1");
            blockTree.Head.Number.Should().Be(1);
        }