Skip to content

Commit

Permalink
Reorder constants again; make 4844 settings testable; add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
flcl42 committed Oct 31, 2023
1 parent 5db3668 commit f149583
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 15 deletions.
20 changes: 20 additions & 0 deletions src/Nethermind/Nethermind.Blockchain.Test/TestEip4844Config.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using Nethermind.Core;

namespace Nethermind.Consensus.Producers.Test;

public class TestEip4844Config : IEip4844Config
{
public TestEip4844Config(ulong? maxBlobGasPerBlock = null)
{
MaxBlobGasPerBlock = maxBlobGasPerBlock ?? Eip4844Constants.MaxBlobGasPerBlock;
}

public ulong MaxBlobGasPerBlock { get; }

public ulong GasPerBlob => Eip4844Constants.GasPerBlob;

public int GetMaxBlobsPerBlock() => (int)(MaxBlobGasPerBlock / GasPerBlob);
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ public static IEnumerable Eip1559TestCases
}
}


public static IEnumerable EnoughShardBlobTransactionsSelectedTestCases
{
get
Expand Down
65 changes: 65 additions & 0 deletions src/Nethermind/Nethermind.Blockchain.Test/TxPoolSourceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using Nethermind.Consensus.Transactions;
using Nethermind.Logging;
using Nethermind.Specs.Forks;
using Nethermind.TxPool;
using NUnit.Framework;
using Nethermind.Consensus.Comparers;
using Nethermind.Core.Test.Builders;
using Nethermind.Specs;
using Nethermind.Core;
using System.Linq;
using System.Collections.Generic;
using NSubstitute;

namespace Nethermind.Consensus.Producers.Test;

public class TxPoolSourceTests
{
[TestCaseSource(nameof(BlobTransactionsWithBlobGasLimitPerBlock))]
public void GetTransactions_should_respect_customizable_blob_gas_limit(int[] blobCountPerTx, ulong customMaxBlobGasPerBlock)
{
TestSingleReleaseSpecProvider specProvider = new(Cancun.Instance);
TransactionComparerProvider transactionComparerProvider = new(specProvider, Build.A.BlockTree().TestObject);

ITxPool txPool = Substitute.For<ITxPool>();
Dictionary<Address, Transaction[]> transactionsWithBlobs = blobCountPerTx
.Select((blobsCount, index) => (blobCount: blobsCount, index))
.ToDictionary(
pair => new Address((new byte[19]).Concat(new byte[] { (byte)pair.index }).ToArray()),
pair => new Transaction[] { Build.A.Transaction.WithShardBlobTxTypeAndFields(pair.blobCount).TestObject });
txPool.GetPendingTransactions().Returns(new Transaction[0]);
txPool.GetPendingLightBlobTransactionsBySender().Returns(transactionsWithBlobs);

ITxFilterPipeline txFilterPipeline = Substitute.For<ITxFilterPipeline>();
txFilterPipeline.Execute(Arg.Any<Transaction>(), Arg.Any<BlockHeader>()).Returns(true);

TestEip4844Config eip4844Config = new(customMaxBlobGasPerBlock);

TxPoolTxSource transactionSelector = new(txPool, specProvider, transactionComparerProvider, LimboLogs.Instance, txFilterPipeline, eip4844Config);

IEnumerable<Transaction> txs = transactionSelector.GetTransactions(new BlockHeader { }, long.MaxValue);
int blobsCount = txs.Sum(tx => tx.BlobVersionedHashes?.Length ?? 0);

Assert.Multiple(() =>
{
Assert.That((ulong)blobsCount * eip4844Config.GasPerBlob, Is.LessThanOrEqualTo(eip4844Config.MaxBlobGasPerBlock));
Assert.That(blobsCount, Is.LessThanOrEqualTo(eip4844Config.GetMaxBlobsPerBlock()));
});
}

public static IEnumerable<TestCaseData> BlobTransactionsWithBlobGasLimitPerBlock()
{
yield return new TestCaseData(new int[] { 1, 2, 4 }, Eip4844Constants.GasPerBlob * 6);
yield return new TestCaseData(new int[] { 1, 2, 6 }, Eip4844Constants.GasPerBlob * 6);
yield return new TestCaseData(new int[] { 1, 6 }, Eip4844Constants.GasPerBlob * 6);
yield return new TestCaseData(new int[] { 6, 1, 5 }, Eip4844Constants.GasPerBlob * 6);
yield return new TestCaseData(new int[] { 1, 2 }, Eip4844Constants.GasPerBlob * 2);
yield return new TestCaseData(new int[] { 1, 1 }, Eip4844Constants.GasPerBlob * 2);
yield return new TestCaseData(new int[] { 2, 1 }, Eip4844Constants.GasPerBlob * 2);
yield return new TestCaseData(new int[] { 2, 2 }, Eip4844Constants.GasPerBlob * 2);
yield return new TestCaseData(new int[] { 3 }, Eip4844Constants.GasPerBlob * 2);
}
}
16 changes: 9 additions & 7 deletions src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using Nethermind.Consensus.Transactions;
using Nethermind.Core;
using Nethermind.Core.Collections;
using Nethermind.Core.Extensions;
using Nethermind.Core.Specs;
using Nethermind.Evm;
using Nethermind.Int256;
Expand All @@ -29,19 +28,22 @@ public class TxPoolTxSource : ITxSource
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)
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<TxPoolTxSource>() ?? throw new ArgumentNullException(nameof(logManager));
_eip4844Config = eip4844ConstantsProvider ?? ConstantEip4844Config.Instance;
}

