diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs index 540921df412..eef8546f726 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs @@ -35,6 +35,7 @@ using Nethermind.Specs; using Nethermind.State; using Nethermind.Trie.Pruning; +using Nethermind.TxPool; using NSubstitute; using NUnit.Framework; @@ -64,7 +65,7 @@ public void For_not_empty_block_tx_filter_should_be_called() ITxFilter txFilter = Substitute.For(); txFilter .IsAllowed(Arg.Any(), Arg.Any()) - .Returns((true, string.Empty)); + .Returns(AcceptTxResult.Accepted); AuRaBlockProcessor processor = CreateProcessor(txFilter); BlockHeader header = Build.A.BlockHeader.WithAuthor(TestItem.AddressD).WithNumber(3).TestObject; diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/MinGasPriceContractTxFilterTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/MinGasPriceContractTxFilterTests.cs index 8d39a8ebe38..0af5045d52e 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/MinGasPriceContractTxFilterTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/MinGasPriceContractTxFilterTests.cs @@ -26,6 +26,7 @@ using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Int256; +using Nethermind.TxPool; using NSubstitute; using NUnit.Framework; @@ -62,7 +63,7 @@ public bool is_allowed_returns_correct(Address address, ulong gasLimit) MinGasPriceContractTxFilter txFilter = new(minGasPriceFilter, dictionaryContractDataStore); Transaction tx = Build.A.Transaction.WithTo(address).WithGasPrice(gasLimit).WithData(null).TestObject; - return txFilter.IsAllowed(tx, Build.A.BlockHeader.TestObject).Allowed; + return txFilter.IsAllowed(tx, Build.A.BlockHeader.TestObject); } } } diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs index e421a7eb786..8907adbd7c2 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs @@ -32,6 +32,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Logging; using Nethermind.Trie.Pruning; +using Nethermind.TxPool; using NSubstitute; using NSubstitute.ExceptionExtensions; using NUnit.Framework; @@ -53,7 +54,7 @@ public void SetUp() _specProvider = Substitute.For(); _notCertifiedFilter.IsAllowed(Arg.Any(), Arg.Any()) - .Returns((false, string.Empty)); + .Returns(AcceptTxResult.Invalid); _certifierContract.Certified(Arg.Any(), Arg.Is
(a => TestItem.Addresses.Take(3).Contains(a))) @@ -90,7 +91,7 @@ public void should_not_allow_addresses_on_contract_error() public void should_default_to_inner_contract_on_non_zero_transactions(bool expected) { _notCertifiedFilter.IsAllowed(Arg.Any(), Arg.Any()) - .Returns((expected, string.Empty)); + .Returns(expected ? AcceptTxResult.Accepted : AcceptTxResult.Invalid); ShouldAllowAddress(TestItem.Addresses.First(), 1ul, expected); } @@ -99,7 +100,7 @@ private void ShouldAllowAddress(Address address, ulong gasPrice = 0ul, bool expe { _filter.IsAllowed( Build.A.Transaction.WithGasPrice(gasPrice).WithSenderAddress(address).TestObject, - Build.A.BlockHeader.TestObject).Allowed.Should().Be(expected); + Build.A.BlockHeader.TestObject).Equals(AcceptTxResult.Accepted).Should().Be(expected); } [Test] diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs index 1a5f38aeefd..a910ec9c6fb 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs @@ -42,6 +42,7 @@ using Nethermind.Specs.ChainSpecStyle; using Nethermind.State; using Nethermind.Trie.Pruning; +using Nethermind.TxPool; using NSubstitute; using NUnit.Framework; @@ -216,9 +217,9 @@ public static IEnumerable V4Tests() { using TestTxPermissionsBlockchain chain = await chainFactory(); Block? head = chain.BlockTree.Head; - (bool Allowed, string Reason) isAllowed = chain.PermissionBasedTxFilter.IsAllowed(tx, head.Header); + AcceptTxResult isAllowed = chain.PermissionBasedTxFilter.IsAllowed(tx, head.Header); chain.TransactionPermissionContractVersions.Get(head.Header.Hash).Should().Be(version); - return (isAllowed.Allowed, chain.TxPermissionFilterCache.Permissions.Contains((head.Hash, tx.SenderAddress))); + return (isAllowed, chain.TxPermissionFilterCache.Permissions.Contains((head.Hash, tx.SenderAddress))); } private static IEnumerable GetTestCases(IEnumerable tests, string testsName, Func> transactionBuilder) @@ -267,7 +268,7 @@ public bool allows_transactions_before_transitions(long blockNumber) Substitute.For()); PermissionBasedTxFilter filter = new(transactionPermissionContract, new PermissionBasedTxFilter.Cache(), LimboLogs.Instance); - return filter.IsAllowed(Build.A.Transaction.WithSenderAddress(TestItem.AddressB).TestObject, Build.A.BlockHeader.WithNumber(blockNumber).TestObject).Allowed; + return filter.IsAllowed(Build.A.Transaction.WithSenderAddress(TestItem.AddressB).TestObject, Build.A.BlockHeader.WithNumber(blockNumber).TestObject); } public class TestTxPermissionsBlockchain : TestContractBlockchain diff --git a/src/Nethermind/Nethermind.Baseline.Test/BaselineTreeTracker_ReorganizationTests.cs b/src/Nethermind/Nethermind.Baseline.Test/BaselineTreeTracker_ReorganizationTests.cs index 5ae7b3da7ea..cc86e7aeddc 100644 --- a/src/Nethermind/Nethermind.Baseline.Test/BaselineTreeTracker_ReorganizationTests.cs +++ b/src/Nethermind/Nethermind.Baseline.Test/BaselineTreeTracker_ReorganizationTests.cs @@ -90,10 +90,10 @@ private void InsertLeafFromArray(Keccak[] transactions, TestRpcBlockchain testRp transaction.SenderAddress = key.Address; ecdsa.Sign(key, transaction, true); transaction.Hash = transaction.CalculateHash(); - AddTxResult result = testRpc.TxPool.SubmitTx(transaction, TxHandlingOptions.None); - if (result != AddTxResult.Added) + AcceptTxResult isAllowed = testRpc.TxPool.SubmitTx(transaction, TxHandlingOptions.None); + if (!isAllowed) { - throw new Exception("failed to add " + result); + throw new Exception("failed to add " + isAllowed); } } } @@ -111,10 +111,10 @@ private void InsertLeavesFromArray(Keccak[][] transactions, TestRpcBlockchain te transaction.SenderAddress = key.Address; ecdsa.Sign(key, transaction, true); transaction.Hash = transaction.CalculateHash(); - AddTxResult result = testRpc.TxPool.SubmitTx(transaction, TxHandlingOptions.None); - if (result != AddTxResult.Added) + AcceptTxResult isAllowed = testRpc.TxPool.SubmitTx(transaction, TxHandlingOptions.None); + if (!isAllowed) { - throw new Exception("failed to add " + result); + throw new Exception("failed to add " + isAllowed); } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs index b95c9070469..2d5d50021c4 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs @@ -134,7 +134,7 @@ private async Task SendTransactionAsync(long gasLimit, UInt256 }; var (_, result) = await _testRpcBlockchain.TxSender.SendTransaction(tx, TxHandlingOptions.None); - Assert.AreEqual(AddTxResult.Added, result); + Assert.AreEqual(AcceptTxResult.Accepted, result); return this; } diff --git a/src/Nethermind/Nethermind.Blockchain/TxFilterAdapter.cs b/src/Nethermind/Nethermind.Blockchain/TxFilterAdapter.cs index 4ecbd93ea54..0ee9967b263 100644 --- a/src/Nethermind/Nethermind.Blockchain/TxFilterAdapter.cs +++ b/src/Nethermind/Nethermind.Blockchain/TxFilterAdapter.cs @@ -37,23 +37,23 @@ public TxFilterAdapter(IBlockTree blockTree, ITxFilter txFilter, ILogManager log _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); } - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions txHandlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions txHandlingOptions) { if (tx is not GeneratedTransaction) { BlockHeader parentHeader = _blockTree.Head?.Header; - if (parentHeader == null) return (true, null); + if (parentHeader == null) return AcceptTxResult.Accepted; - (bool accepted, string? reason) = _txFilter.IsAllowed(tx, parentHeader); - if (reason is not null) + AcceptTxResult isAllowed = _txFilter.IsAllowed(tx, parentHeader); + if (!isAllowed) { - if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, filtered ({reason})."); + if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, filtered ({isAllowed})."); } - return (accepted, reason is null ? null : AddTxResult.Filtered); + return isAllowed; } - return (true, null); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs index 810c0fce849..8272aab1940 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs @@ -31,6 +31,7 @@ using Nethermind.Evm.Tracing; using Nethermind.Logging; using Nethermind.State; +using Nethermind.TxPool; namespace Nethermind.Consensus.AuRa { @@ -138,7 +139,7 @@ private void OnAddingTransaction(object? sender, AddingTxEventArgs e) private AddingTxEventArgs CheckTxPosdaoRules(AddingTxEventArgs args) { - (bool Allowed, string Reason)? TryRecoverSenderAddress(Transaction tx, BlockHeader header) + AcceptTxResult? TryRecoverSenderAddress(Transaction tx, BlockHeader header) { if (tx.Signature != null) { @@ -157,15 +158,15 @@ private AddingTxEventArgs CheckTxPosdaoRules(AddingTxEventArgs args) } BlockHeader parentHeader = GetParentHeader(args.Block); - (bool Allowed, string Reason) txFilterResult = _txFilter.IsAllowed(args.Transaction, parentHeader); - if (!txFilterResult.Allowed) + AcceptTxResult isAllowed = _txFilter.IsAllowed(args.Transaction, parentHeader); + if (!isAllowed) { - txFilterResult = TryRecoverSenderAddress(args.Transaction, parentHeader) ?? txFilterResult; + isAllowed = TryRecoverSenderAddress(args.Transaction, parentHeader) ?? isAllowed; } - if (!txFilterResult.Allowed) + if (!isAllowed) { - args.Set(TxAction.Skip, txFilterResult.Reason); + args.Set(TxAction.Skip, isAllowed.ToString()); } return args; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/AcceptTxResultAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/AcceptTxResultAuRa.cs new file mode 100644 index 00000000000..578cb694022 --- /dev/null +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/AcceptTxResultAuRa.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2021 Demerzel Solutions Limited +// This file is part of the Nethermind library. +// +// The Nethermind library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Nethermind library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Nethermind. If not, see . +// + +using Nethermind.TxPool; + +namespace Nethermind.Consensus.AuRa.Transactions +{ + public readonly struct AcceptTxResultAuRa + { + /// + /// Permission denied for this tx type. + /// + public static readonly AcceptTxResult PermissionDenied = new(100, nameof(PermissionDenied)); + } +} diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/LocalTxFilter.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/LocalTxFilter.cs index 665f00fb9aa..ff92f28f062 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/LocalTxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/LocalTxFilter.cs @@ -18,6 +18,7 @@ using System; using Nethermind.Consensus.Transactions; using Nethermind.Core; +using Nethermind.TxPool; namespace Nethermind.Consensus.AuRa.Transactions { @@ -30,14 +31,14 @@ public LocalTxFilter(ISigner signer) _signer = signer; } - public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) + public AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader) { if (tx.SenderAddress == _signer.Address) { tx.IsServiceTransaction = true; } - return (true, string.Empty); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/MinGasPriceContractTxFilter.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/MinGasPriceContractTxFilter.cs index 025e2f3df06..a1734e42cb6 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/MinGasPriceContractTxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/MinGasPriceContractTxFilter.cs @@ -20,6 +20,7 @@ using Nethermind.Consensus.AuRa.Contracts.DataStore; using Nethermind.Consensus.Transactions; using Nethermind.Core; +using Nethermind.TxPool; namespace Nethermind.Consensus.AuRa.Transactions { @@ -35,19 +36,19 @@ public MinGasPriceContractTxFilter(IMinGasPriceTxFilter minGasPriceFilter, IDict } - public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) + public AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader) { - (bool Allowed, string Reason) result = _minGasPriceFilter.IsAllowed(tx, parentHeader); - if (!result.Allowed) + AcceptTxResult isAllowed = _minGasPriceFilter.IsAllowed(tx, parentHeader); + if (!isAllowed) { - return result; + return isAllowed; } else if (_minGasPrices.TryGetValue(parentHeader, tx, out TxPriorityContract.Destination @override)) { return _minGasPriceFilter.IsAllowed(tx, parentHeader, @override.Value); } - return (true, string.Empty); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/ServiceTxFilter.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/ServiceTxFilter.cs index e1e517bed49..a8b17f886e6 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/ServiceTxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/ServiceTxFilter.cs @@ -19,6 +19,7 @@ using Nethermind.Consensus.Transactions; using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.TxPool; namespace Nethermind.Consensus.AuRa.Transactions { @@ -31,14 +32,14 @@ public ServiceTxFilter(ISpecProvider specProvider) _specProvider = specProvider; } - public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) + public AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader) { if (tx.IsZeroGasPrice(parentHeader, _specProvider)) { tx.IsServiceTransaction = true; } - return (true, string.Empty); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxCertifierFilter.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxCertifierFilter.cs index 3a71ea2adf7..8bcedfdf416 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxCertifierFilter.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxCertifierFilter.cs @@ -27,6 +27,7 @@ using Nethermind.Core.Resettables; using Nethermind.Core.Specs; using Nethermind.Logging; +using Nethermind.TxPool; namespace Nethermind.Consensus.AuRa.Transactions { @@ -47,8 +48,8 @@ public TxCertifierFilter(ICertifierContract certifierContract, ITxFilter notCert _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); } - public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) => - IsCertified(tx, parentHeader) ? (true, string.Empty) : _notCertifiedFilter.IsAllowed(tx, parentHeader); + public AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader) => + IsCertified(tx, parentHeader) ? AcceptTxResult.Accepted : _notCertifiedFilter.IsAllowed(tx, parentHeader); private bool IsCertified(Transaction tx, BlockHeader parentHeader) { diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxGasPriceSender.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxGasPriceSender.cs index 1bca471cde3..5605e838213 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxGasPriceSender.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxGasPriceSender.cs @@ -42,7 +42,7 @@ public TxGasPriceSender( _percentDelta = percentDelta; } - public ValueTask<(Keccak, AddTxResult?)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions) + public ValueTask<(Keccak, AcceptTxResult?)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions) { UInt256 gasPriceEstimated = _gasPriceOracle.GetGasPriceEstimate() * _percentDelta / 100; tx.DecodedMaxFeePerGas = gasPriceEstimated; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPermissionFilter.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPermissionFilter.cs index 8676b47f169..c5622c4631c 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPermissionFilter.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPermissionFilter.cs @@ -25,6 +25,7 @@ using Nethermind.Core.Crypto; using Nethermind.Logging; using Nethermind.State; +using Nethermind.TxPool; namespace Nethermind.Consensus.AuRa.Transactions { @@ -44,18 +45,18 @@ public PermissionBasedTxFilter( _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); } - public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) + public AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader) { if (parentHeader.Number + 1 < _contract.Activation) { - return (true, string.Empty); + return AcceptTxResult.Accepted; } var txPermissions = GetPermissions(tx, parentHeader); var txType = GetTxType(tx, txPermissions.ContractExists); if (_logger.IsTrace) _logger.Trace($"Given transaction: {tx.Hash} sender: {tx.SenderAddress} to: {tx.To} value: {tx.Value}, gas_price: {tx.GasPrice}. " + $"Permissions required: {txType}, got: {txPermissions}."); - return (txPermissions.Permissions & txType) == txType ? (true, string.Empty) : (false, $"permission denied for tx type: {txType}, actual permissions: {txPermissions.Permissions}"); + return (txPermissions.Permissions & txType) == txType ? AcceptTxResult.Accepted : AcceptTxResultAuRa.PermissionDenied.WithMessage($"permission denied for tx type: {txType}, actual permissions: {txPermissions.Permissions}"); } private (ITransactionPermissionContract.TxPermissions Permissions, bool ContractExists) GetPermissions(Transaction tx, BlockHeader parentHeader) diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/BaseFeeTxFilter.cs b/src/Nethermind/Nethermind.Consensus/Transactions/BaseFeeTxFilter.cs index 01a9049f8a0..0e66f77258f 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/BaseFeeTxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/BaseFeeTxFilter.cs @@ -18,11 +18,11 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; -using Nethermind.Logging; +using Nethermind.TxPool; namespace Nethermind.Consensus.Transactions { - /// Filtering transactions that have lower FeeCap than BaseFee + /// Filtering transactions that have lower MaxFeePerGas than BaseFee public class BaseFeeTxFilter : ITxFilter { private readonly ISpecProvider _specProvider; @@ -33,7 +33,7 @@ public BaseFeeTxFilter( _specProvider = specProvider; } - public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) + public AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader) { long blockNumber = parentHeader.Number + 1; IReleaseSpec releaseSpec = _specProvider.GetSpec(blockNumber); @@ -42,10 +42,10 @@ public BaseFeeTxFilter( bool skipCheck = tx.IsServiceTransaction || !isEip1559Enabled; bool allowed = skipCheck || tx.MaxFeePerGas >= baseFee; - return (allowed, - allowed - ? string.Empty - : $"FeeCap too low. FeeCap: {tx.MaxFeePerGas}, BaseFee: {baseFee}, GasPremium:{tx.MaxPriorityFeePerGas}, Block number: {blockNumber}"); + return allowed + ? AcceptTxResult.Accepted + : AcceptTxResult.FeeTooLow.WithMessage( + $"MaxFeePerGas too low. MaxFeePerGas: {tx.MaxFeePerGas}, BaseFee: {baseFee}, MaxPriorityFeePerGas:{tx.MaxPriorityFeePerGas}, Block number: {blockNumber}"); } } } diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/CompositeTxFilter.cs b/src/Nethermind/Nethermind.Consensus/Transactions/CompositeTxFilter.cs index da69a8b2a0d..2a9fcc11cb1 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/CompositeTxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/CompositeTxFilter.cs @@ -18,6 +18,7 @@ using System; using System.Linq; using Nethermind.Core; +using Nethermind.TxPool; namespace Nethermind.Consensus.Transactions { @@ -30,18 +31,18 @@ public CompositeTxFilter(params ITxFilter[] txFilters) _txFilters = txFilters?.Where(f => f != null).ToArray() ?? Array.Empty(); } - public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) + public AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader) { for (int i = 0; i < _txFilters.Length; i++) { - (bool, string) result = _txFilters[i].IsAllowed(tx, parentHeader); - if (!result.Item1) + AcceptTxResult isAllowed = _txFilters[i].IsAllowed(tx, parentHeader); + if (!isAllowed) { - return result; + return isAllowed; } } - return (true, string.Empty); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/FilteredTxSource.cs b/src/Nethermind/Nethermind.Consensus/Transactions/FilteredTxSource.cs index 2a8fa937b28..08b3aed3a50 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/FilteredTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/FilteredTxSource.cs @@ -20,6 +20,7 @@ using Nethermind.Core; using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.TxPool; namespace Nethermind.Consensus.Transactions { @@ -42,15 +43,15 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi { if (tx is T) { - (bool allowed, string reason) = _txFilter.IsAllowed(tx, parent); - if (allowed) + AcceptTxResult acceptTxResult= _txFilter.IsAllowed(tx, parent); + if (acceptTxResult) { if (_logger.IsTrace) _logger.Trace($"Selected {tx.ToShortString()} to be included in block."); yield return tx; } else { - if (_logger.IsDebug) _logger.Debug($"Rejecting ({reason}) {tx.ToShortString()}"); + if (_logger.IsDebug) _logger.Debug($"Rejecting ({acceptTxResult}) {tx.ToShortString()}"); } } else diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/IMinGasPriceTxFilter.cs b/src/Nethermind/Nethermind.Consensus/Transactions/IMinGasPriceTxFilter.cs index 53ebfe414b7..6b2228ed9b5 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/IMinGasPriceTxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/IMinGasPriceTxFilter.cs @@ -17,6 +17,7 @@ using Nethermind.Core; using Nethermind.Int256; +using Nethermind.TxPool; namespace Nethermind.Consensus.Transactions { @@ -27,6 +28,6 @@ public interface IMinGasPriceTxFilter : ITxFilter * The additional method allows us to specify a custom min gas price floor. */ - (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader, in UInt256 minGasPriceFloor); + AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader, in UInt256 minGasPriceFloor); } } diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/ITxFilter.cs b/src/Nethermind/Nethermind.Consensus/Transactions/ITxFilter.cs index fbb93b6981c..5fb305c1664 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/ITxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/ITxFilter.cs @@ -16,11 +16,12 @@ // using Nethermind.Core; +using Nethermind.TxPool; namespace Nethermind.Consensus.Transactions { public interface ITxFilter { - (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader); + AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader); } } diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/MinGasPriceTxFilter.cs b/src/Nethermind/Nethermind.Consensus/Transactions/MinGasPriceTxFilter.cs index 25a6ee45f45..82e6681122e 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/MinGasPriceTxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/MinGasPriceTxFilter.cs @@ -18,6 +18,7 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; +using Nethermind.TxPool; namespace Nethermind.Consensus.Transactions { @@ -37,12 +38,12 @@ public MinGasPriceTxFilter( _specProvider = specProvider; } - public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) + public AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader) { return IsAllowed(tx, parentHeader, _minGasPrice); } - public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader? parentHeader, in UInt256 minGasPriceFloor) + public AcceptTxResult IsAllowed(Transaction tx, BlockHeader? parentHeader, in UInt256 minGasPriceFloor) { UInt256 premiumPerGas = tx.GasPrice; UInt256 baseFeePerGas = UInt256.Zero; @@ -55,7 +56,10 @@ public MinGasPriceTxFilter( } bool allowed = premiumPerGas >= minGasPriceFloor; - return (allowed, allowed ? string.Empty : $"EffectivePriorityFeePerGas too low {premiumPerGas} < {minGasPriceFloor}, BaseFee: {baseFeePerGas}"); + return allowed + ? AcceptTxResult.Accepted + : AcceptTxResult.FeeTooLow.WithMessage( + $"EffectivePriorityFeePerGas too low {premiumPerGas} < {minGasPriceFloor}, BaseFee: {baseFeePerGas}"); } } } diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/NullTxFilter.cs b/src/Nethermind/Nethermind.Consensus/Transactions/NullTxFilter.cs index e47ec47cc28..5f58ef4ed53 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/NullTxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/NullTxFilter.cs @@ -16,12 +16,13 @@ // using Nethermind.Core; +using Nethermind.TxPool; namespace Nethermind.Consensus.Transactions { public class NullTxFilter : ITxFilter { - public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) => (true, string.Empty); + public AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader) => AcceptTxResult.Accepted; public static readonly NullTxFilter Instance = new(); } diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipeline.cs b/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipeline.cs index 95aceac17c9..8058ad2b381 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipeline.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipeline.cs @@ -20,6 +20,7 @@ using System.Linq; using Nethermind.Core; using Nethermind.Logging; +using Nethermind.TxPool; namespace Nethermind.Consensus.Transactions { @@ -48,10 +49,10 @@ public bool Execute(Transaction tx, BlockHeader parentHeader) foreach (ITxFilter filter in _filters) { - var result = filter.IsAllowed(tx, parentHeader); - if ( !result.Allowed) + AcceptTxResult isAllowed = filter.IsAllowed(tx, parentHeader); + if (!isAllowed) { - if (_logger.IsDebug) _logger.Debug($"Rejected tx ({result.Reason}) {tx.ToShortString()}"); + if (_logger.IsDebug) _logger.Debug($"Rejected tx ({isAllowed}) {tx.ToShortString()}"); return false; } } diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 181950a5f49..326cc67b8d7 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -325,10 +325,10 @@ public async Task AddBlock(bool shouldWaitForHead = true, params Transaction[] t _oneAtATime.Set(); } - private async Task AddBlockInternal(params Transaction[] transactions) + private async Task AddBlockInternal(params Transaction[] transactions) { await WaitAsync(_oneAtATime, "Multiple block produced at once."); - AddTxResult[] txResults = transactions.Select(t => TxPool.SubmitTx(t, TxHandlingOptions.None)).ToArray(); + AcceptTxResult[] txResults = transactions.Select(t => TxPool.SubmitTx(t, TxHandlingOptions.None)).ToArray(); Timestamper.Add(TimeSpan.FromSeconds(1)); await BlockProductionTrigger.BuildBlock(); return txResults; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index 0ffe668c019..c6d7100f413 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -741,7 +741,7 @@ public async Task Send_transaction_with_signature_will_not_try_to_sign() using Context ctx = await Context.Create(); ITxSender txSender = Substitute.For(); IBlockchainBridge bridge = Substitute.For(); - txSender.SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast).Returns((TestItem.KeccakA, AddTxResult.Added)); + txSender.SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast).Returns((TestItem.KeccakA, AcceptTxResult.Accepted)); ctx._test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).WithTxSender(txSender).Build(); Transaction tx = Build.A.Transaction.Signed(new EthereumEcdsa(ChainId.Mainnet, LimboLogs.Instance), TestItem.PrivateKeyA).TestObject; @@ -757,7 +757,7 @@ public async Task Send_raw_transaction_will_send_transaction(string rawTransacti using Context ctx = await Context.Create(); ITxSender txSender = Substitute.For(); IBlockchainBridge bridge = Substitute.For(); - txSender.SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast).Returns((TestItem.KeccakA, AddTxResult.Added)); + txSender.SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast).Returns((TestItem.KeccakA, AcceptTxResult.Accepted)); ctx._test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).WithTxSender(txSender).Build(); string serialized = ctx._test.TestEthRpc("eth_sendRawTransaction", rawTransaction); @@ -773,7 +773,7 @@ public async Task Send_transaction_without_signature_will_not_set_nonce_when_zer ITxSender txSender = Substitute.For(); IBlockchainBridge bridge = Substitute.For(); txSender.SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast) - .Returns((TestItem.KeccakA, AddTxResult.Added)); + .Returns((TestItem.KeccakA, AcceptTxResult.Accepted)); ctx._test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev) .WithBlockchainBridge(bridge).WithTxSender(txSender).Build(); @@ -793,7 +793,7 @@ public async Task Send_transaction_without_signature_will_manage_nonce_when_null ITxSender txSender = Substitute.For(); IBlockchainBridge bridge = Substitute.For(); txSender.SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast | TxHandlingOptions.ManagedNonce) - .Returns((TestItem.KeccakA, AddTxResult.Added)); + .Returns((TestItem.KeccakA, AcceptTxResult.Accepted)); ctx._test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev) .WithBlockchainBridge(bridge).WithTxSender(txSender).Build(); @@ -815,7 +815,7 @@ public async Task Send_transaction_should_return_ErrorCode_if_tx_not_added() string serialized = ctx._test.TestEthRpc("eth_sendTransaction", new EthereumJsonSerializer().Serialize(txForRpc)); - Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32010,\"message\":\"InsufficientFunds\"},\"id\":67}", serialized); + Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32010,\"message\":\"InsufficientFunds, Account balance: 0, cumulative cost: 31000\"},\"id\":67}", serialized); } public enum AccessListProvided diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index 4c82f1ddae4..12a9a8c43f2 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -343,12 +343,12 @@ private async Task> SendTx(Transaction tx, { try { - (Keccak txHash, AddTxResult? addTxResult) = + (Keccak txHash, AcceptTxResult? acceptTxResult) = await _txSender.SendTransaction(tx, txHandlingOptions | TxHandlingOptions.PersistentBroadcast); - return addTxResult == AddTxResult.Added + return acceptTxResult.Equals(AcceptTxResult.Accepted) ? ResultWrapper.Success(txHash) - : ResultWrapper.Fail(addTxResult?.ToString() ?? string.Empty, ErrorCodes.TransactionRejected); + : ResultWrapper.Fail(acceptTxResult?.ToString() ?? string.Empty, ErrorCodes.TransactionRejected); } catch (SecurityException e) { diff --git a/src/Nethermind/Nethermind.Mining.Test/MinGasPriceTests.cs b/src/Nethermind/Nethermind.Mining.Test/MinGasPriceTests.cs index d040c3be67d..77e4138d36b 100644 --- a/src/Nethermind/Nethermind.Mining.Test/MinGasPriceTests.cs +++ b/src/Nethermind/Nethermind.Mining.Test/MinGasPriceTests.cs @@ -22,6 +22,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Int256; using Nethermind.Specs; +using Nethermind.TxPool; using NSubstitute; using NUnit.Framework; @@ -44,7 +45,7 @@ public void Test(long minimum, long actual, bool expectedResult) }); MinGasPriceTxFilter _filter = new MinGasPriceTxFilter((UInt256)minimum, specProvider); Transaction tx = Build.A.Transaction.WithGasPrice((UInt256)actual).TestObject; - _filter.IsAllowed(tx, null).Allowed.Should().Be(expectedResult); + _filter.IsAllowed(tx, null).Equals(expectedResult ? AcceptTxResult.Accepted : AcceptTxResult.FeeTooLow).Should().BeTrue(); } [TestCase(0L, 0L, 0L, true)] @@ -69,7 +70,7 @@ public void Test1559(long minimum, long maxFeePerGas, long maxPriorityFeePerGas, .WithMaxPriorityFeePerGas((UInt256)maxPriorityFeePerGas) .WithType(TxType.EIP1559).TestObject; BlockBuilder blockBuilder = Core.Test.Builders.Build.A.Block.Genesis.WithGasLimit(10000).WithBaseFeePerGas((UInt256)1000); - _filter.IsAllowed(tx, blockBuilder.TestObject.Header).Allowed.Should().Be(expectedResult); + _filter.IsAllowed(tx, blockBuilder.TestObject.Header).Equals(expectedResult ? AcceptTxResult.Accepted : AcceptTxResult.FeeTooLow).Should().BeTrue(); } } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs index bea79a1586f..218d4ba3c4b 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs @@ -200,11 +200,11 @@ protected void Handle(TransactionsMessage msg) Transaction tx = transactions[i]; tx.DeliveredBy = Node.Id; tx.Timestamp = _timestamper.UnixTime.Seconds; - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.None); - _floodController.Report(result == AddTxResult.Added); + AcceptTxResult accepted = _txPool.SubmitTx(tx, TxHandlingOptions.None); + _floodController.Report(accepted); if (Logger.IsTrace) Logger.Trace( - $"{Node:c} sent {tx.Hash} tx and it was {result} (chain ID = {tx.Signature?.ChainId})"); + $"{Node:c} sent {tx.Hash} tx and it was {accepted} (chain ID = {tx.Signature?.ChainId})"); } } diff --git a/src/Nethermind/Nethermind.Provide.Vault/VaultTxSender.cs b/src/Nethermind/Nethermind.Provide.Vault/VaultTxSender.cs index eae507bf1dc..84a91c0bd6f 100644 --- a/src/Nethermind/Nethermind.Provide.Vault/VaultTxSender.cs +++ b/src/Nethermind/Nethermind.Provide.Vault/VaultTxSender.cs @@ -108,7 +108,7 @@ private async Task EnsureAccount() } } - public async ValueTask<(Keccak, AddTxResult?)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions) + public async ValueTask<(Keccak, AcceptTxResult?)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions) { await EnsureAccount(); ProvideTx provideTx = new ProvideTx(); diff --git a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs index 283b340f2ac..fac1bac70d9 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs @@ -106,9 +106,9 @@ public void should_ignore_transactions_with_different_chain_id() _txPool = CreatePool(); EthereumEcdsa ecdsa = new EthereumEcdsa(ChainId.Mainnet, _logManager); Transaction tx = Build.A.Transaction.SignedAndResolved(ecdsa, TestItem.PrivateKeyA).TestObject; - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(0); - result.Should().Be(AddTxResult.Invalid); + result.Should().Be(AcceptTxResult.Invalid); } [Test] @@ -127,9 +127,9 @@ public void should_ignore_transactions_with_insufficient_intrinsic_gas() .SignedAndResolved() .TestObject; - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(0); - result.Should().Be(AddTxResult.Invalid); + result.Should().Be(AcceptTxResult.Invalid);; } [Test] @@ -138,9 +138,9 @@ public void should_not_ignore_old_scheme_signatures() _txPool = CreatePool(); Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, false).TestObject; EnsureSenderBalance(tx); - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(1); - result.Should().Be(AddTxResult.Added); + result.Should().Be(AcceptTxResult.Accepted); } [Test] @@ -149,11 +149,11 @@ public void should_ignore_already_known() _txPool = CreatePool(); Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; EnsureSenderBalance(tx); - AddTxResult result1 = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); - AddTxResult result2 = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result1 = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result2 = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(1); - result1.Should().Be(AddTxResult.Added); - result2.Should().Be(AddTxResult.AlreadyKnown); + result1.Should().Be(AcceptTxResult.Accepted); + result2.Should().Be(AcceptTxResult.AlreadyKnown); } [Test] @@ -165,9 +165,9 @@ public void should_add_valid_transactions_recovering_its_address() .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; EnsureSenderBalance(tx); tx.SenderAddress = null; - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(1); - result.Should().Be(AddTxResult.Added); + result.Should().Be(AcceptTxResult.Accepted); } [Test] @@ -179,8 +179,8 @@ public void should_reject_transactions_from_contract_address() .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; EnsureSenderBalance(tx); _stateProvider.UpdateCodeHash(TestItem.AddressA, TestItem.KeccakA, _specProvider.GetSpec(1)); - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); - result.Should().Be(AddTxResult.SenderIsContract); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + result.Should().Be(AcceptTxResult.SenderIsContract); } @@ -202,9 +202,9 @@ public void should_accept_1559_transactions_only_when_eip1559_enabled([Values(fa .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; EnsureSenderBalance(tx); _blockTree.BlockAddedToMain += Raise.EventWith(_blockTree, new BlockReplacementEventArgs(Build.A.Block.WithGasLimit(10000000).TestObject)); - AddTxResult result = txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); txPool.GetPendingTransactions().Length.Should().Be(eip1559Enabled ? 1 : 0); - result.Should().Be(eip1559Enabled ? AddTxResult.Added : AddTxResult.Invalid); + result.Should().Be(eip1559Enabled ? AcceptTxResult.Accepted : AcceptTxResult.Invalid); } [Test] @@ -218,21 +218,21 @@ public void should_ignore_insufficient_funds_for_eip1559_transactions() .WithChainId(ChainId.Mainnet) .WithValue(5).SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; EnsureSenderBalance(tx.SenderAddress, tx.Value - 1); // we should have InsufficientFunds only when balance < tx.Value - AddTxResult result = txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); txPool.GetPendingTransactions().Length.Should().Be(0); - result.Should().Be(AddTxResult.InsufficientFunds); + result.Should().Be(AcceptTxResult.InsufficientFunds); EnsureSenderBalance(tx.SenderAddress, tx.Value); _blockTree.BlockAddedToMain += Raise.EventWith(_blockTree, new BlockReplacementEventArgs(Build.A.Block.WithGasLimit(10000000).TestObject)); result = txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); - result.Should().Be(AddTxResult.Added); + result.Should().Be(AcceptTxResult.Accepted); txPool.GetPendingTransactions().Length.Should().Be(1); } - [TestCase(false, false, ExpectedResult = AddTxResult.Added)] - [TestCase(false, true, ExpectedResult = AddTxResult.Added)] - [TestCase(true, false, ExpectedResult = AddTxResult.Added)] - [TestCase(true, true, ExpectedResult = AddTxResult.SenderIsContract)] - public AddTxResult should_reject_transactions_with_deployed_code_when_eip3607_enabled(bool eip3607Enabled, bool hasCode) + [TestCase(false, false, ExpectedResult = nameof(AcceptTxResult.Accepted))] + [TestCase(false, true, ExpectedResult = nameof(AcceptTxResult.Accepted))] + [TestCase(true, false, ExpectedResult = nameof(AcceptTxResult.Accepted))] + [TestCase(true, true, ExpectedResult = nameof(AcceptTxResult.SenderIsContract))] + public string should_reject_transactions_with_deployed_code_when_eip3607_enabled(bool eip3607Enabled, bool hasCode) { ISpecProvider specProvider = new OverridableSpecProvider(new TestSpecProvider(London.Instance), r => new OverridableReleaseSpec(r) {IsEip3607Enabled = eip3607Enabled}); TxPool txPool = CreatePool(null, specProvider); @@ -241,7 +241,7 @@ public AddTxResult should_reject_transactions_with_deployed_code_when_eip3607_en EnsureSenderBalance(tx); _stateProvider.UpdateCodeHash(TestItem.AddressA, hasCode ? TestItem.KeccakH : Keccak.OfAnEmptyString, London.Instance); - return txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + return txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast).ToString(); } [Test] @@ -249,9 +249,9 @@ public void should_ignore_insufficient_funds_transactions() { _txPool = CreatePool(); Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(0); - result.Should().Be(AddTxResult.InsufficientFunds); + result.Should().Be(AcceptTxResult.InsufficientFunds); } [Test] @@ -261,9 +261,9 @@ public void should_ignore_old_nonce_transactions() Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; EnsureSenderBalance(tx); _stateProvider.IncrementNonce(tx.SenderAddress); - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(0); - result.Should().Be(AddTxResult.OldNonce); + result.Should().Be(AcceptTxResult.OldNonce); } [Test] @@ -275,9 +275,9 @@ public void should_ignore_overflow_transactions() .WithValue(Transaction.BaseTxGasCost) .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; EnsureSenderBalance(tx); - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(0); - result.Should().Be(AddTxResult.Int256Overflow); + result.Should().Be(AcceptTxResult.Int256Overflow); } [Test] @@ -294,9 +294,9 @@ public void should_ignore_overflow_transactions_gas_premium_and_fee_cap() .WithType(TxType.EIP1559) .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; EnsureSenderBalance(tx.SenderAddress, UInt256.MaxValue); - AddTxResult result = txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); txPool.GetPendingTransactions().Length.Should().Be(0); - result.Should().Be(AddTxResult.Int256Overflow); + result.Should().Be(AcceptTxResult.Int256Overflow); } [Test] @@ -308,9 +308,9 @@ public void should_ignore_block_gas_limit_exceeded() .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; EnsureSenderBalance(tx); _headInfo.BlockGasLimit = Transaction.BaseTxGasCost * 4; - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(0); - result.Should().Be(AddTxResult.GasLimitExceeded); + result.Should().Be(AcceptTxResult.GasLimitExceeded); } [Test] @@ -321,20 +321,20 @@ public void should_ignore_tx_gas_limit_exceeded() .WithGasLimit(_txGasLimit + 1) .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; EnsureSenderBalance(tx); - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(0); - result.Should().Be(AddTxResult.GasLimitExceeded); + result.Should().Be(AcceptTxResult.GasLimitExceeded); } - [TestCase(10,0, AddTxResult.FeeTooLow)] - [TestCase(10,5, AddTxResult.FeeTooLow)] - [TestCase(10,6, AddTxResult.InsufficientFunds)] - [TestCase(11,0, AddTxResult.Added)] - [TestCase(11,4, AddTxResult.Added)] - [TestCase(11,5, AddTxResult.InsufficientFunds)] - [TestCase(15,0, AddTxResult.Added)] - [TestCase(16,0, AddTxResult.InsufficientFunds)] - public void should_handle_adding_tx_to_full_txPool_properly(int gasPrice, int value, AddTxResult expected) + [TestCase(10,0, nameof(AcceptTxResult.FeeTooLow))] + [TestCase(10,5, nameof(AcceptTxResult.FeeTooLow))] + [TestCase(10,6, nameof(AcceptTxResult.InsufficientFunds))] + [TestCase(11,0, nameof(AcceptTxResult.Accepted))] + [TestCase(11,4, nameof(AcceptTxResult.Accepted))] + [TestCase(11,5, nameof(AcceptTxResult.InsufficientFunds))] + [TestCase(15,0, nameof(AcceptTxResult.Accepted))] + [TestCase(16,0, nameof(AcceptTxResult.InsufficientFunds))] + public void should_handle_adding_tx_to_full_txPool_properly(int gasPrice, int value, string expected) { _txPool = CreatePool(new TxPoolConfig() {Size = 30}); Transaction[] transactions = GetTransactions(GetPeers(3), true, false); @@ -356,20 +356,20 @@ public void should_handle_adding_tx_to_full_txPool_properly(int gasPrice, int va tx.Value = (UInt256)(value * tx.GasLimit); EnsureSenderBalance(tx.SenderAddress, (UInt256)(15 * tx.GasLimit)); _txPool.GetPendingTransactions().Length.Should().Be(30); - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); - result.Should().Be(expected); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + result.ToString().Should().Contain(expected); } - [TestCase(10,0, AddTxResult.FeeTooLow)] - [TestCase(11,0, AddTxResult.Added)] - [TestCase(11,4, AddTxResult.Added)] - [TestCase(11,5, AddTxResult.FeeTooLow)] - [TestCase(11,15, AddTxResult.FeeTooLow)] - [TestCase(11,16, AddTxResult.InsufficientFunds)] - [TestCase(50,0, AddTxResult.Invalid)] - [TestCase(50,15, AddTxResult.Invalid)] - [TestCase(50,16, AddTxResult.Invalid)] - public void should_handle_adding_1559_tx_to_full_txPool_properly(int gasPremium, int value, AddTxResult expected) + [TestCase(10,0, nameof(AcceptTxResult.FeeTooLow))] + [TestCase(11,0, nameof(AcceptTxResult.Accepted))] + [TestCase(11,4, nameof(AcceptTxResult.Accepted))] + [TestCase(11,5, nameof(AcceptTxResult.FeeTooLow))] + [TestCase(11,15, nameof(AcceptTxResult.FeeTooLow))] + [TestCase(11,16, nameof(AcceptTxResult.InsufficientFunds))] + [TestCase(50,0, nameof(AcceptTxResult.Invalid))] + [TestCase(50,15, nameof(AcceptTxResult.Invalid))] + [TestCase(50,16, nameof(AcceptTxResult.Invalid))] + public void should_handle_adding_1559_tx_to_full_txPool_properly(int gasPremium, int value, string expected) { var specProvider = Substitute.For(); specProvider.GetSpec(Arg.Any()).Returns(London.Instance); @@ -396,9 +396,9 @@ public void should_handle_adding_1559_tx_to_full_txPool_properly(int gasPremium, tx.Value = (UInt256)(value * tx.GasLimit); EnsureSenderBalance(tx.SenderAddress, (UInt256)(15 * tx.GasLimit)); _txPool.GetPendingTransactions().Length.Should().Be(30); - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(30); - result.Should().Be(expected); + result.ToString().Should().Contain(expected); } [TestCase(0)] @@ -524,7 +524,7 @@ public void should_discard_tx_because_of_overflow_of_cumulative_cost_of_this_tx_ transactions[2].GasPrice = 5; _txPool.GetPendingTransactions().Length.Should().Be(2); - _txPool.SubmitTx(transactions[2], TxHandlingOptions.PersistentBroadcast).Should().Be(AddTxResult.Int256Overflow); + _txPool.SubmitTx(transactions[2], TxHandlingOptions.PersistentBroadcast).Should().Be(AcceptTxResult.Int256Overflow); } [Test] @@ -838,11 +838,11 @@ public void should_return_own_nonce_already_used_result_when_trying_to_send_tran { _txPool = CreatePool(); var result1 = _txPool.SubmitTx(GetTransaction(TestItem.PrivateKeyA, TestItem.AddressA), TxHandlingOptions.PersistentBroadcast | TxHandlingOptions.ManagedNonce); - result1.Should().Be(AddTxResult.Added); + result1.Should().Be(AcceptTxResult.Accepted); _txPool.GetOwnPendingTransactions().Length.Should().Be(1); _txPool.GetPendingTransactions().Length.Should().Be(1); var result2 = _txPool.SubmitTx(GetTransaction(TestItem.PrivateKeyA, TestItem.AddressB), TxHandlingOptions.PersistentBroadcast | TxHandlingOptions.ManagedNonce); - result2.Should().Be(AddTxResult.OwnNonceAlreadyUsed); + result2.Should().Be(AcceptTxResult.OwnNonceAlreadyUsed); _txPool.GetOwnPendingTransactions().Length.Should().Be(1); _txPool.GetPendingTransactions().Length.Should().Be(1); } @@ -863,7 +863,7 @@ public void should_retrieve_added_transaction_correctly() _specProvider = Substitute.For(); _specProvider.ChainId.Returns(transaction.Signature.ChainId.Value); _txPool = CreatePool(); - _txPool.SubmitTx(transaction, TxHandlingOptions.PersistentBroadcast).Should().Be(AddTxResult.Added); + _txPool.SubmitTx(transaction, TxHandlingOptions.PersistentBroadcast).Should().Be(AcceptTxResult.Accepted); _txPool.TryGetPendingTransaction(transaction.Hash, out var retrievedTransaction).Should().BeTrue(); retrievedTransaction.Should().BeEquivalentTo(transaction); } @@ -936,9 +936,9 @@ public void should_accept_access_list_transactions_only_when_eip2930_enabled([Va .WithChainId(ChainId.Mainnet) .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; EnsureSenderBalance(tx); - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(eip2930Enabled ? 1 : 0); - result.Should().Be(eip2930Enabled ? AddTxResult.Added : AddTxResult.Invalid); + result.Should().Be(eip2930Enabled ? AcceptTxResult.Accepted : AcceptTxResult.Invalid); } [Test] @@ -951,9 +951,9 @@ public void When_MaxFeePerGas_is_lower_than_MaxPriorityFeePerGas_tx_is_invalid() .WithType(TxType.EIP1559) .TestObject; EnsureSenderBalance(tx); - AddTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(0); - result.Should().Be(AddTxResult.Invalid); + result.Should().Be(AcceptTxResult.Invalid); } [Test] diff --git a/src/Nethermind/Nethermind.TxPool/AddTxResult.cs b/src/Nethermind/Nethermind.TxPool/AcceptTxResult.cs similarity index 52% rename from src/Nethermind/Nethermind.TxPool/AddTxResult.cs rename to src/Nethermind/Nethermind.TxPool/AcceptTxResult.cs index 88fb1d9e0d9..952595b7f07 100644 --- a/src/Nethermind/Nethermind.TxPool/AddTxResult.cs +++ b/src/Nethermind/Nethermind.TxPool/AcceptTxResult.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Demerzel Solutions Limited +// Copyright (c) 2021 Demerzel Solutions Limited // This file is part of the Nethermind library. // // The Nethermind library is free software: you can redistribute it and/or modify @@ -13,83 +13,102 @@ // // You should have received a copy of the GNU Lesser General Public License // along with the Nethermind. If not, see . +// + +using System; namespace Nethermind.TxPool { /// /// Describes potential outcomes of adding transaction to the TX pool. /// - public enum AddTxResult + public readonly struct AcceptTxResult : IEquatable { /// - /// The transaction has been added successfully. This is the only 'success' outcome. + /// The transaction has been accepted. This is the only 'success' outcome. /// - Added, - + public static readonly AcceptTxResult Accepted = new(0, nameof(Accepted)); + /// /// A transaction with the same hash has already been added to the pool in the past. /// - AlreadyKnown, + public static readonly AcceptTxResult AlreadyKnown = new(1, nameof(AlreadyKnown)); /// /// Covers scenarios where sender recovery fails. /// - FailedToResolveSender, + public static readonly AcceptTxResult FailedToResolveSender = new(2, nameof(FailedToResolveSender)); /// /// Fee paid by this transaction is not enough to be accepted in the mempool. /// - FeeTooLow, + public static readonly AcceptTxResult FeeTooLow = new(3, nameof(FeeTooLow)); /// /// Fee paid by this transaction is not enough to be accepted in the mempool. /// - FeeTooLowToCompete, - - /// - /// This transaction has been filtered out by the transaction pool filter. - /// - Filtered, + public static readonly AcceptTxResult FeeTooLowToCompete = new(4, nameof(FeeTooLowToCompete)); /// /// Transaction gas limit exceeds the block gas limit. /// - GasLimitExceeded, + public static readonly AcceptTxResult GasLimitExceeded = new(5, nameof(GasLimitExceeded)); /// /// Sender account has not enough balance to execute this transaction. /// - InsufficientFunds, + public static readonly AcceptTxResult InsufficientFunds = new(6, nameof(InsufficientFunds)); /// /// Calculation of gas price * gas limit + value overflowed int256. /// - Int256Overflow, + public static readonly AcceptTxResult Int256Overflow = new(7, nameof(Int256Overflow)); /// /// Transaction format is invalid. /// - Invalid, + public static readonly AcceptTxResult Invalid = new(8, nameof(Invalid)); /// /// The nonce is not the next nonce after the last nonce of this sender present in TxPool. /// - NonceGap, + public static readonly AcceptTxResult NonceGap = new(9, nameof(NonceGap)); /// /// The EOA (externally owned account) that signed this transaction (sender) has already signed and executed a transaction with the same nonce. /// - OldNonce, + public static readonly AcceptTxResult OldNonce = new(10, nameof(OldNonce)); /// /// A transaction with same nonce has been signed locally already and is awaiting in the pool. /// (I would like to change this behaviour to allow local replacement) /// - OwnNonceAlreadyUsed, + public static readonly AcceptTxResult OwnNonceAlreadyUsed = new(11, nameof(OwnNonceAlreadyUsed)); /// /// Transaction sender has code hash that is not null. /// - SenderIsContract + public static readonly AcceptTxResult SenderIsContract = new(12, nameof(SenderIsContract)); + + + private int Id { get; } + private string Code { get; } + private string? Message { get; } + + public AcceptTxResult(int id, string code, string? message = null) + { + Id = id; + Code = code; + Message = message; + } + + public static implicit operator bool(AcceptTxResult result) => result.Id == Accepted.Id; + public AcceptTxResult WithMessage(string message) => new(Id, Code, message); + public static bool operator ==(AcceptTxResult a, AcceptTxResult b) => a.Equals(b); + public static bool operator !=(AcceptTxResult a, AcceptTxResult b) => !(a == b); + public override bool Equals(object? obj) => Equals((AcceptTxResult)obj); + public bool Equals(AcceptTxResult result) => Id == result.Id; + public override int GetHashCode() => Id.GetHashCode(); + public override string ToString() => Message is null ? $"{Code}" : $"{Code}, {Message}"; } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/AlreadyKnownTxFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/AlreadyKnownTxFilter.cs index 5018f206ef0..cac41b9245b 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/AlreadyKnownTxFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/AlreadyKnownTxFilter.cs @@ -34,17 +34,17 @@ public AlreadyKnownTxFilter(HashCache hashCache) _hashCache = hashCache; } - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions handlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions handlingOptions) { if (_hashCache.Get(tx.Hash!)) { Metrics.PendingTransactionsKnown++; - return (false, AddTxResult.AlreadyKnown); + return AcceptTxResult.AlreadyKnown; } _hashCache.SetForCurrentBlock(tx.Hash!); - return (true, null); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/DeployedCodeFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/DeployedCodeFilter.cs index c04516a3ead..ddb01aaa811 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/DeployedCodeFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/DeployedCodeFilter.cs @@ -15,9 +15,7 @@ // along with the Nethermind. If not, see . // -using System; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Core.Specs; namespace Nethermind.TxPool.Filters @@ -35,9 +33,9 @@ public DeployedCodeFilter(IChainHeadSpecProvider specProvider, IAccountStateProv _specProvider = specProvider; _stateProvider = stateProvider; } - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions txHandlingOptions) => + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions txHandlingOptions) => _stateProvider.IsInvalidContractSender(_specProvider.GetCurrentHeadSpec(), tx.SenderAddress!) - ? (false, AddTxResult.SenderIsContract) - : (true, null); + ? AcceptTxResult.SenderIsContract + : AcceptTxResult.Accepted; } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/FeeTooLowFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/FeeTooLowFilter.cs index 9919a3c428e..21b02303f06 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/FeeTooLowFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/FeeTooLowFilter.cs @@ -43,7 +43,7 @@ public FeeToLowFilter(IChainHeadInfoProvider headInfo, IAccountStateProvider acc _logger = logger; } - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions handlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions handlingOptions) { IReleaseSpec spec = _specProvider.GetCurrentHeadSpec(); Account account = _accounts.GetAccount(tx.SenderAddress!); @@ -57,10 +57,10 @@ public FeeToLowFilter(IChainHeadInfoProvider headInfo, IAccountStateProvider acc Metrics.PendingTransactionsTooLowFee++; if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, too low payable gas price."); - return (false, AddTxResult.FeeTooLow); + return AcceptTxResult.FeeTooLow.WithMessage($"FeePerGas needs to be higher than {lastTx.GasBottleneck.Value} to be added to the TxPool. Affordable FeePerGas of rejected tx: {affordableGasPrice}."); } - return (true, null); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/GapNonceFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/GapNonceFilter.cs index c8ae4b15d2e..25457128922 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/GapNonceFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/GapNonceFilter.cs @@ -39,21 +39,22 @@ public GapNonceFilter(IAccountStateProvider accountStateProvider, TxDistinctSort _logger = logger; } - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions handlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions handlingOptions) { int numberOfSenderTxsInPending = _txs.GetBucketCount(tx.SenderAddress); bool isTxPoolFull = _txs.IsFull(); UInt256 currentNonce = _accounts.GetAccount(tx.SenderAddress!).Nonce; - bool isTxNonceNextInOrder = tx.Nonce <= (long)currentNonce + numberOfSenderTxsInPending; + long nextNonceInOrder = (long)currentNonce + numberOfSenderTxsInPending; + bool isTxNonceNextInOrder = tx.Nonce <= nextNonceInOrder; if (isTxPoolFull && !isTxNonceNextInOrder) { Metrics.PendingTransactionsNonceGap++; if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, nonce in future."); - return (false, AddTxResult.NonceGap); + return AcceptTxResult.NonceGap.WithMessage($"Future nonce. Expected nonce: {nextNonceInOrder}"); } - return (true, null); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/GasLimitTxFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/GasLimitTxFilter.cs index ab25702fec6..72c51faa0f5 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/GasLimitTxFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/GasLimitTxFilter.cs @@ -38,16 +38,16 @@ public GasLimitTxFilter(IChainHeadInfoProvider chainHeadInfoProvider, ITxPoolCon _configuredGasLimit = txPoolConfig.GasLimit ?? long.MaxValue; } - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions handlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions handlingOptions) { long gasLimit = Math.Min(_chainHeadInfoProvider.BlockGasLimit ?? long.MaxValue, _configuredGasLimit); if (tx.GasLimit > gasLimit) { if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, gas limit exceeded."); - return (false, AddTxResult.GasLimitExceeded); + return AcceptTxResult.GasLimitExceeded.WithMessage($"Gas limit: {gasLimit}, gas limit of rejected tx: {tx.GasLimit}"); } - return (true, null); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/IIncomingTxFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/IIncomingTxFilter.cs index 07752b3d25b..31885363bd0 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/IIncomingTxFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/IIncomingTxFilter.cs @@ -25,6 +25,6 @@ namespace Nethermind.TxPool.Filters /// public interface IIncomingTxFilter { - (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions txHandlingOptions); + AcceptTxResult Accept(Transaction tx, TxHandlingOptions txHandlingOptions); } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/LowNonceFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/LowNonceFilter.cs index e58342427bb..4af088d9a13 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/LowNonceFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/LowNonceFilter.cs @@ -35,7 +35,7 @@ public LowNonceFilter(IAccountStateProvider accountStateProvider, ILogger logger _logger = logger; } - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions handlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions handlingOptions) { // As we have limited number of transaction that we store in mem pool its fairly easy to fill it up with // high-priority garbage transactions. We need to filter them as much as possible to use the tx pool space @@ -46,10 +46,10 @@ public LowNonceFilter(IAccountStateProvider accountStateProvider, ILogger logger if (tx.Nonce < currentNonce) { if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, nonce already used."); - return (false, AddTxResult.OldNonce); + return AcceptTxResult.OldNonce.WithMessage($"Current nonce: {currentNonce}, nonce of rejected tx: {tx.Nonce}"); } - return (true, null); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/MalformedTxFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/MalformedTxFilter.cs index c1e52007a18..f1afb811ded 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/MalformedTxFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/MalformedTxFilter.cs @@ -37,17 +37,17 @@ public MalformedTxFilter(IChainHeadSpecProvider specProvider, ITxValidator txVal _logger = logger; } - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions txHandlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions txHandlingOptions) { IReleaseSpec spec = _specProvider.GetCurrentHeadSpec(); if (!_txValidator.IsWellFormed(tx, spec)) { // It may happen that other nodes send us transactions that were signed for another chain or don't have enough gas. if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, invalid transaction."); - return (false, AddTxResult.Invalid); + return AcceptTxResult.Invalid; } - return (true, null); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/NullHashTxFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/NullHashTxFilter.cs index b0faaf9e643..d59a66b8696 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/NullHashTxFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/NullHashTxFilter.cs @@ -26,14 +26,14 @@ namespace Nethermind.TxPool.Filters /// internal class NullHashTxFilter : IIncomingTxFilter { - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions handlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions handlingOptions) { if (tx.Hash is null) { - return (false, AddTxResult.Invalid); + return AcceptTxResult.Invalid.WithMessage("transaction Hash is null"); } - return (true, null); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/NullIncomingTxFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/NullIncomingTxFilter.cs index ae4298efd1b..da6c3f0176f 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/NullIncomingTxFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/NullIncomingTxFilter.cs @@ -25,9 +25,9 @@ private NullIncomingTxFilter() { } public static IIncomingTxFilter Instance { get; } = new NullIncomingTxFilter(); - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions txHandlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions txHandlingOptions) { - return (true, null); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/ReusedOwnNonceTxFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/ReusedOwnNonceTxFilter.cs index 1691331e20d..3999f2ee4f9 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/ReusedOwnNonceTxFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/ReusedOwnNonceTxFilter.cs @@ -40,7 +40,7 @@ public ReusedOwnNonceTxFilter(IAccountStateProvider accountStateProvider, Concur _logger = logger; } - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions handlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions handlingOptions) { bool managedNonce = (handlingOptions & TxHandlingOptions.ManagedNonce) == TxHandlingOptions.ManagedNonce; Account account = _accounts.GetAccount(tx.SenderAddress!); @@ -50,10 +50,10 @@ public ReusedOwnNonceTxFilter(IAccountStateProvider accountStateProvider, Concur { if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, nonce already used."); - return (false, AddTxResult.OwnNonceAlreadyUsed); + return AcceptTxResult.OwnNonceAlreadyUsed; } - return (true, null); + return AcceptTxResult.Accepted; } /// diff --git a/src/Nethermind/Nethermind.TxPool/Filters/TooExpensiveTxFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/TooExpensiveTxFilter.cs index 553145b722b..620d03197e8 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/TooExpensiveTxFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/TooExpensiveTxFilter.cs @@ -43,7 +43,7 @@ public TooExpensiveTxFilter(IChainHeadInfoProvider headInfo, IAccountStateProvid _logger = logger; } - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions handlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions handlingOptions) { IReleaseSpec spec = _specProvider.GetCurrentHeadSpec(); Account account = _accounts.GetAccount(tx.SenderAddress!); @@ -86,17 +86,17 @@ public TooExpensiveTxFilter(IChainHeadInfoProvider headInfo, IAccountStateProvid { if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, cost overflow."); - return (false, AddTxResult.Int256Overflow); + return AcceptTxResult.Int256Overflow; } if (balance < cumulativeCost) { if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, insufficient funds."); - return (false, AddTxResult.InsufficientFunds); + return AcceptTxResult.InsufficientFunds.WithMessage($"Account balance: {balance}, cumulative cost: {cumulativeCost}"); } - return (true, null); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.TxPool/Filters/UnknownSenderFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/UnknownSenderFilter.cs index 6b16189fcf3..74e90a3d0cd 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/UnknownSenderFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/UnknownSenderFilter.cs @@ -35,7 +35,7 @@ public UnknownSenderFilter(IEthereumEcdsa ecdsa, ILogger logger) _logger = logger; } - public (bool Accepted, AddTxResult? Reason) Accept(Transaction tx, TxHandlingOptions handlingOptions) + public AcceptTxResult Accept(Transaction tx, TxHandlingOptions handlingOptions) { /* We have encountered multiple transactions that do not resolve sender address properly. * We need to investigate what these txs are and why the sender address is resolved to null. @@ -47,11 +47,11 @@ public UnknownSenderFilter(IEthereumEcdsa ecdsa, ILogger logger) if (tx.SenderAddress is null) { if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, no sender."); - return (false, AddTxResult.FailedToResolveSender); + return AcceptTxResult.FailedToResolveSender; } } - return (true, null); + return AcceptTxResult.Accepted; } } } diff --git a/src/Nethermind/Nethermind.TxPool/ITxPool.cs b/src/Nethermind/Nethermind.TxPool/ITxPool.cs index 7bfd8d6fbff..d40ec4a58ed 100644 --- a/src/Nethermind/Nethermind.TxPool/ITxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/ITxPool.cs @@ -34,7 +34,7 @@ public interface ITxPool IDictionary GetPendingTransactionsBySender(); void AddPeer(ITxPoolPeer peer); void RemovePeer(PublicKey nodeId); - AddTxResult SubmitTx(Transaction tx, TxHandlingOptions handlingOptions); + AcceptTxResult SubmitTx(Transaction tx, TxHandlingOptions handlingOptions); bool RemoveTransaction(Keccak? hash); bool IsKnown(Keccak? hash); bool TryGetPendingTransaction(Keccak hash, out Transaction? transaction); diff --git a/src/Nethermind/Nethermind.TxPool/ITxSender.cs b/src/Nethermind/Nethermind.TxPool/ITxSender.cs index bdf9fe43cc7..1e903374bac 100644 --- a/src/Nethermind/Nethermind.TxPool/ITxSender.cs +++ b/src/Nethermind/Nethermind.TxPool/ITxSender.cs @@ -23,6 +23,6 @@ namespace Nethermind.TxPool { public interface ITxSender { - ValueTask<(Keccak? Hash, AddTxResult? AddTxResult)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions); + ValueTask<(Keccak? Hash, AcceptTxResult? AddTxResult)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions); } } diff --git a/src/Nethermind/Nethermind.TxPool/NullTxPool.cs b/src/Nethermind/Nethermind.TxPool/NullTxPool.cs index 61526a2b3e7..4ab62e54213 100644 --- a/src/Nethermind/Nethermind.TxPool/NullTxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/NullTxPool.cs @@ -40,7 +40,7 @@ public void AddPeer(ITxPoolPeer peer) { } public void RemovePeer(PublicKey nodeId) { } - public AddTxResult SubmitTx(Transaction tx, TxHandlingOptions txHandlingOptions) => AddTxResult.Added; + public AcceptTxResult SubmitTx(Transaction tx, TxHandlingOptions txHandlingOptions) => AcceptTxResult.Accepted; public bool RemoveTransaction(Keccak? hash) => false; diff --git a/src/Nethermind/Nethermind.TxPool/NullTxSender.cs b/src/Nethermind/Nethermind.TxPool/NullTxSender.cs index 8e5e97c9f0e..de26e23ea5f 100644 --- a/src/Nethermind/Nethermind.TxPool/NullTxSender.cs +++ b/src/Nethermind/Nethermind.TxPool/NullTxSender.cs @@ -25,7 +25,7 @@ public class NullTxSender : ITxSender { public static ITxSender Instance { get; } = new NullTxSender(); - public ValueTask<(Keccak, AddTxResult?)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions) + public ValueTask<(Keccak, AcceptTxResult?)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions) => new((tx.Hash, null)); } diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index b171af94766..392064a3fac 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -250,7 +250,7 @@ public void RemovePeer(PublicKey nodeId) } } - public AddTxResult SubmitTx(Transaction tx, TxHandlingOptions handlingOptions) + public AcceptTxResult SubmitTx(Transaction tx, TxHandlingOptions handlingOptions) { Metrics.PendingTransactionsReceived++; @@ -271,18 +271,18 @@ public AddTxResult SubmitTx(Transaction tx, TxHandlingOptions handlingOptions) for (int i = 0; i < _filterPipeline.Count; i++) { IIncomingTxFilter incomingTxFilter = _filterPipeline[i]; - (bool accepted, AddTxResult? filteringResult) = incomingTxFilter.Accept(tx, handlingOptions); + AcceptTxResult accepted = incomingTxFilter.Accept(tx, handlingOptions); if (!accepted) { Metrics.PendingTransactionsDiscarded++; - return filteringResult.Value; + return accepted; } } return AddCore(tx, startBroadcast); } - private AddTxResult AddCore(Transaction tx, bool isPersistentBroadcast) + private AcceptTxResult AddCore(Transaction tx, bool isPersistentBroadcast) { lock (_locker) { @@ -309,7 +309,7 @@ private AddTxResult AddCore(Transaction tx, bool isPersistentBroadcast) else { Metrics.PendingTransactionsTooLowFee++; - return AddTxResult.FeeTooLowToCompete; + return AcceptTxResult.FeeTooLowToCompete; } } @@ -325,7 +325,7 @@ private AddTxResult AddCore(Transaction tx, bool isPersistentBroadcast) _hashCache.SetLongTerm(tx.Hash!); NewPending?.Invoke(this, new TxEventArgs(tx)); Metrics.TransactionCount = _transactions.Count; - return AddTxResult.Added; + return AcceptTxResult.Accepted; } private IEnumerable<(Transaction Tx, Action? Change)> UpdateBucketWithAddedTransaction( diff --git a/src/Nethermind/Nethermind.TxPool/TxPoolSender.cs b/src/Nethermind/Nethermind.TxPool/TxPoolSender.cs index 6aad33109ac..ec5417dbff1 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPoolSender.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPoolSender.cs @@ -34,9 +34,9 @@ public TxPoolSender(ITxPool txPool, params ITxSealer[] sealers) if (sealers.Length == 0) throw new ArgumentException("Sealers can not be empty.", nameof(sealers)); } - public ValueTask<(Keccak, AddTxResult?)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions) + public ValueTask<(Keccak, AcceptTxResult?)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions) { - AddTxResult? result = null; + AcceptTxResult? result = null; // TODO: this is very not intuitive - can we fix it...? // maybe move nonce reservation to sender itself before sealing @@ -47,14 +47,14 @@ public TxPoolSender(ITxPool txPool, params ITxSealer[] sealers) result = _txPool.SubmitTx(tx, txHandlingOptions); - if (result != AddTxResult.OwnNonceAlreadyUsed && result != AddTxResult.AlreadyKnown + if (result != AcceptTxResult.OwnNonceAlreadyUsed && result != AcceptTxResult.AlreadyKnown || (txHandlingOptions & TxHandlingOptions.ManagedNonce) != TxHandlingOptions.ManagedNonce) { break; } } - return new ValueTask<(Keccak, AddTxResult?)>((tx.Hash, result)); + return new ValueTask<(Keccak, AcceptTxResult?)>((tx.Hash, result)); } } }