diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs index 4ba502850e1..69eb17b7d33 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs @@ -259,8 +259,7 @@ Dictionary GroupTransactions(bool supportBlobs) => SetAccountStates(testCase.MissingAddresses); - TxPoolTxSource poolTxSource = new(transactionPool, specProvider, - transactionComparerProvider, LimboLogs.Instance, txFilterPipeline); + TxPoolTxSource poolTxSource = new(transactionPool, specProvider, transactionComparerProvider, LimboLogs.Instance, txFilterPipeline, ConstantEip4844Config.Instance); BlockHeaderBuilder parentHeader = Build.A.BlockHeader.WithStateRoot(stateProvider.StateRoot).WithBaseFee(testCase.BaseFee); if (spec.IsEip4844Enabled) diff --git a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs index f27ce90d447..179d4ec705c 100644 --- a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs @@ -178,7 +178,7 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f MinGasPrice = 0 }; ITxFilterPipeline txFilterPipeline = TxFilterPipelineBuilder.CreateStandardFilteringPipeline(nodeLogManager, specProvider, blocksConfig); - TxPoolTxSource txPoolTxSource = new(txPool, specProvider, transactionComparerProvider, nodeLogManager, txFilterPipeline); + TxPoolTxSource txPoolTxSource = new(txPool, specProvider, transactionComparerProvider, nodeLogManager, txFilterPipeline, ConstantEip4844Config.Instance); CliqueBlockProducer blockProducer = new( txPoolTxSource, minerProcessor, diff --git a/src/Nethermind/Nethermind.Config/BlocksConfig.cs b/src/Nethermind/Nethermind.Config/BlocksConfig.cs index 229912457e5..183d046bbfd 100644 --- a/src/Nethermind/Nethermind.Config/BlocksConfig.cs +++ b/src/Nethermind/Nethermind.Config/BlocksConfig.cs @@ -3,6 +3,7 @@ using System.Reflection.Metadata; using System.Text; +using Nethermind.Core; using Nethermind.Core.Exceptions; using Nethermind.Core.Extensions; using Nethermind.Int256; @@ -18,6 +19,20 @@ public class BlocksConfig : IBlocksConfig public bool Enabled { get; set; } public long? TargetBlockGasLimit { get; set; } = null; + public int? TargetBlobProductionLimit + { + get => _eip4844Config?.GetMaxBlobsPerBlock(); + set + { + if (TargetBlobProductionLimit != value) + { + _eip4844Config = value is null || value == ConstantEip4844Config.Instance.GetMaxBlobsPerBlock() + ? null + : new CappedEip4844Config(value.Value); + } + } + } + public UInt256 MinGasPrice { get; set; } = 1.Wei(); public bool RandomizedBlocks { get; set; } @@ -54,5 +69,8 @@ public byte[] GetExtraDataBytes() { return _extraDataBytes; } + + private IEip4844Config _eip4844Config = null; + public IEip4844Config GetEip4844Config() => _eip4844Config ?? ConstantEip4844Config.Instance; } } diff --git a/src/Nethermind/Nethermind.Config/IBlocksConfig.cs b/src/Nethermind/Nethermind.Config/IBlocksConfig.cs index f7a929174d6..c021f55fe76 100644 --- a/src/Nethermind/Nethermind.Config/IBlocksConfig.cs +++ b/src/Nethermind/Nethermind.Config/IBlocksConfig.cs @@ -1,13 +1,13 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core; using Nethermind.Int256; namespace Nethermind.Config; public interface IBlocksConfig : IConfig { - //[ConfigItem( // Description = "Defines whether the blocks should be produced.", // DefaultValue = "false")] @@ -18,6 +18,9 @@ public interface IBlocksConfig : IConfig DefaultValue = "null")] long? TargetBlockGasLimit { get; set; } + [ConfigItem(Description = "The blob limit after which the block producer should stop adding blobs. Minimum value is 1.", DefaultValue = "null")] + int? TargetBlobProductionLimit { get; set; } + [ConfigItem( Description = "The minimum gas premium (or the gas price before the London hard fork) for transactions accepted by the block producer.", DefaultValue = "1")] @@ -44,4 +47,6 @@ public interface IBlocksConfig : IConfig int GenesisTimeoutMs { get; set; } byte[] GetExtraDataBytes(); + + IEip4844Config GetEip4844Config(); } diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs index 5fa09b539d8..b5e8629b27e 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs @@ -39,6 +39,7 @@ public class StartBlockProducerAuRa private INethermindApi NethermindApi => _api; private readonly IAuraConfig _auraConfig; + private readonly IBlocksConfig _blocksConfig; private IAuRaValidator? _validator; private DictionaryContractDataStore? _minGasPricesContractDataStore; private TxPriorityContract? _txPriorityContract; @@ -49,6 +50,7 @@ public StartBlockProducerAuRa(AuRaNethermindApi api) { _api = api; _auraConfig = NethermindApi.Config(); + _blocksConfig = NethermindApi.Config(); } private IAuRaStepCalculator StepCalculator @@ -99,7 +101,7 @@ public IBlockProducer BuildProducer(ITxSource? additionalTxSource = null) gasLimitCalculator, _api.SpecProvider, _api.LogManager, - _api.ConfigProvider.GetConfig()); + _blocksConfig); return blockProducer; } @@ -130,7 +132,7 @@ private BlockProcessor CreateBlockProcessor(IReadOnlyTxProcessingScope changeabl _api.FinalizationManager, NullTxSender.Instance, NullTxPool.Instance, - NethermindApi.Config(), + _blocksConfig, _api.LogManager, _api.EngineSigner, _api.SpecProvider, @@ -207,9 +209,9 @@ internal TxPoolTxSource CreateTxPoolTxSource() return new TxPriorityTxSource( _api.TxPool, - _api.StateReader, _api.LogManager, txFilterPipeline, + _blocksConfig.GetEip4844Config(), whitelistContractDataStore, prioritiesContractDataStore, _api.SpecProvider, @@ -268,7 +270,7 @@ private TxPoolTxSource CreateStandardTxPoolTxSource() .WithCustomTxFilter(txSourceFilter) .WithBaseFeeFilter(_api.SpecProvider) .Build; - return new TxPoolTxSource(_api.TxPool, _api.SpecProvider, _api.TransactionComparerProvider, _api.LogManager, txFilterPipeline); + return new TxPoolTxSource(_api.TxPool, _api.SpecProvider, _api.TransactionComparerProvider, _api.LogManager, txFilterPipeline, _blocksConfig.GetEip4844Config()); } private ITxFilter CreateAuraTxFilterForProducer() => TxAuRaFilterBuilders.CreateAuRaTxFilterForProducer(_api, _minGasPricesContractDataStore); @@ -353,13 +355,13 @@ IList GetRandomContracts( return txSource; } - private static IGasLimitCalculator CreateGasLimitCalculator(AuRaNethermindApi api) + private IGasLimitCalculator CreateGasLimitCalculator(AuRaNethermindApi api) { if (api.ChainSpec is null) throw new StepDependencyException(nameof(api.ChainSpec)); var blockGasLimitContractTransitions = api.ChainSpec.AuRa.BlockGasLimitContractTransitions; IGasLimitCalculator gasLimitCalculator = - new TargetAdjustedGasLimitCalculator(api.SpecProvider, api.Config()); + new TargetAdjustedGasLimitCalculator(api.SpecProvider, _blocksConfig); if (blockGasLimitContractTransitions?.Any() == true) { AuRaContractGasLimitOverride auRaContractGasLimitOverride = new( diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPriorityTxSource.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPriorityTxSource.cs index 3054b3a520c..bf60373576c 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPriorityTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPriorityTxSource.cs @@ -12,7 +12,6 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Logging; -using Nethermind.State; using Nethermind.TxPool; namespace Nethermind.Consensus.AuRa.Transactions @@ -25,14 +24,14 @@ public class TxPriorityTxSource : TxPoolTxSource public TxPriorityTxSource( ITxPool transactionPool, - IStateReader stateReader, ILogManager logManager, ITxFilterPipeline txFilterPipeline, + IEip4844Config eip4844Config, IContractDataStore
sendersWhitelist, // expected HashSet based IDictionaryContractDataStore priorities, ISpecProvider specProvider, ITransactionComparerProvider transactionComparerProvider) // expected SortedList based - : base(transactionPool, specProvider, transactionComparerProvider, logManager, txFilterPipeline) + : base(transactionPool, specProvider, transactionComparerProvider, logManager, txFilterPipeline, eip4844Config) { _sendersWhitelist = sendersWhitelist ?? throw new ArgumentNullException(nameof(sendersWhitelist)); _priorities = priorities ?? throw new ArgumentNullException(nameof(priorities)); diff --git a/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs b/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs index 9167e80f900..5cac2b620cf 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs @@ -134,14 +134,15 @@ public IBlockProducer InitBlockProducer(ITxSource? additionalTxSource = null) TxFilterPipelineBuilder.CreateStandardFilteringPipeline( _nethermindApi.LogManager, getFromApi.SpecProvider, - _blocksConfig); + _blocksConfig!); TxPoolTxSource txPoolTxSource = new( getFromApi.TxPool, getFromApi.SpecProvider, transactionComparerProvider, getFromApi.LogManager, - txFilterPipeline); + txFilterPipeline, + _blocksConfig!.GetEip4844Config()); IGasLimitCalculator gasLimitCalculator = setInApi.GasLimitCalculator = new TargetAdjustedGasLimitCalculator(getFromApi.SpecProvider, _blocksConfig); diff --git a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs index 215ae44e976..54347834349 100644 --- a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs @@ -49,6 +49,7 @@ public IBlockProducer InitBlockProducer(ITxSource? additionalTxSource = null) var (getFromApi, _) = _nethermindApi!.ForProducer; + IBlocksConfig blocksConfig = getFromApi.Config(); ReadOnlyBlockTree readOnlyBlockTree = getFromApi.BlockTree.AsReadOnly(); ITxFilterPipeline txFilterPipeline = new TxFilterPipelineBuilder(_nethermindApi.LogManager) @@ -62,7 +63,8 @@ public IBlockProducer InitBlockProducer(ITxSource? additionalTxSource = null) getFromApi.SpecProvider, getFromApi.TransactionComparerProvider!, getFromApi.LogManager, - txFilterPipeline); + txFilterPipeline, + blocksConfig.GetEip4844Config()); ILogger logger = getFromApi.LogManager.GetClassLogger(); if (logger.IsInfo) logger.Info("Starting Neth Dev block producer & sealer"); @@ -102,7 +104,7 @@ public IBlockProducer InitBlockProducer(ITxSource? additionalTxSource = null) getFromApi.BlockTree, getFromApi.Timestamper, getFromApi.SpecProvider, - getFromApi.Config(), + blocksConfig, getFromApi.LogManager); return blockProducer; diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs index f896766bfbd..182d7896a2b 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs @@ -134,7 +134,7 @@ protected virtual TxPoolTxSource CreateTxPoolTxSource( ILogManager logManager) { ITxFilterPipeline txSourceFilterPipeline = CreateTxSourceFilter(blocksConfig); - return new TxPoolTxSource(txPool, _specProvider, transactionComparerProvider, logManager, txSourceFilterPipeline); + return new TxPoolTxSource(txPool, _specProvider, transactionComparerProvider, logManager, txSourceFilterPipeline, _blocksConfig.GetEip4844Config()); } protected virtual ITxFilterPipeline CreateTxSourceFilter(IBlocksConfig blocksConfig) => diff --git a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs index 6bf0215c54a..dded74ac4be 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs @@ -21,30 +21,20 @@ namespace Nethermind.Consensus.Producers { - public class TxPoolTxSource : ITxSource + public class TxPoolTxSource( + ITxPool? transactionPool, + ISpecProvider? specProvider, + ITransactionComparerProvider? transactionComparerProvider, + ILogManager? logManager, + ITxFilterPipeline? txFilterPipeline, + IEip4844Config eip4844Config) + : ITxSource { - private readonly ITxPool _transactionPool; - private readonly ITransactionComparerProvider _transactionComparerProvider; - private readonly ITxFilterPipeline _txFilterPipeline; - private readonly ISpecProvider _specProvider; - protected readonly ILogger _logger; - private readonly IEip4844Config _eip4844Config; - - public TxPoolTxSource( - ITxPool? transactionPool, - ISpecProvider? specProvider, - ITransactionComparerProvider? transactionComparerProvider, - ILogManager? logManager, - ITxFilterPipeline? txFilterPipeline, - IEip4844Config? eip4844ConstantsProvider = null) - { - _transactionPool = transactionPool ?? throw new ArgumentNullException(nameof(transactionPool)); - _transactionComparerProvider = transactionComparerProvider ?? throw new ArgumentNullException(nameof(transactionComparerProvider)); - _txFilterPipeline = txFilterPipeline ?? throw new ArgumentNullException(nameof(txFilterPipeline)); - _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); - _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - _eip4844Config = eip4844ConstantsProvider ?? ConstantEip4844Config.Instance; - } + private readonly ITxPool _transactionPool = transactionPool ?? throw new ArgumentNullException(nameof(transactionPool)); + private readonly ITransactionComparerProvider _transactionComparerProvider = transactionComparerProvider ?? throw new ArgumentNullException(nameof(transactionComparerProvider)); + private readonly ITxFilterPipeline _txFilterPipeline = txFilterPipeline ?? throw new ArgumentNullException(nameof(txFilterPipeline)); + private readonly ISpecProvider _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); + protected readonly ILogger _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); public IEnumerable GetTransactions(BlockHeader parent, long gasLimit, PayloadAttributes? payloadAttributes = null) { @@ -62,7 +52,7 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi int checkedTransactions = 0; int selectedTransactions = 0; - using ArrayPoolList selectedBlobTxs = new(_eip4844Config.GetMaxBlobsPerBlock()); + using ArrayPoolList selectedBlobTxs = new(eip4844Config.GetMaxBlobsPerBlock()); SelectBlobTransactions(blobTransactions, parent, spec, selectedBlobTxs); @@ -128,7 +118,7 @@ private void SelectBlobTransactions(IEnumerable blobTransactions, B foreach (Transaction blobTx in blobTransactions) { - if (blobGasCounter >= _eip4844Config.MaxBlobGasPerBlock) + if (blobGasCounter >= eip4844Config.MaxBlobGasPerBlock) { if (_logger.IsTrace) _logger.Trace($"Declining {blobTx.ToShortString()}, no more blob space. Block already have {blobGasCounter} blob gas which is max value allowed."); break; @@ -136,8 +126,8 @@ private void SelectBlobTransactions(IEnumerable blobTransactions, B checkedBlobTransactions++; - ulong txBlobGas = (ulong)(blobTx.BlobVersionedHashes?.Length ?? 0) * _eip4844Config.GasPerBlob; - if (txBlobGas > _eip4844Config.MaxBlobGasPerBlock - blobGasCounter) + ulong txBlobGas = (ulong)(blobTx.BlobVersionedHashes?.Length ?? 0) * eip4844Config.GasPerBlob; + if (txBlobGas > eip4844Config.MaxBlobGasPerBlock - blobGasCounter) { if (_logger.IsTrace) _logger.Trace($"Declining {blobTx.ToShortString()}, not enough blob space."); continue; diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 335b6f02331..42adf21fd00 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -331,7 +331,7 @@ protected virtual TxPoolTxSource CreateTxPoolTxSource() MinGasPrice = 0 }; ITxFilterPipeline txFilterPipeline = TxFilterPipelineBuilder.CreateStandardFilteringPipeline(LogManager, SpecProvider, blocksConfig); - return new TxPoolTxSource(TxPool, SpecProvider, TransactionComparerProvider, LogManager, txFilterPipeline); + return new TxPoolTxSource(TxPool, SpecProvider, TransactionComparerProvider, LogManager, txFilterPipeline, blocksConfig.GetEip4844Config()); } public BlockBuilder GenesisBlockBuilder { get; set; } = null!; diff --git a/src/Nethermind/Nethermind.Core/IEip4844Config.cs b/src/Nethermind/Nethermind.Core/IEip4844Config.cs index f2c76e77657..e599b8fd222 100644 --- a/src/Nethermind/Nethermind.Core/IEip4844Config.cs +++ b/src/Nethermind/Nethermind.Core/IEip4844Config.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; + namespace Nethermind.Core; /// @@ -24,3 +26,21 @@ private ConstantEip4844Config() { } public static IEip4844Config Instance { get; private set; } } + +public class CappedEip4844Config : IEip4844Config +{ + private const int MinimumBlobs = 1; + private readonly int _maxBlobsPerBlock; + + public CappedEip4844Config(int maxBlobsPerBlockCap) + { + _maxBlobsPerBlock = Math.Min(Eip4844Constants.GetMaxBlobsPerBlock(), Math.Max(MinimumBlobs, maxBlobsPerBlockCap)); + MaxBlobGasPerBlock = GasPerBlob * (ulong)_maxBlobsPerBlock; + } + + public ulong MaxBlobGasPerBlock { get; } + + public ulong GasPerBlob => Eip4844Constants.GasPerBlob; + + public int GetMaxBlobsPerBlock() => _maxBlobsPerBlock; +} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs index fb3f5927289..34fa2e6fc8f 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs @@ -338,7 +338,7 @@ private SyncTestContext CreateSyncManager(int index) MinGasPrice = 0 }; ITxFilterPipeline txFilterPipeline = TxFilterPipelineBuilder.CreateStandardFilteringPipeline(LimboLogs.Instance, specProvider, blocksConfig); - TxPoolTxSource transactionSelector = new(txPool, specProvider, transactionComparerProvider, logManager, txFilterPipeline); + TxPoolTxSource transactionSelector = new(txPool, specProvider, transactionComparerProvider, logManager, txFilterPipeline, ConstantEip4844Config.Instance); DevBlockProducer producer = new( transactionSelector, devChainProcessor,