diff --git a/Directory.Packages.props b/Directory.Packages.props index 065d95f8a88..de1da8ae56d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -70,7 +70,7 @@ - + diff --git a/src/Nethermind/Nethermind.Network.Discovery/Discv5/DiscoveryV5App.cs b/src/Nethermind/Nethermind.Network.Discovery/Discv5/DiscoveryV5App.cs index 55746e2c850..523e03e089c 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Discv5/DiscoveryV5App.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Discv5/DiscoveryV5App.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System.Diagnostics.CodeAnalysis; @@ -20,6 +20,7 @@ using NBitcoin.Secp256k1; using Nethermind.Config; using Nethermind.Core; +using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Core.ServiceStopper; using Nethermind.Crypto; @@ -205,11 +206,13 @@ public async Task StartAsync() public async IAsyncEnumerable DiscoverNodes([EnumeratorCancellation] CancellationToken token) { - Channel ch = Channel.CreateBounded(1); + Channel discoveredNodesChannel = Channel.CreateBounded(1); - async Task DiscoverAsync(IEnumerable startingNode, byte[] nodeId) + async Task DiscoverAsync(IEnumerable startingNode, ArrayPoolSpan nodeId) { - static int[] GetDistances(byte[] srcNodeId, byte[] destNodeId) + using ArrayPoolSpan _ = nodeId; + + static int[] GetDistances(byte[] srcNodeId, in ArrayPoolSpan destNodeId) { const int WiderDistanceRange = 3; @@ -243,8 +246,10 @@ static int[] GetDistances(byte[] srcNodeId, byte[] destNodeId) if (TryGetNodeFromEnr(newEntry, out Node? node2)) { - await ch.Writer.WriteAsync(node2!, token); + await discoveredNodesChannel.Writer.WriteAsync(node2!, token); + if (_logger.IsDebug) _logger.Debug($"A node discovered via discv5: {newEntry} = {node2}."); + _discoveryReport?.NodeFound(); } @@ -253,13 +258,11 @@ static int[] GetDistances(byte[] srcNodeId, byte[] destNodeId) continue; } - IEnumerable? newNodesFound = (await _discv5Protocol.SendFindNodeAsync(newEntry, GetDistances(newEntry.NodeId, nodeId)))?.Where(x => !checkedNodes.Contains(x)); - - if (newNodesFound is not null) + foreach (IEnr newEnr in await _discv5Protocol.SendFindNodeAsync(newEntry, GetDistances(newEntry.NodeId, in nodeId)) ?? []) { - foreach (IEnr? node in newNodesFound) + if (!checkedNodes.Contains(newEnr)) { - nodesToCheck.Enqueue(node); + nodesToCheck.Enqueue(newEnr); } } } @@ -272,16 +275,20 @@ static int[] GetDistances(byte[] srcNodeId, byte[] destNodeId) Task discoverTask = Task.Run(async () => { - byte[] randomNodeId = new byte[32]; + using ArrayPoolSpan selfNodeId = new(32); + _discv5Protocol.SelfEnr.NodeId.CopyTo(selfNodeId); + while (!token.IsCancellationRequested) { try { - List discoverTasks = new List(); - discoverTasks.Add(DiscoverAsync(GetStartingNodes(), _discv5Protocol.SelfEnr.NodeId)); + using ArrayPoolList discoverTasks = new(RandomNodesToLookupCount); + + discoverTasks.Add(DiscoverAsync(GetStartingNodes(), selfNodeId)); for (int i = 0; i < RandomNodesToLookupCount; i++) { + ArrayPoolSpan randomNodeId = new(32); random.NextBytes(randomNodeId); discoverTasks.Add(DiscoverAsync(GetStartingNodes(), randomNodeId)); } @@ -293,11 +300,11 @@ static int[] GetDistances(byte[] srcNodeId, byte[] destNodeId) if (_logger.IsError) _logger.Error($"Discovery via custom random walk failed.", ex); } } - }); + }, token); try { - await foreach (Node node in ch.Reader.ReadAllAsync(token)) + await foreach (Node node in discoveredNodesChannel.Reader.ReadAllAsync(token)) { yield return node; } diff --git a/src/Nethermind/Nethermind.Network.Discovery/Discv5/NettyDiscoveryV5Handler.cs b/src/Nethermind/Nethermind.Network.Discovery/Discv5/NettyDiscoveryV5Handler.cs index ea7d25a16f6..1cb6e9a4e91 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Discv5/NettyDiscoveryV5Handler.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Discv5/NettyDiscoveryV5Handler.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System.Net; @@ -36,9 +36,12 @@ public NettyDiscoveryV5Handler(ILogManager loggerManager) : base(loggerManager) protected override void ChannelRead0(IChannelHandlerContext ctx, DatagramPacket msg) { - var udpPacket = new UdpReceiveResult(msg.Content.ReadAllBytesAsArray(), (IPEndPoint)msg.Sender); - if (!_inboundQueue.Writer.TryWrite(udpPacket) && _logger.IsWarn) + UdpReceiveResult udpPacket = new(msg.Content.ReadAllBytesAsArray(), (IPEndPoint)msg.Sender); + + if (!_inboundQueue.Writer.TryWrite(udpPacket) && _logger.IsDebug) + { _logger.Warn("Skipping discovery v5 message as inbound buffer is full"); + } } public async Task SendAsync(byte[] data, IPEndPoint destination) @@ -53,7 +56,7 @@ public async Task SendAsync(byte[] data, IPEndPoint destination) } catch (SocketException exception) { - if (_logger.IsError) _logger.Error("Error sending data", exception); + if (_logger.IsDebug) _logger.Error("DEBUG/ERROR Error sending data", exception); throw; } } diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index bcd13f9650c..e4d89748f40 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -36,4 +36,4 @@ "Optimism": { "SequencerUrl": "https://sepolia-sequencer.base.org" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/packages.lock.json b/src/Nethermind/Nethermind.Runner/packages.lock.json index 7f71a26adc3..b4dd4eabb03 100644 --- a/src/Nethermind/Nethermind.Runner/packages.lock.json +++ b/src/Nethermind/Nethermind.Runner/packages.lock.json @@ -510,20 +510,20 @@ }, "PierTwo.Lantern.Discv5.Enr": { "type": "Transitive", - "resolved": "1.0.0-preview.6", - "contentHash": "rHuVBANEsOdf+5p1uU35mrdJfb+2z9EtDU5LeHKWDWx5nfGMRK4LtcrbfvDnrdsTLQbxmV88PoBuS23FMLrpYQ==", + "resolved": "1.0.0-preview.7", + "contentHash": "oNF8cPIbYt+8xWoCqPCDfKOEsxhlFUWEXmoV45/XTKipU5ZqvmdTsESCv0o97TP2sNZaZrFrvpovf7aNk3BUKw==", "dependencies": { "Keccak256": "1.0.0", "Multiformats.Base": "2.0.2", "Multiformats.Hash": "1.5.0", "NBitcoin.Secp256k1": "3.1.5", - "PierTwo.Lantern.Discv5.Rlp": "1.0.0-preview.6" + "PierTwo.Lantern.Discv5.Rlp": "1.0.0-preview.7" } }, "PierTwo.Lantern.Discv5.Rlp": { "type": "Transitive", - "resolved": "1.0.0-preview.6", - "contentHash": "X1mOhKZytX60uZwh9aCex0BVidN0hVlf5jKZsufacWpfsN/yMstc/fh3aRM9JWm8x7PQVeY300JXVFhDk4roqA==" + "resolved": "1.0.0-preview.7", + "contentHash": "tAwonG4x8SWFBxd06JvzYNo0xvTsDoM9xfk2tnwIcFzCvY7PORvpOiy9AQcyjqomFQmCNqF4ezwZoRZJV32iQg==" }, "Polly.Core": { "type": "Transitive", @@ -1002,7 +1002,7 @@ "Nethermind.Facade": "[1.37.0-unstable, )", "Nethermind.Network": "[1.37.0-unstable, )", "Nethermind.Network.Enr": "[1.37.0-unstable, )", - "PierTwo.Lantern.Discv5.WireProtocol": "[1.0.0-preview.6, )" + "PierTwo.Lantern.Discv5.WireProtocol": "[1.0.0-preview.7, )" } }, "nethermind.network.dns": { @@ -1519,14 +1519,14 @@ }, "PierTwo.Lantern.Discv5.WireProtocol": { "type": "CentralTransitive", - "requested": "[1.0.0-preview.6, )", - "resolved": "1.0.0-preview.6", - "contentHash": "WjVYiDxyZ3z00kuJJXuWJwRqkWfTrZF1v7qWz4mMASRP6AEhDCF4jMdCuAWkH1uPj00kkluONOc426Z//FcjDw==", + "requested": "[1.0.0-preview.7, )", + "resolved": "1.0.0-preview.7", + "contentHash": "wfa8Drf8r8Ty8r6cebobxANFmM2h0ckA/fWIKkQCnC+Af91IKFTAtiVhtu5oCjRxY21MLuWxqObV8r+JkKSYrg==", "dependencies": { "BouncyCastle.Cryptography": "2.4.0", "NBitcoin.Secp256k1": "3.1.5", - "PierTwo.Lantern.Discv5.Enr": "1.0.0-preview.6", - "PierTwo.Lantern.Discv5.Rlp": "1.0.0-preview.6" + "PierTwo.Lantern.Discv5.Enr": "1.0.0-preview.7", + "PierTwo.Lantern.Discv5.Rlp": "1.0.0-preview.7" } }, "Polly": {