public IEnumerable<Transaction> GetTransactions(BlockHeader parent, long gasLimit, PayloadAttributes? payloadAttributes = null)
Expand All @@ -52,15 +54,15 @@ public IEnumerable<Transaction> GetTransactions(BlockHeader parent, long gasLimi
IDictionary<Address, Transaction[]> pendingTransactions = _transactionPool.GetPendingTransactionsBySender();
IDictionary<Address, Transaction[]> pendingBlobTransactionsEquivalences = _transactionPool.GetPendingLightBlobTransactionsBySender();
IComparer<Transaction> comparer = GetComparer(parent, new BlockPreparationContext(baseFee, blockNumber))
.ThenBy(ByHashTxComparer.Instance); // in order to sort properly and not lose transactions we need to differentiate on their identity which provided comparer might not be doing
.ThenBy(ByHashTxComparer.Instance); // in order to sort properly and not loose transactions we need to differentiate on their identity which provided comparer might not be doing

IEnumerable<Transaction> transactions = GetOrderedTransactions(pendingTransactions, comparer);
IEnumerable<Transaction> blobTransactions = GetOrderedTransactions(pendingBlobTransactionsEquivalences, comparer);
if (_logger.IsDebug) _logger.Debug($"Collecting pending transactions at block gas limit {gasLimit}.");

int checkedTransactions = 0;
int selectedTransactions = 0;
using ArrayPoolList<Transaction> selectedBlobTxs = new(Eip4844Constants.GetMaxBlobsPerBlock());
using ArrayPoolList<Transaction> selectedBlobTxs = new(_eip4844Config.GetMaxBlobsPerBlock());

SelectBlobTransactions(blobTransactions, parent, spec, selectedBlobTxs);

Expand Down Expand Up @@ -126,16 +128,16 @@ private void SelectBlobTransactions(IEnumerable<Transaction> blobTransactions, B

foreach (Transaction blobTx in blobTransactions)
{
if (blobGasCounter >= Eip4844Constants.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;
}

checkedBlobTransactions++;

ulong txBlobGas = (ulong)(blobTx.BlobVersionedHashes?.Length ?? 0) * Eip4844Constants.GasPerBlob;
if (txBlobGas > Eip4844Constants.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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,5 @@ public SinglePendingTxSelector(ITxSource innerSource)
.Take(1);

public override string ToString() => $"{nameof(SinglePendingTxSelector)} [ {_innerSource} ]";

}
}
12 changes: 6 additions & 6 deletions src/Nethermind/Nethermind.Core/Eip4844Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ public class Eip4844Constants
/// <remarks>Defaults to 131072.</remarks>
public const ulong GasPerBlob = 131072;

/// <summary>
/// Gets the <c>TARGET_BLOB_GAS_PER_BLOCK</c> parameter.
/// </summary>
/// <remarks>Defaults to 393216.</remarks>
public static ulong TargetBlobGasPerBlock { get; private set; } = MaxBlobGasPerBlock / 2;

/// <summary>
/// Gets the <c>MAX_BLOB_GAS_PER_BLOCK</c> parameter.
/// </summary>
Expand All @@ -36,6 +30,12 @@ public class Eip4844Constants
/// <remarks>The same as <see cref="MaxBlobGasPerBlock"/>.</remarks>
public static ulong MaxBlobGasPerTransaction => MaxBlobGasPerBlock;

/// <summary>
/// Gets the <c>TARGET_BLOB_GAS_PER_BLOCK</c> parameter.
/// </summary>
/// <remarks>Defaults to 393216.</remarks>
public static ulong TargetBlobGasPerBlock { get; private set; } = MaxBlobGasPerBlock / 2;

/// <summary>
/// Gets the <c>BLOB_GASPRICE_UPDATE_FRACTION</c> parameter.
/// </summary>
Expand Down
26 changes: 26 additions & 0 deletions src/Nethermind/Nethermind.Core/IEip4844Config.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

namespace Nethermind.Core;

/// <summary>
/// <see cref="Eip4844Constants" /> wrapper, made for testing convenience.
/// </summary>
public interface IEip4844Config
{
ulong MaxBlobGasPerBlock { get; }
ulong GasPerBlob { get; }
int GetMaxBlobsPerBlock();
}

public class ConstantEip4844Config : IEip4844Config
{
public ulong MaxBlobGasPerBlock => Eip4844Constants.MaxBlobGasPerBlock;
public ulong GasPerBlob => Eip4844Constants.GasPerBlob;
public int GetMaxBlobsPerBlock() => Eip4844Constants.GetMaxBlobsPerBlock();

static ConstantEip4844Config() => Instance = new ConstantEip4844Config();
private ConstantEip4844Config() { }

public static IEip4844Config Instance { get; private set; }
}

0 comments on commit f149583

Please sign in to comment.