From 1892b4b796cb68f9a131c6dc554ea37b36728a77 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sat, 21 Sep 2024 12:38:41 +0100 Subject: [PATCH 1/8] Move txPool work from Processing loop event to txPool thread --- src/Nethermind/Nethermind.TxPool/TxPool.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index 39ea1d1a85e..047b04d075d 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -191,10 +191,6 @@ private void OnHeadChange(object? sender, BlockReplacementEventArgs e) { try { - // Clear snapshot - _transactionSnapshot = null; - _blobTransactionSnapshot = null; - _hashCache.ClearCurrentBlockCache(); _headBlocksChannel.Writer.TryWrite(e); } catch (Exception exception) @@ -211,8 +207,12 @@ private void ProcessNewHeads() { while (await _headBlocksChannel.Reader.WaitToReadAsync()) { + _hashCache.ClearCurrentBlockCache(); while (_headBlocksChannel.Reader.TryRead(out BlockReplacementEventArgs? args)) { + // Clear snapshot + _transactionSnapshot = null; + _blobTransactionSnapshot = null; try { ArrayPoolList? accountChanges = args.Block.AccountChanges; From 0d0a18e90505b6b89d5e3faea656fcc32640c124 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sat, 21 Sep 2024 12:43:58 +0100 Subject: [PATCH 2/8] Clear per block --- src/Nethermind/Nethermind.TxPool/TxPool.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index 047b04d075d..2f30a203bb0 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -207,12 +207,12 @@ private void ProcessNewHeads() { while (await _headBlocksChannel.Reader.WaitToReadAsync()) { - _hashCache.ClearCurrentBlockCache(); while (_headBlocksChannel.Reader.TryRead(out BlockReplacementEventArgs? args)) { // Clear snapshot _transactionSnapshot = null; _blobTransactionSnapshot = null; + _hashCache.ClearCurrentBlockCache(); try { ArrayPoolList? accountChanges = args.Block.AccountChanges; From 05677dff9fca89ff9044ae05f904266fffb09df0 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sat, 21 Sep 2024 13:08:30 +0100 Subject: [PATCH 3/8] Signal TxPool head moved --- src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs | 10 ++++++++++ src/Nethermind/Nethermind.TxPool/TxPool.cs | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs index 289e4604bec..160b23e89c9 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs @@ -213,7 +213,12 @@ public void should_not_ignore_insufficient_funds_for_eip1559_transactions() txPool.GetPendingTransactionsCount().Should().Be(0); result.Should().Be(AcceptTxResult.InsufficientFunds); EnsureSenderBalance(tx.SenderAddress, tx.Value); + + var headProcessed = new ManualResetEventSlim(false); + txPool.HeadChanged += (s, a) => headProcessed.Set(); _blockTree.BlockAddedToMain += Raise.EventWith(_blockTree, new BlockReplacementEventArgs(Build.A.Block.WithGasLimit(10000000).TestObject)); + + headProcessed.Wait(); result = txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); result.Should().Be(AcceptTxResult.InsufficientFunds); txPool.GetPendingTransactionsCount().Should().Be(0); @@ -719,7 +724,12 @@ public void should_remove_txHash_from_hashCache_when_tx_removed_because_of_txPoo EnsureSenderBalance(higherPriorityTx); _txPool.SubmitTx(higherPriorityTx, TxHandlingOptions.PersistentBroadcast); + var headProcessed = new ManualResetEventSlim(false); + _txPool.HeadChanged += (s, a) => headProcessed.Set(); + _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(Build.A.Block.TestObject)); + + headProcessed.Wait(); _txPool.IsKnown(higherPriorityTx.Hash).Should().BeTrue(); _txPool.IsKnown(transaction.Hash).Should().BeFalse(); } diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index 2f30a203bb0..cb2a97a327c 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -201,18 +201,20 @@ private void OnHeadChange(object? sender, BlockReplacementEventArgs e) } } + public event EventHandler? HeadChanged; + private void ProcessNewHeads() { Task.Factory.StartNew(async () => { while (await _headBlocksChannel.Reader.WaitToReadAsync()) { + _hashCache.ClearCurrentBlockCache(); while (_headBlocksChannel.Reader.TryRead(out BlockReplacementEventArgs? args)) { // Clear snapshot _transactionSnapshot = null; _blobTransactionSnapshot = null; - _hashCache.ClearCurrentBlockCache(); try { ArrayPoolList? accountChanges = args.Block.AccountChanges; @@ -236,6 +238,7 @@ private void ProcessNewHeads() RemoveProcessedTransactions(args.Block); UpdateBuckets(); _broadcaster.OnNewHead(); + HeadChanged?.Invoke(this, args); Metrics.TransactionCount = _transactions.Count; Metrics.BlobTransactionCount = _blobTransactions.Count; } From 2d5fc79f31b00ff02c6f0e72aaa0bca49ab299c1 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sat, 21 Sep 2024 18:50:38 +0100 Subject: [PATCH 4/8] Rename event --- src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs | 4 ++-- src/Nethermind/Nethermind.TxPool/TxPool.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs index 160b23e89c9..bdb1a26a5a6 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs @@ -215,7 +215,7 @@ public void should_not_ignore_insufficient_funds_for_eip1559_transactions() EnsureSenderBalance(tx.SenderAddress, tx.Value); var headProcessed = new ManualResetEventSlim(false); - txPool.HeadChanged += (s, a) => headProcessed.Set(); + txPool.TxPoolHeadChanged += (s, a) => headProcessed.Set(); _blockTree.BlockAddedToMain += Raise.EventWith(_blockTree, new BlockReplacementEventArgs(Build.A.Block.WithGasLimit(10000000).TestObject)); headProcessed.Wait(); @@ -725,7 +725,7 @@ public void should_remove_txHash_from_hashCache_when_tx_removed_because_of_txPoo _txPool.SubmitTx(higherPriorityTx, TxHandlingOptions.PersistentBroadcast); var headProcessed = new ManualResetEventSlim(false); - _txPool.HeadChanged += (s, a) => headProcessed.Set(); + _txPool.TxPoolHeadChanged += (s, a) => headProcessed.Set(); _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(Build.A.Block.TestObject)); diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index cb2a97a327c..996e49d1752 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -59,6 +59,8 @@ public class TxPool : ITxPool, IDisposable private readonly UpdateGroupDelegate _updateBucket; private readonly UpdateGroupDelegate _updateBucketAdded; + public event EventHandler? TxPoolHeadChanged; + /// /// Indexes transactions /// @@ -201,8 +203,6 @@ private void OnHeadChange(object? sender, BlockReplacementEventArgs e) } } - public event EventHandler? HeadChanged; - private void ProcessNewHeads() { Task.Factory.StartNew(async () => @@ -238,7 +238,7 @@ private void ProcessNewHeads() RemoveProcessedTransactions(args.Block); UpdateBuckets(); _broadcaster.OnNewHead(); - HeadChanged?.Invoke(this, args); + TxPoolHeadChanged?.Invoke(this, args); Metrics.TransactionCount = _transactions.Count; Metrics.BlobTransactionCount = _blobTransactions.Count; } From b37b03e51b48915cd3b7fd6a5301c40c01204802 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sat, 21 Sep 2024 18:56:40 +0100 Subject: [PATCH 5/8] Use the event --- src/Nethermind/Nethermind.TxPool/TxBroadcaster.cs | 2 +- src/Nethermind/Nethermind.TxPool/TxPool.cs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Nethermind/Nethermind.TxPool/TxBroadcaster.cs b/src/Nethermind/Nethermind.TxPool/TxBroadcaster.cs index de7eb80c9d0..0e61bb15b55 100644 --- a/src/Nethermind/Nethermind.TxPool/TxBroadcaster.cs +++ b/src/Nethermind/Nethermind.TxPool/TxBroadcaster.cs @@ -142,7 +142,7 @@ public void AnnounceOnce(ITxPoolPeer peer, Transaction[] txs) } } - public void OnNewHead() + public void OnNewHead(object? sender, Block block) { _baseFeeThreshold = CalculateBaseFeeThreshold(); BroadcastPersistentTxs(); diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index 996e49d1752..511128de814 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -59,7 +59,7 @@ public class TxPool : ITxPool, IDisposable private readonly UpdateGroupDelegate _updateBucket; private readonly UpdateGroupDelegate _updateBucketAdded; - public event EventHandler? TxPoolHeadChanged; + public event EventHandler? TxPoolHeadChanged; /// /// Indexes transactions @@ -114,6 +114,7 @@ public TxPool(IEthereumEcdsa ecdsa, _updateBucketAdded = UpdateBucketWithAddedTransaction; _broadcaster = new TxBroadcaster(comparer, TimerFactory.Default, txPoolConfig, chainHeadInfoProvider, logManager, transactionsGossipPolicy); + TxPoolHeadChanged += _broadcaster.OnNewHead; _transactions = new TxDistinctSortedPool(MemoryAllowance.MemPoolSize, comparer, logManager); _blobTransactions = txPoolConfig.BlobsSupport.IsPersistentStorage() @@ -237,8 +238,7 @@ private void ProcessNewHeads() ReAddReorganisedTransactions(args.PreviousBlock); RemoveProcessedTransactions(args.Block); UpdateBuckets(); - _broadcaster.OnNewHead(); - TxPoolHeadChanged?.Invoke(this, args); + TxPoolHeadChanged?.Invoke(this, args.Block); Metrics.TransactionCount = _transactions.Count; Metrics.BlobTransactionCount = _blobTransactions.Count; } @@ -753,6 +753,7 @@ public UInt256 GetLatestPendingNonce(Address address) public void Dispose() { _timer?.Dispose(); + TxPoolHeadChanged -= _broadcaster.OnNewHead; _broadcaster.Dispose(); _headInfo.HeadChanged -= OnHeadChange; _headBlocksChannel.Writer.Complete(); From 8e89cad0fec56c844a464d9f379c6bda3b345d10 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sat, 21 Sep 2024 19:21:12 +0100 Subject: [PATCH 6/8] Use the snapshot in more places --- src/Nethermind/Nethermind.TxPool/TxPool.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index 511128de814..b79fce3ce91 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -167,7 +167,7 @@ public TxPool(IEthereumEcdsa ecdsa, ProcessNewHeads(); } - public Transaction[] GetPendingTransactions() => _transactions.GetSnapshot(); + public Transaction[] GetPendingTransactions() => _transactionSnapshot ??= _transactions.GetSnapshot(); public int GetPendingTransactionsCount() => _transactions.Count; From dcbbf05197a7dc99e6b84f121344b33942e8c428 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sat, 21 Sep 2024 19:41:39 +0100 Subject: [PATCH 7/8] Wait for txpool head --- .../Nethermind.Core.Test/Blockchain/TestBlockchain.cs | 3 +++ src/Nethermind/Nethermind.TxPool/ITxPool.cs | 2 ++ src/Nethermind/Nethermind.TxPool/NullTxPool.cs | 6 ++++++ 3 files changed, 11 insertions(+) diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 8282d206109..443344684a0 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -425,7 +425,10 @@ private async Task AddBlockInternal(params Transaction[] trans await WaitAsync(_oneAtATime, "Multiple block produced at once."); AcceptTxResult[] txResults = transactions.Select(t => TxPool.SubmitTx(t, TxHandlingOptions.None)).ToArray(); Timestamper.Add(TimeSpan.FromSeconds(1)); + var headProcessed = new ManualResetEventSlim(false); + TxPool.TxPoolHeadChanged += (s, a) => headProcessed.Set(); await BlockProductionTrigger.BuildBlock(); + headProcessed.Wait(); return txResults; } diff --git a/src/Nethermind/Nethermind.TxPool/ITxPool.cs b/src/Nethermind/Nethermind.TxPool/ITxPool.cs index 2c11c7515af..ff418e574cd 100644 --- a/src/Nethermind/Nethermind.TxPool/ITxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/ITxPool.cs @@ -16,6 +16,8 @@ public interface ITxPool int GetPendingBlobTransactionsCount(); Transaction[] GetPendingTransactions(); + public event EventHandler? TxPoolHeadChanged; + /// /// Non-blob txs grouped by sender address, sorted by nonce and later tx pool sorting /// diff --git a/src/Nethermind/Nethermind.TxPool/NullTxPool.cs b/src/Nethermind/Nethermind.TxPool/NullTxPool.cs index d0f1587522e..bcc1b237745 100644 --- a/src/Nethermind/Nethermind.TxPool/NullTxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/NullTxPool.cs @@ -16,6 +16,12 @@ private NullTxPool() { } public static NullTxPool Instance { get; } = new(); + public event EventHandler? TxPoolHeadChanged + { + add { } + remove { } + } + public int GetPendingTransactionsCount() => 0; public int GetPendingBlobTransactionsCount() => 0; public Transaction[] GetPendingTransactions() => Array.Empty(); From cc2a2eadffc7236cd7cf6b1d95f1a4d66f2689f6 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sat, 21 Sep 2024 20:22:02 +0100 Subject: [PATCH 8/8] Faster tests --- .../Nethermind.Core.Test/Blockchain/TestBlockchain.cs | 10 +++++----- .../JsonRpcSocketsClientTests.cs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 443344684a0..b024120242c 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -422,13 +422,13 @@ private async Task AddBlockInternal(params Transaction[] trans BlockTree.BlockAddedToMain -= BlockAddedToMain; BlockTree.BlockAddedToMain += BlockAddedToMain; - await WaitAsync(_oneAtATime, "Multiple block produced at once."); + await WaitAsync(_oneAtATime, "Multiple block produced at once.").ConfigureAwait(false); AcceptTxResult[] txResults = transactions.Select(t => TxPool.SubmitTx(t, TxHandlingOptions.None)).ToArray(); Timestamper.Add(TimeSpan.FromSeconds(1)); - var headProcessed = new ManualResetEventSlim(false); - TxPool.TxPoolHeadChanged += (s, a) => headProcessed.Set(); - await BlockProductionTrigger.BuildBlock(); - headProcessed.Wait(); + var headProcessed = new SemaphoreSlim(0); + TxPool.TxPoolHeadChanged += (s, a) => headProcessed.Release(); + await BlockProductionTrigger.BuildBlock().ConfigureAwait(false); + await headProcessed.WaitAsync().ConfigureAwait(false); return txResults; } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs index 373557181ae..c509ec7bec6 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs @@ -125,7 +125,7 @@ static async Task CountNumberOfMessages(Socket socket, CancellationToken to { using JsonRpcResult result = JsonRpcResult.Single(RandomSuccessResponse(1_000, () => disposeCount++), default); await client.SendJsonRpcResult(result); - await Task.Delay(100); + await Task.Delay(10); } disposeCount.Should().Be(messageCount); @@ -220,7 +220,7 @@ async Task ReadMessages(Socket socket, IList receivedMessages, Canc await stream.WriteEndOfMessageAsync(); if (i % 10 == 0) { - await Task.Delay(100); + await Task.Delay(10); } } stream.Close();