From a2147c4da97c76d9de7d6d5177d66c2a76588f1b Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Wed, 26 Nov 2025 16:05:58 +0100 Subject: [PATCH 001/255] Fix history prune scheduling (#9677) * Rename BackgroundTaskScheduler.ScheduleTask -> TryScheduleTask and avoid exceptions In HistoryPruner add checks before going into lock and doing pruning. In historyPruner make pruning task exclusive - don't schedule another before previous isn't finished. * Remove lock from BackgroundTaskScheduler Move CancelledToken out of generic type Specify channel options explicitly * change _currentlyPruning in finally * change _currentlyPruning if failed to schedule pruning * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * More review fixes * fix error handling in SchedulePruneHistory * Update src/Nethermind/Nethermind.History/HistoryPruner.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/Nethermind/Nethermind.History/HistoryPruner.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/Nethermind/Nethermind.Consensus/Scheduler/BackgroundTaskScheduler.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix * comment * small optimization --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Scheduler/BackgroundTaskSchedulerTests.cs | 12 +- .../Scheduler/BackgroundTaskScheduler.cs | 105 ++++++-------- .../Scheduler/IBackgroundTaskScheduler.cs | 2 +- .../RunImmediatelyScheduler.cs | 3 +- .../HistoryPrunerTests.cs | 10 +- .../Nethermind.History/HistoryPruner.cs | 131 +++++++++++++----- .../Eth/V62/Eth62ProtocolHandlerTests.cs | 6 +- .../ProtocolHandlers/ProtocolHandlerBase.cs | 6 +- .../Eth/V62/Eth62ProtocolHandler.cs | 4 +- .../Utils/BackgroundTaskSchedulerWrapper.cs | 12 +- .../FastBlocks/ReceiptsSyncFeed.cs | 1 - 11 files changed, 164 insertions(+), 128 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus.Test/Scheduler/BackgroundTaskSchedulerTests.cs b/src/Nethermind/Nethermind.Consensus.Test/Scheduler/BackgroundTaskSchedulerTests.cs index a4180ffc934..a838bce57d6 100644 --- a/src/Nethermind/Nethermind.Consensus.Test/Scheduler/BackgroundTaskSchedulerTests.cs +++ b/src/Nethermind/Nethermind.Consensus.Test/Scheduler/BackgroundTaskSchedulerTests.cs @@ -35,7 +35,7 @@ public async Task Test_task_will_execute() TaskCompletionSource tcs = new TaskCompletionSource(); await using BackgroundTaskScheduler scheduler = new BackgroundTaskScheduler(_branchProcessor, _chainHeadInfo, 1, 65536, LimboLogs.Instance); - scheduler.ScheduleTask(1, (_, token) => + scheduler.TryScheduleTask(1, (_, token) => { tcs.SetResult(1); return Task.CompletedTask; @@ -52,13 +52,13 @@ public async Task Test_task_will_execute_concurrently_when_configured_so() int counter = 0; SemaphoreSlim waitSignal = new SemaphoreSlim(0); - scheduler.ScheduleTask(1, async (_, token) => + scheduler.TryScheduleTask(1, async (_, token) => { Interlocked.Increment(ref counter); await waitSignal.WaitAsync(token); Interlocked.Decrement(ref counter); }); - scheduler.ScheduleTask(1, async (_, token) => + scheduler.TryScheduleTask(1, async (_, token) => { Interlocked.Increment(ref counter); await waitSignal.WaitAsync(token); @@ -77,7 +77,7 @@ public async Task Test_task_will_cancel_on_block_processing() bool wasCancelled = false; ManualResetEvent waitSignal = new ManualResetEvent(false); - scheduler.ScheduleTask(1, async (_, token) => + scheduler.TryScheduleTask(1, async (_, token) => { waitSignal.Set(); try @@ -107,7 +107,7 @@ public async Task Test_task_that_is_scheduled_during_block_processing_will_conti int executionCount = 0; for (int i = 0; i < 5; i++) { - scheduler.ScheduleTask(1, (_, _) => + scheduler.TryScheduleTask(1, (_, token) => { executionCount++; return Task.CompletedTask; @@ -129,7 +129,7 @@ public async Task Test_task_that_is_scheduled_during_block_processing_but_deadli bool wasCancelled = false; ManualResetEvent waitSignal = new ManualResetEvent(false); - scheduler.ScheduleTask(1, (_, token) => + scheduler.TryScheduleTask(1, (_, token) => { wasCancelled = token.IsCancellationRequested; waitSignal.Set(); diff --git a/src/Nethermind/Nethermind.Consensus/Scheduler/BackgroundTaskScheduler.cs b/src/Nethermind/Nethermind.Consensus/Scheduler/BackgroundTaskScheduler.cs index d6d77481318..c138491985f 100644 --- a/src/Nethermind/Nethermind.Consensus/Scheduler/BackgroundTaskScheduler.cs +++ b/src/Nethermind/Nethermind.Consensus/Scheduler/BackgroundTaskScheduler.cs @@ -4,8 +4,6 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using System.Threading.Channels; @@ -18,15 +16,15 @@ namespace Nethermind.Consensus.Scheduler; /// -/// Provide a way to orchestrate tasks to run in background at a lower priority. +/// Provides a way to orchestrate tasks to run in the background at a lower priority. /// - Task will be run in a lower priority thread, but there is a concurrency limit. -/// - Task closure will have CancellationToken which will be cancelled if block processing happens while the task is running. -/// - Task have a default timeout, which is counted from the time it is queued. If timed out because too many other background -/// task before it for example, the cancellation token passed to it will be cancelled. -/// - Task will still run when block processing is happening and its timed out this is so that it can handle its cancellation. -/// - Task will not run if block processing is happening and it still have some time left. -/// It is up to the task to determine what happen if cancelled, maybe it will reschedule for later, or resume later, but -/// preferably, stop execution immediately. Don't hang BTW. Other background task need to cancel too. +/// - Task closure will have the CancellationToken which will be canceled if block processing happens while the task is running. +/// - The Task has a default timeout, which is counted from the time it is queued. If timed out because too many other background +/// tasks before it, for example, the cancellation token passed to it will be canceled. +/// - Task will still run when block processing is happening, and it's timed out this is so that it can handle its cancellation. +/// - Task will not run if block processing is happening, and it still has some time left. +/// It is up to the task to determine what happens if canceled, maybe it will reschedule for later or resume later, but +/// preferably, stop execution immediately. Don't hang BTW. Other background tasks need to be canceled too. /// - A failure at this level is considered unexpected and loud. Exception should be handled at handler level. /// public class BackgroundTaskScheduler : IBackgroundTaskScheduler, IAsyncDisposable @@ -35,7 +33,6 @@ public class BackgroundTaskScheduler : IBackgroundTaskScheduler, IAsyncDisposabl private readonly CancellationTokenSource _mainCancellationTokenSource; private readonly Channel _taskQueue; - private readonly Lock _queueLock = new(); private readonly BelowNormalPriorityTaskScheduler _scheduler; private readonly ManualResetEventSlim _restartQueueSignal; private readonly Task[] _tasksExecutors; @@ -57,8 +54,14 @@ public BackgroundTaskScheduler(IBranchProcessor branchProcessor, IChainHeadInfoP _blockProcessorCancellationTokenSource = new CancellationTokenSource(); // In priority order, so if we reach an activity with time left, - // we know rest still have time left - _taskQueue = Channel.CreateUnboundedPrioritized(); + // we know the rest still have time left + _taskQueue = Channel.CreateUnboundedPrioritized( + new UnboundedPrioritizedChannelOptions + { + SingleReader = concurrency == 1, + SingleWriter = false, + AllowSynchronousContinuations = false + }); _logger = logManager.GetClassLogger(); _branchProcessor = branchProcessor; _headInfo = headInfo; @@ -81,25 +84,25 @@ public BackgroundTaskScheduler(IBranchProcessor branchProcessor, IChainHeadInfoP private void BranchProcessorOnBranchesProcessing(object? sender, BlocksProcessingEventArgs e) { - // If we are syncing we don't block background task processing + // If we are syncing, we don't block background task processing // as there are potentially no gaps between blocks if (!_headInfo.IsSyncing) { - // Reset background queue processing signal, causing it to wait + // Reset the background queue processing signal, causing it to wait _restartQueueSignal.Reset(); - // On block processing, we cancel the block process cts, causing current task to get cancelled. + // On block processing, we cancel the block process cts, causing the current task to get canceled. _blockProcessorCancellationTokenSource.Cancel(); } } private void BranchProcessorOnBranchProcessed(object? sender, BlockProcessedEventArgs e) { - // Once block is processed, we replace the cancellation token with a fresh uncancelled one + // Once the block is processed, we replace the cancellation token with a fresh uncanceled one using CancellationTokenSource oldTokenSource = Interlocked.Exchange( ref _blockProcessorCancellationTokenSource, new CancellationTokenSource()); - // We also set queue signal causing it to continue processing task. + // We also set a queue signal causing it to continue processing the task. _restartQueueSignal.Set(); } @@ -119,18 +122,18 @@ private async Task StartChannel() Interlocked.Decrement(ref _queueCount); if (token.IsCancellationRequested) { - // In case of task that is suppose to run when a block is being processed, if there is some time left - // from its deadline, we re-queue it. We do this in case there are some task in the queue that already - // reached deadline during block processing in which case, it will need to execute in order to handle + // In case of a task supposed to run when a block is being processed, if there is some time left + // from its deadline, we re-queue it. We do this in case there is some task in the queue that already + // reached deadline during block processing, in which case, it will need to execute to handle // its cancellation. if (DateTimeOffset.UtcNow < activity.Deadline) { Interlocked.Increment(ref _queueCount); await _taskQueue.Writer.WriteAsync(activity); UpdateQueueCount(); - // Requeued, throttle to prevent infinite loop. - // The tasks are in priority order, so we know next is same deadline or longer - // And we want to exit inner loop to refresh CancellationToken + // Re-queued, throttle to prevent infinite loop. + // The tasks are in priority order, so we know next is the same deadline or longer, + // And we want to exit the inner loop to refresh CancellationToken goto Throttle; } } @@ -158,51 +161,33 @@ private async Task StartChannel() } } - public void ScheduleTask(TReq request, Func fulfillFunc, TimeSpan? timeout = null) + public bool TryScheduleTask(TReq request, Func fulfillFunc, TimeSpan? timeout = null) { - timeout ??= DefaultTimeout; - DateTimeOffset deadline = DateTimeOffset.UtcNow + timeout.Value; - IActivity activity = new Activity { - Deadline = deadline, + Deadline = DateTimeOffset.UtcNow + (timeout ?? DefaultTimeout), Request = request, FulfillFunc = fulfillFunc, }; Evm.Metrics.IncrementTotalBackgroundTasksQueued(); - bool success = false; - lock (_queueLock) + if (Interlocked.Increment(ref _queueCount) <= _capacity) { - if (_queueCount + 1 < _capacity) + if (_taskQueue.Writer.TryWrite(activity)) { - success = _taskQueue.Writer.TryWrite(activity); - if (success) - { - Interlocked.Increment(ref _queueCount); - } + UpdateQueueCount(); + return true; } } - if (success) - { - UpdateQueueCount(); - } - else - { - request.TryDispose(); - // This should never happen unless something goes very wrong. - UnableToWriteToTaskQueue(); - } - - [StackTraceHidden, DoesNotReturn] - static void UnableToWriteToTaskQueue() - => throw new InvalidOperationException("Unable to write to background task queue."); + if (_logger.IsWarn) _logger.Warn($"Background task queue is full (Count: {_queueCount}, Capacity: {_capacity}), dropping task."); + Interlocked.Decrement(ref _queueCount); + request.TryDispose(); + return false; } - private void UpdateQueueCount() - => Evm.Metrics.NumberOfBackgroundTasksScheduled = Volatile.Read(ref _queueCount); + private void UpdateQueueCount() => Evm.Metrics.NumberOfBackgroundTasksScheduled = Volatile.Read(ref _queueCount); public async ValueTask DisposeAsync() { @@ -220,21 +205,11 @@ public async ValueTask DisposeAsync() private readonly struct Activity : IActivity { - private static CancellationToken CancelledToken { get; } = CreateCancelledToken(); - - private static CancellationToken CreateCancelledToken() - { - CancellationTokenSource cts = new(); - cts.Cancel(); - return cts.Token; - } - public DateTimeOffset Deadline { get; init; } public TReq Request { get; init; } public Func FulfillFunc { get; init; } - public int CompareTo(IActivity? other) - => Deadline.CompareTo(other.Deadline); + public int CompareTo(IActivity? other) => Deadline.CompareTo(other?.Deadline ?? DateTimeOffset.MaxValue); public async Task Do(CancellationToken cancellationToken) { @@ -245,7 +220,7 @@ public async Task Do(CancellationToken cancellationToken) if (timeToComplete <= TimeSpan.Zero) { // Cancel immediately. Got no time left. - token = CancelledToken; + token = CancellationTokenExtensions.AlreadyCancelledToken; } else { diff --git a/src/Nethermind/Nethermind.Consensus/Scheduler/IBackgroundTaskScheduler.cs b/src/Nethermind/Nethermind.Consensus/Scheduler/IBackgroundTaskScheduler.cs index b585a58f9bc..b43ec458331 100644 --- a/src/Nethermind/Nethermind.Consensus/Scheduler/IBackgroundTaskScheduler.cs +++ b/src/Nethermind/Nethermind.Consensus/Scheduler/IBackgroundTaskScheduler.cs @@ -9,5 +9,5 @@ namespace Nethermind.Consensus.Scheduler; public interface IBackgroundTaskScheduler { - void ScheduleTask(TReq request, Func fulfillFunc, TimeSpan? timeout = null); + bool TryScheduleTask(TReq request, Func fulfillFunc, TimeSpan? timeout = null); } diff --git a/src/Nethermind/Nethermind.Core.Test/RunImmediatelyScheduler.cs b/src/Nethermind/Nethermind.Core.Test/RunImmediatelyScheduler.cs index 1056e8dbd39..cb81087435d 100644 --- a/src/Nethermind/Nethermind.Core.Test/RunImmediatelyScheduler.cs +++ b/src/Nethermind/Nethermind.Core.Test/RunImmediatelyScheduler.cs @@ -16,8 +16,9 @@ private RunImmediatelyScheduler() { } - public void ScheduleTask(TReq request, Func fulfillFunc, TimeSpan? timeout = null) + public bool TryScheduleTask(TReq request, Func fulfillFunc, TimeSpan? timeout = null) { fulfillFunc(request, CancellationToken.None); + return true; } } diff --git a/src/Nethermind/Nethermind.History.Test/HistoryPrunerTests.cs b/src/Nethermind/Nethermind.History.Test/HistoryPrunerTests.cs index bc80429e567..1a9e756427c 100644 --- a/src/Nethermind/Nethermind.History.Test/HistoryPrunerTests.cs +++ b/src/Nethermind/Nethermind.History.Test/HistoryPrunerTests.cs @@ -74,7 +74,7 @@ public async Task Can_prune_blocks_older_than_specified_epochs() CheckOldestAndCutoff(1, cutoff, historyPruner); - await historyPruner.TryPruneHistory(CancellationToken.None); + historyPruner.TryPruneHistory(CancellationToken.None); CheckGenesisPreserved(testBlockchain, blockHashes[0]); for (int i = 1; i <= blocks; i++) @@ -122,7 +122,7 @@ public async Task Can_prune_to_ancient_barriers() CheckOldestAndCutoff(1, BeaconGenesisBlockNumber, historyPruner); - await historyPruner.TryPruneHistory(CancellationToken.None); + historyPruner.TryPruneHistory(CancellationToken.None); CheckGenesisPreserved(testBlockchain, blockHashes[0]); @@ -171,7 +171,7 @@ public async Task Prunes_up_to_sync_pivot() CheckOldestAndCutoff(1, BeaconGenesisBlockNumber, historyPruner); - await historyPruner.TryPruneHistory(CancellationToken.None); + historyPruner.TryPruneHistory(CancellationToken.None); CheckGenesisPreserved(testBlockchain, blockHashes[0]); @@ -221,7 +221,7 @@ public async Task Can_find_oldest_block() CheckOldestAndCutoff(1, cutoff, historyPruner); - await historyPruner.TryPruneHistory(CancellationToken.None); + historyPruner.TryPruneHistory(CancellationToken.None); historyPruner.SetDeletePointerToOldestBlock(); // recalculate oldest block with binary search CheckOldestAndCutoff(cutoff, cutoff, historyPruner); @@ -248,7 +248,7 @@ public async Task Does_not_prune_when_disabled() } var historyPruner = (HistoryPruner)testBlockchain.Container.Resolve(); - await historyPruner.TryPruneHistory(CancellationToken.None); + historyPruner.TryPruneHistory(CancellationToken.None); CheckGenesisPreserved(testBlockchain, blockHashes[0]); diff --git a/src/Nethermind/Nethermind.History/HistoryPruner.cs b/src/Nethermind/Nethermind.History/HistoryPruner.cs index df2313a3f50..ed703a60923 100644 --- a/src/Nethermind/Nethermind.History/HistoryPruner.cs +++ b/src/Nethermind/Nethermind.History/HistoryPruner.cs @@ -14,7 +14,9 @@ using Nethermind.Consensus.Processing; using Nethermind.Consensus.Scheduler; using Nethermind.Core; +using Nethermind.Core.Collections; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Logging; @@ -56,6 +58,7 @@ public class HistoryPruner : IHistoryPruner private long? _cutoffPointer; private ulong? _cutoffTimestamp; private bool _hasLoadedDeletePointer = false; + private int _currentlyPruning = 0; public event EventHandler? NewOldestBlock; @@ -126,25 +129,26 @@ public long? CutoffBlockNumber } long? cutoffBlockNumber = null; - long searchCutoff = _blockTree.Head is null ? _blockTree.SyncPivot.BlockNumber : _blockTree.Head.Number; + long to = _blockTree.Head?.Number ?? _blockTree.SyncPivot.BlockNumber; + + // cutoff is unchanged, can reuse + if (_cutoffTimestamp is not null && cutoffTimestamp == _cutoffTimestamp) + { + return _cutoffPointer; + } + bool lockTaken = false; try { Monitor.TryEnter(_searchLock, LockWaitTimeoutMs, ref lockTaken); - if (lockTaken) { - // cutoff is unchanged, can reuse - if (_cutoffTimestamp is not null && cutoffTimestamp == _cutoffTimestamp) - { - return _cutoffPointer; - } - - // optimisticly search a few blocks from old pointer + // optimistically search a few blocks from an old pointer if (_cutoffPointer is not null) { int attempts = 0; - _ = GetBlocksByNumber(_cutoffPointer.Value, searchCutoff, b => + long from = _cutoffPointer.Value; + using ArrayPoolListRef x = GetBlocksByNumber(from, to, b => { if (attempts >= MaxOptimisticSearchAttempts) { @@ -158,11 +162,11 @@ public long? CutoffBlockNumber } attempts++; return afterCutoff; - }).ToList(); + }).ToPooledListRef((int)(to - from + 1)); } - // if linear search fails fallback to binary search - cutoffBlockNumber ??= BlockTree.BinarySearchBlockNumber(_deletePointer, searchCutoff, (n, _) => + // if linear search fails, fallback to binary search + cutoffBlockNumber ??= BlockTree.BinarySearchBlockNumber(_deletePointer, to, (n, _) => { BlockInfo[]? blockInfos = _chainLevelInfoRepository.LoadLevel(n)?.BlockInfos; @@ -196,7 +200,9 @@ public long? CutoffBlockNumber finally { if (lockTaken) + { Monitor.Exit(_searchLock); + } } return cutoffBlockNumber; @@ -230,7 +236,9 @@ public BlockHeader? OldestBlockHeader finally { if (lockTaken) + { Monitor.Exit(_pruneLock); + } } } @@ -242,38 +250,82 @@ private void OnBlockProcessorQueueEmpty(object? sender, EventArgs e) => SchedulePruneHistory(_processExitSource.Token); private void SchedulePruneHistory(CancellationToken cancellationToken) - => _backgroundTaskScheduler.ScheduleTask(1, - (_, backgroundTaskToken) => + { + if (Volatile.Read(ref _currentlyPruning) == 0) + { + Task.Run(() => { - var cts = CancellationTokenSource.CreateLinkedTokenSource(backgroundTaskToken, cancellationToken); - return TryPruneHistory(cts.Token); + if (Interlocked.CompareExchange(ref _currentlyPruning, 1, 0) == 0) + { + try + { + if (!_backgroundTaskScheduler.TryScheduleTask(1, + (_, backgroundTaskToken) => + { + try + { + using var cts = CancellationTokenSource.CreateLinkedTokenSource(backgroundTaskToken, + cancellationToken); + TryPruneHistory(cts.Token); + } + finally + { + Interlocked.Exchange(ref _currentlyPruning, 0); + } + + return Task.CompletedTask; + })) + { + Interlocked.Exchange(ref _currentlyPruning, 0); + if (_logger.IsDebug) _logger.Debug("Failed to schedule historical block pruning (queue full). Will retry on next trigger."); + } + } + catch + { + Interlocked.Exchange(ref _currentlyPruning, 0); + throw; + } + } }); + } + } - internal Task TryPruneHistory(CancellationToken cancellationToken) + internal void TryPruneHistory(CancellationToken cancellationToken) { + if (_blockTree.Head is null || + _blockTree.SyncPivot.BlockNumber == 0 || + !_hasLoadedDeletePointer || + !ShouldPruneHistory(out ulong? cutoffTimestamp)) + { + SkipLocalPruning(); + return; + } + bool lockTaken = false; + Monitor.TryEnter(_pruneLock, LockWaitTimeoutMs, ref lockTaken); try { - Monitor.TryEnter(_pruneLock, LockWaitTimeoutMs, ref lockTaken); if (lockTaken) { - if (_blockTree.Head is null || - _blockTree.SyncPivot.BlockNumber == 0 || - !TryLoadDeletePointer() || - !ShouldPruneHistory(out ulong? cutoffTimestamp)) + if (!TryLoadDeletePointer() || + !ShouldPruneHistory(out cutoffTimestamp)) { - if (_logger.IsDebug) _logger.Debug($"Skipping historical block pruning."); - return Task.CompletedTask; + SkipLocalPruning(); + return; } if (_logger.IsInfo) { - long? cutoff = CutoffBlockNumber; - cutoff = cutoff is null ? null : long.Min(cutoff!.Value, _blockTree.SyncPivot.BlockNumber); + long? cutoffBlockNumber = CutoffBlockNumber; + long? cutoff = cutoffBlockNumber is null ? null : long.Min(cutoffBlockNumber.Value, _blockTree.SyncPivot.BlockNumber); long? toDelete = cutoff - _deletePointer; - string cutoffString = cutoffTimestamp is null ? $"#{(cutoff is null ? "unknown" : cutoff)}" : $"timestamp {cutoffTimestamp} (#{(cutoff is null ? "unknown" : cutoff)})"; - _logger.Info($"Pruning historical blocks up to {cutoffString}. Estimated {(toDelete is null ? "unknown" : toDelete)} blocks will be deleted."); + string cutoffString = cutoffTimestamp is null + ? $"#{FormatNumberOrUnknown(cutoff)}" + : $"timestamp {cutoffTimestamp} (#{FormatNumberOrUnknown(cutoff)})"; + _logger.Info($"Pruning historical blocks up to {cutoffString}. Estimated {FormatNumberOrUnknown(toDelete)} blocks will be deleted."); + + static string FormatNumberOrUnknown(long? l) => l?.ToString() ?? "unknown"; } PruneBlocksAndReceipts(cutoffTimestamp, cancellationToken); @@ -286,10 +338,15 @@ internal Task TryPruneHistory(CancellationToken cancellationToken) finally { if (lockTaken) + { Monitor.Exit(_pruneLock); + } } - return Task.CompletedTask; + void SkipLocalPruning() + { + if (_logger.IsTrace) _logger.Trace("Skipping historical block pruning."); + } } internal bool SetDeletePointerToOldestBlock() @@ -359,12 +416,13 @@ private bool PruningIntervalHasElapsed() private void PruneBlocksAndReceipts(ulong? cutoffTimestamp, CancellationToken cancellationToken) { int deletedBlocks = 0; - ulong? lastDeletedTimstamp = null; + ulong? lastDeletedTimestamp = null; try { IEnumerable blocks = _historyConfig.Pruning == PruningModes.UseAncientBarriers ? GetBlocksBeforeAncientBarrier() : GetBlocksBeforeTimestamp(cutoffTimestamp!.Value); + foreach (Block block in blocks) { long number = block.Number; @@ -396,20 +454,21 @@ private void PruneBlocksAndReceipts(ulong? cutoffTimestamp, CancellationToken ca _receiptStorage.RemoveReceipts(block); UpdateDeletePointer(number + 1, remaining is null || remaining == 0); - lastDeletedTimstamp = block.Timestamp; + lastDeletedTimestamp = block.Timestamp; deletedBlocks++; Metrics.BlocksPruned++; } } finally { - if (_cutoffPointer < _deletePointer && lastDeletedTimstamp is not null) + if (_cutoffPointer < _deletePointer && lastDeletedTimestamp is not null) { _cutoffPointer = _deletePointer; - _cutoffTimestamp = lastDeletedTimstamp; + _cutoffTimestamp = lastDeletedTimestamp; Metrics.PruningCutoffBlocknumber = _cutoffPointer; Metrics.PruningCutoffTimestamp = _cutoffTimestamp; } + SaveDeletePointer(); if (!cancellationToken.IsCancellationRequested) @@ -445,7 +504,7 @@ private IEnumerable GetBlocksByNumber(long from, long to, Predicate GetBlocksByNumber(long from, long to, Predicate(TReq request, Func fulfillFunc, TimeSpan? timeout = null) + public bool TryScheduleTask(TReq request, Func fulfillFunc, + TimeSpan? timeout = null) { - CancellationTokenSource cts = new CancellationTokenSource(); + CancellationTokenSource cts = new(); cts.Cancel(); fulfillFunc(request, cts.Token); ScheduledTasks++; + return true; } } diff --git a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ProtocolHandlerBase.cs b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ProtocolHandlerBase.cs index 587e344d0d0..1ba8ffcc5a3 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ProtocolHandlerBase.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ProtocolHandlerBase.cs @@ -179,13 +179,13 @@ protected void ReportIn(string messageInfo, int size) } protected void HandleInBackground(ZeroPacket message, Func> handle) where TReq : P2PMessage where TRes : P2PMessage => - BackgroundTaskScheduler.ScheduleSyncServe(DeserializeAndReport(message), handle); + BackgroundTaskScheduler.TryScheduleSyncServe(DeserializeAndReport(message), handle); protected void HandleInBackground(ZeroPacket message, Func> handle) where TReq : P2PMessage where TRes : P2PMessage => - BackgroundTaskScheduler.ScheduleSyncServe(DeserializeAndReport(message), handle); + BackgroundTaskScheduler.TryScheduleSyncServe(DeserializeAndReport(message), handle); protected void HandleInBackground(ZeroPacket message, Func handle) where TReq : P2PMessage => - BackgroundTaskScheduler.ScheduleBackgroundTask(DeserializeAndReport(message), handle); + BackgroundTaskScheduler.TryScheduleBackgroundTask(DeserializeAndReport(message), handle); private TReq DeserializeAndReport(ZeroPacket message) where TReq : P2PMessage { 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 ac6795f86d1..5850486aa32 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs @@ -236,7 +236,7 @@ private void Handle(StatusMessage status) protected void Handle(TransactionsMessage msg) { IOwnedReadOnlyList iList = msg.Transactions; - BackgroundTaskScheduler.ScheduleBackgroundTask((iList, 0), _handleSlow); + BackgroundTaskScheduler.TryScheduleBackgroundTask((iList, 0), _handleSlow); } protected virtual ValueTask HandleSlow((IOwnedReadOnlyList txs, int startIndex) request, CancellationToken cancellationToken) @@ -262,7 +262,7 @@ protected virtual ValueTask HandleSlow((IOwnedReadOnlyList txs, int } // Reschedule and with different start index - BackgroundTaskScheduler.ScheduleBackgroundTask((transactions, i), HandleSlow); + BackgroundTaskScheduler.TryScheduleBackgroundTask((transactions, i), HandleSlow); return ValueTask.CompletedTask; } diff --git a/src/Nethermind/Nethermind.Network/P2P/Utils/BackgroundTaskSchedulerWrapper.cs b/src/Nethermind/Nethermind.Network/P2P/Utils/BackgroundTaskSchedulerWrapper.cs index db849810a5d..47a4836becc 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Utils/BackgroundTaskSchedulerWrapper.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Utils/BackgroundTaskSchedulerWrapper.cs @@ -20,14 +20,14 @@ namespace Nethermind.Network.P2P.Utils; /// public class BackgroundTaskSchedulerWrapper(ProtocolHandlerBase handler, IBackgroundTaskScheduler backgroundTaskScheduler) { - internal void ScheduleSyncServe(TReq request, Func> fulfillFunc) where TRes : P2PMessage => - ScheduleBackgroundTask((request, fulfillFunc), BackgroundSyncSender); + internal bool TryScheduleSyncServe(TReq request, Func> fulfillFunc) where TRes : P2PMessage => + TryScheduleBackgroundTask((request, fulfillFunc), BackgroundSyncSender); - internal void ScheduleSyncServe(TReq request, Func> fulfillFunc) where TRes : P2PMessage => - ScheduleBackgroundTask((request, fulfillFunc), BackgroundSyncSenderValueTask); + internal bool TryScheduleSyncServe(TReq request, Func> fulfillFunc) where TRes : P2PMessage => + TryScheduleBackgroundTask((request, fulfillFunc), BackgroundSyncSenderValueTask); - internal void ScheduleBackgroundTask(TReq request, Func fulfillFunc) => - backgroundTaskScheduler.ScheduleTask((request, fulfillFunc), BackgroundTaskFailureHandlerValueTask); + internal bool TryScheduleBackgroundTask(TReq request, Func fulfillFunc) => + backgroundTaskScheduler.TryScheduleTask((request, fulfillFunc), BackgroundTaskFailureHandlerValueTask); // I just don't want to create a closure... so this happens. private async ValueTask BackgroundSyncSender( diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs index a1e6a7e2766..c8b87ae733e 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs @@ -28,7 +28,6 @@ namespace Nethermind.Synchronization.FastBlocks { - public class ReceiptsSyncFeed : BarrierSyncFeed { protected override long? LowestInsertedNumber => _syncPointers.LowestInsertedReceiptBlockNumber; From 634a1e3c951b42abf12f383ff3c264487f7e7835 Mon Sep 17 00:00:00 2001 From: Marcin Sobczak <77129288+marcindsobczak@users.noreply.github.com> Date: Wed, 26 Nov 2025 16:08:12 +0100 Subject: [PATCH 002/255] Add test for modexp empty and zero values (#9785) * add modexp test * assert error * better zero mod case * one more case * nitpick --- .../Nethermind.Evm.Test/Eip2565Tests.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip2565Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip2565Tests.cs index 14e715eb990..37816776dae 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip2565Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip2565Tests.cs @@ -6,6 +6,7 @@ using System.Numerics; using FluentAssertions; using MathNet.Numerics.Random; +using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Evm.Precompiles; using Nethermind.Int256; @@ -53,6 +54,30 @@ public void ModExp_run_should_not_throw_exception(string inputStr) gas.Should().Be(200); } + // empty base + [TestCase("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000101F0", "00")] + // empty exp + [TestCase("0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001020304050607F0", "01")] + // empty mod + [TestCase("000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000102030405060701", "")] + // empty args + [TestCase("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "")] + // empty args (even sizes) + [TestCase("", "")] + // zero mod + [TestCase("000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001010100", "00")] + // 65-byte args (empty base, empty exp, one-byte mod length input) + [TestCase("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011", "", true)] + public void ModExp_return_expected_values(string inputHex, string expectedResult, bool isError = false) + { + byte[] input = Bytes.FromHexString(inputHex); + byte[] expected = Bytes.FromHexString(expectedResult); + + Result result = ModExpPrecompile.Instance.Run(input, Osaka.Instance); + Assert.That(result.Data, Is.EqualTo(expected)); + Assert.That(result.Error, isError ? Is.Not.Null : Is.Null); + } + private static (byte[], bool) BigIntegerModExp(byte[] inputData) { (int baseLength, int expLength, int modulusLength) = GetInputLengths(inputData); From bd9c16ee7d372bd6c8a52df4bceab6a11e411caf Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Wed, 26 Nov 2025 19:22:28 -0300 Subject: [PATCH 003/255] Skip creating precompile error string if no error (#9795) --- src/Nethermind/Nethermind.Evm/CallResult.cs | 2 +- src/Nethermind/Nethermind.Evm/ICodeInfo.cs | 2 + .../Nethermind.Evm/VirtualMachine.cs | 37 +++++++++++++------ 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/CallResult.cs b/src/Nethermind/Nethermind.Evm/CallResult.cs index 8c1e4b9b1af..744d65a9304 100644 --- a/src/Nethermind/Nethermind.Evm/CallResult.cs +++ b/src/Nethermind/Nethermind.Evm/CallResult.cs @@ -6,7 +6,7 @@ namespace Nethermind.Evm; -public unsafe partial class VirtualMachine +public partial class VirtualMachine { protected readonly ref struct CallResult { diff --git a/src/Nethermind/Nethermind.Evm/ICodeInfo.cs b/src/Nethermind/Nethermind.Evm/ICodeInfo.cs index 40909e8abdd..07156260530 100644 --- a/src/Nethermind/Nethermind.Evm/ICodeInfo.cs +++ b/src/Nethermind/Nethermind.Evm/ICodeInfo.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Evm.Precompiles; namespace Nethermind.Evm.CodeAnalysis; @@ -34,6 +35,7 @@ public interface ICodeInfo /// By default, this returns false. /// bool IsPrecompile => false; + IPrecompile? Precompile => null; /// /// Gets the code section. diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index b38ce65a793..9a91d5f760b 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -979,33 +979,34 @@ private CallResult RunPrecompile(EvmState state) UInt256 transferValue = state.Env.TransferValue; long gasAvailable = state.GasAvailable; - IPrecompile precompile = ((PrecompileInfo)state.Env.CodeInfo).Precompile!; + IPrecompile precompile = state.Env.CodeInfo.Precompile!; IReleaseSpec spec = BlockExecutionContext.Spec; long baseGasCost = precompile.BaseGasCost(spec); long dataGasCost = precompile.DataGasCost(callData, spec); - bool wasCreated = _worldState.AddToBalanceAndCreateIfNotExists(state.Env.ExecutingAccount, transferValue, spec); + bool wasCreated = _worldState.AddToBalanceAndCreateIfNotExists(state.Env.ExecutingAccount, in transferValue, spec); // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-161.md // An additional issue was found in Parity, // where the Parity client incorrectly failed // to revert empty account deletions in a more limited set of contexts // involving out-of-gas calls to precompiled contracts; - // the new Geth behavior matches Parity’s, + // the new Geth behavior matches Parity's, // and empty accounts will cease to be a source of concern in general // in about one week once the state clearing process finishes. - if (state.Env.ExecutingAccount.Equals(_parityTouchBugAccount.Address) - && !wasCreated - && transferValue.IsZero - && spec.ClearEmptyAccountWhenTouched) + if (!wasCreated && + transferValue.IsZero && + spec.ClearEmptyAccountWhenTouched && + state.Env.ExecutingAccount.Equals(_parityTouchBugAccount.Address)) { _parityTouchBugAccount.ShouldDelete = true; } - if (!UpdateGas(checked(baseGasCost + dataGasCost), ref gasAvailable)) + if ((ulong)baseGasCost + (ulong)dataGasCost > (ulong)long.MaxValue || + !UpdateGas(baseGasCost + dataGasCost, ref gasAvailable)) { - return new(default, false, 0, true, EvmExceptionType.OutOfGas); + return new(output: default, precompileSuccess: false, fromVersion: 0, shouldRevert: true, EvmExceptionType.OutOfGas); } state.GasAvailable = gasAvailable; @@ -1022,19 +1023,31 @@ private CallResult RunPrecompile(EvmState state) exceptionType: !success ? EvmExceptionType.PrecompileFailure : EvmExceptionType.None ) { - SubstateError = $"Precompile {precompile.GetStaticName()} failed with error: {output.Error}" + SubstateError = success ? null : GetErrorString(precompile, output.Error) }; } catch (DllNotFoundException exception) { - if (_logger.IsError) _logger.Error($"Failed to load one of the dependencies of {precompile.GetType()} precompile", exception); + if (_logger.IsError) LogMissingDependency(precompile, exception); throw; } catch (Exception exception) { - if (_logger.IsError) _logger.Error($"Precompiled contract ({precompile.GetType()}) execution exception", exception); + if (_logger.IsError) LogExecutionException(precompile, exception); return new(output: default, precompileSuccess: false, fromVersion: 0, shouldRevert: true); } + + [MethodImpl(MethodImplOptions.NoInlining)] + void LogExecutionException(IPrecompile precompile, Exception exception) + => _logger.Error($"Precompiled contract ({precompile.GetType()}) execution exception", exception); + + [MethodImpl(MethodImplOptions.NoInlining)] + void LogMissingDependency(IPrecompile precompile, DllNotFoundException exception) + => _logger.Error($"Failed to load one of the dependencies of {precompile.GetType()} precompile", exception); + + [MethodImpl(MethodImplOptions.NoInlining)] + static string GetErrorString(IPrecompile precompile, string? error) + => $"Precompile {precompile.GetStaticName()} failed with error: {error}"; } /// From f9acb5c4cfbf7317cf658b4d4b342fd4431a06b5 Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 26 Nov 2025 23:23:39 +0100 Subject: [PATCH 004/255] chore(sync): remove redundant await in peer refresh loop (#9792) Update SyncPeerPool.cs --- src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs index 25d3d60e5d3..d0bbb7e0ba3 100644 --- a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs +++ b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs @@ -446,7 +446,6 @@ private async Task RunRefreshPeerLoop() } if (_logger.IsInfo) _logger.Info("Exiting sync peer refresh loop"); - await Task.CompletedTask; } private void StartUpgradeTimer() From 5af3bc8acc1bfad57c0ae6b5e7f9156f624a3c7a Mon Sep 17 00:00:00 2001 From: strmfos <155266597+strmfos@users.noreply.github.com> Date: Wed, 26 Nov 2025 23:33:06 +0100 Subject: [PATCH 005/255] fix: Correct NullSigner.CanSign to return false (#9788) --- .../Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs | 2 +- src/Nethermind/Nethermind.Consensus/NullSigner.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs index 628ff7f9c60..17af0b2ad38 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs @@ -19,7 +19,7 @@ public void Test() { NullSigner signer = NullSigner.Instance; signer.Address.Should().Be(Address.Zero); - signer.CanSign.Should().BeTrue(); + signer.CanSign.Should().BeFalse(); } [Test, MaxTime(Timeout.MaxTestTime)] diff --git a/src/Nethermind/Nethermind.Consensus/NullSigner.cs b/src/Nethermind/Nethermind.Consensus/NullSigner.cs index 8f5e70ba4da..2210d911435 100644 --- a/src/Nethermind/Nethermind.Consensus/NullSigner.cs +++ b/src/Nethermind/Nethermind.Consensus/NullSigner.cs @@ -18,7 +18,7 @@ public class NullSigner : ISigner, ISignerStore public Signature Sign(in ValueHash256 message) { return new(new byte[65]); } - public bool CanSign { get; } = true; // TODO: why true? + public bool CanSign { get; } = false; public PrivateKey? Key { get; } = null; From aac12b193cbecdcf24a843dc754a4046c29ffcb1 Mon Sep 17 00:00:00 2001 From: 0xLogicalx Date: Wed, 26 Nov 2025 23:33:38 +0100 Subject: [PATCH 006/255] Optimize CacheBenchmark empty byte allocations (#9791) Update CacheBenchmark.cs --- .../CacheBenchmark.cs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Nethermind/Nethermind.Trie.Benchmark/CacheBenchmark.cs b/src/Nethermind/Nethermind.Trie.Benchmark/CacheBenchmark.cs index 1d17ea69086..ecd63cccdf2 100644 --- a/src/Nethermind/Nethermind.Trie.Benchmark/CacheBenchmark.cs +++ b/src/Nethermind/Nethermind.Trie.Benchmark/CacheBenchmark.cs @@ -1,3 +1,4 @@ +using System; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Jobs; using Nethermind.Core.Caching; @@ -55,7 +56,7 @@ public MemCountingCache Post_init_trie_cache_with_item_400() { MemCountingCache cache = new MemCountingCache(1024 * 1024, string.Empty); - cache.Set(Keccak.Zero, new byte[0]); + cache.Set(Keccak.Zero, Array.Empty()); return cache; } @@ -64,8 +65,8 @@ public MemCountingCache With_2_items_cache_504() { MemCountingCache cache = new MemCountingCache(1024 * 1024, string.Empty); - cache.Set(TestItem.KeccakA, new byte[0]); - cache.Set(TestItem.KeccakB, new byte[0]); + cache.Set(TestItem.KeccakA, Array.Empty()); + cache.Set(TestItem.KeccakB, Array.Empty()); return cache; } @@ -74,9 +75,9 @@ public MemCountingCache With_3_items_cache_608() { MemCountingCache cache = new MemCountingCache(1024 * 1024, string.Empty); - cache.Set(TestItem.KeccakA, new byte[0]); - cache.Set(TestItem.KeccakB, new byte[0]); - cache.Set(TestItem.KeccakC, new byte[0]); + cache.Set(TestItem.KeccakA, Array.Empty()); + cache.Set(TestItem.KeccakB, Array.Empty()); + cache.Set(TestItem.KeccakC, Array.Empty()); return cache; } @@ -85,10 +86,10 @@ public MemCountingCache Post_dictionary_growth_cache_824_and_136_lost() { MemCountingCache cache = new MemCountingCache(1024 * 1024, string.Empty); - cache.Set(TestItem.KeccakA, new byte[0]); - cache.Set(TestItem.KeccakB, new byte[0]); - cache.Set(TestItem.KeccakC, new byte[0]); - cache.Set(TestItem.KeccakD, new byte[0]); + cache.Set(TestItem.KeccakA, Array.Empty()); + cache.Set(TestItem.KeccakB, Array.Empty()); + cache.Set(TestItem.KeccakC, Array.Empty()); + cache.Set(TestItem.KeccakD, Array.Empty()); return cache; } } From 0f332c9e26996cffd49c193e3892e3a76e9d67f3 Mon Sep 17 00:00:00 2001 From: bigbear <155267841+aso20455@users.noreply.github.com> Date: Thu, 27 Nov 2025 00:51:39 +0200 Subject: [PATCH 007/255] fix: NodeKey.GetHashCode() violates Equals/GetHashCode contract (#9744) --- .../Nethermind.Synchronization/FastSync/StateSyncItem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncItem.cs b/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncItem.cs index 26dddeabc47..97c558ddec0 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncItem.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncItem.cs @@ -64,8 +64,8 @@ public override bool Equals(object obj) public override int GetHashCode() { - uint hash0 = (uint)hash.GetHashCode(); - ulong hash1 = ((ulong)(uint)(address?.GetHashCode() ?? 1) << 32) | (ulong)(uint)(Path?.GetHashCode() ?? 2); + uint hash0 = (uint)Hash.GetHashCode(); + ulong hash1 = ((ulong)(uint)(Address.GetHashCode()) << 32) | (ulong)(uint)(Path?.GetHashCode() ?? 2); return (int)BitOperations.Crc32C(hash0, hash1); } From b4ac6f99345344e545c9cfc2fb34302a1c298063 Mon Sep 17 00:00:00 2001 From: ANtutov Date: Thu, 27 Nov 2025 00:52:14 +0200 Subject: [PATCH 008/255] chore: remove dead IsSyncing field and its assignment (#9790) * chore: remove dead IsSyncing field and its assignment * Apply suggestion from @LukaszRozmej * Simplify result creation in SyncingSubscription Refactor SyncingSubscription logic for clarity and efficiency. * Fix resource leak by using 'using' statement --------- Co-authored-by: Lukasz Rozmej --- .../Modules/Subscribe/SyncingSubscription.cs | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SyncingSubscription.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SyncingSubscription.cs index f750e8a40e0..026acce91b7 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SyncingSubscription.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SyncingSubscription.cs @@ -40,8 +40,6 @@ public SyncingSubscription( private class SubscriptionSyncingResult { - [JsonIgnore] - public bool? IsSyncing { get; set; } public long? StartingBlock { get; set; } public long? CurrentBlock { get; set; } public long? HighestBlock { get; set; } @@ -63,24 +61,15 @@ private void OnConditionsChange(object? sender, BlockEventArgs e) if (_logger.IsTrace) _logger.Trace($"Syncing subscription {Id} changed syncing status from {_lastIsSyncing} to {isSyncing}"); _lastIsSyncing = isSyncing; - JsonRpcResult result; - if (isSyncing == false) - { - result = CreateSubscriptionMessage(isSyncing); - } - else - { - result = CreateSubscriptionMessage(new SubscriptionSyncingResult() - { - IsSyncing = syncingResult.IsSyncing, - StartingBlock = syncingResult.StartingBlock, - CurrentBlock = syncingResult.CurrentBlock, - HighestBlock = syncingResult.HighestBlock - }); - } - - using (result) + using (JsonRpcResult result = !isSyncing + ? CreateSubscriptionMessage(false) + : CreateSubscriptionMessage(new SubscriptionSyncingResult() + { + StartingBlock = syncingResult.StartingBlock, + CurrentBlock = syncingResult.CurrentBlock, + HighestBlock = syncingResult.HighestBlock + })) { await JsonRpcDuplexClient.SendJsonRpcResult(result); } From f8992c37f46dde5aed38a66ef57fc3bd8c40d7ce Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Thu, 27 Nov 2025 06:31:35 -0300 Subject: [PATCH 009/255] Move engaging NoGC out of hot path (#9799) * Move engaging NoGC out of hot path * AI was right * Better naming --- .../Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs | 11 +++++++++-- src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs | 10 +++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs index 8ffde88cf20..38856536a0b 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs @@ -90,8 +90,15 @@ protected async Task> NewPayload(IExecutionPayloa long startTime = Stopwatch.GetTimestamp(); try { - using IDisposable region = _gcKeeper.TryStartNoGCRegion(); - return await _newPayloadV1Handler.HandleAsync(executionPayload); + Task regionTask = _gcKeeper.TryStartNoGCRegionAsync(); + try + { + return await _newPayloadV1Handler.HandleAsync(executionPayload); + } + finally + { + (await regionTask).Dispose(); + } } catch (BlockchainException exception) { diff --git a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs index a581d7e6e05..6dbd20f8cff 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs @@ -20,23 +20,27 @@ public class GCKeeper private readonly ILogger _logger; private static readonly long _defaultSize = 512.MB(); private Task _gcScheduleTask = Task.CompletedTask; + private readonly Func _tryStartNoGCRegionFunc; public GCKeeper(IGCStrategy gcStrategy, ILogManager logManager) { _gcStrategy = gcStrategy; _logger = logManager.GetClassLogger(); + _tryStartNoGCRegionFunc = TryStartNoGCRegion; } - public IDisposable TryStartNoGCRegion(long? size = null) + public Task TryStartNoGCRegionAsync() => Task.Run(_tryStartNoGCRegionFunc); + + private IDisposable TryStartNoGCRegion() { - size ??= _defaultSize; + long size = _defaultSize; bool pausedGCScheduler = GCScheduler.MarkGCPaused(); if (_gcStrategy.CanStartNoGCRegion()) { FailCause failCause = FailCause.None; try { - if (!System.GC.TryStartNoGCRegion(size.Value, true)) + if (!System.GC.TryStartNoGCRegion(size, disallowFullBlockingGC: true)) { failCause = FailCause.GCFailedToStartNoGCRegion; } From 0ba377039e3ae1c13a4ce4b438841eeb798853c7 Mon Sep 17 00:00:00 2001 From: Fibonacci747 Date: Thu, 27 Nov 2025 10:50:49 +0100 Subject: [PATCH 010/255] chore: remove duplicate AddDatabase registrations in DbModule (#9802) --- src/Nethermind/Nethermind.Init/Modules/DbModule.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Init/Modules/DbModule.cs b/src/Nethermind/Nethermind.Init/Modules/DbModule.cs index 97232b0b397..8e308a7479b 100644 --- a/src/Nethermind/Nethermind.Init/Modules/DbModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/DbModule.cs @@ -70,9 +70,7 @@ protected override void Load(ContainerBuilder builder) .AddDatabase(DbNames.Blocks) .AddDatabase(DbNames.Headers) .AddDatabase(DbNames.BlockInfos) - .AddDatabase(DbNames.BadBlocks) .AddDatabase(DbNames.Bloom) - .AddDatabase(DbNames.Metadata) .AddDatabase(DbNames.BlobTransactions) .AddColumnDatabase(DbNames.Receipts) From 028b3283e5db3f847852931fc9256eeccd4f9594 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 27 Nov 2025 10:51:20 +0100 Subject: [PATCH 011/255] chore: streamline nullability suppression in LruCache (#9796) Update LruCache.cs --- src/Nethermind/Nethermind.Core/Caching/LruCache.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Caching/LruCache.cs b/src/Nethermind/Nethermind.Core/Caching/LruCache.cs index 727f21d6827..bc87e4e83ba 100644 --- a/src/Nethermind/Nethermind.Core/Caching/LruCache.cs +++ b/src/Nethermind/Nethermind.Core/Caching/LruCache.cs @@ -53,10 +53,7 @@ public TValue Get(TKey key) return value; } -#pragma warning disable 8603 - // fixed C# 9 - return default; -#pragma warning restore 8603 + return default!; } public bool TryGet(TKey key, out TValue value) @@ -70,10 +67,7 @@ public bool TryGet(TKey key, out TValue value) return true; } -#pragma warning disable 8601 - // fixed C# 9 - value = default; -#pragma warning restore 8601 + value = default!; return false; } From 6310f4d04e2f70e64352a2a571bdf66d24121187 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 27 Nov 2025 10:53:21 +0100 Subject: [PATCH 012/255] Remove unused transaction hash collections in SendBlobs CLI (#9798) Update SetupCli.cs --- tools/SendBlobs/SetupCli.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/SendBlobs/SetupCli.cs b/tools/SendBlobs/SetupCli.cs index 4b68a8557ec..af627173441 100644 --- a/tools/SendBlobs/SetupCli.cs +++ b/tools/SendBlobs/SetupCli.cs @@ -209,7 +209,7 @@ public static void SetupDistributeCommand(Command root) FundsDistributor distributor = new( rpcClient, chainId, parseResult.GetValue(keyFileOption), SimpleConsoleLogManager.Instance); - IEnumerable hashes = await distributor.DitributeFunds( + await distributor.DitributeFunds( signer, parseResult.GetValue(keyNumberOption), parseResult.GetValue(maxFeeOption), @@ -267,7 +267,7 @@ public static void SetupReclaimCommand(Command root) ulong chainId = HexConvert.ToUInt64(chainIdString); FundsDistributor distributor = new(rpcClient, chainId, parseResult.GetValue(keyFileOption), SimpleConsoleLogManager.Instance); - IEnumerable hashes = await distributor.ReclaimFunds( + await distributor.ReclaimFunds( new(parseResult.GetValue(receiverOption)!), parseResult.GetValue(maxFeeOption), parseResult.GetValue(maxPriorityFeeGasOption)); From e695a18eb7cb971a0f4c0f9e353cfd07e547cdf4 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Thu, 27 Nov 2025 08:52:27 -0300 Subject: [PATCH 013/255] Reduce storage tracking allocations (#9664) * Reduce storage tracking allocations * formatting * Formatting * Switch to new * Less changes * Remove thread static * Use extension * Fast empty path * Use faster checks for StackPool * Also reset skip flag * Feedback * Fix * AI feedback * formatting --- .../Nethermind.Core/Caching/StaticPool.cs | 91 ++++++++++ .../Nethermind.Core/Collections/StackList.cs | 25 ++- .../Extensions/DictionaryExtensions.cs | 30 +++ .../Resettables/IResettable.cs | 15 ++ .../Resettables/IReturnable.cs | 17 ++ src/Nethermind/Nethermind.Evm/StackPool.cs | 20 +- .../PartialStorageProviderBase.cs | 41 +---- .../PersistentStorageProvider.cs | 171 ++++++++++++++---- .../Nethermind.State/StateProvider.cs | 39 ++-- src/Nethermind/Nethermind.State/WorldState.cs | 3 +- 10 files changed, 351 insertions(+), 101 deletions(-) create mode 100644 src/Nethermind/Nethermind.Core/Caching/StaticPool.cs create mode 100644 src/Nethermind/Nethermind.Core/Extensions/DictionaryExtensions.cs create mode 100644 src/Nethermind/Nethermind.Core/Resettables/IResettable.cs create mode 100644 src/Nethermind/Nethermind.Core/Resettables/IReturnable.cs diff --git a/src/Nethermind/Nethermind.Core/Caching/StaticPool.cs b/src/Nethermind/Nethermind.Core/Caching/StaticPool.cs new file mode 100644 index 00000000000..520010fb55a --- /dev/null +++ b/src/Nethermind/Nethermind.Core/Caching/StaticPool.cs @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Collections.Concurrent; +using System.Threading; +using Nethermind.Core.Resettables; + +namespace Nethermind.Core.Caching; + +/// +/// High performance static pool for reference types that support reset semantics. +/// +/// +/// The pooled type. Must be a reference type that implements and +/// has a public parameterless constructor. +/// +public static class StaticPool where T : class, IResettable, new() +{ + /// + /// Hard cap for the total number of items that can be stored in the shared pool. + /// Prevents unbounded growth under bursty workloads while still allowing reuse. + /// + private const int MaxPooledCount = 4096; + + /// + /// Global pool shared between threads. + /// + private static readonly ConcurrentQueue _pool = []; + + /// + /// Manual count of items in the queue. + /// We maintain this separately because ConcurrentQueue.Count + /// is an O(n) traversal — it walks the internal segment chain. + /// Keeping our own count avoids that cost and keeps the hot path O(1). + /// + private static int _poolCount; + + /// + /// Rents an instance of from the pool. + /// + /// + /// The method first attempts to dequeue an existing instance from the shared pool. + /// If the pool is empty, a new instance is created using the parameterless constructor. + /// + /// + /// A reusable instance of . The returned instance is not guaranteed + /// to be zeroed or reset beyond the guarantees provided by and + /// the constructor. Callers should treat it as a freshly created instance. + /// + public static T Rent() + { + // Try to pop from the global pool — this is only hit when a thread + // has exhausted its own fast slot or is cross-thread renting. + if (Volatile.Read(ref _poolCount) > 0 && _pool.TryDequeue(out T? item)) + { + // We track count manually with Interlocked ops instead of using queue.Count. + Interlocked.Decrement(ref _poolCount); + return item; + } + + // Nothing available, allocate new instance + return new(); + } + + /// + /// Returns an instance of to the pool for reuse. + /// + /// + /// The instance is reset via before being enqueued. + /// If adding the instance would exceed , the instance is + /// discarded and not pooled. + /// + /// + /// The instance to return to the pool. Must not be . + /// After returning, the caller must not use the instance again. + /// + public static void Return(T item) + { + // We use Interlocked.Increment to reserve a slot up front. + // This guarantees a bounded queue length without relying on slow Count(). + if (Interlocked.Increment(ref _poolCount) > MaxPooledCount) + { + // Roll back reservation if we'd exceed the cap. + Interlocked.Decrement(ref _poolCount); + return; + } + + item.Reset(); + _pool.Enqueue(item); + } +} diff --git a/src/Nethermind/Nethermind.Core/Collections/StackList.cs b/src/Nethermind/Nethermind.Core/Collections/StackList.cs index 2170d94de1b..1537fc69d04 100644 --- a/src/Nethermind/Nethermind.Core/Collections/StackList.cs +++ b/src/Nethermind/Nethermind.Core/Collections/StackList.cs @@ -4,10 +4,12 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; +using Nethermind.Core.Caching; +using Nethermind.Core.Resettables; namespace Nethermind.Core.Collections { - public sealed class StackList : List + public sealed class StackList : List, IResettable, IReturnable where T : struct, IComparable { public T Peek() => this[^1]; @@ -47,10 +49,7 @@ public bool TryPop(out T item) } } - public void Push(T item) - { - Add(item); - } + public void Push(T item) => Add(item); public bool TryGetSearchedItem(T activation, out T item) { @@ -79,5 +78,21 @@ public bool TryGetSearchedItem(T activation, out T item) return result; } + + internal static StackList Rent() + => StaticPool>.Rent(); + + public void Return() => Return(this); + public void Reset() => Clear(); + + private static void Return(StackList value) + { + const int MaxPooledCapacity = 128; + + if (value.Capacity > MaxPooledCapacity) + return; + + StaticPool>.Return(value); + } } } diff --git a/src/Nethermind/Nethermind.Core/Extensions/DictionaryExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/DictionaryExtensions.cs new file mode 100644 index 00000000000..6168e96121f --- /dev/null +++ b/src/Nethermind/Nethermind.Core/Extensions/DictionaryExtensions.cs @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Collections.Generic; +using Nethermind.Core.Resettables; + +namespace Nethermind.Core.Extensions; + +public static class DictionaryExtensions +{ + /// + /// Returns all values in the dictionary to their pool by calling on each value, + /// then clears the dictionary. + /// + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary, which must implement . + /// The dictionary whose values will be returned and cleared. + /// + /// Use this method when you need to both return pooled objects and clear the dictionary in one operation. + /// + public static void ResetAndClear(this IDictionary dictionary) + where TValue : class, IReturnable + { + foreach (TValue value in dictionary.Values) + { + value.Return(); + } + dictionary.Clear(); + } +} diff --git a/src/Nethermind/Nethermind.Core/Resettables/IResettable.cs b/src/Nethermind/Nethermind.Core/Resettables/IResettable.cs new file mode 100644 index 00000000000..3680f13bbf2 --- /dev/null +++ b/src/Nethermind/Nethermind.Core/Resettables/IResettable.cs @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +namespace Nethermind.Core.Resettables; + +/// +/// Defines a contract for objects that can be reset to their initial state. +/// +public interface IResettable +{ + /// + /// Resets the object to its initial state. + /// + void Reset(); +} diff --git a/src/Nethermind/Nethermind.Core/Resettables/IReturnable.cs b/src/Nethermind/Nethermind.Core/Resettables/IReturnable.cs new file mode 100644 index 00000000000..228bb5ebb86 --- /dev/null +++ b/src/Nethermind/Nethermind.Core/Resettables/IReturnable.cs @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +namespace Nethermind.Core.Resettables; + +/// +/// Defines a contract for objects that can be returned to a pool or resettable resource manager. +/// Implementations should ensure that releases or resets the object for reuse. +/// +public interface IReturnable +{ + /// + /// Returns the object to its pool or resource manager, making it available for reuse. + /// Implementations should ensure the object is properly reset or cleaned up. + /// + void Return(); +} diff --git a/src/Nethermind/Nethermind.Evm/StackPool.cs b/src/Nethermind/Nethermind.Evm/StackPool.cs index a51014738ee..2be787ee0b2 100644 --- a/src/Nethermind/Nethermind.Evm/StackPool.cs +++ b/src/Nethermind/Nethermind.Evm/StackPool.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Runtime.Intrinsics; +using System.Threading; using static Nethermind.Evm.EvmState; @@ -29,24 +30,35 @@ private readonly struct StackItem(byte[] dataStack, ReturnState[] returnStack) /// public void ReturnStacks(byte[] dataStack, ReturnState[] returnStack) { - if (_stackPool.Count <= MaxStacksPooled) + // Reserve a slot first - O(1) bound without touching ConcurrentQueue.Count. + if (Interlocked.Increment(ref _poolCount) > MaxStacksPooled) { - _stackPool.Enqueue(new(dataStack, returnStack)); + // Cap hit - roll back the reservation and drop the item. + Interlocked.Decrement(ref _poolCount); + return; } + + _stackPool.Enqueue(new StackItem(dataStack, returnStack)); } + // Manual reservation count - upper bound on items actually in the queue. + private int _poolCount; + public const int StackLength = (EvmStack.MaxStackSize + EvmStack.RegisterLength) * 32; public (byte[], ReturnState[]) RentStacks() { - if (_stackPool.TryDequeue(out StackItem result)) + if (Volatile.Read(ref _poolCount) > 0 && _stackPool.TryDequeue(out StackItem result)) { + Interlocked.Decrement(ref _poolCount); return (result.DataStack, result.ReturnStack); } + // Count was positive but we lost the race or the enqueuer has not published yet. + // Include extra Vector256.Count and pin so we can align to 32 bytes. + // This ensures the stack is properly aligned for SIMD operations. return ( - // Include extra Vector256.Count and pin so we can align to 32 bytes GC.AllocateUninitializedArray(StackLength + Vector256.Count, pinned: true), new ReturnState[EvmStack.ReturnStackSize] ); diff --git a/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs b/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs index 57c3253791e..d1b125d01e9 100644 --- a/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs +++ b/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System; @@ -7,6 +7,7 @@ using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Resettables; +using Nethermind.Core.Extensions; using Nethermind.Evm.Tracing.State; using Nethermind.Logging; @@ -148,29 +149,6 @@ public void Commit(bool commitRoots = true) Commit(NullStateTracer.Instance, commitRoots); } - protected struct ChangeTrace - { - public static readonly ChangeTrace _zeroBytes = new(StorageTree.ZeroBytes, StorageTree.ZeroBytes); - public static ref readonly ChangeTrace ZeroBytes => ref _zeroBytes; - - public ChangeTrace(byte[]? before, byte[]? after) - { - After = after ?? StorageTree.ZeroBytes; - Before = before ?? StorageTree.ZeroBytes; - } - - public ChangeTrace(byte[]? after) - { - After = after ?? StorageTree.ZeroBytes; - Before = StorageTree.ZeroBytes; - IsInitialValue = true; - } - - public byte[] Before; - public byte[] After; - public bool IsInitialValue; - } - /// /// Commit persistent storage /// @@ -202,22 +180,19 @@ protected virtual void CommitStorageRoots() /// Used for storage-specific logic /// /// Storage tracer - protected virtual void CommitCore(IStorageTracer tracer) - { - _changes.Clear(); - _intraBlockCache.Clear(); - _transactionChangesSnapshots.Clear(); - } + protected virtual void CommitCore(IStorageTracer tracer) => Reset(); /// /// Reset the storage state /// - public virtual void Reset(bool resetBlockChanges = true) + public virtual void Reset(bool resetBlockChanges = true) => Reset(); + + private void Reset() { if (_logger.IsTrace) _logger.Trace("Resetting storage"); _changes.Clear(); - _intraBlockCache.Clear(); + _intraBlockCache.ResetAndClear(); _transactionChangesSnapshots.Clear(); } @@ -270,7 +245,7 @@ protected StackList SetupRegistry(in StorageCell cell) ref StackList? value = ref CollectionsMarshal.GetValueRefOrAddDefault(_intraBlockCache, cell, out bool exists); if (!exists) { - value = new StackList(); + value = StackList.Rent(); } return value; diff --git a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs index 6e01ca39f2f..a62d6d194c5 100644 --- a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs +++ b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System; @@ -8,18 +8,20 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; +using System.Threading; using System.Threading.Tasks; using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Core.Resettables; using Nethermind.Core.Threading; using Nethermind.Evm.Tracing.State; -using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Serialization.Rlp; -using Nethermind.Trie; using Nethermind.Trie.Pruning; +using Nethermind.Int256; +using Nethermind.Trie; namespace Nethermind.State; @@ -34,7 +36,7 @@ internal sealed class PersistentStorageProvider : PartialStorageProviderBase private readonly ITrieStore _trieStore; private readonly StateProvider _stateProvider; private readonly ILogManager? _logManager; - internal readonly IStorageTreeFactory _storageTreeFactory; + private readonly IStorageTreeFactory _storageTreeFactory; private readonly Dictionary _storages = new(4_096); private readonly Dictionary _toUpdateRoots = new(); @@ -66,7 +68,7 @@ public PersistentStorageProvider(ITrieStore trieStore, } public Hash256 StateRoot { get; set; } = null!; - private readonly bool _populatePreBlockCache; + internal readonly bool _populatePreBlockCache; /// /// Reset the storage state @@ -78,7 +80,7 @@ public override void Reset(bool resetBlockChanges = true) _committedThisRound.Clear(); if (resetBlockChanges) { - _storages.Clear(); + _storages.ResetAndClear(); _toUpdateRoots.Clear(); } } @@ -140,10 +142,10 @@ protected override void CommitCore(IStorageTracer tracer) HashSet toUpdateRoots = (_tempToUpdateRoots ??= new()); bool isTracing = tracer.IsTracingStorage; - Dictionary? trace = null; + Dictionary? trace = null; if (isTracing) { - trace = new Dictionary(); + trace = []; } for (int i = 0; i <= currentPosition; i++) @@ -158,7 +160,7 @@ protected override void CommitCore(IStorageTracer tracer) { if (isTracing && change.ChangeType == ChangeType.JustCache) { - trace![change.StorageCell] = new ChangeTrace(change.Value, trace[change.StorageCell].After); + trace![change.StorageCell] = new StorageChangeTrace(change.Value, trace[change.StorageCell].After); } continue; @@ -204,7 +206,7 @@ protected override void CommitCore(IStorageTracer tracer) if (isTracing) { - trace![change.StorageCell] = new ChangeTrace(change.Value); + trace![change.StorageCell] = new StorageChangeTrace(change.Value); } } } @@ -353,21 +355,23 @@ public void CommitTrees(IBlockCommitter blockCommitter) // may make it worse. Always check on mainnet. using ArrayPoolListRef commitTask = new(_storages.Count); - foreach (KeyValuePair storage in _storages) + foreach (PerContractState storage in _storages.Values) { - storage.Value.EnsureStorageTree(); // Cannot be called concurrently + storage.EnsureStorageTree(); // Cannot be called concurrently if (blockCommitter.TryRequestConcurrencyQuota()) { commitTask.Add(Task.Factory.StartNew((ctx) => { PerContractState st = (PerContractState)ctx; st.Commit(); + st.Return(); blockCommitter.ReturnConcurrencyQuota(); - }, storage.Value)); + }, storage)); } else { - storage.Value.Commit(); + storage.Commit(); + storage.Return(); } } @@ -379,7 +383,7 @@ public void CommitTrees(IBlockCommitter blockCommitter) private PerContractState GetOrCreateStorage(Address address) { ref PerContractState? value = ref CollectionsMarshal.GetValueRefOrAddDefault(_storages, address, out bool exists); - if (!exists) value = new PerContractState(address, this); + if (!exists) value = PerContractState.Rent(address, this); return value; } @@ -411,9 +415,9 @@ private void PushToRegistryOnly(in StorageCell cell, byte[] value) _changes.Add(new Change(in cell, value, ChangeType.JustCache)); } - private static void ReportChanges(IStorageTracer tracer, Dictionary trace) + private static void ReportChanges(IStorageTracer tracer, Dictionary trace) { - foreach ((StorageCell address, ChangeTrace change) in trace) + foreach ((StorageCell address, StorageChangeTrace change) in trace) { byte[] before = change.Before; byte[] after = change.After; @@ -452,38 +456,44 @@ public StorageTree Create(Address address, IScopedTrieStore trieStore, Hash256 s private sealed class DefaultableDictionary() { private bool _missingAreDefault; - private readonly Dictionary _dictionary = new(Comparer.Instance); + private readonly Dictionary _dictionary = new(Comparer.Instance); public int EstimatedSize => _dictionary.Count; + public int Capacity => _dictionary.Capacity; + public void Reset() + { + _missingAreDefault = false; + _dictionary.Clear(); + } public void ClearAndSetMissingAsDefault() { _missingAreDefault = true; _dictionary.Clear(); } - public ref ChangeTrace GetValueRefOrAddDefault(UInt256 storageCellIndex, out bool exists) + public ref StorageChangeTrace GetValueRefOrAddDefault(UInt256 storageCellIndex, out bool exists) { - ref ChangeTrace value = ref CollectionsMarshal.GetValueRefOrAddDefault(_dictionary, storageCellIndex, out exists); + ref StorageChangeTrace value = ref CollectionsMarshal.GetValueRefOrAddDefault(_dictionary, storageCellIndex, out exists); if (!exists && _missingAreDefault) { // Where we know the rest of the tree is empty // we can say the value was found but is default // rather than having to check the database - value = ChangeTrace.ZeroBytes; + value = StorageChangeTrace.ZeroBytes; exists = true; } return ref value; } - public ref ChangeTrace GetValueRefOrNullRef(UInt256 storageCellIndex) + public ref StorageChangeTrace GetValueRefOrNullRef(UInt256 storageCellIndex) => ref CollectionsMarshal.GetValueRefOrNullRef(_dictionary, storageCellIndex); - public ChangeTrace this[UInt256 key] + public StorageChangeTrace this[UInt256 key] { set => _dictionary[key] = value; } - public Dictionary.Enumerator GetEnumerator() => _dictionary.GetEnumerator(); + public Dictionary.Enumerator GetEnumerator() => _dictionary.GetEnumerator(); private sealed class Comparer : IEqualityComparer { @@ -499,27 +509,35 @@ public int GetHashCode([DisallowNull] UInt256 obj) } } - private sealed class PerContractState + private sealed class PerContractState : IReturnable { + private static readonly Func _loadFromTreeStorageFunc = LoadFromTreeStorage; + + private readonly DefaultableDictionary BlockChange = new(); + private PersistentStorageProvider _provider; + private Address _address; private StorageTree? StorageTree; - private DefaultableDictionary BlockChange = new DefaultableDictionary(); private bool _wasWritten = false; - private readonly Func _loadFromTreeStorageFunc; - private readonly Address _address; - private readonly PersistentStorageProvider _provider; - public PerContractState(Address address, - PersistentStorageProvider provider) + private PerContractState(Address address, PersistentStorageProvider provider) => Initialize(address, provider); + + private void Initialize(Address address, PersistentStorageProvider provider) { _address = address; _provider = provider; - _loadFromTreeStorageFunc = LoadFromTreeStorage; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void EnsureStorageTree() { if (StorageTree is not null) return; + CreateStorageTree(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CreateStorageTree() + { // Note: GetStorageRoot is not concurrent safe! And so do this whole method! Account? acc = _provider._stateProvider.GetAccount(_address); Hash256 storageRoot = acc?.StorageRoot ?? Keccak.EmptyTreeHash; @@ -558,23 +576,32 @@ public void Clear() BlockChange.ClearAndSetMissingAsDefault(); } + public void Return() + { + _address = null; + _provider = null; + StorageTree = null; + _wasWritten = false; + Pool.Return(this); + } + public void SaveChange(StorageCell storageCell, byte[] value) { _wasWritten = true; - ref ChangeTrace valueChanges = ref BlockChange.GetValueRefOrAddDefault(storageCell.Index, out bool exists); + ref StorageChangeTrace valueChanges = ref BlockChange.GetValueRefOrAddDefault(storageCell.Index, out bool exists); if (!exists) { - valueChanges = new ChangeTrace(value); + valueChanges = new StorageChangeTrace(value); } else { - valueChanges.After = value; + valueChanges = new StorageChangeTrace(valueChanges.Before, value); } } public ReadOnlySpan LoadFromTree(in StorageCell storageCell) { - ref ChangeTrace valueChange = ref BlockChange.GetValueRefOrAddDefault(storageCell.Index, out bool exists); + ref StorageChangeTrace valueChange = ref BlockChange.GetValueRefOrAddDefault(storageCell.Index, out bool exists); if (!exists) { byte[] value = !_provider._populatePreBlockCache ? @@ -610,7 +637,7 @@ private byte[] LoadFromTreePopulatePrewarmCache(in StorageCell storageCell) long priorReads = Db.Metrics.ThreadLocalStorageTreeReads; byte[] value = _provider._preBlockCache is not null - ? _provider._preBlockCache.GetOrAdd(storageCell, _loadFromTreeStorageFunc) + ? _provider._preBlockCache.GetOrAdd(storageCell, _loadFromTreeStorageFunc, this) : LoadFromTreeStorage(storageCell); if (Db.Metrics.ThreadLocalStorageTreeReads == priorReads) @@ -621,7 +648,7 @@ private byte[] LoadFromTreePopulatePrewarmCache(in StorageCell storageCell) return value; } - private byte[] LoadFromTreeStorage(StorageCell storageCell) + private byte[] LoadFromTreeStorage(in StorageCell storageCell) { Db.Metrics.IncrementStorageTreeReads(); @@ -631,6 +658,9 @@ private byte[] LoadFromTreeStorage(StorageCell storageCell) : StorageTree.GetArray(storageCell.Hash.Bytes); } + private static byte[] LoadFromTreeStorage(StorageCell storageCell, PerContractState @this) + => @this.LoadFromTreeStorage(storageCell); + public (int writes, int skipped) ProcessStorageChanges() { EnsureStorageTree(); @@ -659,7 +689,7 @@ private byte[] LoadFromTreeStorage(StorageCell storageCell) using ArrayPoolListRef bulkWrite = new(BlockChange.EstimatedSize); Span keyBuf = stackalloc byte[32]; - foreach (KeyValuePair kvp in BlockChange) + foreach (KeyValuePair kvp in BlockChange) { byte[] after = kvp.Value.After; if (!Bytes.AreEqual(kvp.Value.Before, after) || kvp.Value.IsInitialValue) @@ -692,5 +722,68 @@ public void RemoveStorageTree() { StorageTree = null; } + + internal static PerContractState Rent(Address address, PersistentStorageProvider persistentStorageProvider) + => Pool.Rent(address, persistentStorageProvider); + + private static class Pool + { + private static readonly ConcurrentQueue _pool = []; + private static int _poolCount; + + public static PerContractState Rent(Address address, PersistentStorageProvider provider) + { + if (Volatile.Read(ref _poolCount) > 0 && _pool.TryDequeue(out PerContractState item)) + { + Interlocked.Decrement(ref _poolCount); + item.Initialize(address, provider); + return item; + } + + return new PerContractState(address, provider); + } + + public static void Return(PerContractState item) + { + const int MaxItemSize = 512; + const int MaxPooledCount = 2048; + + if (item.BlockChange.Capacity > MaxItemSize) + return; + + // shared pool fallback + if (Interlocked.Increment(ref _poolCount) > MaxPooledCount) + { + Interlocked.Decrement(ref _poolCount); + return; + } + + item.BlockChange.Reset(); + _pool.Enqueue(item); + } + } + } + + private readonly struct StorageChangeTrace + { + public static readonly StorageChangeTrace _zeroBytes = new(StorageTree.ZeroBytes, StorageTree.ZeroBytes); + public static ref readonly StorageChangeTrace ZeroBytes => ref _zeroBytes; + + public StorageChangeTrace(byte[]? before, byte[]? after) + { + After = after ?? StorageTree.ZeroBytes; + Before = before ?? StorageTree.ZeroBytes; + } + + public StorageChangeTrace(byte[]? after) + { + After = after ?? StorageTree.ZeroBytes; + Before = StorageTree.ZeroBytes; + IsInitialValue = true; + } + + public readonly byte[] Before; + public readonly byte[] After; + public readonly bool IsInitialValue; } } diff --git a/src/Nethermind/Nethermind.State/StateProvider.cs b/src/Nethermind/Nethermind.State/StateProvider.cs index 5abb93111b2..7587ebd28e7 100644 --- a/src/Nethermind/Nethermind.State/StateProvider.cs +++ b/src/Nethermind/Nethermind.State/StateProvider.cs @@ -33,7 +33,7 @@ internal class StateProvider { private static readonly UInt256 _zero = UInt256.Zero; - private readonly Dictionary> _intraTxCache = new(); + private readonly Dictionary> _intraTxCache = new(); private readonly HashSet _committedThisRound = new(); private readonly HashSet _nullAccountReads = new(); // Only guarding against hot duplicates so filter doesn't need to be too big @@ -111,7 +111,7 @@ public bool IsContract(Address address) } public bool AccountExists(Address address) => - _intraTxCache.TryGetValue(address, out Stack value) + _intraTxCache.TryGetValue(address, out StackList value) ? _changes[value.Peek()]!.ChangeType != ChangeType.Delete : GetAndAddToCache(address) is not null; @@ -426,7 +426,7 @@ public void Restore(int snapshot) { int nextPosition = lastIndex - i; ref readonly Change change = ref changes[nextPosition]; - Stack stack = _intraTxCache[change!.Address]; + StackList stack = _intraTxCache[change!.Address]; int actualPosition = stack.Pop(); if (actualPosition != nextPosition) ThrowUnexpectedPosition(lastIndex, i, actualPosition); @@ -441,7 +441,10 @@ public void Restore(int snapshot) else { // Remove address entry entirely if no more changes - _intraTxCache.Remove(change.Address); + if (_intraTxCache.Remove(change.Address, out StackList? removed)) + { + removed.Return(); + } } } } @@ -487,7 +490,7 @@ void Trace(Address address, in UInt256 balance, in UInt256 nonce) public void CreateEmptyAccountIfDeletedOrNew(Address address) { - if (_intraTxCache.TryGetValue(address, out Stack value)) + if (_intraTxCache.TryGetValue(address, out StackList value)) { //we only want to persist empty accounts if they were deleted or created as empty //we don't want to do it for account empty due to a change (e.g. changed balance to zero) @@ -587,7 +590,7 @@ public void Commit(IReleaseSpec releaseSpec, IWorldStateTracer stateTracer, bool continue; } - Stack stack = _intraTxCache[change.Address]; + StackList stack = _intraTxCache[change.Address]; int forAssertion = stack.Pop(); if (forAssertion != stepsBack - i) { @@ -670,7 +673,7 @@ public void Commit(IReleaseSpec releaseSpec, IWorldStateTracer stateTracer, bool _changes.Clear(); _committedThisRound.Clear(); _nullAccountReads.Clear(); - _intraTxCache.Clear(); + _intraTxCache.ResetAndClear(); if (commitRoots) { @@ -697,9 +700,9 @@ Task CommitCodeAsync() } // Mark all inserted codes as persisted - foreach (var kvp in dict) + foreach (Hash256AsKey kvp in dict.Keys) { - _persistedCodeInsertFilter.Set(kvp.Key.Value.ValueHash256); + _persistedCodeInsertFilter.Set(kvp.Value.ValueHash256); } // Reuse Dictionary if not already re-initialized @@ -759,7 +762,7 @@ private void FlushToTree() KeccakCache.ComputeTo(key.Value.Bytes, out ValueHash256 keccak); - var account = change.After; + Account account = change.After; Rlp accountRlp = account is null ? null : account.IsTotallyEmpty ? StateTree.EmptyAccountRlp : Rlp.Encode(account); bulkWrite.Add(new PatriciaTree.BulkSetEntry(keccak, accountRlp?.Bytes)); @@ -855,7 +858,7 @@ private void SetState(Address address, Account? account) private Account? GetThroughCache(Address address) { - if (_intraTxCache.TryGetValue(address, out Stack value)) + if (_intraTxCache.TryGetValue(address, out StackList value)) { return _changes[value.Peek()].Account; } @@ -881,7 +884,7 @@ private void PushDelete(Address address) private void Push(Address address, Account? touchedAccount, ChangeType changeType) { - Stack stack = SetupCache(address); + StackList stack = SetupCache(address); if (changeType == ChangeType.Touch && _changes[stack.Peek()]!.ChangeType == ChangeType.Touch) { @@ -894,23 +897,23 @@ private void Push(Address address, Account? touchedAccount, ChangeType changeTyp private void PushNew(Address address, Account account) { - Stack stack = SetupCache(address); + StackList stack = SetupCache(address); stack.Push(_changes.Count); _changes.Add(new Change(address, account, ChangeType.New)); } - private void PushRecreateEmpty(Address address, Account account, Stack stack) + private void PushRecreateEmpty(Address address, Account account, StackList stack) { stack.Push(_changes.Count); _changes.Add(new Change(address, account, ChangeType.RecreateEmpty)); } - private Stack SetupCache(Address address) + private StackList SetupCache(Address address) { - ref Stack? value = ref CollectionsMarshal.GetValueRefOrAddDefault(_intraTxCache, address, out bool exists); + ref StackList? value = ref CollectionsMarshal.GetValueRefOrAddDefault(_intraTxCache, address, out bool exists); if (!exists) { - value = new Stack(); + value = StackList.Rent(); } return value; @@ -943,7 +946,7 @@ public void Reset(bool resetBlockChanges = true) _blockChanges.Clear(); _codeBatch?.Clear(); } - _intraTxCache.Clear(); + _intraTxCache.ResetAndClear(); _committedThisRound.Clear(); _nullAccountReads.Clear(); _changes.Clear(); diff --git a/src/Nethermind/Nethermind.State/WorldState.cs b/src/Nethermind/Nethermind.State/WorldState.cs index c9767295a04..91d32300615 100644 --- a/src/Nethermind/Nethermind.State/WorldState.cs +++ b/src/Nethermind/Nethermind.State/WorldState.cs @@ -86,12 +86,11 @@ private void GuardInScope() if (!_isInScope) ThrowOutOfScope(); } + [Conditional("DEBUG")] [MethodImpl(MethodImplOptions.AggressiveInlining)] private void DebugGuardInScope() { -#if DEBUG if (!_isInScope) ThrowOutOfScope(); -#endif } [StackTraceHidden, DoesNotReturn] From cd86f19754e64663e7d954dcff7b585d8204c136 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Thu, 27 Nov 2025 09:20:23 -0300 Subject: [PATCH 014/255] Devirtualize filter{store | manager} (#9779) * Devirtualize filter{store | manager} * Feedback * Lets not get fancy * More specific * Feedback --- .../Filters/FilterManagerTests.cs | 26 +++++-- .../Filters/FilterStoreTests.cs | 1 + .../Nethermind.Facade/BlockchainBridge.cs | 4 +- .../Filters/FilterManager.cs | 6 +- .../Nethermind.Facade/Filters/FilterStore.cs | 16 +++- .../Filters/IFilterManager.cs | 15 ---- .../Nethermind.Facade/Filters/IFilterStore.cs | 32 -------- .../Filters/NullFilterManager.cs | 42 ---------- .../Filters/NullFilterStore.cs | 76 ------------------- .../Nethermind.Init/Modules/RpcModules.cs | 4 +- .../Steps/RegisterRpcModules.cs | 2 +- .../Modules/SubscribeModuleTests.cs | 2 +- .../Modules/Subscribe/LogsSubscription.cs | 4 +- .../SubscriptionFactoryExtensions.cs | 10 +-- 14 files changed, 47 insertions(+), 193 deletions(-) delete mode 100644 src/Nethermind/Nethermind.Facade/Filters/IFilterManager.cs delete mode 100644 src/Nethermind/Nethermind.Facade/Filters/IFilterStore.cs delete mode 100644 src/Nethermind/Nethermind.Facade/Filters/NullFilterManager.cs delete mode 100644 src/Nethermind/Nethermind.Facade/Filters/NullFilterStore.cs diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs index 36194e57e04..0b863d6112b 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using FluentAssertions; using Nethermind.Blockchain.Filters; using Nethermind.Blockchain.Test.Builders; @@ -11,6 +12,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; +using Nethermind.Core.Timers; using Nethermind.Facade.Filters; using Nethermind.Logging; using Nethermind.TxPool; @@ -21,7 +23,7 @@ namespace Nethermind.Blockchain.Test.Filters; public class FilterManagerTests { - private IFilterStore _filterStore = null!; + private FilterStore _filterStore = null!; private IBranchProcessor _branchProcessor = null!; private IMainProcessingContext _mainProcessingContext = null!; private ITxPool _txPool = null!; @@ -34,7 +36,7 @@ public class FilterManagerTests public void Setup() { _currentFilterId = 0; - _filterStore = Substitute.For(); + _filterStore = new FilterStore(new TimerFactory(), 20, 10); _branchProcessor = Substitute.For(); _mainProcessingContext = Substitute.For(); _mainProcessingContext.BranchProcessor.Returns(_branchProcessor); @@ -49,11 +51,11 @@ public void TearDown() } [Test, MaxTime(Timeout.MaxTestTime)] - public void removing_filter_removes_data() + public async Task removing_filter_removes_data() { LogsShouldNotBeEmpty(static _ => { }, static _ => { }); _filterManager.GetLogs(0).Should().NotBeEmpty(); - _filterStore.FilterRemoved += Raise.EventWith(new FilterEventArgs(0)); + await Task.Delay(60); _filterManager.GetLogs(0).Should().BeEmpty(); } @@ -324,8 +326,8 @@ private void Assert(IEnumerable> filterBuilders, BlockFilter blockFilter = new(_currentFilterId++); filters.Add(blockFilter); - _filterStore.GetFilters().Returns(filters.OfType().ToArray()); - _filterStore.GetFilters().Returns(filters.OfType().ToArray()); + _filterStore.SaveFilters(filters.OfType()); + _filterStore.SaveFilters(filters.OfType()); _filterManager = new FilterManager(_filterStore, _mainProcessingContext, _txPool, _logManager); _branchProcessor.BlockProcessed += Raise.EventWith(_branchProcessor, new BlockProcessedEventArgs(block, [])); @@ -367,3 +369,15 @@ private static TxReceipt BuildReceipt(Action builder) return builderInstance.TestObject; } } + +file static class FilterExtensions +{ + public static void SaveFilters(this FilterStore store, IEnumerable filters) + where T : FilterBase + { + foreach (T filter in filters) + { + store.SaveFilter(filter); + } + } +} diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs index f7fdea314f1..d6706b6a5e1 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs @@ -166,6 +166,7 @@ public async Task CleanUps_filters() Assert.That(() => store.FilterExists(1), Is.False.After(30, 5), "filter 1 doesn't exist"); Assert.That(() => store.FilterExists(2), Is.False.After(30, 5), "filter 2 doesn't exist"); Assert.That(() => store.FilterExists(3), Is.False.After(30, 5), "filter 3 doesn't exist"); + store.RefreshFilter(0); Assert.That(() => removedFilterIds, Is.EquivalentTo([1, 2, 3]).After(30, 5)); } } diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index bd319ebb868..430ab4cb28b 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -44,8 +44,8 @@ public class BlockchainBridge( IStateReader stateReader, ITxPool txPool, IReceiptFinder receiptStorage, - IFilterStore filterStore, - IFilterManager filterManager, + FilterStore filterStore, + FilterManager filterManager, IEthereumEcdsa ecdsa, ITimestamper timestamper, ILogFinder logFinder, diff --git a/src/Nethermind/Nethermind.Facade/Filters/FilterManager.cs b/src/Nethermind/Nethermind.Facade/Filters/FilterManager.cs index 4cdf0466491..179c8648e19 100644 --- a/src/Nethermind/Nethermind.Facade/Filters/FilterManager.cs +++ b/src/Nethermind/Nethermind.Facade/Filters/FilterManager.cs @@ -15,7 +15,7 @@ namespace Nethermind.Blockchain.Filters { - public class FilterManager : IFilterManager + public sealed class FilterManager { private readonly ConcurrentDictionary> _logs = new(); @@ -27,12 +27,12 @@ public class FilterManager : IFilterManager new(); private Hash256? _lastBlockHash; - private readonly IFilterStore _filterStore; + private readonly FilterStore _filterStore; private readonly ILogger _logger; private long _logIndex; public FilterManager( - IFilterStore filterStore, + FilterStore filterStore, IMainProcessingContext mainProcessingContext, ITxPool txPool, ILogManager logManager) diff --git a/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs b/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs index 808f05d887d..f7b192cb42c 100644 --- a/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs +++ b/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs @@ -17,7 +17,7 @@ namespace Nethermind.Blockchain.Filters { - public class FilterStore : IFilterStore + public sealed class FilterStore : IDisposable { private readonly TimeSpan _timeout; private int _currentFilterId = -1; @@ -84,6 +84,16 @@ private void CleanupStaleFilters() } public IEnumerable GetFilters() where T : FilterBase + { + // Return Array.Empty() to avoid allocating enumerator + // and which has a non-allocating fast-path for + // foreach via IEnumerable + if (_filters.IsEmpty) return Array.Empty(); + + return GetFiltersEnumerate(); + } + + private IEnumerable GetFiltersEnumerate() where T : FilterBase { // Reuse the enumerator var enumerator = Interlocked.Exchange(ref _enumerator, null) ?? _filters.GetEnumerator(); @@ -131,7 +141,7 @@ public void RemoveFilter(int filterId) public void SaveFilter(FilterBase filter) { - if (_filters.ContainsKey(filter.Id)) + if (!_filters.TryAdd(filter.Id, filter)) { throw new InvalidOperationException($"Filter with ID {filter.Id} already exists"); } @@ -140,8 +150,6 @@ public void SaveFilter(FilterBase filter) { _currentFilterId = Math.Max(filter.Id, _currentFilterId); } - - _filters[filter.Id] = filter; } private int GetFilterId(bool generateId) diff --git a/src/Nethermind/Nethermind.Facade/Filters/IFilterManager.cs b/src/Nethermind/Nethermind.Facade/Filters/IFilterManager.cs deleted file mode 100644 index 27a07e029b8..00000000000 --- a/src/Nethermind/Nethermind.Facade/Filters/IFilterManager.cs +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core.Crypto; -using Nethermind.Facade.Filters; - -namespace Nethermind.Blockchain.Filters -{ - public interface IFilterManager - { - FilterLog[] PollLogs(int filterId); - Hash256[] PollBlockHashes(int filterId); - Hash256[] PollPendingTransactionHashes(int filterId); - } -} diff --git a/src/Nethermind/Nethermind.Facade/Filters/IFilterStore.cs b/src/Nethermind/Nethermind.Facade/Filters/IFilterStore.cs deleted file mode 100644 index 58e978f67d9..00000000000 --- a/src/Nethermind/Nethermind.Facade/Filters/IFilterStore.cs +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using Nethermind.Blockchain.Find; - -namespace Nethermind.Blockchain.Filters -{ - public interface IFilterStore : IDisposable - { - bool FilterExists(int filterId); - IEnumerable GetFilters() where T : FilterBase; - T? GetFilter(int filterId) where T : FilterBase; - BlockFilter CreateBlockFilter(bool setId = true); - PendingTransactionFilter CreatePendingTransactionFilter(bool setId = true); - - LogFilter CreateLogFilter( - BlockParameter fromBlock, - BlockParameter toBlock, - object? address = null, - IEnumerable? topics = null, - bool setId = true); - - void SaveFilter(FilterBase filter); - void RemoveFilter(int filterId); - void RefreshFilter(int filterId); - FilterType GetFilterType(int filterId); - - event EventHandler FilterRemoved; - } -} diff --git a/src/Nethermind/Nethermind.Facade/Filters/NullFilterManager.cs b/src/Nethermind/Nethermind.Facade/Filters/NullFilterManager.cs deleted file mode 100644 index 6fc634af8d2..00000000000 --- a/src/Nethermind/Nethermind.Facade/Filters/NullFilterManager.cs +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core.Crypto; -using Nethermind.Facade.Filters; - -namespace Nethermind.Blockchain.Filters -{ - public class NullFilterManager : IFilterManager - { - public static NullFilterManager Instance { get; } = new(); - - private NullFilterManager() - { - } - - public FilterLog[] GetLogs(int filterId) - { - return []; - } - - public FilterLog[] PollLogs(int filterId) - { - return []; - } - - public Hash256[] GetBlocksHashes(int filterId) - { - return []; - } - - public Hash256[] PollBlockHashes(int filterId) - { - return []; - } - - public Hash256[] PollPendingTransactionHashes(int filterId) - { - return []; - } - } -} diff --git a/src/Nethermind/Nethermind.Facade/Filters/NullFilterStore.cs b/src/Nethermind/Nethermind.Facade/Filters/NullFilterStore.cs deleted file mode 100644 index a034ba44364..00000000000 --- a/src/Nethermind/Nethermind.Facade/Filters/NullFilterStore.cs +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using Nethermind.Blockchain.Find; - -namespace Nethermind.Blockchain.Filters -{ - public class NullFilterStore : IFilterStore - { - private NullFilterStore() - { - } - - public static NullFilterStore Instance { get; } = new(); - - public bool FilterExists(int filterId) - { - return false; - } - - public IEnumerable GetFilters() where T : FilterBase - { - return Array.Empty(); - } - - public BlockFilter CreateBlockFilter(bool setId = true) - { - throw new InvalidOperationException($"{nameof(NullFilterStore)} does not support filter creation"); - } - - public PendingTransactionFilter CreatePendingTransactionFilter(bool setId = true) - { - throw new InvalidOperationException($"{nameof(NullFilterStore)} does not support filter creation"); - } - - public LogFilter CreateLogFilter(BlockParameter fromBlock, BlockParameter toBlock, object? address = null, IEnumerable? topics = null, bool setId = true) - { - throw new InvalidOperationException($"{nameof(NullFilterStore)} does not support filter creation"); - } - - public void SaveFilter(FilterBase filter) - { - throw new InvalidOperationException($"{nameof(NullFilterStore)} does not support filter creation"); - } - - public void RemoveFilter(int filterId) - { - throw new InvalidOperationException($"{nameof(NullFilterStore)} does not support filter creation"); - } - - public void RefreshFilter(int filterId) - { - throw new InvalidOperationException($"{nameof(NullFilterStore)} does not support filter refreshing"); - } - - public FilterType GetFilterType(int filterId) - { - throw new InvalidOperationException($"{nameof(NullFilterStore)} does not support filter creation"); - } - - public T? GetFilter(int filterId) where T : FilterBase - { - return null; - } - - public event EventHandler FilterRemoved - { - add { } - remove { } - } - - public void Dispose() { } - } -} diff --git a/src/Nethermind/Nethermind.Init/Modules/RpcModules.cs b/src/Nethermind/Nethermind.Init/Modules/RpcModules.cs index 420c1fa26b0..8f0ee78e45f 100644 --- a/src/Nethermind/Nethermind.Init/Modules/RpcModules.cs +++ b/src/Nethermind/Nethermind.Init/Modules/RpcModules.cs @@ -81,8 +81,8 @@ protected override void Load(ContainerBuilder builder) .AddSingleton() .AddScoped((ctx) => ctx.Resolve().CreateBlockchainBridge()) .AddSingleton() - .AddSingleton((timerFactory, rpcConfig) => new FilterStore(timerFactory, rpcConfig.FiltersTimeout)) - .AddSingleton() + .AddSingleton((timerFactory, rpcConfig) => new FilterStore(timerFactory, rpcConfig.FiltersTimeout)) + .AddSingleton() .AddSingleton() // Proof diff --git a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs index ed451c7272a..bb808aad08d 100644 --- a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs +++ b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs @@ -30,7 +30,7 @@ public class RegisterRpcModules( IBlockTree blockTree, ISpecProvider specProvider, IReceiptMonitor receiptMonitor, - IFilterStore filterStore, + FilterStore filterStore, ITxPool txPool, IEthSyncingInfo ethSyncingInfo, IPeerPool peerPool, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs index 64c5f12b867..edf0f8bbfa5 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs @@ -52,7 +52,7 @@ public class SubscribeModuleTests private IBlockTree _blockTree = null!; private ITxPool _txPool = null!; private IReceiptStorage _receiptStorage = null!; - private IFilterStore _filterStore = null!; + private FilterStore _filterStore = null!; private ISubscriptionManager _subscriptionManager = null!; private IJsonRpcDuplexClient _jsonRpcDuplexClient = null!; private IJsonSerializer _jsonSerializer = null!; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/LogsSubscription.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/LogsSubscription.cs index 5afc5f20663..4ea94824146 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/LogsSubscription.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/LogsSubscription.cs @@ -24,7 +24,7 @@ public class LogsSubscription : Subscription public LogsSubscription( IJsonRpcDuplexClient jsonRpcDuplexClient, IReceiptMonitor receiptCanonicalityMonitor, - IFilterStore? store, + FilterStore? store, IBlockTree? blockTree, ILogManager? logManager, Filter? filter = null) @@ -33,7 +33,7 @@ public LogsSubscription( _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); _receiptCanonicalityMonitor = receiptCanonicalityMonitor ?? throw new ArgumentNullException(nameof(receiptCanonicalityMonitor)); _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - IFilterStore filterStore = store ?? throw new ArgumentNullException(nameof(store)); + FilterStore filterStore = store ?? throw new ArgumentNullException(nameof(store)); if (filter is not null) { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionFactoryExtensions.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionFactoryExtensions.cs index 3b4fcc3d4df..bc5ee9b6d7c 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionFactoryExtensions.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionFactoryExtensions.cs @@ -2,10 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Blockchain.Filters; using Nethermind.Core.Specs; @@ -37,7 +33,7 @@ ISpecProvider specProvider public static void RegisterLogsSubscription( this ISubscriptionFactory subscriptionFactory, IReceiptMonitor receiptMonitor, - IFilterStore? filterStore, + FilterStore? filterStore, IBlockTree? blockTree, ILogManager? logManager ) @@ -110,7 +106,7 @@ public static void RegisterStandardSubscriptions( ILogManager? logManager, ISpecProvider specProvider, IReceiptMonitor receiptMonitor, - IFilterStore? filterStore, + FilterStore? filterStore, ITxPool? txPool, IEthSyncingInfo ethSyncingInfo, IPeerPool? peerPool, @@ -131,7 +127,7 @@ public static void RegisterStandardEthSubscriptions( ILogManager? logManager, ISpecProvider specProvider, IReceiptMonitor receiptMonitor, - IFilterStore? filterStore, + FilterStore? filterStore, ITxPool? txPool, IEthSyncingInfo ethSyncingInfo ) From 4a93be9b01d1015a4eeacf9628cd6b634900e028 Mon Sep 17 00:00:00 2001 From: oxBoni Date: Thu, 27 Nov 2025 14:48:32 +0100 Subject: [PATCH 015/255] Cache masternode quorum math in VotesManager (#9794) Update VotesManager.cs --- src/Nethermind/Nethermind.Xdc/VotesManager.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc/VotesManager.cs b/src/Nethermind/Nethermind.Xdc/VotesManager.cs index 7e6f2cccbbd..c3774d821db 100644 --- a/src/Nethermind/Nethermind.Xdc/VotesManager.cs +++ b/src/Nethermind/Nethermind.Xdc/VotesManager.cs @@ -97,20 +97,22 @@ public Task HandleVote(Vote vote) //Unknown epoch switch info, cannot process vote return Task.CompletedTask; } - if (epochInfo.Masternodes.Length == 0) + int masternodeCount = epochInfo.Masternodes.Length; + if (masternodeCount == 0) { throw new InvalidOperationException($"Epoch has empty master node list for {vote.ProposedBlockInfo.Hash}"); } double certThreshold = _specProvider.GetXdcSpec(proposedHeader, vote.ProposedBlockInfo.Round).CertThreshold; - bool thresholdReached = roundVotes.Count >= epochInfo.Masternodes.Length * certThreshold; + double requiredVotes = masternodeCount * certThreshold; + bool thresholdReached = roundVotes.Count >= requiredVotes; if (thresholdReached) { if (!vote.ProposedBlockInfo.ValidateBlockInfo(proposedHeader)) return Task.CompletedTask; Signature[] validSignatures = GetValidSignatures(roundVotes, epochInfo.Masternodes); - if (validSignatures.Length < epochInfo.Masternodes.Length * certThreshold) + if (validSignatures.Length < requiredVotes) return Task.CompletedTask; // At this point, the QC should be processed for this *round*. From 78c331ff0e475853f2ea895dbf110570d1ff5271 Mon Sep 17 00:00:00 2001 From: Snezhkko Date: Thu, 27 Nov 2025 16:06:19 +0200 Subject: [PATCH 016/255] fix: RlpxHost.Init guard to reference RlpxHost instead of PeerManager (#9805) --- src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs b/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs index 0b7c243373d..6e3e9af762b 100644 --- a/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs +++ b/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs @@ -105,7 +105,7 @@ public async Task Init() { if (_isInitialized) { - throw new InvalidOperationException($"{nameof(PeerManager)} already initialized."); + throw new InvalidOperationException($"{nameof(RlpxHost)} already initialized."); } _isInitialized = true; From 67e9c6eeaeeb3681b6c2baa7b2c9552359bd1726 Mon Sep 17 00:00:00 2001 From: MozirDmitriy Date: Fri, 28 Nov 2025 10:14:31 +0200 Subject: [PATCH 017/255] chore: remove unused block parameter (#9814) --- .../Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs index a38952dc51d..a26bf787bc3 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs @@ -211,7 +211,7 @@ private bool TryTraceTransaction( if (TryGetBlockTraces(block.Header, out List? traces) && traces is not null) { - ParityLikeTxTrace? trace = GetTxTrace(block, txHash, traces); + ParityLikeTxTrace? trace = GetTxTrace(txHash, traces); if (trace is not null) { FilterTrace(trace, traceTypes); @@ -249,7 +249,7 @@ private bool TryGetBlockTraces(BlockHeader block, out List? t } } - private static ParityLikeTxTrace? GetTxTrace(Block block, Hash256 txHash, List traces) + private static ParityLikeTxTrace? GetTxTrace(Hash256 txHash, List traces) { int index = traces.FindIndex(t => t.TransactionHash == txHash); return index != -1 ? traces[index] : null; From e5daa159c510b629c55eb273cd83d45693c166be Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Fri, 28 Nov 2025 08:06:09 -0300 Subject: [PATCH 018/255] Remove defensive copies from SecP256k1 (#9817) * Remove defensive copies from SecP256k1 * Remove type entirely * Remove unneeded .ToArray() * Max optimize --- src/Nethermind/Nethermind.Consensus/Signer.cs | 2 +- .../Crypto/SignatureTests.cs | 2 +- src/Nethermind/Nethermind.Crypto/Ecdsa.cs | 6 +- .../Nethermind.Crypto/EthereumEcdsa.cs | 4 +- .../Nethermind.Crypto/SpanSecP256k1.cs | 63 ------------------- .../EcRecoverPrecompile.cs | 10 ++- .../CL/P2P/P2PBlockValidator.cs | 2 +- .../Nethermind.Wallet/DevKeyStoreWallet.cs | 4 +- src/Nethermind/Nethermind.Wallet/DevWallet.cs | 2 +- .../ProtectedKeyStoreWallet.cs | 2 +- 10 files changed, 20 insertions(+), 77 deletions(-) delete mode 100644 src/Nethermind/Nethermind.Crypto/SpanSecP256k1.cs diff --git a/src/Nethermind/Nethermind.Consensus/Signer.cs b/src/Nethermind/Nethermind.Consensus/Signer.cs index 922fab54f15..66a70c68ad5 100644 --- a/src/Nethermind/Nethermind.Consensus/Signer.cs +++ b/src/Nethermind/Nethermind.Consensus/Signer.cs @@ -40,7 +40,7 @@ public Signer(ulong chainId, IProtectedPrivateKey key, ILogManager logManager) public Signature Sign(in ValueHash256 message) { if (!CanSign) throw new InvalidOperationException("Cannot sign without provided key."); - byte[] rs = SpanSecP256k1.SignCompact(message.Bytes, _key!.KeyBytes, out int v); + byte[] rs = SecP256k1.SignCompact(message.Bytes, _key!.KeyBytes, out int v); return new Signature(rs, v); } diff --git a/src/Nethermind/Nethermind.Core.Test/Crypto/SignatureTests.cs b/src/Nethermind/Nethermind.Core.Test/Crypto/SignatureTests.cs index d810fd16248..939457a1f4d 100644 --- a/src/Nethermind/Nethermind.Core.Test/Crypto/SignatureTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Crypto/SignatureTests.cs @@ -41,7 +41,7 @@ public void can_recover_from_message() var signatureObject = new Signature(signatureSlice, recoveryId); var keccak = Keccak.Compute(Bytes.Concat(messageType, data)); Span publicKey = stackalloc byte[65]; - bool result = SpanSecP256k1.RecoverKeyFromCompact(publicKey, keccak.Bytes, signatureObject.Bytes.ToArray(), signatureObject.RecoveryId, false); + bool result = SecP256k1.RecoverKeyFromCompact(publicKey, keccak.Bytes, signatureObject.Bytes, signatureObject.RecoveryId, false); result.Should().BeTrue(); } } diff --git a/src/Nethermind/Nethermind.Crypto/Ecdsa.cs b/src/Nethermind/Nethermind.Crypto/Ecdsa.cs index 36b7ba7f49f..e980ed857d2 100644 --- a/src/Nethermind/Nethermind.Crypto/Ecdsa.cs +++ b/src/Nethermind/Nethermind.Crypto/Ecdsa.cs @@ -21,7 +21,7 @@ public Signature Sign(PrivateKey privateKey, in ValueHash256 message) InvalidPrivateKey(); } - byte[] signatureBytes = SpanSecP256k1.SignCompact(message.Bytes, privateKey.KeyBytes, out int recoveryId); + byte[] signatureBytes = SecP256k1.SignCompact(message.Bytes, privateKey.KeyBytes, out int recoveryId); Signature signature = new(signatureBytes, recoveryId); #if DEBUG @@ -40,7 +40,7 @@ public Signature Sign(PrivateKey privateKey, in ValueHash256 message) public PublicKey? RecoverPublicKey(Signature signature, in ValueHash256 message) { Span publicKey = stackalloc byte[65]; - bool success = SpanSecP256k1.RecoverKeyFromCompact(publicKey, message.Bytes, signature.Bytes, signature.RecoveryId, false); + bool success = SecP256k1.RecoverKeyFromCompact(publicKey, message.Bytes, signature.Bytes, signature.RecoveryId, false); if (!success) { return null; @@ -52,7 +52,7 @@ public Signature Sign(PrivateKey privateKey, in ValueHash256 message) public CompressedPublicKey? RecoverCompressedPublicKey(Signature signature, in ValueHash256 message) { Span publicKey = stackalloc byte[33]; - bool success = SpanSecP256k1.RecoverKeyFromCompact(publicKey, message.Bytes, signature.Bytes, signature.RecoveryId, true); + bool success = SecP256k1.RecoverKeyFromCompact(publicKey, message.Bytes, signature.Bytes, signature.RecoveryId, true); if (!success) { return null; diff --git a/src/Nethermind/Nethermind.Crypto/EthereumEcdsa.cs b/src/Nethermind/Nethermind.Crypto/EthereumEcdsa.cs index 73f844d8aca..fa4f58359e0 100644 --- a/src/Nethermind/Nethermind.Crypto/EthereumEcdsa.cs +++ b/src/Nethermind/Nethermind.Crypto/EthereumEcdsa.cs @@ -30,7 +30,7 @@ public class EthereumEcdsa(ulong chainId) : Ecdsa, IEthereumEcdsa private static Address? RecoverAddress(Span signatureBytes64, byte v, ReadOnlySpan message) { Span publicKey = stackalloc byte[65]; - bool success = SpanSecP256k1.RecoverKeyFromCompact( + bool success = SecP256k1.RecoverKeyFromCompact( publicKey, message, signatureBytes64, @@ -41,7 +41,7 @@ public class EthereumEcdsa(ulong chainId) : Ecdsa, IEthereumEcdsa } public static bool RecoverAddressRaw(ReadOnlySpan signatureBytes64, byte v, ReadOnlySpan message, Span resultPublicKey65) => - SpanSecP256k1.RecoverKeyFromCompact( + SecP256k1.RecoverKeyFromCompact( resultPublicKey65, message, signatureBytes64, diff --git a/src/Nethermind/Nethermind.Crypto/SpanSecP256k1.cs b/src/Nethermind/Nethermind.Crypto/SpanSecP256k1.cs deleted file mode 100644 index cbe4fb1aea4..00000000000 --- a/src/Nethermind/Nethermind.Crypto/SpanSecP256k1.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; - -namespace Nethermind.Crypto; - -/// -/// Span wrapper upon SecP256k1. Try to avoid allocations if given span is of Keccak size. -/// -public static class SpanSecP256k1 -{ - [ThreadStatic] private static byte[]? _signMessageHash; - [ThreadStatic] private static byte[]? _signPrivateKey; - - public static byte[]? SignCompact(ReadOnlySpan messageHash, ReadOnlySpan privateKey, out int recoveryId) - { - byte[] messageHashArray; - if (messageHash.Length == 32) - { - _signMessageHash ??= new byte[32]; - messageHash.CopyTo(_signMessageHash); - messageHashArray = _signMessageHash; - } - else - { - // Why? Dont know... - messageHashArray = messageHash.ToArray(); - } - - byte[] privateKeyArray; - if (privateKey.Length == 32) - { - _signPrivateKey ??= new byte[32]; - privateKey.CopyTo(_signPrivateKey); - privateKeyArray = _signPrivateKey; - } - else - { - // Why? Dont know... - privateKeyArray = privateKey.ToArray(); - } - - return SecP256k1.SignCompact(messageHashArray, privateKeyArray, out recoveryId); - } - - [ThreadStatic] private static byte[]? _recoverMessageHash; - - public static bool RecoverKeyFromCompact(Span publicKey, ReadOnlySpan messageHash, ReadOnlySpan signature, int recoveryId, bool compressed) - { - byte[] messageHashArray; - if (messageHash.Length == 32) - { - _recoverMessageHash ??= new byte[32]; - messageHash.CopyTo(_recoverMessageHash); - messageHashArray = _recoverMessageHash; - } - else - { - // Why? Dont know... - messageHashArray = messageHash.ToArray(); - } - - return SecP256k1.RecoverKeyFromCompact(publicKey, messageHashArray, signature, recoveryId, compressed); - } -} diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs index c6e0b475962..666cc07d6bb 100644 --- a/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -70,8 +71,13 @@ private Result RunInternal(ReadOnlySpan inputDataSpan) return Empty; } - byte[] result = ValueKeccak.Compute(publicKey.Slice(1, 64)).ToByteArray(); - result.AsSpan(0, 12).Clear(); + byte[] result = new byte[32]; + KeccakHash.ComputeHashBytesToSpan(publicKey.Slice(1, 64), result); + + ref byte refResut = ref MemoryMarshal.GetArrayDataReference(result); + + // Clear first 12 bytes, as address is last 20 bytes of the hash + Unsafe.InitBlockUnaligned(ref refResut, 0, 12); return result; } } diff --git a/src/Nethermind/Nethermind.Optimism/CL/P2P/P2PBlockValidator.cs b/src/Nethermind/Nethermind.Optimism/CL/P2P/P2PBlockValidator.cs index 4f8c7495049..36b3655e20c 100644 --- a/src/Nethermind/Nethermind.Optimism/CL/P2P/P2PBlockValidator.cs +++ b/src/Nethermind/Nethermind.Optimism/CL/P2P/P2PBlockValidator.cs @@ -153,7 +153,7 @@ private bool IsSignatureValid(ReadOnlySpan payloadData, Span signatu byte[] signedHash = KeccakHash.ComputeHashBytes(sequencerSignedData); Span publicKey = stackalloc byte[65]; - bool success = SpanSecP256k1.RecoverKeyFromCompact( + bool success = SecP256k1.RecoverKeyFromCompact( publicKey, signedHash, signature.Slice(0, 64), diff --git a/src/Nethermind/Nethermind.Wallet/DevKeyStoreWallet.cs b/src/Nethermind/Nethermind.Wallet/DevKeyStoreWallet.cs index bc056c21f84..d0d2743a4a7 100644 --- a/src/Nethermind/Nethermind.Wallet/DevKeyStoreWallet.cs +++ b/src/Nethermind/Nethermind.Wallet/DevKeyStoreWallet.cs @@ -100,7 +100,7 @@ public Signature Sign(Hash256 message, Address address, SecureString passphrase) key = _keyStore.GetKey(address, passphrase).PrivateKey; } - var rs = SpanSecP256k1.SignCompact(message.Bytes, key.KeyBytes, out int v); + var rs = SecP256k1.SignCompact(message.Bytes, key.KeyBytes, out int v); return new Signature(rs, v); } @@ -116,7 +116,7 @@ public Signature Sign(Hash256 message, Address address) throw new SecurityException("Can only sign without passphrase when account is unlocked."); } - var rs = SpanSecP256k1.SignCompact(message.Bytes, key.KeyBytes, out int v); + var rs = SecP256k1.SignCompact(message.Bytes, key.KeyBytes, out int v); return new Signature(rs, v); } } diff --git a/src/Nethermind/Nethermind.Wallet/DevWallet.cs b/src/Nethermind/Nethermind.Wallet/DevWallet.cs index cd941753bc7..e5ca68166a8 100644 --- a/src/Nethermind/Nethermind.Wallet/DevWallet.cs +++ b/src/Nethermind/Nethermind.Wallet/DevWallet.cs @@ -117,7 +117,7 @@ private bool CheckPassword(Address address, SecureString passphrase) public Signature Sign(Hash256 message, Address address) { - var rs = SpanSecP256k1.SignCompact(message.Bytes, _keys[address].KeyBytes, out int v); + var rs = SecP256k1.SignCompact(message.Bytes, _keys[address].KeyBytes, out int v); return new Signature(rs, v); } } diff --git a/src/Nethermind/Nethermind.Wallet/ProtectedKeyStoreWallet.cs b/src/Nethermind/Nethermind.Wallet/ProtectedKeyStoreWallet.cs index c33deb9ee7a..2afe410ddfa 100644 --- a/src/Nethermind/Nethermind.Wallet/ProtectedKeyStoreWallet.cs +++ b/src/Nethermind/Nethermind.Wallet/ProtectedKeyStoreWallet.cs @@ -97,7 +97,7 @@ private Signature SignCore(Hash256 message, Address address, Func ge { var protectedPrivateKey = (ProtectedPrivateKey)_unlockedAccounts.Get(address.ToString()); using PrivateKey key = protectedPrivateKey is not null ? protectedPrivateKey.Unprotect() : getPrivateKeyWhenNotFound(); - var rs = SpanSecP256k1.SignCompact(message.Bytes, key.KeyBytes, out int v); + var rs = SecP256k1.SignCompact(message.Bytes, key.KeyBytes, out int v); return new Signature(rs, v); } } From 8b3e87138924d48025bc5a1d24b1b780daae6dda Mon Sep 17 00:00:00 2001 From: Diptanshu Kakwani Date: Fri, 28 Nov 2025 21:51:04 +0530 Subject: [PATCH 019/255] Allow Inner Reverts for eth_gasEstimate (#9822) * address inner revert for eth_gasEstimate * add new error type --- .../Tracing/EstimateGasTracer.cs | 10 +++- .../Tracing/GasEstimator.cs | 9 ++- .../Tracing/GasEstimationTests.cs | 58 ++++++++++++++++++- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/Tracing/EstimateGasTracer.cs b/src/Nethermind/Nethermind.Blockchain/Tracing/EstimateGasTracer.cs index 2a3b74b2d2a..1d6e7187eaa 100644 --- a/src/Nethermind/Nethermind.Blockchain/Tracing/EstimateGasTracer.cs +++ b/src/Nethermind/Nethermind.Blockchain/Tracing/EstimateGasTracer.cs @@ -40,6 +40,8 @@ public EstimateGasTracer() public bool OutOfGas { get; private set; } + public bool TopLevelRevert { get; private set; } + public override void MarkAsSuccess(Address recipient, GasConsumed gasSpent, byte[] output, LogEntry[] logs, Hash256? stateRoot = null) { @@ -108,6 +110,7 @@ public override void ReportAction(long gas, UInt256 value, Address from, Address if (_currentNestingLevel == -1) { OutOfGas = false; + TopLevelRevert = false; IntrinsicGasAt = gas; } @@ -146,7 +149,12 @@ public void ReportActionError(EvmExceptionType exceptionType, long gasLeft) public override void ReportOperationError(EvmExceptionType error) { - OutOfGas |= error == EvmExceptionType.OutOfGas || error == EvmExceptionType.Revert; + OutOfGas |= error == EvmExceptionType.OutOfGas; + + if (error == EvmExceptionType.Revert && _currentNestingLevel == 0) + { + TopLevelRevert = true; + } } private void UpdateAdditionalGas(long? gasLeft = null) diff --git a/src/Nethermind/Nethermind.Blockchain/Tracing/GasEstimator.cs b/src/Nethermind/Nethermind.Blockchain/Tracing/GasEstimator.cs index 777682391ac..8f245f699f2 100644 --- a/src/Nethermind/Nethermind.Blockchain/Tracing/GasEstimator.cs +++ b/src/Nethermind/Nethermind.Blockchain/Tracing/GasEstimator.cs @@ -5,6 +5,7 @@ using System.Threading; using Nethermind.Config; using Nethermind.Core; +using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; @@ -134,6 +135,10 @@ private long BinarySearchEstimate( private static string GetError(EstimateGasTracer gasTracer, string defaultError = "Transaction execution fails") => gasTracer switch { + { TopLevelRevert: true } => gasTracer.Error ?? + (gasTracer.ReturnValue?.Length > 0 ? + $"execution reverted: {gasTracer.ReturnValue.ToHexString(true)}" + : "execution reverted"), { OutOfGas: true } => "Gas estimation failed due to out of gas", { StatusCode: StatusCode.Failure } => gasTracer.Error ?? "Transaction execution fails", _ => defaultError @@ -149,6 +154,8 @@ private bool TryExecutableTransaction(Transaction transaction, BlockHeader block transactionProcessor.SetBlockExecutionContext(new BlockExecutionContext(block, specProvider.GetSpec(block))); TransactionResult result = transactionProcessor.CallAndRestore(txClone, gasTracer.WithCancellation(token)); - return result.TransactionExecuted && gasTracer.StatusCode == StatusCode.Success && !gasTracer.OutOfGas; + // Transaction succeeds if it executed, has success status, no OutOfGas, and no top-level revert + return result.TransactionExecuted && gasTracer.StatusCode == StatusCode.Success && + !gasTracer.OutOfGas && !gasTracer.TopLevelRevert; } } diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs index 5552059366d..0cd32af7226 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs @@ -604,7 +604,8 @@ public void Should_estimate_gas_for_explicit_gas_check_and_revert(long gasLimit, if (shouldSucceed) { - result.Should().BeGreaterThan(1_000_000, "Gas estimation should account for the gas threshold in the contract"); + result.Should().BeGreaterThan(1_000_000, + "Gas estimation should account for the gas threshold in the contract"); err.Should().BeNull(); } else @@ -613,6 +614,61 @@ public void Should_estimate_gas_for_explicit_gas_check_and_revert(long gasLimit, } } + [Test] + public void Should_succeed_with_internal_revert() + { + using TestEnvironment testEnvironment = new(); + long gasLimit = 100_000; + Transaction tx = Build.A.Transaction.WithGasLimit(gasLimit).TestObject; + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + + long gasLeft = gasLimit - 22000; + testEnvironment.tracer.ReportAction(gasLeft, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.TRANSACTION, false); + + gasLeft = 63 * gasLeft / 64; + testEnvironment.tracer.ReportAction(gasLeft, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.CALL, false); + + gasLeft = 63 * gasLeft / 64; + testEnvironment.tracer.ReportAction(gasLeft, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.CALL, false); + + testEnvironment.tracer.ReportActionRevert(gasLeft - 1000, Array.Empty()); + testEnvironment.tracer.ReportActionEnd(gasLeft - 500, Array.Empty()); + testEnvironment.tracer.ReportActionEnd(gasLeft, Array.Empty()); + testEnvironment.tracer.MarkAsSuccess(Address.Zero, 25000, Array.Empty(), Array.Empty()); + + long result = testEnvironment.estimator.Estimate(tx, block.Header, testEnvironment.tracer, out string? err); + + result.Should().BeGreaterThan(0); + err.Should().BeNull(); + testEnvironment.tracer.TopLevelRevert.Should().BeFalse(); + testEnvironment.tracer.OutOfGas.Should().BeFalse(); + } + + [Test] + public void Should_fail_with_top_level_revert() + { + using TestEnvironment testEnvironment = new(); + long gasLimit = 100_000; + Transaction tx = Build.A.Transaction.WithGasLimit(gasLimit).TestObject; + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + + long gasLeft = gasLimit - 22000; + testEnvironment.tracer.ReportAction(gasLeft, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.TRANSACTION, false); + + testEnvironment.tracer.ReportActionRevert(gasLeft - 1000, Array.Empty()); + testEnvironment.tracer.MarkAsFailed(Address.Zero, 25000, Array.Empty(), "execution reverted"); + + long result = testEnvironment.estimator.Estimate(tx, block.Header, testEnvironment.tracer, out string? err); + + result.Should().Be(0); + err.Should().Be("execution reverted"); + testEnvironment.tracer.TopLevelRevert.Should().BeTrue(); + } + private class TestEnvironment : IDisposable { public ISpecProvider _specProvider; From a3d1853d37cbdcb915f7ac06bc1d0037bfdf7475 Mon Sep 17 00:00:00 2001 From: Bashmunta Date: Fri, 28 Nov 2025 19:37:47 +0200 Subject: [PATCH 020/255] fix: mismatches in error messages (#9823) fix mismatches in error messages --- src/Nethermind/Nethermind.Serialization.Json/IntConverter.cs | 2 +- src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Serialization.Json/IntConverter.cs b/src/Nethermind/Nethermind.Serialization.Json/IntConverter.cs index ebee61024f3..1edf445d735 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/IntConverter.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/IntConverter.cs @@ -16,7 +16,7 @@ private static int FromString(ReadOnlySpan s) { if (s.Length == 0) { - throw new JsonException("null cannot be assigned to long"); + throw new JsonException("null cannot be assigned to int"); } if (s.SequenceEqual("0x0"u8)) diff --git a/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs b/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs index 08d9afa23f2..a2637fb085c 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs @@ -19,7 +19,7 @@ public static ulong FromString(ReadOnlySpan s) { if (s.Length == 0) { - throw new JsonException("null cannot be assigned to long"); + throw new JsonException("null cannot be assigned to ulong"); } if (s.SequenceEqual("0x0"u8)) From 9284c85dd6a64b030ce63c954094dc3532971fc0 Mon Sep 17 00:00:00 2001 From: Fibonacci747 Date: Fri, 28 Nov 2025 18:39:05 +0100 Subject: [PATCH 021/255] fix: avoid allocation in PutSpan by throwing immediately (#9819) * fix: avoid allocation in PutSpan by throwing immediately * Update RpcDb.cs --- src/Nethermind/Nethermind.Db.Rpc/RpcDb.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Nethermind/Nethermind.Db.Rpc/RpcDb.cs b/src/Nethermind/Nethermind.Db.Rpc/RpcDb.cs index 98279f33c4a..459e6ea53b6 100644 --- a/src/Nethermind/Nethermind.Db.Rpc/RpcDb.cs +++ b/src/Nethermind/Nethermind.Db.Rpc/RpcDb.cs @@ -51,7 +51,7 @@ public byte[] this[ReadOnlySpan key] public void Set(ReadOnlySpan key, byte[] value, WriteFlags flags = WriteFlags.None) { - throw new InvalidOperationException("RPC DB does not support writes"); + ThrowWritesNotSupported(); } public byte[] Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) @@ -63,7 +63,7 @@ public byte[] Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) public void Remove(ReadOnlySpan key) { - throw new InvalidOperationException("RPC DB does not support writes"); + ThrowWritesNotSupported(); } public bool KeyExists(ReadOnlySpan key) @@ -85,7 +85,7 @@ public void Clear() { } public IWriteBatch StartWriteBatch() { - throw new InvalidOperationException("RPC DB does not support writes"); + ThrowWritesNotSupported(); } private byte[] GetThroughRpc(ReadOnlySpan key) @@ -113,9 +113,11 @@ public Span GetSpan(ReadOnlySpan key) public void PutSpan(ReadOnlySpan key, ReadOnlySpan value, WriteFlags writeFlags) { - Set(key, value.ToArray(), writeFlags); + ThrowWritesNotSupported(); } + private static void ThrowWritesNotSupported() => throw new InvalidOperationException("RPC DB does not support writes"); + public void DangerousReleaseMemory(in ReadOnlySpan span) { } From ec7873cd18b6c51a3924d80bf158aa80b8b20b0c Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Fri, 28 Nov 2025 16:12:11 -0300 Subject: [PATCH 022/255] Fix merge issue (#9824) --- src/Nethermind/Nethermind.Db.Rpc/RpcDb.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Nethermind/Nethermind.Db.Rpc/RpcDb.cs b/src/Nethermind/Nethermind.Db.Rpc/RpcDb.cs index 459e6ea53b6..61bb02e57e1 100644 --- a/src/Nethermind/Nethermind.Db.Rpc/RpcDb.cs +++ b/src/Nethermind/Nethermind.Db.Rpc/RpcDb.cs @@ -86,6 +86,8 @@ public void Clear() { } public IWriteBatch StartWriteBatch() { ThrowWritesNotSupported(); + // Make compiler happy + return null!; } private byte[] GetThroughRpc(ReadOnlySpan key) From bcddbf822fffb83383a2a0b3a3dce11b6b96c325 Mon Sep 17 00:00:00 2001 From: oxBoni Date: Fri, 28 Nov 2025 23:58:07 +0100 Subject: [PATCH 023/255] Fix ColumnsDb constructor recursion and reuse resolved keys (#9818) * Update ColumnsDb.cs * Update ColumnsDb.cs --- src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs b/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs index d5a240d1e96..5a83aa1483b 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs @@ -18,11 +18,14 @@ public class ColumnsDb : DbOnTheRocks, IColumnsDb where T : struct, Enum private readonly IDictionary _columnDbs = new Dictionary(); public ColumnsDb(string basePath, DbSettings settings, IDbConfig dbConfig, IRocksDbConfigFactory rocksDbConfigFactory, ILogManager logManager, IReadOnlyList keys, IntPtr? sharedCache = null) - : base(basePath, settings, dbConfig, rocksDbConfigFactory, logManager, GetEnumKeys(keys).Select(static (key) => key.ToString()).ToList(), sharedCache: sharedCache) + : this(basePath, settings, dbConfig, rocksDbConfigFactory, logManager, ResolveKeys(keys), sharedCache) { - keys = GetEnumKeys(keys); + } - foreach (T key in keys) + private ColumnsDb(string basePath, DbSettings settings, IDbConfig dbConfig, IRocksDbConfigFactory rocksDbConfigFactory, ILogManager logManager, (IReadOnlyList Keys, IList ColumnNames) keyInfo, IntPtr? sharedCache) + : base(basePath, settings, dbConfig, rocksDbConfigFactory, logManager, keyInfo.ColumnNames, sharedCache: sharedCache) + { + foreach (T key in keyInfo.Keys) { _columnDbs[key] = new ColumnDb(_db, this, key.ToString()!); } @@ -61,6 +64,14 @@ private static IReadOnlyList GetEnumKeys(IReadOnlyList keys) return keys; } + private static (IReadOnlyList Keys, IList ColumnNames) ResolveKeys(IReadOnlyList keys) + { + IReadOnlyList resolvedKeys = GetEnumKeys(keys); + IList columnNames = resolvedKeys.Select(static key => key.ToString()).ToList(); + + return (resolvedKeys, columnNames); + } + protected override void BuildOptions(IRocksDbConfig dbConfig, Options options, IntPtr? sharedCache, IMergeOperator? mergeOperator) { base.BuildOptions(dbConfig, options, sharedCache, mergeOperator); From 5e7891f9565b630d81985e9944c03b60da8c7dd5 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Fri, 28 Nov 2025 20:17:37 -0300 Subject: [PATCH 024/255] Resolve Transitive dependency warnings (#9827) * Resolve Transitive dependency warnings * Update Directory.Packages.props Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Directory.Packages.props | 3 +- .../Core/ByteArrayToHexBenchmarks.cs | 7 --- .../Nethermind.Benchmark.csproj | 1 - .../Nethermind.HealthChecks.csproj | 1 + .../Nethermind.Network.Discovery.csproj | 1 + .../Nethermind.Runner/packages.lock.json | 48 +++++-------------- 6 files changed, 17 insertions(+), 44 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index afd33e24308..460430443d4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -24,7 +24,7 @@ - + @@ -43,6 +43,7 @@ + diff --git a/src/Nethermind/Nethermind.Benchmark/Core/ByteArrayToHexBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Core/ByteArrayToHexBenchmarks.cs index aa4ab3250b8..d52cba7a728 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/ByteArrayToHexBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/ByteArrayToHexBenchmarks.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using BenchmarkDotNet.Attributes; -using HexMate; using Nethermind.Core.Extensions; namespace Nethermind.Benchmarks.Core @@ -28,11 +27,5 @@ public string SafeLookup() { return Bytes.ByteArrayToHexViaLookup32Safe(array, false); } - - [Benchmark(Baseline = true)] - public string HexMateA() - { - return Convert.ToHexString(array, HexFormattingOptions.Lowercase); - } } } diff --git a/src/Nethermind/Nethermind.Benchmark/Nethermind.Benchmark.csproj b/src/Nethermind/Nethermind.Benchmark/Nethermind.Benchmark.csproj index 47d883bbd2e..4fe68806389 100644 --- a/src/Nethermind/Nethermind.Benchmark/Nethermind.Benchmark.csproj +++ b/src/Nethermind/Nethermind.Benchmark/Nethermind.Benchmark.csproj @@ -6,7 +6,6 @@ - diff --git a/src/Nethermind/Nethermind.HealthChecks/Nethermind.HealthChecks.csproj b/src/Nethermind/Nethermind.HealthChecks/Nethermind.HealthChecks.csproj index 3fe6267162e..7f6f3d606ef 100644 --- a/src/Nethermind/Nethermind.HealthChecks/Nethermind.HealthChecks.csproj +++ b/src/Nethermind/Nethermind.HealthChecks/Nethermind.HealthChecks.csproj @@ -3,6 +3,7 @@ + diff --git a/src/Nethermind/Nethermind.Network.Discovery/Nethermind.Network.Discovery.csproj b/src/Nethermind/Nethermind.Network.Discovery/Nethermind.Network.Discovery.csproj index ee01ab7f32e..e21eb0552dd 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Nethermind.Network.Discovery.csproj +++ b/src/Nethermind/Nethermind.Network.Discovery/Nethermind.Network.Discovery.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Nethermind/Nethermind.Runner/packages.lock.json b/src/Nethermind/Nethermind.Runner/packages.lock.json index 66249443c4c..de5f39f1097 100644 --- a/src/Nethermind/Nethermind.Runner/packages.lock.json +++ b/src/Nethermind/Nethermind.Runner/packages.lock.json @@ -123,19 +123,6 @@ "resolved": "2.14.1", "contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw==" }, - "IdentityModel": { - "type": "Transitive", - "resolved": "5.2.0", - "contentHash": "nuhkbaDH9l5QzNJp2MtP3qio57MPtiRneUN8Ocr7od0JvSYaIe3gBj/vxllr11S/Qvu1AG4GZXoyv5469ewYDA==" - }, - "IdentityModel.OidcClient": { - "type": "Transitive", - "resolved": "5.2.1", - "contentHash": "OuPhDNAw/EoJVEmYO6/ChZUBcug4OGoGKTKLUyBCsGhlKegxJk25LYQ0EL7GCBMgkEL+BYNJukNZyaJ+JNaWog==", - "dependencies": { - "IdentityModel": "5.2.0" - } - }, "IPNetwork2": { "type": "Transitive", "resolved": "2.1.2", @@ -149,17 +136,6 @@ "resolved": "1.0.0", "contentHash": "duyRtj4I3+yZZZC7Ma5S/cxzWn5CLPRcXeXtmBcLS3TpjwLm74afQEGzfYEWma8H/dbpUiHl2ozYszKuQ8QpEg==" }, - "KubernetesClient": { - "type": "Transitive", - "resolved": "15.0.1", - "contentHash": "IOsMJaBpiHELr7ZeiJQypdtLDbc/HqxbEh9UMaDvLpBvGIzS+KhjA0LJVEbGgvubmhWHxLPfgHAL0le1zr2RwA==", - "dependencies": { - "Fractions": "7.3.0", - "IdentityModel.OidcClient": "5.2.1", - "System.IdentityModel.Tokens.Jwt": "7.1.2", - "YamlDotNet": "16.0.0" - } - }, "libsodium": { "type": "Transitive", "resolved": "1.0.20", @@ -622,15 +598,6 @@ "System.Composition.Runtime": "6.0.0" } }, - "System.IdentityModel.Tokens.Jwt": { - "type": "Transitive", - "resolved": "7.1.2", - "contentHash": "Thhbe1peAmtSBFaV/ohtykXiZSOkx59Da44hvtWfIMFofDA3M3LaVyjstACf2rKGn4dEDR2cUpRAZ0Xs/zB+7Q==", - "dependencies": { - "Microsoft.IdentityModel.JsonWebTokens": "7.1.2", - "Microsoft.IdentityModel.Tokens": "7.1.2" - } - }, "System.Reactive": { "type": "Transitive", "resolved": "6.0.0", @@ -648,8 +615,8 @@ }, "YamlDotNet": { "type": "Transitive", - "resolved": "16.0.0", - "contentHash": "kZ4jR5ltFhnjaUqK9x81zXRIUTH4PTXTTEmJDNQdkDLQhcv+2Nl19r0dCSvPW1mstOYBfXTnjdieRbUO6gHMDw==" + "resolved": "16.3.0", + "contentHash": "SgMOdxbz8X65z8hraIs6hOEdnkH6hESTAIUa7viEngHOYaH+6q5XJmwr1+yb9vJpNQ19hCQY69xbFsLtXpobQA==" }, "nethermind.abi": { "type": "Project", @@ -889,6 +856,7 @@ "dependencies": { "AspNetCore.HealthChecks.UI": "[9.0.0, )", "AspNetCore.HealthChecks.UI.InMemory.Storage": "[9.0.0, )", + "KubernetesClient": "[18.0.5, )", "Nethermind.Api": "[1.36.0-unstable, )", "Nethermind.Merge.Plugin": "[1.36.0-unstable, )" } @@ -1336,6 +1304,16 @@ "Grpc.Core": "2.46.6" } }, + "KubernetesClient": { + "type": "CentralTransitive", + "requested": "[18.0.5, )", + "resolved": "18.0.5", + "contentHash": "xkttIbnGNibYwAyZ0sqeQle2w90bfaJrkF8BaURWHfSMKPbHwys9t/wq1XmT64eA4WRVXLENYlXtqmWlEstG6A==", + "dependencies": { + "Fractions": "7.3.0", + "YamlDotNet": "16.3.0" + } + }, "MathNet.Numerics.FSharp": { "type": "CentralTransitive", "requested": "[5.0.0, )", From 6d757d66895920884be5638cb0792a34b050995b Mon Sep 17 00:00:00 2001 From: Nikita Mescheryakov Date: Sat, 29 Nov 2025 02:40:29 +0300 Subject: [PATCH 025/255] Fix buyGas in simulate (#9761) * test * Try fix * Try fix * Remove flag from non rpc calls * Fix json rpc tests * Fix more tests * Fix system tx processor * Fix blockchain tests * More fixes * Update src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fix restore * Fix small issues * Update src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs Co-authored-by: Lukasz Rozmej * known failing tests --------- Co-authored-by: Lukasz Rozmej Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- scripts/known-failing-hive-tests.txt | 5 - .../TransactionProcessorTests.cs | 19 +-- .../Tracing/BlockProcessorFacade.cs | 12 +- .../Tracing/GasEstimationTests.cs | 1 + .../TransactionProcessorTraceTest.cs | 2 +- .../VirtualMachineTestsBase.cs | 12 +- .../SystemTransactionProcessor.cs | 14 ++- .../TransactionProcessor.cs | 112 ++++++++++-------- .../Simulate/SimulateTxTracer.cs | 2 +- .../Modules/DebugRpcModuleTests.cs | 2 +- ...DebugSimulateTestsBlocksAndTransactions.cs | 4 +- .../Eth/EthRpcModuleTests.EstimateGas.cs | 13 +- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 11 +- .../EthSimulateTestsBlocksAndTransactions.cs | 2 +- .../Eth/Simulate/EthSimulateTestsHiveBase.cs | 3 +- .../Modules/Trace/ParityStyleTracerTests.cs | 2 +- .../Modules/TraceRpcModuleTests.cs | 16 ++- .../Nethermind.JsonRpc/JsonRpcService.cs | 10 ++ .../OptimismTransactionProcessor.cs | 8 +- .../TaikoTransactionProcessor.cs | 25 +++- 20 files changed, 163 insertions(+), 112 deletions(-) diff --git a/scripts/known-failing-hive-tests.txt b/scripts/known-failing-hive-tests.txt index 63ff5f96d73..d9464669c7c 100644 --- a/scripts/known-failing-hive-tests.txt +++ b/scripts/known-failing-hive-tests.txt @@ -1,10 +1,5 @@ # rpc-compat -eth_getStorageAt/get-storage-invalid-key (nethermind) -eth_getStorageAt/get-storage-invalid-key-too-large (nethermind) -eth_simulateV1/ethSimulate-two-blocks-with-complete-eth-sends (nethermind) -eth_simulateV1/ethSimulate-use-as-many-features-as-possible (nethermind) - # graphql 01_eth_blockNumber (nethermind) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs index 43c0b7632b5..aca28678395 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs @@ -289,14 +289,14 @@ public void Can_estimate_with_value(bool systemUser) Block block = Build.A.Block.WithParent(_baseBlock).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; EstimateGasTracer tracer = new(); - Action action = () => _transactionProcessor.CallAndRestore(tx, new BlockExecutionContext(block.Header, _specProvider.GetSpec(block.Header)), tracer); + TransactionResult result = _transactionProcessor.CallAndRestore(tx, new BlockExecutionContext(block.Header, _specProvider.GetSpec(block.Header)), tracer); + if (!systemUser) { - action.Should().Throw(); + result.Should().Be(TransactionResult.InsufficientSenderBalance); } else { - action.Should().NotThrow(); tracer.GasSpent.Should().Be(21000); } } @@ -319,7 +319,7 @@ public long Should_not_estimate_tx_with_high_value(UInt256 txValue) long estimate = estimator.Estimate(tx, block.Header, tracer, out string? err, 0); - if (txValue > AccountBalance) + if (txValue + (UInt256)gasLimit > AccountBalance) { Assert.That(err, Is.Not.Null); // Should have error Assert.That(err, Is.EqualTo("Transaction execution fails")); @@ -336,20 +336,21 @@ public static IEnumerable EstimateWithHighTxValueTestCases { get { + UInt256 gasLimit = 100000; yield return new TestCaseData((UInt256)1) { TestName = "Sanity check", ExpectedResult = GasCostOf.Transaction }; - yield return new TestCaseData(AccountBalance - 1) + yield return new TestCaseData(AccountBalance - 1 - gasLimit) { TestName = "Less than account balance", ExpectedResult = GasCostOf.Transaction }; - yield return new TestCaseData(AccountBalance - GasCostOf.Transaction) + yield return new TestCaseData(AccountBalance - GasCostOf.Transaction - gasLimit) { TestName = "Account balance - tx cost", ExpectedResult = GasCostOf.Transaction }; - yield return new TestCaseData(AccountBalance - GasCostOf.Transaction + 1) + yield return new TestCaseData(AccountBalance - GasCostOf.Transaction - gasLimit + 1) { TestName = "More than (account balance - tx cost)", ExpectedResult = GasCostOf.Transaction }; yield return new TestCaseData(AccountBalance) - { TestName = "Exactly account balance", ExpectedResult = GasCostOf.Transaction }; + { TestName = "Exactly account balance", ExpectedResult = 0L }; yield return new TestCaseData(AccountBalance + 1) { TestName = "More than account balance", ExpectedResult = 0L }; - yield return new TestCaseData(UInt256.MaxValue) + yield return new TestCaseData(UInt256.MaxValue - gasLimit) { TestName = "Max value possible", ExpectedResult = 0L }; } } diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/BlockProcessorFacade.cs b/src/Nethermind/Nethermind.Consensus/Tracing/BlockProcessorFacade.cs index 224f2ae63b7..3ba3590e63c 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/BlockProcessorFacade.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/BlockProcessorFacade.cs @@ -27,14 +27,8 @@ CompositeBlockPreprocessorStep preprocessorStep preprocessorStep.RecoverData(block); IReleaseSpec spec = specProvider.GetSpec(block.Header); - try - { - (Block? processedBlock, TxReceipt[] _) = blockProcessor.ProcessOne(block, options, tracer, spec, token); - return processedBlock; - } - catch (InvalidBlockException) - { - return null; - } + + (Block? processedBlock, TxReceipt[] _) = blockProcessor.ProcessOne(block, options, tracer, spec, token); + return processedBlock; } } diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs index 0cd32af7226..20ed04b918a 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs @@ -506,6 +506,7 @@ public void Should_succeed_when_address_zero_has_no_value_transfer() TestEnvironment testEnvironment = new(); Transaction tx = Build.A.Transaction .WithGasLimit(100000) + .WithGasPrice(0) .WithSenderAddress(Address.Zero) .WithValue(0) // No value transfer - should work even with zero balance .TestObject; diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTraceTest.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTraceTest.cs index d139a885c33..81f14bde867 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTraceTest.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTraceTest.cs @@ -20,7 +20,7 @@ public class TransactionProcessorTraceTest : VirtualMachineTestsBase [TestCase(50000)] public void Trace_should_not_charge_gas(long gasLimit) { - (Block block, Transaction transaction) = PrepareTx(BlockNumber, gasLimit); + (Block block, Transaction transaction) = PrepareTx(BlockNumber, gasLimit, gasPrice: 0); ParityLikeTxTracer tracer = new(block, transaction, ParityTraceTypes.All); _processor.Trace(transaction, new BlockExecutionContext(block.Header, Spec), tracer); var senderBalance = tracer.BuildResult().StateChanges[TestItem.AddressA].Balance; diff --git a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs index a686d51fdef..5031e029d19 100644 --- a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs +++ b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs @@ -197,9 +197,10 @@ protected TestAllTracerWithOutput Execute(ForkActivation activation, long gasLim int value = 1, long blockGasLimit = DefaultBlockGasLimit, byte[][]? blobVersionedHashes = null, - ulong excessBlobGas = 0) + ulong excessBlobGas = 0, + ulong gasPrice = 1) { - return PrepareTx((blockNumber, Timestamp), gasLimit, code, senderRecipientAndMiner, value, blockGasLimit, blobVersionedHashes, excessBlobGas); + return PrepareTx((blockNumber, Timestamp), gasLimit, code, senderRecipientAndMiner, value, blockGasLimit, blobVersionedHashes, excessBlobGas, gasPrice: gasPrice); } protected (Block block, Transaction transaction) PrepareTx( @@ -211,7 +212,8 @@ protected TestAllTracerWithOutput Execute(ForkActivation activation, long gasLim long blockGasLimit = DefaultBlockGasLimit, byte[][]? blobVersionedHashes = null, ulong excessBlobGas = 0, - Transaction transaction = null) + Transaction transaction = null, + ulong gasPrice = 1) { senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; @@ -243,7 +245,7 @@ protected TestAllTracerWithOutput Execute(ForkActivation activation, long gasLim transaction ??= Build.A.Transaction .WithGasLimit(gasLimit) - .WithGasPrice(1) + .WithGasPrice(gasPrice) .WithValue(value) .WithBlobVersionedHashes(blobVersionedHashes) .WithNonce(TestState.GetNonce(senderRecipientAndMiner.Sender)) @@ -261,7 +263,7 @@ protected TestAllTracerWithOutput Execute(ForkActivation activation, long gasLim /// deprecated. Please use activation instead of blockNumber. /// protected (Block block, Transaction transaction) PrepareTx(long blockNumber, long gasLimit, byte[] code, - byte[] input, UInt256 value, SenderRecipientAndMiner senderRecipientAndMiner = null) + byte[] input, UInt256 value, SenderRecipientAndMiner senderRecipientAndMiner = null, ulong gasPrice = 1) { return PrepareTx((blockNumber, Timestamp), gasLimit, code, input, value, senderRecipientAndMiner); } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/SystemTransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/SystemTransactionProcessor.cs index 24de0b64ba7..a4bd99c0758 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/SystemTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/SystemTransactionProcessor.cs @@ -45,9 +45,19 @@ protected override TransactionResult Execute(Transaction tx, ITxTracer tracer, E : opts); } + protected override TransactionResult BuyGas(Transaction tx, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, + in UInt256 effectiveGasPrice, out UInt256 premiumPerGas, out UInt256 senderReservedGasPayment, + out UInt256 blobBaseFee) + { + premiumPerGas = 0; + senderReservedGasPayment = 0; + blobBaseFee = 0; + return TransactionResult.Ok; + } + protected override IReleaseSpec GetSpec(BlockHeader header) => SystemTransactionReleaseSpec.GetReleaseSpec(base.GetSpec(header), _isAura, header.IsGenesis); - protected override TransactionResult ValidateGas(Transaction tx, BlockHeader header, long minGasRequired, bool validate) => TransactionResult.Ok; + protected override TransactionResult ValidateGas(Transaction tx, BlockHeader header, long minGasRequired) => TransactionResult.Ok; protected override TransactionResult IncrementNonce(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts) => TransactionResult.Ok; @@ -71,4 +81,6 @@ protected override bool RecoverSenderIfNeeded(Transaction tx, IReleaseSpec spec, return (sender is null || (spec.IsEip158IgnoredAccount(sender) && !WorldState.AccountExists(sender))) && base.RecoverSenderIfNeeded(tx, spec, opts, in effectiveGasPrice); } + + protected override void PayRefund(Transaction tx, UInt256 refundAmount, IReleaseSpec spec) { } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 21580b779de..b2c3a7f5fec 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -180,9 +180,16 @@ protected virtual TransactionResult Execute(Transaction tx, ITxTracer tracer, Ex bool deleteCallerAccount = RecoverSenderIfNeeded(tx, spec, opts, effectiveGasPrice); - if (!(result = ValidateSender(tx, header, spec, tracer, opts))) return result; - if (!(result = BuyGas(tx, spec, tracer, opts, effectiveGasPrice, out UInt256 premiumPerGas, out UInt256 senderReservedGasPayment, out UInt256 blobBaseFee))) return result; - if (!(result = IncrementNonce(tx, header, spec, tracer, opts))) return result; + if (!(result = ValidateSender(tx, header, spec, tracer, opts)) || + !(result = BuyGas(tx, spec, tracer, opts, effectiveGasPrice, out UInt256 premiumPerGas, out UInt256 senderReservedGasPayment, out UInt256 blobBaseFee)) || + !(result = IncrementNonce(tx, header, spec, tracer, opts))) + { + if (restore) + { + WorldState.Reset(resetBlockChanges: false); + } + return result; + } if (commit) WorldState.Commit(spec, tracer.IsTracingState ? tracer : NullTxTracer.Instance, commitRoots: false); @@ -211,7 +218,7 @@ protected virtual TransactionResult Execute(Transaction tx, ITxTracer tracer, Ex } else { - if (!opts.HasFlag(ExecutionOptions.SkipValidation)) + if (!senderReservedGasPayment.IsZero) WorldState.AddToBalance(tx.SenderAddress!, senderReservedGasPayment, spec); DecrementNonce(tx); @@ -400,10 +407,10 @@ protected virtual TransactionResult ValidateStatic( return TransactionResult.TransactionSizeOverMaxInitCodeSize; } - return ValidateGas(tx, header, intrinsicGas.MinimalGas, validate); + return ValidateGas(tx, header, intrinsicGas.MinimalGas); } - protected virtual TransactionResult ValidateGas(Transaction tx, BlockHeader header, long minGasRequired, bool validate) + protected virtual TransactionResult ValidateGas(Transaction tx, BlockHeader header, long minGasRequired) { if (tx.GasLimit < minGasRequired) { @@ -485,69 +492,69 @@ protected virtual TransactionResult ValidateSender(Transaction tx, BlockHeader h return TransactionResult.Ok; } + protected static bool ShouldValidateGas(Transaction tx, ExecutionOptions opts) + => !opts.HasFlag(ExecutionOptions.SkipValidation) || !tx.MaxFeePerGas.IsZero || !tx.MaxPriorityFeePerGas.IsZero; + protected virtual TransactionResult BuyGas(Transaction tx, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, in UInt256 effectiveGasPrice, out UInt256 premiumPerGas, out UInt256 senderReservedGasPayment, out UInt256 blobBaseFee) { premiumPerGas = UInt256.Zero; senderReservedGasPayment = UInt256.Zero; blobBaseFee = UInt256.Zero; - bool validate = !opts.HasFlag(ExecutionOptions.SkipValidation); + bool validate = ShouldValidateGas(tx, opts); - if (validate) + BlockHeader header = VirtualMachine.BlockExecutionContext.Header; + if (validate && !TryCalculatePremiumPerGas(tx, header.BaseFeePerGas, out premiumPerGas)) { - BlockHeader header = VirtualMachine.BlockExecutionContext.Header; - if (!TryCalculatePremiumPerGas(tx, header.BaseFeePerGas, out premiumPerGas)) - { - TraceLogInvalidTx(tx, "MINER_PREMIUM_IS_NEGATIVE"); - return TransactionResult.MinerPremiumNegative; - } + TraceLogInvalidTx(tx, "MINER_PREMIUM_IS_NEGATIVE"); + return TransactionResult.MinerPremiumNegative; + } - UInt256 senderBalance = WorldState.GetBalance(tx.SenderAddress!); - if (UInt256.SubtractUnderflow(in senderBalance, in tx.ValueRef, out UInt256 balanceLeft)) - { - TraceLogInvalidTx(tx, $"INSUFFICIENT_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}"); - return TransactionResult.InsufficientSenderBalance; - } + UInt256 senderBalance = WorldState.GetBalance(tx.SenderAddress!); + if (UInt256.SubtractUnderflow(in senderBalance, in tx.ValueRef, out UInt256 balanceLeft)) + { + TraceLogInvalidTx(tx, $"INSUFFICIENT_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}"); + return TransactionResult.InsufficientSenderBalance; + } - bool overflows; - if (spec.IsEip1559Enabled && !tx.IsFree()) + bool overflows; + if (spec.IsEip1559Enabled && !tx.IsFree()) + { + overflows = UInt256.MultiplyOverflow((UInt256)tx.GasLimit, tx.MaxFeePerGas, out UInt256 maxGasFee); + if (overflows || balanceLeft < maxGasFee) { - overflows = UInt256.MultiplyOverflow((UInt256)tx.GasLimit, tx.MaxFeePerGas, out UInt256 maxGasFee); - if (overflows || balanceLeft < maxGasFee) - { - TraceLogInvalidTx(tx, $"INSUFFICIENT_MAX_FEE_PER_GAS_FOR_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}, MAX_FEE_PER_GAS: {tx.MaxFeePerGas}"); - return TransactionResult.InsufficientMaxFeePerGasForSenderBalance; - } - - if (tx.SupportsBlobs) - { - overflows = UInt256.MultiplyOverflow(BlobGasCalculator.CalculateBlobGas(tx), (UInt256)tx.MaxFeePerBlobGas!, out UInt256 maxBlobGasFee); - if (overflows || UInt256.AddOverflow(maxGasFee, maxBlobGasFee, out UInt256 multidimGasFee) || multidimGasFee > balanceLeft) - { - TraceLogInvalidTx(tx, $"INSUFFICIENT_MAX_FEE_PER_BLOB_GAS_FOR_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}"); - return TransactionResult.InsufficientSenderBalance; - } - } + TraceLogInvalidTx(tx, $"INSUFFICIENT_MAX_FEE_PER_GAS_FOR_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}, MAX_FEE_PER_GAS: {tx.MaxFeePerGas}"); + return TransactionResult.InsufficientMaxFeePerGasForSenderBalance; } - overflows = UInt256.MultiplyOverflow((UInt256)tx.GasLimit, effectiveGasPrice, out senderReservedGasPayment); - if (!overflows && tx.SupportsBlobs) + if (tx.SupportsBlobs) { - overflows = !_blobBaseFeeCalculator.TryCalculateBlobBaseFee(header, tx, spec.BlobBaseFeeUpdateFraction, out blobBaseFee); - if (!overflows) + overflows = UInt256.MultiplyOverflow(BlobGasCalculator.CalculateBlobGas(tx), (UInt256)tx.MaxFeePerBlobGas!, out UInt256 maxBlobGasFee); + if (overflows || UInt256.AddOverflow(maxGasFee, maxBlobGasFee, out UInt256 multidimGasFee) || multidimGasFee > balanceLeft) { - overflows = UInt256.AddOverflow(senderReservedGasPayment, blobBaseFee, out senderReservedGasPayment); + TraceLogInvalidTx(tx, $"INSUFFICIENT_MAX_FEE_PER_BLOB_GAS_FOR_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}"); + return TransactionResult.InsufficientSenderBalance; } } + } - if (overflows || senderReservedGasPayment > balanceLeft) + overflows = UInt256.MultiplyOverflow((UInt256)tx.GasLimit, effectiveGasPrice, out senderReservedGasPayment); + if (!overflows && tx.SupportsBlobs) + { + overflows = !_blobBaseFeeCalculator.TryCalculateBlobBaseFee(header, tx, spec.BlobBaseFeeUpdateFraction, out blobBaseFee); + if (!overflows) { - TraceLogInvalidTx(tx, $"INSUFFICIENT_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}"); - return TransactionResult.InsufficientSenderBalance; + overflows = UInt256.AddOverflow(senderReservedGasPayment, blobBaseFee, out senderReservedGasPayment); } } - if (validate) WorldState.SubtractFromBalance(tx.SenderAddress, senderReservedGasPayment, spec); + if (overflows || senderReservedGasPayment > balanceLeft) + { + TraceLogInvalidTx(tx, $"INSUFFICIENT_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}"); + return TransactionResult.InsufficientSenderBalance; + } + + if (!senderReservedGasPayment.IsZero) WorldState.SubtractFromBalance(tx.SenderAddress, senderReservedGasPayment, spec); return TransactionResult.Ok; } @@ -912,13 +919,18 @@ protected virtual GasConsumed Refund(Transaction tx, BlockHeader header, IReleas long operationGas = spentGas; spentGas = Math.Max(spentGas, floorGas); - // If noValidation we didn't charge for gas, so do not refund - if (!opts.HasFlag(ExecutionOptions.SkipValidation)) - WorldState.AddToBalance(tx.SenderAddress!, (ulong)(tx.GasLimit - spentGas) * gasPrice, spec); + UInt256 refundAmount = (ulong)(tx.GasLimit - spentGas) * gasPrice; + PayRefund(tx, refundAmount, spec); return new GasConsumed(spentGas, operationGas); } + protected virtual void PayRefund(Transaction tx, UInt256 refundAmount, IReleaseSpec spec) + { + if (!refundAmount.IsZero) + WorldState.AddToBalance(tx.SenderAddress!, refundAmount, spec); + } + protected virtual long CalculateClaimableRefund(long spentGas, long totalRefund, IReleaseSpec spec) => RefundHelper.CalculateClaimableRefund(spentGas, totalRefund, spec); diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateTxTracer.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateTxTracer.cs index 161c044e970..25f078f9fb1 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateTxTracer.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateTxTracer.cs @@ -90,7 +90,7 @@ public override void MarkAsSuccess(Address recipient, GasConsumed gasSpent, byte Address = entry.Address, Topics = entry.Topics, Data = entry.Data, - LogIndex = (ulong)i, + LogIndex = _txIndex + (ulong)i, TransactionHash = _tx.Hash!, TransactionIndex = _txIndex, BlockHash = _currentBlockHash, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs index a0471307c08..e5adef5fd85 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs @@ -60,7 +60,7 @@ public async Task Debug_traceCall_fails_when_not_enough_balance() ); response.Should().BeOfType() - .Which.Error?.Message?.Should().Contain("insufficient funds"); + .Which.Error?.Message?.Should().Contain("insufficient sender balance"); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs index 20fb25101bd..615f684eda1 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs @@ -124,7 +124,7 @@ public async Task TestTransferLogsAddress() TestRpcBlockchain chain = await EthRpcSimulateTestsBase.CreateChain(); Console.WriteLine("current test: simulateTransferOverBlockStateCalls"); var result = chain.DebugRpcModule.debug_simulateV1(payload!, BlockParameter.Latest); - Assert.That(result.Data.First().Traces.First().TxHash, Is.EqualTo(new Core.Crypto.Hash256("0xea104c39737cea12ae19c0985b3bc799096f3dbd2574594c2ecb4d0731e042cc"))); + Assert.That(result.Data.First().Traces.First().TxHash, Is.EqualTo(new Core.Crypto.Hash256("0xe690a6e09e13d163bc8b92c725202e9633770b14c8541a0ee48794ae014351f0"))); } [Test] @@ -136,7 +136,7 @@ public async Task TestSerializationDebugSimulate() Assert.That(response, Is.TypeOf()); JsonRpcSuccessResponse successResponse = (JsonRpcSuccessResponse)response; IReadOnlyList> data = (IReadOnlyList>)successResponse.Result!; - Assert.That(data.First().Traces.First().TxHash, Is.EqualTo(new Core.Crypto.Hash256("0xea104c39737cea12ae19c0985b3bc799096f3dbd2574594c2ecb4d0731e042cc"))); + Assert.That(data.First().Traces.First().TxHash, Is.EqualTo(new Core.Crypto.Hash256("0xe690a6e09e13d163bc8b92c725202e9633770b14c8541a0ee48794ae014351f0"))); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs index 1347539d7e7..a24af91894b 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs @@ -49,7 +49,7 @@ public async Task Eth_estimateGas_web3_sample_not_enough_gas_system_account() using Context ctx = await Context.Create(); ctx.Test.ReadOnlyState.AccountExists(Address.SystemUser).Should().BeFalse(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( - "{\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); + "{\"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", transaction); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x53b8\",\"id\":67}")); @@ -63,7 +63,7 @@ public async Task Eth_estimateGas_web3_sample_not_enough_gas_other_account() Address someAccount = new("0x0001020304050607080910111213141516171819"); ctx.Test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( - "{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); + "{\"from\":\"0x0001020304050607080910111213141516171819\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", transaction); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x53b8\",\"id\":67}")); @@ -77,7 +77,7 @@ public async Task Eth_estimateGas_web3_above_block_gas_limit() Address someAccount = new("0x0001020304050607080910111213141516171819"); ctx.Test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( - "{\"from\":\"0x0001020304050607080910111213141516171819\",\"gas\":\"0x100000\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); + "{\"from\":\"0x0001020304050607080910111213141516171819\",\"gas\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", transaction); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x53b8\",\"id\":67}")); @@ -174,7 +174,7 @@ public async Task Estimate_gas_with_gas_pricing() { using Context ctx = await Context.Create(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( - "{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}"); + $"{{\"from\": \"{TestItem.AddressA}\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}}"); string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", transaction); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x5208\",\"id\":67}")); } @@ -184,7 +184,7 @@ public async Task Estimate_gas_without_gas_pricing_after_1559_legacy() { using Context ctx = await Context.CreateWithLondonEnabled(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( - "{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}"); + $"{{\"from\": \"{TestItem.AddressA}\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x100000000\"}}"); string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", transaction); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x5208\",\"id\":67}")); } @@ -290,7 +290,8 @@ public async Task should_estimate_transaction_with_deployed_code_when_eip3607_en Transaction tx = Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyA).TestObject; LegacyTransactionForRpc transaction = new LegacyTransactionForRpc(tx, 1, Keccak.Zero, 1L) { - To = TestItem.AddressB + To = TestItem.AddressB, + GasPrice = 0 }; string serialized = diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index c564a24787b..7e509b1f037 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -54,7 +54,7 @@ public async Task Eth_call_web3_sample_not_enough_gas_system_account() using Context ctx = await Context.Create(); ctx.Test.ReadOnlyState.AccountExists(Address.SystemUser).Should().BeFalse(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( - "{\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); + "{\"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); string serialized = await ctx.Test.TestEthRpc("eth_call", transaction, "0x0"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); @@ -82,7 +82,7 @@ public async Task Eth_call_web3_sample_not_enough_gas_other_account() Address someAccount = new("0x0001020304050607080910111213141516171819"); ctx.Test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( - "{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); + "{\"from\":\"0x0001020304050607080910111213141516171819\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); string serialized = await ctx.Test.TestEthRpc("eth_call", transaction, "0x0"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); @@ -136,7 +136,8 @@ public async Task should_not_reject_transactions_with_deployed_code_when_eip3607 Transaction tx = Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyA).TestObject; LegacyTransactionForRpc transaction = new(tx, 1, Keccak.Zero, 1L) { - To = TestItem.AddressB + To = TestItem.AddressB, + GasPrice = 0 }; string serialized = @@ -248,7 +249,7 @@ public async Task Eth_call_with_gas_pricing() { using Context ctx = await Context.Create(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( - "{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}"); + $"{{\"from\": \"{TestItem.AddressA}\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}}"); string serialized = await ctx.Test.TestEthRpc("eth_call", transaction); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); } @@ -258,7 +259,7 @@ public async Task Eth_call_without_gas_pricing_after_1559_legacy() { using Context ctx = await Context.CreateWithLondonEnabled(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( - "{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}"); + $"{{\"from\": \"{TestItem.AddressA}\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x100000000\"}}"); string serialized = await ctx.Test.TestEthRpc("eth_call", transaction); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs index 4cae9fee60b..b49a681eea0 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs @@ -277,7 +277,7 @@ public static SimulatePayload CreateTransferLogsAddressPayloa }, "calls": [ { - "type": "0x3", + "type": "0x2", "from": "0xc000000000000000000000000000000000000000", "to": "0xc100000000000000000000000000000000000000", "gas": "0x5208", diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs index 0f478d0bda9..93eae058322 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs @@ -28,6 +28,7 @@ public class EthSimulateTestsHiveBase private static readonly object[] HiveTestCases = { new object[] {"baseFee", true, "{\"blockStateCalls\": [\r\n {\r\n \"blockOverrides\": {\r\n \"blobBaseFee\": \"0x0\"\r\n },\r\n \"stateOverrides\": {\r\n \"0xc000000000000000000000000000000000000000\": {\r\n \"balance\": \"0x5f5e100\"\r\n },\r\n \"0xc200000000000000000000000000000000000000\": {\r\n \"code\": \"0x\"\r\n }\r\n },\r\n \"calls\": [\r\n {\r\n \"from\": \"0xc000000000000000000000000000000000000000\",\r\n \"to\": \"0xc200000000000000000000000000000000000000\",\r\n \"maxFeePerBlobGas\": \"0xa\",\r\n \"blobVersionedHashes\": [\r\n \"0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014\"\r\n ]\r\n }\r\n ]\r\n },\r\n {\r\n \"blockOverrides\": {\r\n \"blobBaseFee\": \"0x1\"\r\n },\r\n \"calls\": [\r\n {\r\n \"from\": \"0xc000000000000000000000000000000000000000\",\r\n \"to\": \"0xc200000000000000000000000000000000000000\",\r\n \"maxFeePerBlobGas\": \"0xa\",\r\n \"blobVersionedHashes\": [\r\n \"0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014\"\r\n ]\r\n }\r\n ]\r\n }\r\n ]\r\n }"}, +new object[] {"baseFee-no-blob-base-fee-override", true, "{\"blockStateCalls\": [\r\n {\r\n \"stateOverrides\": {\r\n \"0xc000000000000000000000000000000000000000\": {\r\n \"balance\": \"0x5f5e100\"\r\n },\r\n \"0xc200000000000000000000000000000000000000\": {\r\n \"code\": \"0x\"\r\n }\r\n },\r\n \"calls\": [\r\n {\r\n \"from\": \"0xc000000000000000000000000000000000000000\",\r\n \"to\": \"0xc200000000000000000000000000000000000000\",\r\n \"maxFeePerBlobGas\": \"0xa\",\r\n \"blobVersionedHashes\": [\r\n \"0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014\"\r\n ]\r\n }\r\n ]\r\n },\r\n {\r\n \"blockOverrides\": {\r\n \"blobBaseFee\": \"0x1\"\r\n },\r\n \"calls\": [\r\n {\r\n \"from\": \"0xc000000000000000000000000000000000000000\",\r\n \"to\": \"0xc200000000000000000000000000000000000000\",\r\n \"maxFeePerBlobGas\": \"0xa\",\r\n \"blobVersionedHashes\": [\r\n \"0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014\"\r\n ]\r\n }\r\n ]\r\n }\r\n ]\r\n }"}, new object[] {"multicall-add-more-non-defined-BlockStateCalls-than-fit-but-now-with-fit", true, "{\"blockStateCalls\": [{\"blockOverrides\": {\"number\": \"0xa\"}, \"stateOverrides\": {\"0xc100000000000000000000000000000000000000\": {\"code\": \"0x608060405234801561001057600080fd5b506000366060484641444543425a3a60014361002c919061009b565b406040516020016100469a99989796959493929190610138565b6040516020818303038152906040529050915050805190602001f35b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006100a682610062565b91506100b183610062565b92508282039050818111156100c9576100c861006c565b5b92915050565b6100d881610062565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610109826100de565b9050919050565b610119816100fe565b82525050565b6000819050919050565b6101328161011f565b82525050565b60006101408201905061014e600083018d6100cf565b61015b602083018c6100cf565b610168604083018b610110565b610175606083018a6100cf565b61018260808301896100cf565b61018f60a08301886100cf565b61019c60c08301876100cf565b6101a960e08301866100cf565b6101b76101008301856100cf565b6101c5610120830184610129565b9b9a505050505050505050505056fea26469706673582212205139ae3ba8d46d11c29815d001b725f9840c90e330884ed070958d5af4813d8764736f6c63430008120033\"}}, \"calls\": [{\"from\": \"0xc000000000000000000000000000000000000000\", \"to\": \"0xc100000000000000000000000000000000000000\", \"input\": \"0x\"}]}, {\"calls\": [{\"from\": \"0xc000000000000000000000000000000000000000\", \"to\": \"0xc100000000000000000000000000000000000000\", \"input\": \"0x\"}]}, {\"blockOverrides\": {\"number\": \"0x14\"}, \"calls\": [{\"from\": \"0xc000000000000000000000000000000000000000\", \"to\": \"0xc100000000000000000000000000000000000000\", \"input\": \"0x\"}]}, {\"calls\": [{\"from\": \"0xc000000000000000000000000000000000000000\", \"to\": \"0xc100000000000000000000000000000000000000\", \"input\": \"0x\"}]}]}"}, new object[] {"multicall-basefee-too-low-without-validation-38012", true, "{\"blockStateCalls\": [{\"blockOverrides\": {\"baseFeePerGas\": \"0xa\"}, \"stateOverrides\": {\"0xc000000000000000000000000000000000000000\": {\"balance\": \"0x7d0\"}}, \"calls\": [{\"from\": \"0xc100000000000000000000000000000000000000\", \"to\": \"0xc100000000000000000000000000000000000000\", \"maxFeePerGas\": \"0x0\", \"maxPriorityFeePerGas\": \"0x0\"}]}]}"}, new object[] {"multicall-block-timestamps-incrementing", true, "{\"blockStateCalls\": [{\"blockOverrides\": {\"time\": \"0x5e47e91a\"}}, {\"blockOverrides\": {\"time\": \"0x5e47e91b\"}}]}"}, @@ -79,7 +80,7 @@ public async Task TestsimulateHive(string name, bool shouldSucceed, string data) { EthereumJsonSerializer serializer = new(); SimulatePayload? payload = serializer.Deserialize>(data); - TestRpcBlockchain chain = await EthRpcSimulateTestsBase.CreateChain(); + TestRpcBlockchain chain = await EthRpcSimulateTestsBase.CreateChain(Osaka.Instance); Console.WriteLine($"current test: {name}"); ResultWrapper>> result = chain.EthRpcModule.eth_simulateV1(payload!, BlockParameter.Latest); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs index 339f5804a13..9ee6c353c93 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs @@ -70,7 +70,7 @@ public async Task TearDownAsync() [Test] public void Can_trace_raw_parity_style() { - ResultWrapper result = _traceRpcModule.trace_rawTransaction(Bytes.FromHexString("f889808609184e72a00082271094000000000000000000000000000000000000000080a47f74657374320000000000000000000000000000000000000000000000000000006000571ca08a8bbf888cfa37bbf0bb965423625641fc956967b81d12e23709cead01446075a01ce999b56a8a88504be365442ea61239198e23d1fce7d00fcfc5cd3b44b7215f"), new[] { "trace" }); + ResultWrapper result = _traceRpcModule.trace_rawTransaction(Bytes.FromHexString("f8838080829c4094000000000000000000000000000000000000000080a47f74657374320000000000000000000000000000000000000000000000000000006000571ca08a8bbf888cfa37bbf0bb965423625641fc956967b81d12e23709cead01446075a01ce999b56a8a88504be365442ea61239198e23d1fce7d00fcfc5cd3b44b7215f"), new[] { "trace" }); Assert.That(result.Data, Is.Not.Null); } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index f3cd2df13ec..41e56ab82bd 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -675,6 +675,8 @@ public async Task Trace_call_runs_on_top_of_specified_block() Transaction transaction = Build.A.Transaction .SignedAndResolved(addressKey) .WithTo(TestItem.AddressC) + .WithMaxFeePerGas(0) + .WithMaxPriorityFeePerGas(0) .WithValue(send) .TestObject; @@ -704,6 +706,8 @@ public async Task Trace_callMany_runs_on_top_of_specified_block() Transaction transaction = Build.A.Transaction .SignedAndResolved(addressKey) .WithTo(TestItem.AddressC) + .WithMaxFeePerGas(0) + .WithMaxPriorityFeePerGas(0) .WithValue(send) .TestObject; @@ -733,6 +737,8 @@ public async Task Trace_rawTransaction_runs_on_top_of_specified_block() Transaction transaction = Build.A.Transaction .WithTo(TestItem.AddressC) .WithValue(send) + .WithMaxFeePerGas(0) + .WithMaxPriorityFeePerGas(0) .SignedAndResolved(addressKey) .TestObject; @@ -762,8 +768,8 @@ public async Task Trace_call_simple_tx_test() } private static readonly IEnumerable<(object, string[], string)> Trace_call_without_blockParameter_test_cases = [ - (new { from = "0x7f554713be84160fdf0178cc8df86f5aabd33397", to = "0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f", value = "0x0", gasPrice = "0x119e04a40a", gas = "0xf4240" }, ["trace"], "{\"jsonrpc\":\"2.0\",\"result\":{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{\"action\":{\"callType\":\"call\",\"from\":\"0x7f554713be84160fdf0178cc8df86f5aabd33397\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f\",\"value\":\"0x0\"},\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}],\"vmTrace\":null},\"id\":67}"), - (new { from = "0xc71acc7863f3bc7347b24c3b835643bd89d4d161", to = "0xa760e26aa76747020171fcf8bda108dfde8eb930", value = "0x0", gasPrice = "0x2108eea5bc", gas = "0xf4240" }, ["trace"], "{\"jsonrpc\":\"2.0\",\"result\":{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{\"action\":{\"callType\":\"call\",\"from\":\"0xc71acc7863f3bc7347b24c3b835643bd89d4d161\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0xa760e26aa76747020171fcf8bda108dfde8eb930\",\"value\":\"0x0\"},\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}],\"vmTrace\":null},\"id\":67}") + (new { from = TestItem.AddressA, to = "0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f", value = "0x0", gasPrice = "0x119e04a40a", gas = "0xf4240" }, ["trace"], $"{{\"jsonrpc\":\"2.0\",\"result\":{{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{{\"action\":{{\"callType\":\"call\",\"from\":\"{TestItem.AddressA}\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f\",\"value\":\"0x0\"}},\"result\":{{\"gasUsed\":\"0x0\",\"output\":\"0x\"}},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}}],\"vmTrace\":null}},\"id\":67}}"), + (new { from = TestItem.AddressA, to = "0xa760e26aa76747020171fcf8bda108dfde8eb930", value = "0x0", gasPrice = "0x2108eea5bc", gas = "0xf4240" }, ["trace"], $"{{\"jsonrpc\":\"2.0\",\"result\":{{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{{\"action\":{{\"callType\":\"call\",\"from\":\"{TestItem.AddressA}\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0xa760e26aa76747020171fcf8bda108dfde8eb930\",\"value\":\"0x0\"}},\"result\":{{\"gasUsed\":\"0x0\",\"output\":\"0x\"}},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}}],\"vmTrace\":null}},\"id\":67}}") ]; [TestCaseSource(nameof(Trace_call_without_blockParameter_test_cases))] public async Task Trace_call_without_blockParameter_test((object transaction, string[] traceTypes, string expectedResult) testCase) @@ -817,7 +823,7 @@ public async Task Trace_callMany_is_blockParameter_optional_test() { Context context = new(); await context.Build(); - string calls = "[[{\"from\":\"0xfe35e70599578efef562e1f1cdc9ef693b865e9d\",\"to\":\"0x8cf85548ae57a91f8132d0831634c0fcef06e505\",\"gas\":\"0xf4240\"},[\"trace\"]],[{\"from\":\"0x2a6ae6f33729384a00b4ffbd25e3f1bf1b9f5b8d\",\"to\":\"0xab736519b5433974059da38da74b8db5376942cd\",\"gasPrice\":\"0xb2b29a6dc\",\"gas\":\"0xf4240\"},[\"trace\"]]]"; + string calls = $"[[{{\"from\":\"{TestItem.AddressA}\",\"to\":\"0x8cf85548ae57a91f8132d0831634c0fcef06e505\",\"gas\":\"0xf4240\"}},[\"trace\"]],[{{\"from\":\"{TestItem.AddressB}\",\"to\":\"0xab736519b5433974059da38da74b8db5376942cd\",\"gasPrice\":\"0xb2b29a6dc\",\"gas\":\"0xf4240\"}},[\"trace\"]]]"; string serialized = await RpcTest.TestSerializedRequest( context.TraceRpcModule, @@ -827,8 +833,8 @@ public async Task Trace_callMany_is_blockParameter_optional_test() context.TraceRpcModule, "trace_callMany", calls); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{\"action\":{\"callType\":\"call\",\"from\":\"0xfe35e70599578efef562e1f1cdc9ef693b865e9d\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0x8cf85548ae57a91f8132d0831634c0fcef06e505\",\"value\":\"0x0\"},\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}],\"vmTrace\":null},{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{\"action\":{\"callType\":\"call\",\"from\":\"0x2a6ae6f33729384a00b4ffbd25e3f1bf1b9f5b8d\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0xab736519b5433974059da38da74b8db5376942cd\",\"value\":\"0x0\"},\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}],\"vmTrace\":null}],\"id\":67}"), serialized.Replace("\"", "\\\"")); - Assert.That(serialized_without_blockParameter_param, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{\"action\":{\"callType\":\"call\",\"from\":\"0xfe35e70599578efef562e1f1cdc9ef693b865e9d\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0x8cf85548ae57a91f8132d0831634c0fcef06e505\",\"value\":\"0x0\"},\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}],\"vmTrace\":null},{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{\"action\":{\"callType\":\"call\",\"from\":\"0x2a6ae6f33729384a00b4ffbd25e3f1bf1b9f5b8d\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0xab736519b5433974059da38da74b8db5376942cd\",\"value\":\"0x0\"},\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}],\"vmTrace\":null}],\"id\":67}"), serialized_without_blockParameter_param.Replace("\"", "\\\"")); + Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":[{{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{{\"action\":{{\"callType\":\"call\",\"from\":\"{TestItem.AddressA}\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0x8cf85548ae57a91f8132d0831634c0fcef06e505\",\"value\":\"0x0\"}},\"result\":{{\"gasUsed\":\"0x0\",\"output\":\"0x\"}},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}}],\"vmTrace\":null}},{{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{{\"action\":{{\"callType\":\"call\",\"from\":\"{TestItem.AddressB}\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0xab736519b5433974059da38da74b8db5376942cd\",\"value\":\"0x0\"}},\"result\":{{\"gasUsed\":\"0x0\",\"output\":\"0x\"}},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}}],\"vmTrace\":null}}],\"id\":67}}"), serialized.Replace("\"", "\\\"")); + Assert.That(serialized_without_blockParameter_param, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":[{{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{{\"action\":{{\"callType\":\"call\",\"from\":\"{TestItem.AddressA}\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0x8cf85548ae57a91f8132d0831634c0fcef06e505\",\"value\":\"0x0\"}},\"result\":{{\"gasUsed\":\"0x0\",\"output\":\"0x\"}},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}}],\"vmTrace\":null}},{{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{{\"action\":{{\"callType\":\"call\",\"from\":\"{TestItem.AddressB}\",\"gas\":\"0xef038\",\"input\":\"0x\",\"to\":\"0xab736519b5433974059da38da74b8db5376942cd\",\"value\":\"0x0\"}},\"result\":{{\"gasUsed\":\"0x0\",\"output\":\"0x\"}},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}}],\"vmTrace\":null}}],\"id\":67}}"), serialized_without_blockParameter_param.Replace("\"", "\\\"")); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs b/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs index 2398cfda693..1246c6b49cf 100644 --- a/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs +++ b/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs @@ -11,6 +11,7 @@ using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; +using Nethermind.Blockchain; using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.JsonRpc.Exceptions; @@ -271,6 +272,15 @@ private JsonRpcErrorResponse HandleInvocationException(Exception ex, string meth { InnerException: InsufficientBalanceException } => GetErrorResponse(methodName, ErrorCodes.InvalidInput, ex.InnerException.Message, ex.ToString(), request.Id, returnAction), + { InnerException: InvalidTransactionException e } => + GetErrorResponse(methodName, ErrorCodes.Default, e.Reason.ErrorDescription, null, request.Id, returnAction), + + InvalidTransactionException e => + GetErrorResponse(methodName, ErrorCodes.Default, e.Reason.ErrorDescription, null, request.Id, returnAction), + + InvalidBlockException or { InnerException: InvalidBlockException } => + GetErrorResponse(methodName, ErrorCodes.Default, ex.Message, null, request.Id, returnAction), + _ => HandleException(ex, methodName, request, returnAction) }; diff --git a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs index 74ef34c9529..fef3c326ff7 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs @@ -72,7 +72,7 @@ protected override TransactionResult BuyGas(Transaction tx, IReleaseSpec spec, I senderReservedGasPayment = UInt256.Zero; blobBaseFee = UInt256.Zero; - bool validate = !opts.HasFlag(ExecutionOptions.SkipValidation); + bool validate = ShouldValidateGas(tx, opts); UInt256 senderBalance = WorldState.GetBalance(tx.SenderAddress!); @@ -81,10 +81,10 @@ protected override TransactionResult BuyGas(Transaction tx, IReleaseSpec spec, I return TransactionResult.InsufficientSenderBalance; } - if (validate && !tx.IsDeposit()) + if (!tx.IsDeposit()) { BlockHeader header = VirtualMachine.BlockExecutionContext.Header; - if (!tx.TryCalculatePremiumPerGas(header.BaseFeePerGas, out premiumPerGas)) + if (validate && !tx.TryCalculatePremiumPerGas(header.BaseFeePerGas, out premiumPerGas)) { TraceLogInvalidTx(tx, "MINER_PREMIUM_IS_NEGATIVE"); return TransactionResult.MinerPremiumNegative; @@ -122,7 +122,7 @@ protected override TransactionResult BuyGas(Transaction tx, IReleaseSpec spec, I senderReservedGasPayment += l1Cost; // no overflow here, otherwise previous check would fail } - if (validate) + if (!senderReservedGasPayment.IsZero) WorldState.SubtractFromBalance(tx.SenderAddress!, senderReservedGasPayment, spec); return TransactionResult.Ok; diff --git a/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs b/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs index b396bfaa51e..1b86e2c2bf8 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs @@ -28,12 +28,19 @@ protected override TransactionResult ValidateStatic(Transaction tx, BlockHeader => base.ValidateStatic(tx, header, spec, tx.IsAnchorTx ? opts | ExecutionOptions.SkipValidationAndCommit : opts, in intrinsicGas); protected override TransactionResult BuyGas(Transaction tx, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, - in UInt256 effectiveGasPrice, out UInt256 premiumPerGas, out UInt256 senderReservedGasPayment, out UInt256 blobBaseFee) - => base.BuyGas(tx, spec, tracer, tx.IsAnchorTx ? opts | ExecutionOptions.SkipValidationAndCommit : opts, in effectiveGasPrice, out premiumPerGas, out senderReservedGasPayment, out blobBaseFee); + in UInt256 effectiveGasPrice, out UInt256 premiumPerGas, out UInt256 senderReservedGasPayment, + out UInt256 blobBaseFee) + { + if (tx.IsAnchorTx) + { + premiumPerGas = UInt256.Zero; + senderReservedGasPayment = UInt256.Zero; + blobBaseFee = UInt256.Zero; + return TransactionResult.Ok; + } - protected override GasConsumed Refund(Transaction tx, BlockHeader header, IReleaseSpec spec, ExecutionOptions opts, - in TransactionSubstate substate, in long unspentGas, in UInt256 gasPrice, int codeInsertRefunds, long floorGas) - => base.Refund(tx, header, spec, tx.IsAnchorTx ? opts | ExecutionOptions.SkipValidationAndCommit : opts, substate, unspentGas, gasPrice, codeInsertRefunds, floorGas); + return base.BuyGas(tx, spec, tracer, opts, in effectiveGasPrice, out premiumPerGas, out senderReservedGasPayment, out blobBaseFee); + } protected override void PayFees(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, in TransactionSubstate substate, long spentGas, in UInt256 premiumPerGas, in UInt256 blobBaseFee, int statusCode) @@ -83,4 +90,12 @@ protected override TransactionResult IncrementNonce(Transaction tx, BlockHeader return base.IncrementNonce(tx, header, spec, tracer, opts); } + + protected override void PayRefund(Transaction tx, UInt256 refundAmount, IReleaseSpec spec) + { + if (!tx.IsAnchorTx) + { + base.PayRefund(tx, refundAmount, spec); + } + } } From 096dbb36efe3073fb4f91530af58382bc6a43934 Mon Sep 17 00:00:00 2001 From: oxBoni Date: Sat, 29 Nov 2025 16:50:02 +0100 Subject: [PATCH 026/255] Remove redundant Math.Min call in SnapServer storage guard (#9828) Update SnapServer.cs --- src/Nethermind/Nethermind.State/SnapServer/SnapServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.State/SnapServer/SnapServer.cs b/src/Nethermind/Nethermind.State/SnapServer/SnapServer.cs index ecb459db54e..bc3dd8b21dc 100644 --- a/src/Nethermind/Nethermind.State/SnapServer/SnapServer.cs +++ b/src/Nethermind/Nethermind.State/SnapServer/SnapServer.cs @@ -226,7 +226,7 @@ public IOwnedReadOnlyList GetByteCodes(IReadOnlyList reque break; } - if (responseSize > 1 && (Math.Min(byteLimit, HardResponseByteLimit) - responseSize) < 10000) + if (responseSize > 1 && (byteLimit - responseSize) < 10000) { break; } From 315cce64de8e590901540154a11e684063fea967 Mon Sep 17 00:00:00 2001 From: oxBoni Date: Sat, 29 Nov 2025 16:50:31 +0100 Subject: [PATCH 027/255] Remove unnecessary pragma suppression from SortedPool events (#9830) Update SortedPool.Events.cs --- .../Nethermind.TxPool/Collections/SortedPool.Events.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Nethermind/Nethermind.TxPool/Collections/SortedPool.Events.cs b/src/Nethermind/Nethermind.TxPool/Collections/SortedPool.Events.cs index 9e6f0303765..b71516f43ae 100644 --- a/src/Nethermind/Nethermind.TxPool/Collections/SortedPool.Events.cs +++ b/src/Nethermind/Nethermind.TxPool/Collections/SortedPool.Events.cs @@ -7,10 +7,8 @@ namespace Nethermind.TxPool.Collections { public partial class SortedPool { -#pragma warning disable 67 public event EventHandler? Inserted; public event EventHandler? Removed; -#pragma warning restore 67 public class SortedPoolEventArgs(TKey key, TValue value) { From b962328a466157622d34e2dbc31f2d14494861b9 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Sat, 29 Nov 2025 14:07:23 -0300 Subject: [PATCH 028/255] Shrink ReadToEndAsync async machine (#9831) * Shrink ReadToEndAsync async machine * Update src/Nethermind/Nethermind.JsonRpc/PipeReaderExtensions.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Nethermind.JsonRpc/PipeReaderExtensions.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.JsonRpc/PipeReaderExtensions.cs b/src/Nethermind/Nethermind.JsonRpc/PipeReaderExtensions.cs index 44aaa377457..1f57e3b7611 100644 --- a/src/Nethermind/Nethermind.JsonRpc/PipeReaderExtensions.cs +++ b/src/Nethermind/Nethermind.JsonRpc/PipeReaderExtensions.cs @@ -3,6 +3,7 @@ using System.Buffers; using System.IO.Pipelines; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -15,11 +16,21 @@ public static async Task ReadToEndAsync(this PipeReader reader, Canc while (true) { ReadResult result = await reader.ReadAsync(cancellationToken).ConfigureAwait(false); - ReadOnlySequence buffer = result.Buffer; if (result.IsCompleted || result.IsCanceled) { return result; } + + // Separate method to shrink the async state machine by not including + // the ReadOnlySequence buffer in the main method + AdvanceReaderToEnd(reader, in result); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void AdvanceReaderToEnd(PipeReader reader, in ReadResult result) + { + // Extract buffer reading to a separate method to reduce async state machine size + ReadOnlySequence buffer = result.Buffer; reader.AdvanceTo(buffer.Start, buffer.End); } } From d10a4e5960f01c8f71943116b2f0f4f6047c5c2f Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Sat, 29 Nov 2025 16:57:45 -0300 Subject: [PATCH 029/255] Optimize BlockParameter parsing (#9835) --- .../Find/BlockParameter.cs | 108 +++++++++--------- 1 file changed, 56 insertions(+), 52 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs b/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs index 7d5f4735021..ced17296aaa 100644 --- a/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs +++ b/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs @@ -8,9 +8,9 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Text.Json.Serialization; - +using System.Text; using System.Text.Json; +using System.Text.Json.Serialization; using Nethermind.Core.Crypto; using Nethermind.Serialization.Json; @@ -136,11 +136,14 @@ public override void Write(Utf8JsonWriter writer, BlockParameter value, JsonSeri { return reader.TokenType switch { - JsonTokenType.String when (reader.HasValueSequence ? reader.ValueSequence.Length : reader.ValueSpan.Length) > 66 => JsonSerializer.Deserialize(reader.GetString()!, options), + JsonTokenType.String => !reader.HasValueSequence ? + reader.ValueSpan.Length <= 66 ? + ReadStringFormat(reader.ValueSpan) : + ReadStringComplex(ref reader, options) : + ReadStringFormatValueSequence(ref reader, options), JsonTokenType.StartObject => ReadObjectFormat(ref reader, typeToConvert, options), JsonTokenType.Null => BlockParameter.Latest, JsonTokenType.Number when !EthereumJsonSerializer.StrictHexFormat => new BlockParameter(reader.GetInt64()), - JsonTokenType.String => ReadStringFormat(ref reader), _ => throw new FormatException("unknown block parameter type") }; } @@ -181,28 +184,62 @@ private BlockParameter ReadObjectFormat(ref Utf8JsonReader reader, Type typeToCo }; } - private BlockParameter ReadStringFormat(ref Utf8JsonReader reader) + private static BlockParameter ReadStringFormat(ReadOnlySpan span) { - // Check for known string values first (fast path) - BlockParameter? knownValue = reader switch + int length = span.Length; + // Creates a jmp table based on length + switch (length) { - _ when reader.ValueTextEquals(ReadOnlySpan.Empty) || reader.ValueTextEquals("latest"u8) => BlockParameter.Latest, - _ when reader.ValueTextEquals("earliest"u8) => BlockParameter.Earliest, - _ when reader.ValueTextEquals("pending"u8) => BlockParameter.Pending, - _ when reader.ValueTextEquals("finalized"u8) => BlockParameter.Finalized, - _ when reader.ValueTextEquals("safe"u8) => BlockParameter.Safe, - _ => null - }; + case 0: + // Empty string => latest + return BlockParameter.Latest; + case 4: + if (Ascii.EqualsIgnoreCase(span, "safe"u8)) + return BlockParameter.Safe; + break; + case 6: + if (Ascii.EqualsIgnoreCase(span, "latest"u8)) + return BlockParameter.Latest; + break; + case 7: + if (Ascii.EqualsIgnoreCase(span, "pending"u8)) + return BlockParameter.Pending; + break; + case 8: + if (Ascii.EqualsIgnoreCase(span, "earliest"u8)) + return BlockParameter.Earliest; + break; + case 9: + if (Ascii.EqualsIgnoreCase(span, "finalized"u8)) + return BlockParameter.Finalized; + break; + } + + // Unknown tag or 0x quantity etc + return ReadStringFormatOther(span); + } - if (knownValue is not null) + [SkipLocalsInit] + private static BlockParameter ReadStringFormatValueSequence(ref Utf8JsonReader reader, JsonSerializerOptions options) + { + if (reader.ValueSequence.Length > 66) { - return knownValue; + return ReadStringComplex(ref reader, options); } Span span = stackalloc byte[66]; int hexLength = reader.CopyString(span); span = span[..hexLength]; + return ReadStringFormat(span); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static BlockParameter ReadStringComplex(ref Utf8JsonReader reader, JsonSerializerOptions options) + => JsonSerializer.Deserialize(reader.GetString()!, options)!; + + private static BlockParameter ReadStringFormatOther(ReadOnlySpan span) + { // Try hex format if (span.Length >= 2 && span.StartsWith("0x"u8)) { @@ -226,19 +263,12 @@ _ when reader.ValueTextEquals("safe"u8) => BlockParameter.Safe, return new BlockParameter(decimalValue); } - // Try case-insensitive string match - BlockParameter? result = TryMatchCaseInsensitive(span); - if (result is not null) - { - return result; - } - ThrowInvalidFormatting(); return null; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static long ParseHexNumber(Span span) + private static long ParseHexNumber(ReadOnlySpan span) { int oddMod = span.Length % 2; int length = (span.Length >> 1) + oddMod; @@ -254,35 +284,9 @@ private static long ParseHexNumber(Span span) }; } - [DoesNotReturn] - [StackTraceHidden] + [DoesNotReturn, StackTraceHidden] private static void ThrowInvalidFormatting() - { - throw new FormatException("unknown block parameter type"); - } - - private static BlockParameter? TryMatchCaseInsensitive(Span span) - { - if (span.Length > 10) return null; // Longest keyword is "finalized" (9 chars) - - Span lower = stackalloc byte[span.Length]; - for (int i = 0; i < span.Length; i++) - { - byte ch = span[i]; - lower[i] = (ch >= 'A' && ch <= 'Z') ? (byte)(ch + 32) : ch; - } - - return lower switch - { - _ when lower.SequenceEqual("latest"u8) => BlockParameter.Latest, - _ when lower.SequenceEqual("earliest"u8) => BlockParameter.Earliest, - _ when lower.SequenceEqual("pending"u8) => BlockParameter.Pending, - _ when lower.SequenceEqual("finalized"u8) => BlockParameter.Finalized, - _ when lower.SequenceEqual("safe"u8) => BlockParameter.Safe, - _ => null - }; - } - + => throw new FormatException("unknown block parameter type"); public static BlockParameter GetBlockParameter(string? value) { From fc3f0f3165b9e95dd11457f1b7ad6c0493eb8239 Mon Sep 17 00:00:00 2001 From: VolodymyrBg Date: Sat, 29 Nov 2025 22:18:51 +0200 Subject: [PATCH 030/255] fix: correct EOFCREATE error message (#9836) --- src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs b/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs index e71a41fc8b8..9953e46c9e4 100644 --- a/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs +++ b/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs @@ -1473,7 +1473,7 @@ private static bool ValidateEofCreate( if (eofContainer.Header.ContainerSections is null || initCodeSectionId >= eofContainer.Header.ContainerSections.Value.Count) { if (Logger.IsTrace) - Logger.Trace($"EOF: Eof{VERSION}, {Instruction.EOFCREATE}'s immediate must fall within the Containers' range available, i.e.: {eofContainer.Header.CodeSections.Count}"); + Logger.Trace($"EOF: Eof{VERSION}, {Instruction.EOFCREATE}'s immediate must fall within the Containers' range available, i.e.: {eofContainer.Header.ContainerSections?.Count}"); return false; } From 329517aa8184313f22c8533aad5bb784fd6e3ce1 Mon Sep 17 00:00:00 2001 From: sashass1315 Date: Sun, 30 Nov 2025 03:30:28 +0200 Subject: [PATCH 031/255] chore: remove unused ShouldSerialize hooks and fix nullable properties (#9820) * chore: remove unused ShouldSerialize hooks and fix nullable properties * remove private readonly bool _isAuRaBlock * fix build --------- Co-authored-by: Marcos Antonio Maceo <35319980+stdevMac@users.noreply.github.com> Co-authored-by: Lukasz Rozmej --- .../Nethermind.Facade/Eth/BlockForRpc.cs | 17 +++++------------ src/Nethermind/Nethermind.Optimism/CL/L2Api.cs | 2 +- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/Nethermind/Nethermind.Facade/Eth/BlockForRpc.cs b/src/Nethermind/Nethermind.Facade/Eth/BlockForRpc.cs index 6bafdd3d166..9180c47237f 100644 --- a/src/Nethermind/Nethermind.Facade/Eth/BlockForRpc.cs +++ b/src/Nethermind/Nethermind.Facade/Eth/BlockForRpc.cs @@ -18,14 +18,13 @@ namespace Nethermind.Facade.Eth; public class BlockForRpc { private static readonly BlockDecoder _blockDecoder = new(); - private readonly bool _isAuRaBlock; public BlockForRpc() { } [SkipLocalsInit] public BlockForRpc(Block block, bool includeFullTransactionData, ISpecProvider specProvider, bool skipTxs = false) { - _isAuRaBlock = block.Header.AuRaSignature is not null; + bool isAuRaBlock = block.Header.AuRaSignature is not null; Difficulty = block.Difficulty; ExtraData = block.ExtraData; GasLimit = block.GasLimit; @@ -33,7 +32,7 @@ public BlockForRpc(Block block, bool includeFullTransactionData, ISpecProvider s Hash = block.Hash; LogsBloom = block.Bloom; Miner = block.Beneficiary; - if (!_isAuRaBlock) + if (!isAuRaBlock) { MixHash = block.MixHash; Nonce = new byte[8]; @@ -106,29 +105,23 @@ public BlockForRpc(Block block, bool includeFullTransactionData, ISpecProvider s [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public Bloom LogsBloom { get; set; } public Address Miner { get; set; } - public Hash256 MixHash { get; set; } - - public bool ShouldSerializeMixHash() => !_isAuRaBlock && MixHash is not null; + public Hash256? MixHash { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public byte[] Nonce { get; set; } - - public bool ShouldSerializeNonce() => !_isAuRaBlock; + public byte[]? Nonce { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public long? Number { get; set; } public Hash256 ParentHash { get; set; } public Hash256 ReceiptsRoot { get; set; } public Hash256 Sha3Uncles { get; set; } - public byte[] Signature { get; set; } - public bool ShouldSerializeSignature() => _isAuRaBlock; + public byte[]? Signature { get; set; } public long Size { get; set; } public Hash256 StateRoot { get; set; } [JsonConverter(typeof(NullableRawLongConverter))] public long? Step { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public UInt256? TotalDifficulty { get; set; } - public bool ShouldSerializeStep() => _isAuRaBlock; public UInt256 Timestamp { get; set; } public UInt256? BaseFeePerGas { get; set; } diff --git a/src/Nethermind/Nethermind.Optimism/CL/L2Api.cs b/src/Nethermind/Nethermind.Optimism/CL/L2Api.cs index 41951eeec66..8affb3fc6d2 100644 --- a/src/Nethermind/Nethermind.Optimism/CL/L2Api.cs +++ b/src/Nethermind/Nethermind.Optimism/CL/L2Api.cs @@ -52,7 +52,7 @@ private PayloadAttributesRef PayloadAttributesFromBlockForRpc(BlockForRpc? block EIP1559Params = block.ExtraData.Length == 0 ? null : block.ExtraData[1..], GasLimit = block.GasLimit, ParentBeaconBlockRoot = block.ParentBeaconBlockRoot, - PrevRandao = block.MixHash, + PrevRandao = block.MixHash!, SuggestedFeeRecipient = block.Miner, Timestamp = block.Timestamp.ToUInt64(null), Withdrawals = block.Withdrawals?.ToArray() From 6b5b80ab49c91c68521a02203e0991f977638d3f Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Sun, 30 Nov 2025 02:34:19 +0100 Subject: [PATCH 032/255] Auto-update fast sync settings (#9840) Co-authored-by: rubo --- src/Nethermind/Nethermind.Runner/configs/base-mainnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/base-sepolia.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/chiado.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/gnosis.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/joc-testnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-mainnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/op-sepolia.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/sepolia.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-mainnet.json | 6 +++--- .../Nethermind.Runner/configs/worldchain-sepolia.json | 6 +++--- 14 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index 8e78db7b6bf..e5d9a12deee 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 38520000, - "PivotHash": "0x2917da7d4e067e563b7fc3ef3137477a24b4f59e09be3b9d6e1277b044bd326d" + "PivotNumber": 38820000, + "PivotHash": "0xd646e691ac5ea46f05d469d8adc96f654e1904ff8b889bf36379161da9dc02e9" }, "Discovery": { "DiscoveryVersion": "V5" @@ -36,4 +36,4 @@ "Optimism": { "SequencerUrl": "https://mainnet-sequencer.base.org" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index ada93cbfccc..be34c860f07 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 34030000, - "PivotHash": "0x5ee6cfb55a38c0c97a9b7dce826efd38bad5a4224b3e348d5ecfe3739c700994" + "PivotNumber": 34330000, + "PivotHash": "0x5b33d1dd55fdf3c9a6fca658dd2cf7aa9a878010bfb86e24fd90a880639f0f63" }, "Discovery": { "DiscoveryVersion": "V5" @@ -36,4 +36,4 @@ "Optimism": { "SequencerUrl": "https://sepolia-sequencer.base.org" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.json b/src/Nethermind/Nethermind.Runner/configs/chiado.json index bc8d57d9e0c..62d995d565a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.json +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.json @@ -18,8 +18,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 18890000, - "PivotHash": "0xa2bdaed82c6a81efc4f29b716ac6bd6d39308c52d68690e8be848091daafabb0", + "PivotNumber": 19000000, + "PivotHash": "0x72069a43422affcdb22db49db2e0eb898568b1e8b82c59318a9e4b8137f43476", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": 10000000000, "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.json b/src/Nethermind/Nethermind.Runner/configs/gnosis.json index cd9b4a3280e..b08ef56e8e0 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.json +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.json @@ -14,8 +14,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 43270000, - "PivotHash": "0x52b1d954c69cfcc675394247ecb51113aa7ddaa1efdba34de5ef18369786bb3c", + "PivotNumber": 43390000, + "PivotHash": "0x775967263553a1bc18f7da358e9859ffeee1df31c856da56a23b2716789b047a", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000, diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json index e761d672e00..b2a50e6313e 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 20840000, - "PivotHash": "0xc55b678aa86b32fa800d46c9862ef50c2890b4f023c4b8213cdcac43f8de0433", - "PivotTotalDifficulty": "37764460" + "PivotNumber": 20960000, + "PivotHash": "0x5989b4e69e1451575bc72c0061df585f4bfaf95e9e589132086f3b995eedde7a", + "PivotTotalDifficulty": "37942677" }, "Metrics": { "NodeName": "JOC-Mainnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json index c99f634ed1f..b028c906d13 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 14440000, - "PivotHash": "0xe62450ea0d1dec45020d590f1a906f96c334d0b304f148e465f38f5d45c4ec09", - "PivotTotalDifficulty": "24123062" + "PivotNumber": 14560000, + "PivotHash": "0x263ac3329ed5026ef50f19c8441d53b0a90749c2dc0afc7f0238efedbf8a7109", + "PivotTotalDifficulty": "24285335" }, "Metrics": { "NodeName": "JOC-Testnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json index cbbc7df4776..756fb530922 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 25910000, - "PivotHash": "0xe809fbbdc4eddd1044a0847b2207f7d6619653a3a1c7fe8c95ba03d7b0531c6e", + "PivotNumber": 26160000, + "PivotHash": "0x84f64864c83be7cc01902ca7148f505a31dd1c7329995392edfadd232bae790d", "PivotTotalDifficulty": "0", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json index 86abf95447b..012fe3ab716 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 21080000, - "PivotHash": "0x37045b9032c2cc2a4e9041ce1276580c3d38a20b9272e156918b5f8234ed59b5", + "PivotNumber": 21380000, + "PivotHash": "0x030d6393c66a0c209b0a00eb7ed02c22331466c4636d915c4d47cb25bdbaa627", "PivotTotalDifficulty": "37331807", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index 6a92c67988c..8adaa804f4c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -10,8 +10,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 23857000, - "PivotHash": "0x05aff3fbd91d0faa080e195b1870c5e7925bb551b7db6951e7c698117fc8afb3", + "PivotNumber": 23906000, + "PivotHash": "0x9b144715d2cb04ed968418c7432b131a9a6592834bc7b4fe3a8073e2ef46e9a1", "PivotTotalDifficulty": "58750003716598352816469", "FastSyncCatchUpHeightDelta": "10000000000", "AncientReceiptsBarrier": 15537394, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index 4c3d98525e4..9c852560784 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -15,8 +15,8 @@ "FastSyncCatchUpHeightDelta": "10000000000", "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, - "PivotNumber": 144120000, - "PivotHash": "0x3b727d82d92cf02e2fb04961b582f6a514c25e319260ac01b91e34f3ddcd44eb" + "PivotNumber": 144420000, + "PivotHash": "0xefbea42290af475ab67e48d84f0d7a25b7ce6a1a7f82fdc9800dd6a99c50f502" }, "Discovery": { "DiscoveryVersion": "V5" @@ -38,4 +38,4 @@ "Optimism": { "SequencerUrl": "https://mainnet-sequencer.optimism.io" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index ff92f07904d..60decde1508 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 36010000, - "PivotHash": "0x510e0bc26a218acf7959f2156cf50dd9875477dd169c19a84168e6181f8a0de2" + "PivotNumber": 36320000, + "PivotHash": "0x0ff5d1fb43adf5c47335f2378ee9dc8cc9c3c0cb5e3111d260cc5000da0c3eea" }, "Discovery": { "DiscoveryVersion": "V5" @@ -36,4 +36,4 @@ "Optimism": { "SequencerUrl": "https://sepolia-sequencer.optimism.io" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index ed2e0a1d35b..8db46fe746a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -17,8 +17,8 @@ "FastSync": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 9685000, - "PivotHash": "0x4aaa98fd5699adc0fdc6ea7bf826c118210463dfd4934da0ca2c8c5f95289e4f", + "PivotNumber": 9733000, + "PivotHash": "0x2ee122331c383d2efa6d427802a10bfb9afbbb4c913e4bb7056b56ee02d09cf7", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 1450409, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index f48d853d191..666e9ae74e2 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 22250000, - "PivotHash": "0xcccd653577d55d4fab46c8b196e6d3765bd745ae9068703593367ebdf7afceb4" + "PivotNumber": 22550000, + "PivotHash": "0x00eda4a81030e7858a2b147067e5da68e9435f79bdb9566086d069a8c49084f3" }, "Discovery": { "DiscoveryVersion": "V5" @@ -36,4 +36,4 @@ "Optimism": { "SequencerUrl": "https://worldchain-mainnet-sequencer.g.alchemy.com" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index a5dc130b7e7..b6c7d6b7a0f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 21640000, - "PivotHash": "0x7d6c13f48501b2b44180820a213dea4457f91ec8538550c3e1a131ff913b909f" + "PivotNumber": 21940000, + "PivotHash": "0x116346ef68ad36a4bf58abb5824464767616c92ed89c6997b9e4aa4d6662ec57" }, "Discovery": { "DiscoveryVersion": "V5" @@ -36,4 +36,4 @@ "Optimism": { "SequencerUrl": "https://worldchain-sepolia-sequencer.g.alchemy.com" } -} +} \ No newline at end of file From ef9debfb843a03676fd636e5f9fff83d956cf9a7 Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Sun, 30 Nov 2025 02:34:41 +0100 Subject: [PATCH 033/255] Update OP Superchain chains (#9841) Co-authored-by: emlautarom1 --- .../Chains/arena-z-mainnet.json.zst | Bin 85813 -> 86789 bytes .../Chains/arena-z-sepolia.json.zst | Bin 81863 -> 82732 bytes .../Chains/automata-mainnet.json.zst | Bin 77351 -> 78333 bytes src/Nethermind/Chains/base-mainnet.json.zst | Bin 36735 -> 36336 bytes src/Nethermind/Chains/base-sepolia.json.zst | Bin 44935 -> 44662 bytes src/Nethermind/Chains/bob-mainnet.json.zst | Bin 68712 -> 68865 bytes src/Nethermind/Chains/boba-mainnet.json.zst | Bin 1037 -> 1083 bytes src/Nethermind/Chains/boba-sepolia.json.zst | Bin 1080 -> 1068 bytes src/Nethermind/Chains/camp-sepolia.json.zst | Bin 74054 -> 74451 bytes src/Nethermind/Chains/cyber-mainnet.json.zst | Bin 72440 -> 72568 bytes src/Nethermind/Chains/cyber-sepolia.json.zst | Bin 72436 -> 72528 bytes src/Nethermind/Chains/dictionary | Bin 65536 -> 65536 bytes .../Chains/ethernity-mainnet.json.zst | Bin 70200 -> 70721 bytes .../Chains/ethernity-sepolia.json.zst | Bin 74088 -> 74522 bytes .../Chains/fraxtal-mainnet.json.zst | Bin 142635 -> 142764 bytes src/Nethermind/Chains/funki-mainnet.json.zst | Bin 77354 -> 78364 bytes src/Nethermind/Chains/funki-sepolia.json.zst | Bin 72483 -> 72562 bytes .../Chains/hashkeychain-mainnet.json.zst | Bin 80946 -> 81914 bytes src/Nethermind/Chains/ink-mainnet.json.zst | Bin 85795 -> 86760 bytes src/Nethermind/Chains/ink-sepolia.json.zst | Bin 85768 -> 86677 bytes src/Nethermind/Chains/lisk-mainnet.json.zst | Bin 68643 -> 68805 bytes src/Nethermind/Chains/lisk-sepolia.json.zst | Bin 70320 -> 70357 bytes src/Nethermind/Chains/lyra-mainnet.json.zst | Bin 36163 -> 36247 bytes src/Nethermind/Chains/metal-mainnet.json.zst | Bin 68716 -> 68868 bytes src/Nethermind/Chains/metal-sepolia.json.zst | Bin 36720 -> 36273 bytes src/Nethermind/Chains/mint-mainnet.json.zst | Bin 68709 -> 68854 bytes src/Nethermind/Chains/mode-mainnet.json.zst | Bin 36725 -> 36318 bytes src/Nethermind/Chains/mode-sepolia.json.zst | Bin 41149 -> 40768 bytes src/Nethermind/Chains/op-mainnet.json.zst | Bin 1051 -> 1197 bytes src/Nethermind/Chains/op-sepolia.json.zst | Bin 49078 -> 48555 bytes .../Chains/orderly-mainnet.json.zst | Bin 36710 -> 36291 bytes src/Nethermind/Chains/ozean-sepolia.json.zst | Bin 70241 -> 70663 bytes .../Chains/pivotal-sepolia.json.zst | Bin 74023 -> 74434 bytes .../Chains/polynomial-mainnet.json.zst | Bin 68694 -> 68843 bytes src/Nethermind/Chains/race-mainnet.json.zst | Bin 70097 -> 70602 bytes src/Nethermind/Chains/race-sepolia.json.zst | Bin 70199 -> 70647 bytes .../Chains/redstone-mainnet.json.zst | Bin 68576 -> 68728 bytes .../Chains/settlus-mainnet-mainnet.json.zst | Bin 81800 -> 82811 bytes .../Chains/settlus-sepolia-sepolia.json.zst | Bin 85733 -> 86632 bytes src/Nethermind/Chains/shape-mainnet.json.zst | Bin 68549 -> 68702 bytes src/Nethermind/Chains/shape-sepolia.json.zst | Bin 72529 -> 72605 bytes .../Chains/soneium-mainnet.json.zst | Bin 85831 -> 86803 bytes .../Chains/soneium-minato-sepolia.json.zst | Bin 77525 -> 78465 bytes src/Nethermind/Chains/sseed-mainnet.json.zst | Bin 70232 -> 70725 bytes src/Nethermind/Chains/swan-mainnet.json.zst | Bin 67435 -> 67554 bytes src/Nethermind/Chains/swell-mainnet.json.zst | Bin 81903 -> 82910 bytes src/Nethermind/Chains/tbn-mainnet.json.zst | Bin 81558 -> 82315 bytes src/Nethermind/Chains/tbn-sepolia.json.zst | Bin 74091 -> 74492 bytes .../Chains/unichain-mainnet.json.zst | Bin 115518 -> 116353 bytes .../Chains/unichain-sepolia.json.zst | Bin 100647 -> 101480 bytes .../Chains/worldchain-mainnet.json.zst | Bin 72374 -> 72631 bytes .../Chains/worldchain-sepolia.json.zst | Bin 72600 -> 72688 bytes .../Chains/xterio-eth-mainnet.json.zst | Bin 72480 -> 72607 bytes src/Nethermind/Chains/zora-mainnet.json.zst | Bin 41095 -> 40811 bytes src/Nethermind/Chains/zora-sepolia.json.zst | Bin 36763 -> 36276 bytes 55 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/Nethermind/Chains/arena-z-mainnet.json.zst b/src/Nethermind/Chains/arena-z-mainnet.json.zst index 0d8b97f79717adfbdd103ac9d75b6f81863e99a4..0de98135facb039b74e59347eab1b85b355859f4 100644 GIT binary patch delta 18784 zcmXtfV|3q5v~_ITw(Z7t8rw!=C%>5g7)@i_wr$&Jtj1}QzR!Kvz4K|$ti5NgGv|Dm zJ!r{=4ljiU=vr7mA$6kJba9y4!3p-_M5si6$UCA|o?gDhcw>pfRq*!1O{HaBi{d3S zcKM;oHn`zO_(29h^+C2k{==h?iW1vIzc~}^xf97XEx`L*PV6wPL>Q~VavTuNzd%1c^vPb};e_{Nz3HUhD4B@E*y1GX;L5GL?_t<<4&Fa%C2i}RWzPM3zvxqy_6hSbOgivL-JB{&FEA$@H#A45_955 zPvM@8cfp+=<+8fX+iQ98ed7xNUuX|+&Dx8dQ6Sfy$iriD^!1G_48KzT zTwUH;BZLl z1RUxnorWW!Yvp-s9Z!fyz*VUTG5#?jmk3*-&BgYqO(Y+@z?_Q_()vF&!~d#LvHw>+ z_P=UQ7INh@eJ2hXrJY2wW|ENpss_ZW(uM}O2SC0lp2k^}#tj1Y7z|U0tse>%K{N=S zB$1xhS#&@M9rYH_%lYO_n!D?ut$jgY8{E)O(~m-t(Juy#u1E%sTize+tQri(69VI_ zN9U~?OolFb7X(fYIWMR}f1VS`D^XUkr$w3qHz?l^4&_lum@xMt!MS0P+YjDhioPmv z1tg1w{*mP#8e)fu72v0B27wEi1cIRgQRYws{dg8PRc!TcQlXO=Ah82-I7FmdaK^%* z2g*?BUi%IHhnH88-F;uN79?hGGvpu^c{N9*yLZhYu_ID6Bp6XVMH>@u)Ok9X=n}aO zGHWr&0Wf@%AQL9E!ZXo)ndjh*E?A@t03Q`}4~B0}2!e%!LUVwGBh!HxNDN{U4S_{r zK-&reBP!45%Lju%h)N7nB!jR3$61HcfP`?~2R{Ud4rMAgfk1_WB4Q(hpa_P#1cO20 z0t>>gMi9co;Ik2h8iydV0RwvkyC(~Q4hzCZCYTpe2MvKi;UE$zaX_*Sf`y<0w*4l- z>G+63a2R;`;9z`-k{pJUg&E=zECL&tIUG_VX(b2pIu!Ick^6XQc9bk2Dqi1co?l`M zc>E@!(5MuN`@uSm{cvO!U|2%sCiG;ObfUM_V31tS|4nwapS}*K#nc}R1Ge9!0P;9Dm8REhi4L_&5 z|0gmO90>6I{}QM_fC5VZ76ge0*Do(hrvq0Fg=45B_HJ)c#NAL7^paoNl$^hYa4&nCksFG0rGXN1F+j#>?+Q~HO zlL#hEBMBv88Tp}Mc1UjHL?5LG72CjBPMN^4$4JG6#1AwIz6_=$ySrwXKi4SHP^icl zr3`lsHnMR<e|cZPEtDYN;r4!-F!EdJqxQ4IchpS zUOk~BA!&hRN!nA0ioX%dIbRzB;>Ncab5+tnaUmRtk-brU2O=}f&(Br| z-Z2?9c9CalZlfcZGegQDSXC4tIzp&Z3GC4Lw8#!j<*IN911=TUUDFl~C(KfMW8!$i zU>feB@EPCyX}pc}!%OyGMb;RVSX!n>_y`A#)RgK!skq^5(G6^3xgE@Tupth^*$I&) z%g2+559`bMA>pY^=((CxF`G*&b(o{~I(~n`e2>3-3klo8uqEY}=t9zEnjk`_IwSn! zEuhtXtaQZ~MdnO5mXGc`?P?_n6K!jP%s`zezJ*CG1dL@2B>TjO!Ln!0>>r=by9>xX z8R!nJ=$xKDGK|x5gZ2+nC@QgzQI+1ol?IWq#f8oKq&bg86;l&+V+)VdYPM=5-Wl~Y z^V%-_uZqvMc3vuS;MJQ7(g?LcC^bYo__GR0K+A)=xPX3dnYE}BQY35g{I(=E(|rMAcO}7EzH9yo_FMvtLuEdd$e(eePf(Fv)D=OFowvbSO^P+$7Tv0ALmm#Q%z_&H|C|f z4iRbFJNQMaV&Bv%JvFGTANfvXe{-8c$5pTc10!zWbtMs{%PQ)~Q|d~<;xdMF;z9>9 zw8tYvL-^YDmqvnj1wFmHZ~KG#QWq$Mk9BFK^C-16v0B-V{Aho1_7 zS1EZ{p|KqS+(C^{662M$nV%rH4}&MCi!4NoghYWjG+>|2 z735M2Dh-ZZ-xRf<%nC890m<-<$a>*g78vLuSb`J=Yx}q8dBxaS90(mzt)cQ5A+o&j zAYV$u>_5-HT)9rhWsl39h_E-3cH51Bw(}BiN~Wf3PkXh5)9g9pw@NGtw#LoxI33tr zMRAjewib*8L(E80qfMC$zwkTh(`b^Crfn%?e~l4zRuKBfB}B7X2=zR@%x}u__{XUy zrzXlIb%XFU0IBws-;KVHRgv#Mg0ZpPUXHyG;zw>xi=Jx zELB|m@IFdfS4dS;Q&5+iz~gy$I^JR~1o2It>C;!lG)7uSMB|lKFy4Q9*1Jcei6a%X zSR0a;Vqr=6CZvD{+qLcPxLBtERi*1V*@K2Lj|3k@>4+CbMWbhAH0F3*<$|Nys2varhmlf+ybV}`QtVul z8OIz*m=tK7O=N20JDG|`6I~T)P^L*R3G7Bu?BB)Mr3*LsZ&N!QFJTIV3Lm?cGt$p> z+rL#KV}FQgBq|XZ!ZnrW>&wr63cOA;;*9eC5|QVahU1i;W}yeL*-cFGbt-Tne9xpu zQ}Xog--z3^(pFJu8RFb^EB2`*u<&GcUCJdjV+oST+hUL`jV2A5RjPOQ*o|~+gmcJ3~ z^jsx~Q7hd3R`mleqm}Ty%1TR`k4DR5c6-?0zJA9k#V*nzCIhyqF)4GLD9c>RC~DX< zj#AjZyr2y{mCM!HcpiEj>Z5N4q{^PdzH)P#RVrB2iR#e9`urFqETOjaA(`WLI#j6* z7XIr;Y}$ff{)5U!a?8siUZCi#;q-MQuWp@XP}J_Y#wlQzBPuVz6I_%x$7i%L_D|%E zjAM=TROdLuA}yMUk~glxEQ-S`av+cKz&#F|M_J6mDUejJI&bg)0i6-Pr` zasrFb%`Gq>Raygk*BNvsNb%IOf$weJJIPowIjw1<&}SziZz(|_U);Wqk04VmNj?SV zHiM^mH4IQrWRD09#$izo(Mqr|8FMhWwA^`Eiry59^VqnQ&@-7h!;)a9d{JKz-Lv64q!}GgN)$N8{y?nb)l;0kc(>tt#LR7w8(#x){9BcElnpN*Bfl9;ad9~0*;5pV_{o3z>Ls7Szfpr4 zJ6r6u*pli~i55Am#yKw1gwLkR|6@LkE=el>AxEs?q~BxJM_6s7)APH5elDx>FH@#>(^_#-*;Ezu6*pJYD>EET0ke}@ z)jDYsKAA}zfOyS{j7;9U`*^+>cL+o3AM{`DQ&Gga;&JVv@*NbipVCs?H#Es=XYbMz zDw?@X45%`ibc_i&X|Z1oO&k#n2M89^2b)_vnpCfq249Jm7-AAiF1Wect*_e{m|L*; z#@c%k;vS{ppm0{!(#$N9>ck{0;Jm!!GCN$8K%o@dbn%S-g0A2)RZXs3`s4t<0|8$f zF*l4A(ojzQy+VY}xKd0z5>MR|R;^A@R=PQvUkShGC$F$&HMwM>i~MQ1;(6tT2luuQ zY(tC#5(?qT;rvC2{6|POi!mN`Bbs5)*zNhjDp4?q+aj?Y6cr3omnmrg){Wt{r2Vdk zf0|uT5-5y1Q~9HQPk=2S{-MM@n30AS2L=WKMg|j#8AL{gg%mj)a-X3=!773U1{2`U z6e7Tt7-^=)hKD3g4hJcQ6hejs2?o~Bh9)PLUtwbcwtMx1w0}<+l(%>WKiDDi(#@%= zMPgBupOp*R*b}c(j}0LQK>miQN4dy6+u%s9ldZ%r4qpTR(z9mHSlyaEkYzi{ixx= z#&mtCXBo>%`Nyy{3g4<6#=`>Tz88f&BQ^c4p+P&0M#UT7J1F1>Tp94eQ%KrVeT@U2 zoYUu5&19#cP-j|>o?>dx$6-v+eeCX};EHe(6C+4`B3f_)q%4A{%zcu?YsH9|)aHys zhrIvJDg0GRBKU%vgXbgmN7`XuWqF?%DRDXQ(Hf<6mK`NJViDq?=5jkpaLh_) zbT?uWf*|aA|D*m7;M&>UuSuG0+=FO$JfThmfH^at{i$=QK|H@;Ju;lQA42w5` zY!Bruz|N?jwg}IU%KWkm+h+sIS}AcTLc`SfLZ@{(zeT=UX_+t;UV)>Eq`G1)589&k`||V;G(D(7p&-#& ztUSkasw;K@pBhZiO9AM#y-VB!61$GNw0{Rqsn>pYTiXG(x*@eZu=Tp`A(9`OfYa`*4qz_A%92EX2*TJ zI($6gvv$|`ZHT%9x}pf;?xE>{wcDTlSL&3O0=Cp zKXq6VLLQ%~w;5VJ5pXsqoiyQH8teeY_u3RppmGJ^`FwI70i-3=In-M&Yk8F9cFB4- zNdEQIqXVp=8`|(JA)TL5o6*C6zbr||o}i9{=}qWmk*KO5jUckgZ0+0(&XOVY*8G0r z+U^Uuj2u}1@hT!XgI|^Pa#sblyxL_SM=pyxyA9n zpM6(@S#>{BhG*a#Eys)}9{%IGRP_L}{8A$KjLo=5e~mucq5q(@KdJxM4zw&Hn?KpY z&Su);<-5z-L)WwAbt{D*8DoQF|Ct|YzrX;5_m~s*BAb$WNl01~rdDH2AV-(Ff3e9W zk)eT8A7PD@zSmzm3pX~MD)p_nxJ-Q40DF(~x8G!Hb*&3CdJCQ-ah zp3lD;h@32A2k;m|-YMQ%AOCkMI7-%oEAU0=FZd7S0#p`1!YNLE9;$Z4B=^J5`bxqI zOek&boiSC>?FvR!f(G2~%A>gS34H+3woRNjIGI_w$yP2#j$$d}2el^e>4bU+Du=91 z);2h&n{w!K1`O~8{1=FDxAgz)e8t4tbr>o~%05t`t zZN<)ypN4Y`bMnI|&AZg65CnXv2^ZQ=QZ&C!7T(5W*cQQ=C6nN<^O-gO+y6@osBsY9 zJfZkz4%IYOMcePyL^2809&*+XyuroOvuFRZ?qN@m)*H==CxF`9BFY34M;aUGnm>CD z4}d&c_f1e1C=JY4M^UQdlZYkQrd}qRp0JG;okYUhsrCGu(-p0GXwMj`ZTim%+HR)J zf-;k*(Bd%y#v@f_;T(<=aI9dh{DL?b@H89?1WUuQ&hR9{TDScqMtOmsbbstE*&z9g zv6jB*5`cT%j&Ve@@O!GDA|3f(h|_fY2fA5aK}2MhiX?v7=nd>pYg!48ud_#;6NaLD zAE!E++ZJnVR@U)%%@3+D@(A9K)B8V=k>n}34G+{)=`$m=zN@bHfERxW{8}1Pt9Z;o zF@)gjt6bAn8pX8}zW#jzGNAi3k8-rgC0Ml4u17|Zo1<*TeHB2M`|k@b{8jSF)yHxF zgP7cB#&kL6+E)rNzg-CH6zr#M+#9S@Zl7%{Y+z3(CjCe@_F{|d7fcB5fnpr;-eHET z6Wt@$3D(VFDh@9M>hwbcJ*FQM`Br91u;235TZHlj;VnNqNbrlu6-ezr$h%)ZB(7H* zff0TguQ?~p#JG=mpNqLJDc#OQv7RcaFj^{U%HzqZJ#il^LJt>{2kb^Cn8ydkVS6PZ zuSu|5`#~R#{yh@U8H>QfUIC!1JM(7K=p)?+qB?31ECvG*{6ZymWCzy`Y;9b#O9~vP z3+*c*medD(ryYKGZ&sc-cT(6)X*utJ#+`6vw5Z<;|BkEAwk^2k4%4irzR_ZsT^Y`{DKH1|$=h~p zrm#n2&W{TKwzpFZqLHq%#BD_t!E~JP4V?LmB$lF6dy{rp({X|F2Wv$3^fwmu% zp&%t??7#lu1ExQ|=Dwqm<^LNO`;ls$!Po|#f# zLwD#CEI-Bq+69g_{?IFkr^bt`4x`R+Y$qc9Nf@UEeuNNAO!PP(6fxD?;Acpu>21Yp z)JOS!eyeH$1s)jpy+C4Qk#%2Yjt`nU8p=02gJzc7dgM&u&-d|twEcJ8EX%*l z5xO!iz^61gs)+9_`9}j>j*IWPZgX*fYwHHgdFtn1SSwp+?1Cw7BoQz3H;)PY%I3vL zNbC%120Fwv%7Jr}!|Ju|LphLflA(mqf)A&?rjVD04Yyq*Z8!s~w*lJF=+d6mr}D2s zr?q%}pHnYl3MkDPI|sXnFFuWbV^kWiNQ2S@fFXu={vXP3Q4}%JK>{(;bv9Gh8d&73 z#}mA_vEq2~4V-(u{eFPH;VJ`x>0jmU|}$O4~V@4*xQ^ zf&Z9$c7hc7$!rDf<$%>UablQ+ykq8g>EIhZv^{Mcva2UskAoV+hKT$*ZbL0E*8yCz= z+2cr7X=;0SlhkDgke?AEkg~cg((;DJ09MCTzg3uyL(%2a-1yi2&ps8FaXxJ1bZR;ufdMrAA?Vr3 zx(J4`+N8+buJNDZOO%jtPULM_z!L(|<>c9Cf(_y^Yhqt`;ZsTX;E9L@Mv6FFn3lDE zhT(d=?|=@0z4SIw*XnAs?JKt3izJSeSr}(golm%wXFv6)Vm(bPbM|*Lx^c;XqAdxQ z$;&(!mG8guDdvHi1Pu%kqzFW8D0{DC(*^6b(h|5H1bYi+CGw?uk;d93;C?tS61*LS zx*a*5&kV?Mo?Q=->iSaW_t(3@1$`7<6&z&OI**IF*(0~6;?I*_z+O(1{I(8oLO@XY z99ebGf<5Gl!$yrF>84rl>saCYy;9H|L-lF3#|1IqX@kdGY{Y;ut#Gwk0G(VZQ~sda z`A%~)j3ITnCfjBLmuwU{w@zUr|%n-FsPVKbYHZzpqW0-xJOjj4r3hi-z(2jVD+2NGqqxQ;Fpp&d@+&6X zjpP$4Q$2F|AqV}n??oi3a+M+8jFFT22F0D^wr~0&^3B@Vt}H#kwa2STuz8siYy@ij zWxp8Kd>S^!3hU>umMZca^)5{Y*~|Lbxf8fCsGG=&P>G_p&d^p4OfHiCF%tWu1P7ge zUkimVtC1D1tC%_=;8x6OiNQPvqIrGo-)am5d=RY1#z4kBt-%zB-4qRNsTzHL%vM5A z|Gf9V{w=UC+0`8axS@EsDxf328^*XDF}J&zNUyAbzQ@|4tOHlmP;IF6Atattl&D;mc|SK)#njR?cUyZvOobVem?Xd zq)yHIsq*RU@@n0;z0YtKM!%qRTP+)ch#;oL_v%`wyAkg1+fORmyeQCNOb`R_6gi6J z$wJZH3s>W%jEkL;f5&ebvu0vu6JF|ru5}QPn0NhH$5I zz#u+S#wweBHB4LoTTSe1{das0m2T6$%@z?A_vFUr{Q*V2xtYBdt_?r2PZXDq*AtN< z$KdIA;Ub6z`D7|W>@>r}2Yt#LrYqH|sEpI!KQ0@{DS07pjD*sL9g;{%v(XnqRct%M-Xv-bJd3z7UUPQiNF{;}KKNGMUcT}Lx}S=BdvMLi3J*XCrcey^ z&P{T-O5V*W=)5?~4rJe=BI%E}#+P=8F15*6}-uQgiKc-rSb zQR)Fe#7&o4^kQ9N<(vqDd_tBBD)A`B>!Bg)e8CBy?!Be9f1nAv!kX_nwbiQepB)X; zQRH2a5vW@lwA^|7kJ4Wjh9p01EL6U0HSQ#&$}jxqHkd~3epnWGD~SjU#|i}Mbyx2sup!g6XYj4#I({ma0LzZ#~_ z1yc~WbW_Z^FVhgU;5u<_Ip^1OxfcFA#0vIloRs5C)pI9gnrsIeJ3gRU00_UDWiP zwpMoZ+f>KD4$(TE<(`(Sq%WV&RR=Oo2=3;c^}YIOg_T^M2c~G{0W;yly{b+-TWT=p zi|+(=R~xT7btc(;y8$AQw&y}{d}E~$z*u~fSBwsb$0SiwhVT6yDC;!?sZ8Yf4}D~p zRS}>*yhq%t-fDB(3_)03NTLHOG8hiCb7c_A&ds0%_OIz|dFmbmx+_>)@*tF#VC(Ae zGQiW)E}QE(Uz`}u*<8zK`-zK>d6Oc`W!Ve#f-OBG_}wmCm^4!H>UPsE!xFriSiVr~ z7wYH|AF(~FsSs%F)G>RA)+p+Q%Bo%>$$!u&WK$`VG#mk=e{Es5gfR2J zQCa@+U^Df|Qv6z;kvZAWQ*#J%+)$|9^t5ml>#o`^_Iqet1W$x=-$5!1*E5?CdBXT8 z_|y1-*gV%Rq^agc9pH5@l&_?u*MqtugivSxeluT}si{CM5m(MF_(`DKz+_>L4J` zY~B4+g8k8TyqCVreI0e6<#(%3o%!XGh7L1Xc6O8i!g^5OUoalP zB>E=pZVKcjqIigx_{Tk{<)1>3ki@i)n4CM1s1E% zOjMnIq>C1X$4b8u4!*k|l803_swx@^?BMH?M!vVc%s<$82(3Y!I#RFZ{C+r77E<47 z6C{_JR<;WfHCEaP`n{utH5r7HWTx*nLDho z6Kpy&e;SagY5TszVY$}Oxq&{o=Ndcl_<*kM?0up$vOt^uDseoq+(6c1|vQhn-(tFXn`0kZMw^8T#;q4gC7WL^=O_n-#R*SWDcf= zlu9Sd7k&k-ID7mZ3GDLNzok$0-STb2N;u>F+ZfQUTEt0!s0qlTjrxJ(DG`fTQj8a{ z<%3fa_r6(Hw#V3I#Z&Gbqcd^NMl91~2z(=-=4sR;bOYaMe13>ZbCX_#%x0u}LA60g z8ToB|?d>OGylaW16JPKZ&;Ow}Lfe18AxU~$z(N4T_(wsKUS;Oj@T9JnwC{TxpcB*_ zB3C^8-l7dfi`DfmBxW*#_S6>VUQ)(vAAHaPP=`{nQ)JpmJKbf{m}zpr?LB(V1*| zn9~3WBP_R|pR{D953x{(id@fykG7`1vUx&*;VX}n_->EnE5Z9Cf6YTRHF>C5qY?G3 z>2XjmnM1CVG+SPmho+wjlG+Y6xoJM{&Ear+u zEi07#B-6|+_Sfv)VBZC*pnh%7E}xZk&=jCA=4EpRj&L@%xnZZT{owjS=u09xEcO%z zFW>16T)Fq*(M3`GRfE_`BGF$oo3Dg*gA3Mq6Lp@sh)TbEr3cz&xpHFLh2hGM3bzJs zH!2>ribF`jPvUAVJzi#EmjdTNgRbl{ZeZcDWI`2i_#K+3|Jn>;7|JtRhSOWD$*r~= zdywV7%4>SW&0KAd;qxs280R+mh5|RZ>Nf);vK`lazWwFG=5|n-Li@@z^FOKWcBaaC z1X~3@DA?sfeED@d^=+Cv5&wbx(;EU#s)nzS^J!NmXaeyyh5LkM1voV>F&`tA2x(n@ z9xTw@zM=RRb|T@1asJ?b`8FFjlYQ1qVMNCswIhNf9E%f}-1V>~g! zp|6Mz$p&|Nmo)u5y@dt`lw5;P{0!s2QUtVM)Hrn00|X}R1^!icX-h5@l%_6tQRT6^StVebZv4-k-G??Q&NJA_is) zw9h24i|)1DcXEl^wur`B1oPPO1DOO_T-)VNWa|`5&jo2Z_tV_crB)&1 z5r=q=WQ3$N0EHW3(*rwVFgfe(DEA#DS@wfiiKHo~S+O*@JqZhu1jfxhv+oY#url{l z)wU+{hu#cQwPD5PNX2kknxunDo;~M{(&F;Zd408S;Ur9L489_OHM&ASz02NJET@G~ zs^4yCp|qGm&@vLg9o8o!i*KGw?=S484QI)4t&&Q8qj|~DrQy~cmmKJm%e<;2UtFUu z2>EJ{?IoVQ79(Wc#4WSe-&5DBZpFk$bb-ez6NpfELMO_nMx*D*ei2{MxxZ@N3Ad2K z?W$)p86x{OTW!aI`(BtYhVhU0-=bk?ZGM34>`sC778EU(zsk2F&NEB$JF|s&{+wc! zBt^hrFX!c9sjee#eq&B;0cOF7ATfgrCg_dmX~y9E(BZL^FPG4H$Tgz{mGY`Zil?s@ zaG=%!&Bfd6qvY?8p^a&#e?pktl>7O6Q=Sn&z@nzsPGDpGMOICDxr&yhuEQ zdRI2$Bm6)Jo?DSXV@m~L_&l#G1AF0$B$^c z{GZS_=783$u1cm&^VX_%?(M8z-sQwhJXqIPgPG2*(h7Tobcx$g$GWP|w@^_Z2vM40 zIJw$EjleETxZKn{TM~dsPp8E{1P6j$Q`IxdCNH1zbLQ#}h-Y_a*mNi^1WxDw1 zz9LZ9F98z2YdeFM<;9@PC5+36ZxSzC=}P(oz?xb-=-&pf)ejtjY^Ah38%mDr@)Otp zeVL84@H$K^qtBeqi$c<`lG6yxw0mQv#<{rki9X|AH;DbjGQu1$W*Wvd=uL4mQux&W zP$hN@Q8y!JmSX4o3*XB7{o8-GAw7WKB?u50iYRoM_WkP(qPa{h>cF(2c~{rtau5a2 zLbkJk#wUV37OVKjg*g9v2;QJ$tsAN%PJ{ zva@xeil^7}z7>gKB&U99MNca>JZJmOGa2sD#fkH>JCWzzWt%ZgB#xHs*J?Q5adK@# zoyke0e_>k3LyVLx;9fpTbb90dgal&If9$z4i4R5d9LRIn2YvBW?%po)#jH=Oa3WI< zy}&7v5Eh|s25O;4_!C3G6?u{VOIuhr-N{p9fKkqD$v&<}PU;CYR$ah1Z(ik^`^KoF zRLe5JyY$C19vdyO0ujQFRsnz5a&Jy7 zL2_o`i+|zPA)@5$u*W+UiEvG+@~WDwELr7}cyI8MAcavRa7LA`Q_EQ`bhpuB9apFL zZeq#xTHujte#J}Gf#g1dV9%2$;TEYz9WzP+)!GGNsm%=I>TvT20x*1G{~ z+dki=M?t)^nKKf|E)=$BL;xnv>8R@Yc=#vN_h?kq@FI#oXU4^2+t#S(_}?r0DE@xS zyyI$fH#C+BQ|JNF zF;IP2g$9~Uu>|Bo8O+vbowhfxId#Z>=lt(t+o!oqk&qWZY|cV`sS_{)Tk;}v>X~GV zyb@5@z3q*pGfLl)X7ws9MjO(g!3FfSf6TSQ`cnn|3d(8v$y7!KNThSW_k_8Jul=L@ z)`3Ko?eOEaFoWU5#k%ec{RMU;qs#Ijh6^P+wdI-8DkogwP2PrqGQ7pKFrm3Sv#tFV1!lU2Mj-^(E=L-EGvb{pDtIs*ZlUdQ6bmyZ^r4yBnR zYpIL%J`A%8=ssV*f%_Mfmox1XLCc*-zlFgJl{YFx?Tco}LMbH|);noz9UI2cuF(ex zk9F@&YbLa!YlvKo8bTG;Y7Tf3$c2-~^fi9PwfpTWpi&h`gDK`lqLZEXoQJJlhaZG> zK|U0OaU(vl5d-`cPA6qG5>pK-i^4hZ^t4w*gDxj;KWbnF=GXtN)kUc;ui1N6DZ;po zSnkxr{Ij>X5{7hab#M8KHMMupqx$cS5tnZ5rt$UYMPpYq^4&Z?Kiv5eb3tJvOs*L= z(jf%0^E}=pj}8^fwB{X_tE&z%c8abqPm8?tSmk2Izc!$sS5GGC{J!gEE?|9L+h&;2 zq;Ts!Sh--LwPXgz;zOrK6^09t$d3^D8Ef^x{?LFF5xRyt=l+T0-E9`6cIteD^t{)g9G^lzY9sC<> znGe~-^^y-;pZS4R;cLD%EX%@yRaIlHZ!&}z?Rcw?FnhhNqdXxQ)VD5)XhMc|g$qkm zi`=@AXA@6&*C3HB8X`eozyz;rJl~!Vj75allq3VJBSIsGC1R%0BKqVIc|LWQ(QO0s7A#a4_$!H51ZZ%LlR@2U>2>nmw^BfrGbGiYZ=;jR_7 z6#EUZ9SOch24YdhBBRL6uNp{YqSGgdhT%B7cZow>QGBml(@r60-qeWVs(2szat(hp zuxbH$Y*Ta8TinfnS};ERmY;%R(nIET0j+R@xEn3_81A()k!HbeNKH|?Z+gcQ3u zgA;$E+U20%Le#wF&{irX*j2S!@7=|}f{z0@dbK(rMgB)wbyaO!-`vD;;nCI~GV>gv zpJ}D*TEDs%qse9ajgGj<%0GEmxL9jmWRoGi0in0{Ax8Y#s##4cq!vU|4duoI2mwCbjW zcGNIenX+4Z#c?w`;g-3yj$BRhjJakQw)AA8j54?CZkc7Tc-ZTJc5;3z;xy^&^F$0? zIT6|mwCg*VJI3-eu2oyIcU?SM=>Z@^2RDbvhN|mTXEvv{nM|hN4u-nOu^T(K*|siS z>!S_CR@$w)Qv=(T*DK9<)-E%fIOf`AfG89$(yakCG-#xN)HXmgJQlI__ZsG6G126yX^DtIISVIc-U(pm(El3<( zshEY0#+7(}_|HnX4@rdS&=)n`ueIWxPB+I4P~{MCysi))9_Hn76z=o;F|ryP=*_Aa z^W}FB{1j+93NxzRM9rJj^#Ho9apH%S=`A^DzC}z2buIB|&~2vd(8a4|IbJCj6^+i@ z$A0zQzi&kfI`!`p)|>g~k6zJ}d$5;--sTwElecF!qDlXe!#%~Sd4Wmica&sSpZDiylp4?yiC%H z`GWzAcD!-v$9S7L%1p_2y4j7gt##G#F}o5|UWu;6vQ3fz)2O0@0~-Vl z$KQt4-lk1^Zxu~>!*f_TmBHM^I}e^IUyl*$gb}N(Ez_&A#+xF(%N_ihTk4hfo8i?b zinR8py@14pom5q_CII3C5v&OgQ%*)hQu2R3ZD~IhL`5fJMxoKMfzZR~1SAq1ocpaQ zcJaxz9E#)Z!|~c<DbLuTG-LYE60yr&>1Dk%^=u?vRv-5I3(%7?aINO()Ip= zz|mn8>4L+?VmvWK$2iK$e`fFq!ZD&kVes{03xxvL_CqLEI2Jlbu7g9 zdWk{;@AmciNYnxtgI{jonRl=k@@Fv&XbPJkC5I#rg8F1vF*?Cu zb1LKvS4^&AkX4ZQF){m6B(#~<3gto&-LHQ35SVNZY_g5QV6|t1b_{AXGL7c=uo=8R zHCML2R0MdI02<%ue2{uCg!(x>@fsd)&#^dU$U0)GgM^tLZl{D7^fRv;`#%5Oo} z?YF{RUJG@_bMLN6X$v_OW62*VNZ2bFuQ$@Mh z{`Tug1kEo#AINa8&Nj=)w zr;ESE13%`mJYHJmrnKw=6<&#+>s3)fj}hRk#<|zO7obcq^7)&_`A1%f>Px`KDCorH zhh`(#5S{s&-3d+iQ~JWMmb>)S$j6P6gfE&Umx*v}4s{pC%lMh*hvC>|th}j7-x8d# z2#)U6$mNsl&YKbi=`(Z%>!8o!&|+{g`~s}k_vuFdS|soL|&UuWif_?aGx zAmj|NX~aXTWbvtP6bP`onVNdLTB(Lr2UQ2>#j+_Wq}Gk%$R<9Y5qEIfLL+CUJ$iz2 z0KM)7I+fBHh74k9Gjofe6~$mINo}}vR9u9L)PMPhOR2|GCQLDkDaqk~ikr2idrQTU zpr!6*o_u=>1B(PcJuTlMjXd)A5)*}$L^dIyG8SE1p?I!Fp!U`oTLc)2Ldhm;LU$wF znbPcRl(#L}G9i%?jbMtA@rQ7V>lvG^0lut0Ltfs<-nVf)^VC?6l08C<`R# zDf!?F8Z0GIGE2&RADFLMC3uZZcD3@XNFUg)&s`dC75oNV7}iuQGbqIV7hbY`8)@bV;=v->y5FxRIM;>CrG3cBKsE`= zPD2P-0kl`UP87IjWD-P0aD)U-xedH2_PFaAVeaMABakaBM2zl~4;)fuR`S zIwYfGeV6bmBY6$3qys0ne*Nh$1yhZzV$!ZTL|4FN8y2Wj$p39hxWxw@sh-t3mBsSi zqP99NVshF^{hK(QJN4GkIA&-eQ2xDGj{zM&i6fcH7AYAXEzA@TZio#f6b>Vd6r&%^ zG@ecjt_Y1I3{4yk9Zdp`oZ`R6ML|J-F@PxbW*DE6rk}*|JDFhkof@Ku8tA1`%-Pte z!?h@5epY_U)r9Pau7|1(Bx|a_ggGs{P6a=U~8h_5@o^Ug(6#X{XU}J}beihs^n{5pI;QFE9TR9^Pi;QAO zE(CoO21_zZmF?)v9BCgcRIMeP3LoFxKPr1h@Ty+3@f=Fm$9`f|I0t~oLetobcT_(TW%u!iGPYk((`0>X!`jp3)=ZsycK25aAS#%ijcp<%gRxMhYtDp( zKw%b?Rj?I&pkxQy`+X^w&*A-}+MN{eT~aZC#uW!EHt2HyaWY_a)*lcaa;c> zKx!A6gQ4gvrLut{+Uh>?f={A`S0Ev0SqN!SgWp1e09QHmOmykYVc)qOUmjoR&u%iul(s+brIVJ4c(s#&id?RPk{cQj>%Z9 zK}TXK91|&kAv=S>uJ5>4Q9a{hQ=zmPBK}7D;my^;3{OZ>c<*p!d(?!1xpvZ{R$?Ay zttI{kev8swX_h&%9aDfeBR$pI*3Q_tgP-Z2s-0)A`B18~-CxB&v65?@xSZuSHMGR+ zl{x`N%i(e|$eWo3)1q8711!|0pJQmIIOL(NHV#*3GB5}q*KgvulcAi$G)oXqFG9eF z=r`mvNd_%xAr_?>{K5>YcH{((kf4Wd7st7LQs@(?6TngA{{;jI`}RMmbVY1ohhJtH zHlTmPBU7OeedXw%K)tXv2zli${k z92GUI1fg% zTumwQf16UDzYHNPLIp1r&)(T1jSZwkf|;U}2sD&-+M&Sho5SAdPleF&HnWxubOm(_ z%Py_JEmP_CpYSW>{tRHKTHWTK5@D(wIiY5j|ptc_?c%BmF zTVWJB37Q@i{k!)!VYhe|>_b%BHzHHCFo_7m=-lHG;Sd|A)9@7TBPmc~bKa85dP@kb z9_D+E;2u~$m}b`9IE_a9{B#@(+@uWX?N|(L&gjQW2o$YAm=E@k!6YF#AKygm9dR9J zf1_h6c<5%`H8(j3zzIME{F5;ECP(&77GbhdjP_6q+9z$`;(AP0yl72cg(My22nz9( zf6^6Lalcsep`TdznC@NSelRWut^C>{AFw@3ks#J|aB{ve^;;7=lGB*@4Z$(Tf%gxi zMs}+Xt`J=U!BFPAJxh@W{U&Xj0LUCke+PSpC^*jgTj0C)Zq8~k2FG>s>zT&TyGyb^ zE6pT7tSZ)pGKpQw;!1 z;@^1n_!YC8-xOeJVl3H`r$;{@G=6SaBpE_CqeGdvYJiCcE8HDT5%Wm2T1=lCdLGMu(`+7sQvXcvWvI^-IL4P-W?&8W)kgIu;ABD}(an zsP(CS!V~x#nHE$9CLXipD* z@0?(iA;>s8d5+97c#AwP^Q`6i^!XY5>b$hOYDX|@ls}ASs64F)HKqsECPL*BnFPYY zq7WIT`c$bwQ16_PmM03>AJ8d8(|0sr(qrbo$~--i?obrdBH#$-e*$6&1mjU%BLYC6 zY`uxF*no^seQtfCT`W*c1_GZkC2-ErPwC5%Nrn+-)x!=R8BdEN`{5BV;z@vt(TGSQ zAjKa7Wul(hm=e@|l;c^VhJ8nFtllng2&kr@PmGfwD~lNxx-=b(dW@90D8~%p{}(L^ADiY2O9UG#y+rNA86T! zH|@jCeW-aK*su>Y?!#O6;nqIXv=40C2O9U`EyRJl2G&=6f36Qb+y_qgq0>I_XdgJ+ zhac|4hkZx~M1jb`Duk`WWEcPw3l>#XRaI40RaHbpL_|bIfkCO7DE^!VC%>B>>d6KF zlb^J41QS`41SXg(Kbx7!&7^YX(845iNi3Eelr)x<#7nA5q=bZ(M3+P^Gy(}n24@6m zMC_6xauI;^f2c5VngdY?7A`*x^K4$O3WgoD8ShWxSK1BAxwGTu4u-^w|A5QyVy!K)K!Ep@f{bS#NU&>XQ z_W`~Sn|;vsp=clc_o3N`+dhc);eQ{PeQ4W0Bu9zre?#vx1iqlOkD;78>j@M8uCobO zTvD}*spL1z#3X&)&P021aUe-h@?2CVl37Vx+05AuZmko^BLPp-E8ry~RrC1Gbd)v8 z?}F!i$J3N*YRfPUo+Wsl8Ka%u^-`rT7j-NXe=bZ2vRbl1-f!X>P|V8nqvU1Kb^)xrbCq?MKWf?_$5>$#|xd+;x7U1b^i7j-%{|j9l{F)k1(Iks1Gh_mk(fBtDZD&61mxnO^zjSF+LS|+@-offBTPadGDm0m{A(M;lpQLZI&nJdC@Up zG>~7xpimaSAmAk`e>ndN3WMH03ek>e;;BvnCM+`WEr{|`>6F;|7+-b?6T$nR*&?CM zm8STFNhu}X7hPdTgVV5{?#&9pN^Vu5`35MALxETdRAnpD_IZa=e*zU!O1#B#F^~i53O=#P8&n2#tG?d>;M+a**73YOEZVdQUrBj6Ye4XJz9FhqFih@jpuOW>J ziBhJXlfsuZ;!_E^*3NK74O5==r910j?E|Oo z>=G~TM8g=tvQm+@d+PiJ_GRawn@K zcOSv(>9AE&xtEy2&x-LP&U@k;QKUn`@r<65o^xwaw_|mA+XM{b%^9)VvzO!tU9%3%8G|dz_EF2TY_Q(9lVJ` z42jXighEKRk1cUnISiwS3gr%O9~2&)`Iqfm?h0<1dEX$PCcD&SLL z;-oS)W}}QLLD85MmZC}z@ZR3=8E^J?OE?7jeW;Oi)|NyB+-F}izSQQw5c)qb{~t*F z4}Sj-BwFK00{HK$#()p>CSiFBytMa+n9QPczjH7=?BQ@oPtj&0cw2+vQ69t1#Rxb5 z+okaLe-$nNjUW6s?HKJ)F~x1wmnUlm1}O&W?+-!DCHSy5|qkf#ydXphV~n z5)i12KgY8xM@>z=E#)rajN7nlC5sd$_zMzYDcqLV{5yZ$gr8ZIk*0n!5W+OUDkRhx z>X(b7?I|i0Y8u+VJ*0SKCd5l(magZ%8AeP%Oo!voCI~n6-X`8JNQALzayiO{~iUgGE{i6R5`Ike}ID@6csKp?1)A- zk^PAMnf;M1e#46$DIU*{z24`m44;6tH(T|1{V7S|2-ra~ z?rP9lUem#4ThRV}Ds}O);H?`|f357x4Ig18jmyu?it*IsYe++tq+wYD`FT9oH;$We z!MSpAuF=HG`rX)#H;TP3zI9BjD`}}f?Y;YW*%gR%#6y>T2KH(ZtVcBY!=8l?-*Pb zSLD3ms;p`vY~n4a8UH|u9)BN-9l>c-GN!S@Q#@9=tq&|e^KQPLT+-2FiKiRA>If=OxA4_{_Tw*T<(b>J!Z0|tg&xNcS87N4NgW*4Q=!AVq@cTLrP;qhsn|yU6j6m) z9@D(c0FaU41}GaC#d8DE7z)B>_AClYRMg@u@a)GYbI#lng%wc4mU{93KC`0lr7%R( zfUm`2G*HEV=ESzs9aWOQaFdOnugv4lyiZ$`gEmqph7^{Y8 zb@3cLFCA&qOO%7*O-L8sNo>CJ#L&>+a$hX$dXZ+=dlD1a!H^gw zdBB8$0}cuVPHBwv0n?vCg3FoQ&V|6 zh|ybAEr$~hABGA2w<4oPS6Yai`5Y-%{Ud6vaGk6$whVtczL1n>p|Db!o27$vS1pIy z8G{jcRLL!tj~P`#moYDS6wc~s`IY)o4jWP+q-0XmusSxcuw4R>Hj!-rvSJkRuFT18 z|Fe$rwh1HIJge>v4Tz=)gF3KDz`UnQxq%lher(udTX{|`Fbpv@B{ux)?j-pVB0Vi& zY;nCLJvdU3UmTk{bFs3a(yUh{gI-&0mvqT0Mdd=%;XGVNY3S2|g7q_gCQZIKCihuB zpAk@2&)yS~#u>K1`1Vi)%*lr_X2bu4ek)K}-o53=^onMtv9hGGBpDLV{S!psLQAo% zB*iPDqXLPuDW@Vp&sJKTABDv1d@MPMJCdfm>FFoN#kVEm@ifG7!7+q&On+S zm6Jnn_1*zk$r6%HZMRKHwIm+b>qB=Po{_~RukN{P?8OxHCmo!hx4`Qdm!+~KGJ>99 z<`U)+C093Nm2Gl*%_jD&=1bK-3@kDuB_>ftV`bx1V{>^xNahiEFplWoWb-5rsf_=y zNlm95sl%d4BGNtP)*PKNbSUi-o8&z?niq&kF({2cv5kwwG8h@$bMhH+%}!brC18&* zig&e*wMxwQ2Mi&U27Ze{t&hx)GRC6fR@4M4JWfSn7s?&Srl5;PVKi120YveYJNgE? z@kxIP<#MV4lT=`aHVF~XZVa>#^C=r})lg)FNm%wxM&%|Bf6|40w;Ahwpe?~?{w}$F34}iRH@!!W|399UlQX#A*h|I3n$BM5` zwDN=Tj$+{s6kPnjRfcdP+~sfrM5BnY&1M77U2PD7TR*+;RMTs*YRd?tr#v)I_DCYP zBhb1>>28$^I>GFn1OCxK#ShU%=tZKz92L#jRq+e!^q3LFa2~3iNTmSO(y0cjIzfB^i z>(_;WW>I1jCbFhkl;X^7ikz?_2mXKvbYWr8bQF^ccpUNJp}s~^8lVk|R)Bz^4YKjp zc$lLvdOiY1z~3%4jAGcv7zPbt91{nIU5fC=Jt*5?k;9Bbf%zFh9R*C z)zsF*EE*VwatOhVd8**UpuC+bUFB>>S7>ISXc#;aNds}sr>x8vAXAmxnma(c-M3iQ zELC+vl6xeX8ACY)qFEBET)34i^w*$R0_P$*FAdMYDP>Q&%X9=uB0Y|k23mNl-z#&3 ztw&Q~jB(OQMiT%13J!|tV+ie2o?}MwFrjqPogzd8v(~6c1r^yi^Sku495?QSJH0Wm z460haeAM-fwRuT;o;l}HbkeCn%$Pm@wr9TclR#RdWJSMh57TywACPaW_4a1Dv17l7 z*NWWyA1FQ-M_Fch7$kgV4gB{n$8p?Azxl}+=}Ega0e z5yAVpEb($W2QMrED4c{AC5*i@ExH3Hk@I!S?B}_=Q_+#Z&=qKkH!7AK$_n>T0|0WU zPwC?OY18m<8xd7ZPipQ`mYR+7GzXJ26D?|{^$Ly3W+@RZv3Y{#PxJGo{Mo``iqm0!kw*!OLhQ&F|)`$LP!iRRu6aCXOkb zcI&!^WA9eymg) zht(|`E{3J7Nr8c)12-6c8UzRe@=Fjg5zP;T3K>3ZNO(R@u}EG39R$kLp3ak>5lPC( zkP{sdf(af>2tE)5egFhyfDu_zsjS?>0A%OZj%ezKKdo2!3~r!3=i1qEvz^z`;GNA! z;nFTL{!Bs%S-dBE+Ckr^-G;CrDs|d{$TRxc+j`{9L$~V>>57HEq%;t;oJz`u{a!1} zwUeFH2<=#b@$qRyz5|{S0@i=3i@AUuijG%Lm{3}Y;IAw`>nj8TRQ!dz5=$Lt{;)}x znF7VO`5uRQyB`VxP{}aoAjet6a`5tc7qF2O7&>*2e{fx+*I;M{lIjWL`E^5{G4xJo43K^7B8Is$8B-m)16;+ z{>o^33ph}bc@xYPwK>+)qE^b}An!#H<6A1uNwpMFcbr9mgCR1O>M|rG&e&!|0GlOC zkMeE)>_i>f^)>Cgn`VBz8$kwif?}vicMU%_y^eRa!pctvwAjF>ATy@8q zoFaUa=PzjRSOxH`=A}E-_G!L!4~{wB+In>>!2&TLA&<@cbrf?;;Dr4_?;5$dk+dyx z==0iB(-+sNrLGlGbDJUw{t0rUViC=K&bac_G0VDu>jI&DEBUCZ?x7%c(Oxq*Eb6yz zZELa@0{no}4g4SI?Brfm(KI!)T*7s5bw0ZS%m$m^WbZ&h1I66254Q{VP>MfPYqNj#0HBo7KtNpH@rZ{d$rdjdcQs&*i+}fPq$B3bcOZ|kt0o76MED+ zev^}yE!93S5S*u`ua36zRXE=Sr{AWpX5}>JAheRa#lcrS;NInmIT~OcS&Heu5f>Qb zlQUm+G!%e)@2M>NbJib3H8eDp*z^|~^s~5^Uhqr=Y{>Y>dwHUP)kebXO_|2I6^Vj& zUOd~Ce55)qMzG`tRc){AHWe?}9{~}z$*%%QJ`5l#q7G;&HP8P(xo!mvGzV&71B8rL zrQrxVJJJJ7!Sxa>Kjm)|uJVVuZyO;T>b-pQl`wz}Zb-ApZ_rjdo~@uxfCT7(1j_0e zdV_^NGm9H%>9!rMVLKu@6kRe(XQG<@wZlp$Cil|^rj_$7z6s=ZvM0qy3Z$E6Lo%bo z4M3zu>1+-a`M&7fi4&7%C9AEnN__<&YM_IUX!s?Oi9JD_MBj;Ip-44!n{RCQH*3my zni7!mF8hgIr=UZ2EF?ei3BZzI6<hBvSI66MWl+x>v>I6Ds@{!b9 zIm$HGD~Hj*yE$62RYgD#$;RpLVq}yy9ufY|dAI<6HojmtG7`&~g(+h@Q^S_lN;XU2 zr;sn?lH9uiZ*sG7=bcLznSOsTyVK{;BMFQ@jH$7hUPbo%{j}jzB~imPXD{p@UWp2wz5S+Q zviM)D=5FHC4x-=Ci0FfTOFK&2c`-8hzbel8;K19@_ew@+bmbx8aWpT2qXaT%HNk-v zlikjyrJ1haD~ygVZ(Jr+jMRm_X78gSlO(}J)-GQ2JQD*C+_eq%B>>ZFuKd{^)b%BZ z5pM9}Sl?2bALqcMEM3_o`6S17Y1aFKqgD;(XOnBouc~7g3?Jjvb*^we(!o^+_AQE& z!7d8E3Z|jYgPdtFc&N~+kdQqP0Yji+2kE889BS-)LYR$sm%AdZFvh{&ODguu=hmmp zGPvuk`1FXKe|5A}R9*=16`Hk9_+mD=;pGWEm0`)x;h93mWYOl^@Hc%WHUNIp(C@+l zI+ak=Y$wU3RnNb52l!{T#$PqNn@$oCIZqaPXcJV(!P>`lO(T?=i=#CK1On%-{M-^X z${TAaU4g^NYOCO*Z{m3Yg`4%;0fO2zP#3QL-&MqOq^=K7%v??veU=mW%e#S;hE3vu z`DC}hhHthFri3zUPlJjSF16K??#uG+KYp^pR*&!FmSrCjIc&`!$X>UGp#3Kn3A?|d zQtF!vFBxAmZsiB+2QHwBcY$l14BH|KqlbuVo4&?FI9(!36-5mQ8CgGrXN+h0x&Mwl7Yl}+r%MP7=^5Y9GpT7u0+u~s$)OK7s zm%hFHGH5}Jj`-qrp)QrSNC2|rd7xKUnGogXxMvy4P0FpM7dPhVFESHBdVTz3uCS1x4 z&wzAxLoz8bCpo4Xz$+xtyJk!)KwV0E&Creum^Pw|v|Tl>5mE zP7wD{d&(^_ni@Q^8IWkr6D1fDO;LNyX`6KIQytYsqnnU}zn4Jk5--%Lv%L6(?ojrP z%$6K`JK;mehH8hp%whI@1u1fG?1)l=uuOejyjVcX0(?Xw ze%h=Tnk`Gr43_?slOEog%}*Aq%&~o@;37*(!YFS~t7|dwc3I9BYJ)w5jHbgH5!M~| zuN>Zn-_sT-c@=Idsl7IqEym^;<(($D<_tddKxcF>0r|Vs)!UPlBS~evV`zrA%#6I5 zV2N*6^ax~}2r@vm1qZs1tec^gipIr?e$|SgufZ{XkWGzm=82y}&KRz(y;WG#E?R`a zY|gtyzPew+5Cd}Ks<&5132n*Gz~FaU+hx+0^GuSteZy+qgwk|6kZ!HN0{tAYf7R7T z@M}@G0`reSqL!-W3KM$B9R7C94MDiR;H>tVfe5|meYg2hv3*-tWAb0BWbc*Ac|TuZ z?#d5zq*V|_TS888!IDzya5%!wIgrTbdj~!RT_j(#xl_o94u~+j)!oycmjJ3See*z6 zKyn-F?g(f5nhJSy3equx!>+>Rv!{&o75bQofGgumtyuW_L|9qy@I>1O$FNJ&(Qmm7 z-rzJgrV&*xg96ydi=s22t%uBLbcs+_n5%`oO7QSyJbswQzu%(h zHrVUNPeQJ*L5D@w)l#Qv>NZs( zR-Rr!-#AkQeT)r02a;0zIlu*iPNedV)0iUmeyhZHuCbW$0fs7{B1u}`J?hpL@z_49 z^3wY>*o3mnPjA-6$6d!I9Pj#x>q9jPi_;z>~tJHTv=8b{F!VGQ50P%SncQ6=p)|6(MQdnp{cBWnPr#~_ zRLvSqi?`yb_;3J$h}n~NgsP%B1zcA<$~A9xYoHBBSU%bO(ezhr+~(|WAn1bK-R|xg zORXQKkEhg)1!x*~z28q?*;Ontdd7FUd~;Q@s^5#xZlsCFJ(vXEb^iWZ?~=kVZw*lV zT#7su?YwAI_XuPpizr44Y`H_5T(zO@C9}DWX!|!nfvgOnz!bG%bh5NOn0T1SrlGS( zo}LnE|CTw1o&riYY_T>Ou%|cT+kuv_&({>Mr1$iv0OI}nI^-?41CbALArA`K#41wp zSMJxjj-Qi>G3?o(AfhVac^Ucx`)6yLFu-siomA;&an-u_pqo8MmiG=%H80Xx0KnUq z2&WHnW+!<^WOjr$#WzX*lN=X8R!eA@QCx=t&^mAE^*PJ*Z^oqr&i0?k3cpJjOd4sv za`8&fVlDft(s+EwcrM^pVKVrsK+zUR5O9@T>6Lm_$NuyIwwN6iA$c;4?Fe!|X(3|4fa-1gw z$j_{gvRW;^D8fEs2K-;PPu+J?%PPO4pdx>2e*#w881ok_YKt9|i4UFiIs0XJ&Yr~D z?bP+5e`R z4cJh%gE&;UeAqW9Zj@!qi_SgnkR^#qo^WT~Hm=0bA4)OI`+a=Tru|x(Nom2Hk?O5G zJX(roFqW)%eQ)z%rnXE7^5a;Z#-#XMZXjLy2_41w5nMVCO_}HjUyl(kgi!>Ju7YBh z>AJ$SkOZB96bRN*O@t{vor-nTlM##mLQ6W~_g<$)XyIN@pcXutkra=@80^TBPEK~1 zb{E}8`6nozFFn*L#J{{G8b?bKdLlz&J9}c@q7j-@kcr1*jRM5^lqwIhDlpQ*zrG(2 zMSlO0)nE=EXqUM1lBMN>?L5Q&MR4&59o+3eXqDd$#226tNEg8MmB<2OUYtmTj>|*+ z#++x;QUHojQmcmdNsi^i+33Gux<$0SOZR7nMmB|=vU^9m(Lw@H82-8i%|T4zO@fmq zxj3>==Z%T*OFtsr^7Kcfx!AC!#3Qc2W=E@i_J}VEeEZbRkj#tr_u{zH8vQa6PWHRW zoDaeTP7&-FYF42<%T^MFC*E?IK>s%WDa^~UGh?x9N6W@(Tp0NAB}d|gXb!ZTL#4oe zO0_ZL0Sl}!Zag7X%)rMFSWZQvKU76~Ci{MiEjBO&p9Tp2OJb>tD{Uyv_a&PdGtYBJ zaPDp34%U5x{Cy1b05`Cd?F*-&J^YEUs&ktR+>{`X*%f--+`hr>#>!_f@25Ft?cwGO zBo26i_J;{)ymwK0lpee|6}O{U%l_OQ%uBXY+xcWLDN`X89;!4nW+7?2glKSWu0q%ja#`1Jzx`D{v~q4UtWnwOi|$VdOpSyznxw; zoCcn-0bpAY7M%`{sOSVtaK!SAF;K+K?!yOAxCCE;(Acy4n*HvM-sKkH)q)w`gV}U z+j$+tQ+ySuce16*#%4FkVL3~#R&oz{St&BuJXh8diY)SBx%%Hd2Ssk z{S7~MzjW|wgja4N)xN^MDJFh^rplzR4m}L0Zi((7`dxH2O3%U5nqj67T_g0qz>-BZX1G_p5#_+@j^( zg4YEx-guM^6FX#rKyJ2ZANd&6bvscheHom8(}aoC-$SdU-Bf@P__AMkozZkrQTvav zWrGGenRt7>0`X8HoVs#BfAmsTw_$%e2(*H!m?vU7;j=`(W(SH`*zLj z#o0=Ih-h2Vcx@JQ%zJS(tl0tl%0L}K=>r# zPD&X-DK{lBpf~@hNEhjH3h;ZIqJK-U>KuaO6rNT7VlYAG4%F-+2d}q7AdhqHxn5Lr z>C&kAmz`!Q}s1n;oN z)}@>XcgPux_c$z_o6udkF$OOl9h)BM$j^H;dux#m2g!JP_!0~05XoX@Or9rXhi5&S ze3B%IdmOV?@~0`n7&Y_HjJh>{7DwZ|LC&1d&bJ=l7B}PrW^FXAmoo6AQqkk43$NoW zjJrX8F`l6A^n3a?+gfw$?3d*8)3F5KAja&3FIEL;nT*m4)I@di1!$2`T5(w}Y@tS$ z2}OV+9@nmrLDo=O_z2~%(HmU-If;S2C(Sn>!syCsInpUOG z6n2ph=W@~ZyJ4tbR5OSr9t*b+B;xE}e`wsiLMGVTk8^VH2;sq;LrpTWOsp1ZC84Tl zu;3doQFrO7@vZlrtpT$?zM-6PCQxjonZ zhVvmFbs-mwNl*ID2hwAPq>qBxq|XYmRjV4iCq`|u`OOK&lnHt~1!JNde%|Rnt4#MUGCducyrtx8$%8Be9VEuO zFaF{LE@Hw82}A>h~?xg#c0GLjxg>7+~<-dg+Zse`XHm`qcff!QzRh=C#(vF zSK!k|MeXh8V4$Gky}GU~^lOg0k7T{TARP62(2JqA%yZXnAH(h7Tbaa5(}7{zw?PhHWt)skfT-i3n~8 z6w~=L_sQONn%^5StAyx{`T~bstm@zHYyPSa+OU_nqEvt-+b;=w3fbc;MO(oRYa!Iv z|LUn1AShIvZP(Xch*w=n<-uE;@LXn=gk_oOfbC@V&%4O)u1+P;z;*-96Nk#Q#J$WL z?2j&HaM#8P?hy1oNC@QT5M>xam2OTguoz6uo5r`pIKJD7-(U%>=UvH@4kV>3?aajN zZNShj&?KI&SV>r)KHR7{X|%ARBU9@e`}{~h=ONt9X#;djLP6RDP1uCiLbt^&HMNXI z&)g(J`&{KnD+CrHzv8}31|Kpdo@x5npJA>G_#Fleki$1Ofzae|c{!YdrccTQGD$Ly z+lMIT9{(L4jAIVnIj+_#yO)EZw$w0!5ch=s*EA=rkAOC2Q`TqrdoiOTNgCG+>dEZs zC!GowvKY6G4FX?E%0^ikPCD}%Q({UL-;6p&;jPmWrN}j=KqAc#R7qS6|GWXx+0KSI zuO58CyYu;W4zNzo4g*lH`u2DL0@G7_i-^S)ETybW!UR1O!v>PQD9!)$1SBM(k^571 zsPWM{)@MA$m^LXZDA}6AVHGhxVG|8xi9uU0@>eG}p~C-!J+v9vQ{JEk?58%ljTL6_ z3{crlb`zLALr7?YP5~c{P6+|V-8%Zk7AQCoA;MNIDi58oK<8!sC@65?IFjy?dMt^W zeN>mV(^tJ5TsZF<2v<9$rpU=V{(k1L^yE&ieM9N`oQ0e5h&x?M5ih z>OL!ndTTje0)>Hr9`W_bX`n?S0u@O=af9QD+ zgT&0+N%8d{?{{`YQkelD?Ui>R!(=(W4s;LkyqW{I99SYor%T)9U(!~$^=Om(%#@W^ z0qT&)I|_Hp^n63v#w}%6h6$+DJ$w(m@_x24w(;J8r3E6+9qredzH}wWzyau!OjlT7 z*7u5~;Z;>v4|fsJPaQ}1S6OzI_$_xtc`;jlbljYuqA|qvUs(rW3`2#QV_XF@WL`f{ zblj~d#d@H8s@N<;>pYX{L%tzu)55nxO$db^@7LlNAt0af@VnAx)Av#YCQ7eoy-2pb ztMdKvIpHbv`e=+qSyzN?=(`Bl)Ro#b$SI-ix;n18R&hyUz+eW{dy)AGM`9NR#sof(#I=eCuMBlj<;BUh>K46TZz6JF{vtjk(o2#W*I4Hc`jsbO*GJ| zf?MQhdVk8k`dMn=mxM`BK-TywBNptA>*xgYXNB4SY+EcbCR#GKo%z z*C9_!auo#@9StUXT)sZ#fYE7k=^9f`U|BC**v{j z3;T6o9$gwZdxdQ@d<^p&)w-_y{yM-~d|6v@yCzm&&U9VBrZrL}`R37e791<}c;r0&-kz8{3nrUy*b83BbG`IhfWh?Oq zh+FAUPs+KSke;onbD`l9@zRiTwF9xnSS5lCmzSn;a$xi0lK{}njE4Sw(~M7pi1+cZYdwF14WnS>{8?7V zH{1g3^1rWDqc*fJOw??2`}~Nk>r+kI=J2EjW3X5lp<|E)&Wa-S+q&hvn(TnH^TTCFXCEElJwV`&n(3V0^ItO*~{9*Bk?g^_fOj*DJ zzO#4sh-{q6j@(k~Z=iR_dzg{|Z)uX%=k2pXwFh-_HZ_BHhk3C1)b(XSut=u$#@>lzh?&D;(W@tr>M%TYya9OK~5g$e5aW%N>x{ve0(GzK9(f)-7dQ|X`InJ z&tq(H4fle^iUKo7uRC1Fv)X9!sJMVZa2#}QEKm#{%n0ca4+w6}0LO30h{!|$*}xHX zGeRp9U;4rnQK0mMC>U&tBWoaU`wOJ$nH#Fse$n+&a5=)i>iCTxVw#q!T9u!CFE1ew zC#>-Vx7cQ61Sg7Pab3|xg1$x>rpCBewkNoiTg$hnRlgc7h=_>Vhci)yvQD6z-d=gj z>Tcp;w**F1O(Di_1twg>%)=gle(RN0C-^4w6=M%|wqq^K$Ql)AZbmul`~#)cWX$Gz z5CM~cdo#SQUD>9hJretCg~y0^8edZt)Px_2d;=#u{&nmMKT*{x*acf(h`uwZ315&I ziG4(Z!0&+wd%$JADl*Li1cI^>V_eD zY8bVPcQV{ZGW41^z;Cx(E564*&cx%bUX=Tl&pG+EEB=tDY^zs+L&wZ@B;e^a2&7FW zsv(`b+KoR3hSbUdVSs1{93WL<-LX{4?G3VILDY(IS(8sUCDp z58qrZdT#!a6jz6LiLk z=~FpXo@};c+L!BpL)v4DZ46l^JFJ*fH6=RLjecU-hk^LSb?O?Rqmu_ua(@j?lu|}s3lsA=~CfD~DLfUh5 z=^Bw_+O3pR8>cC?^axrxwtVOeGv(+<*%CXJxLsS5e7Fl9ZH>6JZOqc0(w2{&n}e>{ z53p4nAAl28=58`ulX14K?MF6^FcMKG3@Lwer8kdJ2VFC#>FRTIInDG^o2JcD=ATor zcb=|{!oTRwa1-0B{xfc?V{0Mq*$!sY#)xZGcA$8rwUXl54P9l6d~(%{Wis1XjiI@> z_-|vnaoWCFiiTY$;F@2gt$CWxJaQV}kk_qw3Fw>BAeM?Xa`o3X+~xAP?5!=Sn!P#d ziosNJwcJbQ(i~=0_L$kGxxIMBq0?|{6m?yXWwPBCHMOB;o4z%-PJN9|m-#x|6$uC>e}y^dr3j3M&rU~itLZc&r1 z7BWiy>$3U#qt6QT>H~JiGhat|GJfR%v+47v5qOPyFTLQpsgTxnTTYY2F^?#gu7EjJ z^W?+_Se`^;ieYH5B_Vu-=RuK1=PhaFjY)n~9Zakr@Ft)3-9O+Y9+vsuj;FEihG~rU zQ1ZPamuQ7NDxF8d07MKBB@)XgNFBhGNUA7!Txc2wWh(827)Im^FT4G&d%(ZDe5R?n z0I!Q=A=1*}5aD38hMVhC_*;j>VxY%1V`EfRQXvoF_dgUp;#jVIk0`8_gP8LMFZ>jE zx@ki5D?-|O5_mc|5HKk;DG7k6sE9}ly|7|;nUTn07&9aydQcdXTIgvqG2Lx?n44Ne zb^MY;FcWl$pA@b%M8R-`Za_4GPzw#SM;BRCy=fFxNGjXG(|?X2Hil*WEYkhY;`ad^aTDT0II!$x1v*n)#96>%= zP=VjkV)Q0Qj!ke+r!e0f*t2pbrex65`>tr zI{B&W4y9|CRRMv=f-h-qk)b3-H~ANnbC6kpCT>X8kd(D8B1ve!XO2}eEY)KMHgJ4swwyi)*wF|E(2|JM{esX6GX0wJ}@SUwr~~eZo_WgyNO;M;BFxPC>$g zEl>K%+h0sNoHU?|kbM{z_E6rSCDR9xgakMjyhi4GcIzqiDrNh2GJpB26WB^(-xbme z`cc!H%NPvm$=*hHD_0gWb3+$wai9K`991q4IUdplLKeo81akF(oS6!4#4*_j!FCFJ zg*0*r@OZsWUUs9@XXNfwI>eSJDV48BNsfTDR-u>K3eSUsE3<>;(4r7 zge!61^WJ@C&HVvQ+{CiUlx@)W;<-vC*yH1Y@}uuVJ@Fp%vi_lFbTR{O zmo9`W9s?qoI$ChJv=qm+MiNg64_?(NUcP5NxhnzsoF8y*$J^#FH0^*Dap23Vs(}%HeD`Eh^J(2Su|U3*zDm&I_KxaD&2s zi9?Du7y}1QPhZ!{b<_=J`1-tOUAQlK;wH4owReW4itD%oEm<M8u{<5nQ^S^k8lTlD#lkqEqb;`YMvWIqXG)hqi2am zFV=qR9*Mc1@Op_0;bNL;lX<>)@p(igNHRj+-z3gFAyk7Ij?U z2p7j=^lnB=4jMnQi{}u|2L~L`mvaB_I|xCvA~V5`mN9mk=Ou%Sq-fl1$RH&lqOA!=NNq1X} zz1z<1oRpa+3aRy*j1jw9g1sCwHN2(ZNT5zNpI`x_TLq3zJovjNqmN- zt1A1Zo=O~hu-+#yhTc@qrVy2(ah^WW5BlJ)G6|&+7iv7y$F8v7Wvup8b{3_OS2rJL zi7Y&u$wxFM3tQy1(oq37GM!Mc&6ce?xM`1lYn01Sn3L;WD2oPR zzLgRYh5OU#t7eKhRq!WBqC{BhF}YR&q4H#?wgKZ(VQvlx7Ho7WhKjz^<(#Q+899+@ zBIs`XM@t?N!C2&&slLc$}zw+9Q(=x=y zG&F5ZIGalm`F_HqC%lEwaQ%Tnnf>IC`ljTQx*0qg&pk=FzZ1J;2L|7;PR3s!oi>I&~&eYugS80Qj`5)RL0JfK(YX;%zP&J8;YF#aswK;z#nlQ z0Q6py8SG4-I;-4>k(_6*$n`8hbh%>d{u*ylKYHuqO5pC2J8M(fP+0zh<=|&v2HCNLK2?7CBlxb(?c$Vyg&UjEJr3pa1i{PxMwQt9NFvK~c6r zEg~k6%zPloj$1_A5&e=XJxg&k;F&ks3oRi6r8})^j0=yOSB}&_1p5zS2s9+<{{3=y zz~Q^kfoMo99P?C1Wu4~{tHrP^QA5@R4xa!=FvKX=D;a3kU1iB68JAq29TlWgR=42_ zL!2j1o3JxXTKyDOD_yLHxV`Evrn{s&IP@4$4uk3d*=|aifaosqSdjkIu7BY9@h2A> z49fj2UP{6E$TO@Ys2Mr4C`x= zatsMq4?q9cjHGgN*ZlS58_exK0uYiIvZ;VBsJB$;5kHTK3^#fd+rm>{{;tfA&-VZ* z#v~_lhKd*%8&a)TzCnB#HiDFdoFjN@Cc215feR+PHQ4_UTktOF1|cE8G)Dn-Ci*Mu zI(vbVC#p{#j1r>Kf@VDwS(Ybm1Ofim+3(PyMD`0dX#*@-a{$aRG5qvokrEy(au&QX zg>Pkl+qoREDWA|1g6dRq$Sn^Zva25WaT<@AS5qArUSj%E-;~>}O+J}EG98nbj&B3{ zy$mPrG9_VI)>y#93LRWq&?eF^%zSGB%d<}@4qFaBgO@{ABK<2ZNV2&8b0z>X{P@?v z_FQqb-7m`sG!bITHZb{HNXT2pG*6CyedLsPxIS|r6S;;DS;BY13qlwADMtlB1^Be1 z`m{)<5!XVvwW&{M3_$H4;nmc1gaTf+c{%M`-aRbhQ;3w_Tb%`IpTLy&jA58C+1?Rk z&*4$?qt5>;-Om4+U;sFdZ#L%2X5@Oj+NPKxxnJpFHtoqA%Q=zz$dw$Evu0?{Cq2Uw zD$JGiaugxvK{KH|X4T_pl1w=sqzBvMsHfNK`4gUBzyHDK_4>XQKAH^&BgfaxU#l3N zJd?THI$**!bW44C?@Nw+1lCeE@_QVxK_Hq{pWfMTi44t?xjL&)C#$4bCV^$5j@7sm zX>YkT#r@#d84X32;b6I&8uXVWPFWxm)u?;TH?cXe4KvT?OOz6*>3rcxP$^*Q7IF!r z?-p@QRchYfGT#M5(it2W=+NJMh^0osTo#p^j4T}rZJw;R#lgs{a<``vxn*k#WF&?Z z0hZ2FGH~<78DzHQT*As)(~bM`8MMhZ%g1WMA+-juSaAgH_jEegA#Rd&kFUCjd~$E3 za+#8MkwdAQu-9U9j>Be~DA$K}y~Eu?Ro|Sd1Cikui*%*x<0y8vIRWM$U?=WWJEPI~ zs$#SD?iRf*!MFNbX<+ty{bY)w{IyoW=7}nC&#q8=otu~~ig~8|2f+(Z>+%H$&&1e? z4{mP-y}J`Pz2oO8^@H7N@A(?8EJaVXD{P*y-8apLSVC_5LcCK?s`#hDJkv=IE ztu%fvbT2nfAPUX#6?g>65cbQHe!CaQ9MzicpO06K3MS5;akE1^^X~{Z;ODGhHXZtBDd~S`` zA#}A}$_l6I%VNm3&>RA7M`I#%G$eFUY$ z{fk5oF%$R@aAdq3PWo#*h3-UCo9oxatyOyzN*_;{VDtqR{&*Mw_G*ltkB@;K%e6ZH zTIKa8JxZ{elb+q7zzL8TFUvnwcQ|X+VjCFlT_H9#x^=9RE;8h1^h&=mabeAu3?!d9Y`E<`yD#oOaS@sp-w2_&+(CL2k zYpi{Cd|HHYb6qsoppNOK7qctAvsrk*t30-axMq*h-Wz;08tY&%o-^B@cVCkjcbAq$ zW*fu+52G6QjDPskTn!fa{03pU6+G&EWnl?afM0CqoQmfiTD{=o8fz$$6oB}?1(5wI$4uT`^R(1g9h zL5~RamQ@(0kLfz%fW}z7YR9c?xB6o=O_}j2;4%f zqvY;+$nQNI?C_f8wV{dqhE}n&)2jQ|GN6QQr^a;)XHF)h5ikm`9)Uu4#EeH5DimnM z33iCAJ4Cl6QpBN6URB-`{dJlCVx68Nb$wAZi+FyiZZAr@uN0bNIlS&1yi5wC)|kA= zLn7U)X+$AELRj>7D+MoSGRwK!W=Eff&t&fAg>u8djF4WOge=ZW0tU@S1zdkQ`9={zsQv}m=UsQre5$hxsMQ^pd z{enXUh3nMVZYo+cJ`)5L!k~1IwAfH7Hc=j+3Bw)NfZ)xWXMc-$oxsqo@Im~YbE99j zsCj)YBeG|3fz7vzwdyg;+7+cee_wo9UZu)0G7CvOrKAp!X{(GwX8Bv1trLZ0wSXkA zIv^K)s2GSbtlvRXIM?zuHnNIm_4~{*aaxrYn^|5MYBFhA6}TK#Ikjxnt!i5=5(-tN z$VdB-{6C2QA4LBT!v6=s{{vfM(copuTy(EyKs@ol1?p@hAERk_{l`!fi6RDzn3msx zb^;_UHc7R>ef5}22pqCTo~Oo9!~f)J|C5*hPtEZE)tUE4vaoG(WB5-E4N#9VO|cY? zLKH3_kVinMd`v>XP)z-xEXQC7ROyrl``?OHO^^V9RvG8!a!Tiai4!0uf8~LA!VN(n z(Z!hlg6ZXhKn@6lqpU&UoLLp@34;fUA@v7=2MgtU^v~ zE5wbP{SsweH_hz>?l3}Li6XOh=DMRcg>06yrYBNIu!GC&@54Hy#_qbOBV^)C@9r-P z1N{V;3c-u$Z{LPXRy>AR_anJbGzS5JKtXY6F%e<0^RgWlV5nq)Z>BF4Xm6nfGAo1f zLCxTq>$6(<0V&%MrK?Zipd+Ed!22R%F|p!d4Fa=_a9|-ILBO>FgF?t+!9kCKka_Oq zgET+|0JA9xI|%`U!i2{M$Ps~<0%NR!p#dpC%=Li|fx2J@I)eG z>PzwiB?WAHv|>)-ZvcbRcq07;LmWzkj0O@R%KvYIvcMTaz}^<%Soy-BKu~>CSla7Q z8g%)d zz#v41e|gg23j2VAY78M0@r zrjpfZPkK2k4QG$8_$0DDJY=NQiB5dkzL4<5_hdyd@cUA1Inn9K9UsSy3wRr|rG2_*hu)#8f=5h2@S=oOH=zbwLsfiIeGr zumM9<80;`S5R*4su!=GZ<3_RTZ5$cleE44SD7P?^17lc$6SGO}!hC|BP~dr@35!rc z?nvdP%c#D_@$>ZKTH@kOq*eKA!lkxvO3uOI(Z#MCFUsm{)=1a}sv1Y#>xIe~!c+&r z8J&(#-M6XyY!ziAhhY|8ca}l^I=$JJ_5dM~G`8HlqpyH<{s0#{2Ed@ z3Kos|?(I7x=UygPg3|Ff+}U%_=DW%48A#bM3OMX@P8J)M6(nSA(e+bNiB=ychz<4l z28y67t=fnQVtZ08F6+JV}P59vD~xRaJ)l<8ySJfepx$XM zET-I}+W{q1vhGC!zR`#@_CJg4PMKrE{>Lxx>aSBoprE}%o9C7*;cMwlRXs4miZ-Ar zBT>pAZH=Nw+CGP2vo>N&12zO}!hsX6l!OkU2e>0CScg;aN02XbQJYO+*NbuUSEvj0 zRT+dL5TGuU5&oGgCY&SNQX)PgeX(H^MHmu;&S;^M(O>V}<|+PHsQ&C#H8ZLZ*}LtR zw~@ibj;qsQG<-HUF`rYgjNCMzQBXQ>PWT6nw2&9d?uokdiLlJXY*&6%e0i?{Eah3y z3edqYLiHUR?|@i)7zTojLptBjm=F^zXw=vsg8XSue(u<~AR&2QF3=dGDM5fcS|T=* z%T!ub6iJCKXk&}Fdz&;;yL*U@dm1^06;unM3KL?f?A%bI_w!^{eXJd>@XEYM$1x~# za}%vxo}Wvl&P$WX>YeRO_Lx~8II@(!2RP^mSXB{Ky(p^)J+3Gfw6ccg8avwx4dn6u zyEbs?4ycsuUP?ye;omwch-s+qKleRviXNFtaO$x{qK&cog}5x!G>g8!Ni*IaV1id( zxY(Rcz^RC#U@j(I<2F~r#uSE;ENNIXfYy-kxgJV0z97Ys9dRV{MNDK`&L7ou1DHLM zAL0oTs`X@joPey87AuejFUZqGs2d;3jNo@|Qe!`BdzT2i1r;RTuVh7c+G?vb-z3S! z+s)B5lO%;B6|W)hcR~Q--pFd!l9k8AoAK2af{7MlNQ-u)Fw46AO7Y~mSx~quaV5pw zi#cmo?YyaXpeAj*wsn>cxlbQ8nR;o4k)o?xlf~`9r!9*fL~zz4M;u{A6Yi_cUCl%7 zWlE$?$y_p_R8AT~?eEwHD3ThW$Np}Q_~=jd%t(1NmtHEfb60SQIDhEQXI(2l zaCbb(UQo=`mKM}hSVCiZao^pes7Pa3K2irYlwa zFp4 zjg2yDcNOxm8m}3h2T9B>0vlFvG_(4n>}U~}x`jX_L`v9-d?7k%2=E*%%)eX~EMzJ9 z6st+nB?_UpZc6(|gTzziJb?908){9(vibch*3je;>t09(REZ_cQACE^{516zHbB1wr$oX?gMWBj$J0C2Cyg^%GIGI8{Hw z<+}R#GdTvywwkf#;JX)7?6`)S*3GsFEJf8@H<6MlE;!?hcgg$T6F^IHL+p+sk~2da zxe1J^o;inyi7LHxqGbxdO~OjVczbliIo4r0GtWT2@HTTVOb3W8jvyUMPech4Lu7&S z2w9p@I?~_t4Dbk%+7;6WnH~8WGN>pv&**!R=meNZW|Zj}ud*pST~4TDL>uIUfeI1}j<7IRmz+E74C}hI=!`6=oSr2vKO^S3txjbVARvBg+|#q z+mdBL*Frr$Yvs1&y|Wv-A`d}RSzh|JNaT_taR0-}rL-h!6fmAiw)l0RRku1ksIB~J z$@poaG``T)@v?%N#dM<}FKaa#qm16;WAgAljhls0qKrZIyFi6bnP-7lZk3H!NRzo4 zN%Lfn)x?~;0$w%ClR{f&Y97q^w&y%R7OFNEPh&FvR&O_eRi|Pbi4XYM9;Yp@5bT;( z!nJNX(~2tB1|WarOYpR2y4vFx#oj6%=Y_?2-16&(WPM=)etqRAxeXwHB_~j5!Y`%n-_vns$oJVzA!3<~_7u2bD`^Xh!LvKK{|U&DM#es47H%UO zl^Q+U-`G$5nTc7q)->~9_HUjGWlNTFYG6f+)rt^F1t6bfGFPreNG5Vec?IKAOA$%R z4Me0h$KHyHcbbruBo&Ql@mb=tewG)Z^Jow&Wal%Z^y0B8n+$*(H;Lv`?N_l?pZ%%F z7Pl5jR*|cAt)9~=pc3VjL^(*nFe=R=Il>zl3o`2w@!KRf-pKB_Gig+;hQVeXp^0No zSbw_K0;DSh3-4(oL$kQxsbAGbZ%`m7U7qEq(Bl@U6AO=jG!@z+9SBe)KNdoy)co0O z*J4LvS;AmcV@>A8V~H!zz|LegmQELTMcgMARZfE)=T=9cE1JMppw?v2OL0EFa+ENz ztzwZnlDS;iue9U{!g9#LqNfxd8(UXTt5%V618ATjkIdy0^97A@;Js%gPOD`Vaz&nl zksNo9$0m)UOy$xo`C6A%Ce+l7PpWuteWoQW{ApKA~XWV9}p! z2Rtv+JY!i=>v(7CSO;5T4@wI*^EKPH-u2FRef6Nzsa|T7`)s0?ZFE|33ku59QtD}q zQ4Py6I2{G+U06vMQXZu-O zpf{|~7^&%PB9kWG8k-u?X*G_Oa?OjU@|0|z=g;GXgRH^Ssg6lm&Qp9pn_Ph%CLez3?Fyaht~Z`cV_vtRx*OmkjJv@XBS8&6AXp=9`VtZt!)PK}_YD0N%i8K;o`i+Y80C+lolp+k`7ms0!#4rl0Uf=lnw=zlN8$#hw(vX?s zooM1v%A4!t$p_L?kl_DY%z*+xgHQvAsL*aF{R`Zp}9uuBz1b1yAP$#YwR>VALV!@5Tm z`L#^9Btz{d1V0CJOJQdf0EyTbgu0LYE`@xcW1rdUUPh#H%^xQw(I^|tbi4)A;k7s> z?~)cdUszQzKRrsKwp0`quPRKGX+(NfMpZ$c2VXmo5>=p<-b^pZsW zT6gJC0^)Ah**_%hEhtvrpiYgcm*y=hGe%@wGrUypAa=%rsVDRGFnGzwx`{tK%i$xUd#l}=JewtJl z0KMY(g(J(KiE5axytjuGI__|e(E+x|XX|@qASR|Tb=ykj*Ill#iT~jI{YU8g7f+M+ z`Kiwie^w=E1V2VCTlT5|X#DUiI61x3aayfscld2yf&ab`(9)#4#1_Ctj}u@b*=wWC8LtK9i6;3Z9#!z&wDcj80kfBU86d>l-0{c zgc33XWP8@gr1T^W!}ftN@yt*wJNHg2I*@hF`QWfhg>X$s7KC{Q)l0Gm`^}R4h+IF* zvCL8rEr+KH2%<-A@Pw5E*Z%B$DP!dm6H6a*YqZh>R$1v$rd*q=G;*%pry z$a7o`KE~uMwjp~G(0Atv*;`sRsDQzi!U9hhz832kgN6GRr-@=?=nF!gM7aIo?!PWuha5!9Dw2qtenkCDt)j zY|#h~xmRXSHUgxMkTy7oiaI(eeM}Ah+n>Ty`!=8CHB9SF{W)`4y~vO@KAxH+ksoOV zMvA78NlNPx4=H6FaFBjKk$h=I4d$pEMRAY-0);|Y{IM?4k3K9BTR^y|Ny8%ihnM?% zd~uYeDvZYRUDbg4PoxNBS@0$?b=b$tv=_83f!(`-rAV{_%$D%IL)2qRDe*)3RsqRV zrg=wEBmY%&{$dL^K1m}bGciV7QlO6owz-MDS>yoK9(Nm+Y7({Xhir+K)=Z59;^6p6>?{tJNwR8hp z{-{R-UopxaGvQlew1bC$cGL{=T6?O`i}EAJMO-XMsu(8t70wuu|8U96LBnw}l051^ z`uwVFWJhEtdZq81Gw@VZ5In!wxx8rrAEuF?OPuz4ggh^TxPnPq-0qaPdmH3l|2@o5 z2SzZV*1%h_$I(tmQ~4&l^$oW`yx+O6HCLRQD+J>S@W_;X{8nC|5EKj7@$K$_)cjee zmSARvkGlA;6)P}ViMN8G44B?U-PfVaq=i4t!fQ_*VOkPsE-Id0D1s*1-l!%Zy*1e}iAA7tZ=zkS{tPEYIC16khP>)j` zF+0`Y8}e1As`^!~jEyl%&XOhoynoWwqnkI33-GR))IwgMZI}iT>QwMe=bO3@O_j0{ zYueRyM{wGpWmn37bo`9Gcr2ZuoOL%4EECZ(#^E;P#mlry25UNvv}g*_$hHXDGc!3{ zKI6wn)p1?KiQzyB0l;iu;QbiqTpBmzA`a7(M|ox6koIx%`a^?^M)Mp7d6xSV!$9{V6l#PVSX9&$sW1zBMK=k@H)s`r z$>0M6j31m&(C!?zu@cZFZYU@%Q(E%Q=6_bvN}&iQMhvY&)2s#nk|aFwdy-#Wjx*^# zg9@GN1DMkhPXfa3@lbU(S9d7A)UFR`_uNIF_ry^A8H}l#K1)%iZS5R1mDNI4ouGWX zDYQtZ-)V8ecS`X}!#-SCGx$n^wjyFTLYp(<>h~{Es#WKmNSCOa*likR$S2;r3PIPX zL=)m5+d=W*R|*LL>(XS^hKQH{=9{Zw6MEwf{Moj4_+_T2Co#;%YVd7Es9=hlyq-Uf zr`t%Qm)%v1{yTj_E0%COa3YG0Gm*6oD=@u%+W^n<0p!#fe@t4slrGRD>cjH6TSlVv zwnkGL`>1Oc_rkLV*4<8s%C8>Nme@Q|0u##!_&!VKu*M&NGWx<@QhNzIw~c&f)c4v5 zN1vI%6XT%edb%6C)U}>}#Q+DZ!RkK5jAW959Z+&;@Lv5ZM4pWlJUAMGivqg-V~Cqj}|qQI-ZsNG~7a}Uxq@|Z4< zl1wZ^1iJF8;C%-dMfHtzX8iM2;-dshz>V65ot}Ad3$yZu^rS7xy71pN2! zIS*h?wvm>Gn)6{hmp*{k@v6w40EC<;tm>D)PFJYkJ^UH}xY-{^eM9t%fo5iZVwIcJ z{$H{uBy*RvnlEND%pmhn;Jr1}fC%ctRSw%I#@$PA@mPDHlsHqs zeGu)G{Rv?@o|4R`jy!_&I)R?HqwotY*BLmDo?53aYCpC z*d;0ZOW179&ZbZj`&yLO%|TE;nCS8==9luhM~;VN(ri39{ZM$Ky=3@4)54FX18S8i z5)yo4+Zy$4bF)ry?1cANpW?fRv&AOBcI5ViQKRf<5W%rwTC9N_Xzix{ z#vK2U;`P(nSNS%5IGbZ1Q&WxULXyRG2{1Zg=1qYGO?KY0JUw7YZfk ztI$0<{3HUQ(^A)L|HwdpBSPR1Jbt%RvWQl8V>ln|pF2baHs=gu5w;$G+c5Ykb;2;}WEns}QieP0 zxflcjX>LCBDd`7N1MUE=rDgEOw6!j(Kcxc&!g3)7+ho*S1db!SF)al@UfZ6{fm$UJ zlRMU$kZx|_8n3A(6sEVJDq;h0{ulBn3->IS%--2`B98sd%BM^NtPb|EdL>qU)XO*2f7wOrEYo&m%2e?Ayq%J0)$)MeG(T^rn zv8p9Bp){UUl4V6^FLz`xlh((%f5)Uot+G7y53A$_X#(O$4LE7I0D3}o!yt5=}Uowi_ zE$XHT>6HBK(2Hf2v=Kx@!jt7+z#pPxoj))1ep%!CNiTLAiNgSNwb?7AH01*Qz%z+f zJjpg|!#pL%;fBetm>F_a=$RYa<+ntZf1_tCENg#X==$C*Egv?t{Pxetz4!20L<{SG zQ4v8>vasJGWCv=}^laXI5&-bGUy5WjL)Hp04|fc?8EX{>P~^&jRo`KKxV}(_fksuK zL}%faG?dbzzeK)HNT(WA^cDNy?4(_g z>7g)=OF!Sq+I?>K>8>qAE#^Q=|5AN1ECq$3;pRV zg&9hp47&E0(2mzNy@D7*LB8$pd$8~LgSZH`$&0IiWp(Cg6`mh@u~Bu(NLY3PeR2^V z)3A{R{dmABE!MYTdj(k-ETek!d9u;D3~q2FQWU&t-z~`INN12#Vc71KO6K6OD0Z=t zF_(Fd=rD_IKb>Y1a~Wb=&&V3ao1fNu{Fr=yIkpnMG4M|X$`saTl>-C2T>+0=L>mzP z#+t66r6?tdEf+5~PE6odLb8TlDEQ(m z+n>@sxl43UX?qY4Fz{}v9hmYtj_ENhX^4d0RS2{B}gU+qb4fo<62;`6eJE0h z(wH1^UOZs!y<3azbS?;q7m-5dzP>v-dj?!3M+U%|;?!IK7uB?VF#=ISwPBD}5u5R{ z%G7Fj3+TZ#6dR-yuNe~l!}rS5(A2v zbTKo+KnbTbA48lC@{a{9&e&HLpyaluo}-69`84opa)pv2d9|rfQd`?S*!@^x{6&>^2cZk(g64hFUlO^ zh)_@^)NK*;*Z_r3i;-u>@+^(0Ip$b{7#Wq*)eZL;-D|X09?)$DaVrG}2ADRN47ki@78ZajYg(GIurIDs;e<53h|B8F>i84`cLN4mH?c*!r3((Bh zpoc(GHTQ_s*{LS2F8m>;;1{E|(FW?_T%E47tSBje$J~q%RLczq0El0(F{5d0Dl2ah zVv`S4RY^`oOC*h`O}BFzs!NG8jwyrtHomh5Jz~ePAqeM+_BGihABh<|q4PSya(fQn zgy8?JEHhl$jl6a#p865CgY%l~I zOUMOT`D8WEPi4b$;I#Qnq_gU)hlYdEk8kgpa7) zUq$edjWi9n1rP)N4A_WtIcdCh2({7HzsoU+P|W)9M%#PNN?14&vi>Mu>z!=oDUKuPu@Ynuk#nL zB@OyVsht0Qw+gth%{{-5rremKY#>j={JniDY6&|^Odc+vx=L7_jCz%8OX?}M%%S@K z(j^b1DgaQf0HgQY*U~Rv-Z|Me4K1ySvx{_To6xsx@A8fDp9e{qgOVC9<43lGJ)s&$ zkx3k2T+)B_DR{O$8lO;Vea7Il#T#U_mC#xxOLPVtFgAw~{*{|(S3W4NyHrQIo9_JC z;mZ&c3S2a+Gp+K}4p;xtGpd4g`9##98Wj)F5CvMT1ejG5Fp?6EpXg~kM0bBnP>$WvUCC5jqiIA#ZSE742v2Tc%KbxXPv?;09*#{~ zEZ|3&2Gri77c|l}e&9FxI8pASmeFDAE;XTEvAVDUdBAR+_COBBIx^pKQ3Dc1VvF@kAD$2PA2hb{?(}9P zs~HaES-ko1mIZ5i0iTw&FSbGy))YvSl$olS0p_93@e_mrf^ogi>pF9>pJ>A%>MXLk z%a|t%gviV(tV%`6@w@#{0gHAsbr3{vm;DAGu;l@Y4KeT94DKu}b3_Vqw`|aJEXXHO zb5UW^cLMCAn5jeY$qkDZK`i}ItD_^8mG)8usH;`8g-Z4sS8=Rjg>ZG)Kd41J2q+j8 zfVuv;CtQCYCA?S$ijS4$qudv%)%ksh0M)bnN-|a8-!AOmd+MPZ+gBEdZ~n^m5W-5? zjJ651lHKx)q+m?RY)fvQRlb1OFnWQcB7up9x^IlB^yc}GzJx85la;xa7bpWDi=5@4 z>KJ!xu>-xs1)w*@8SGymob~sPi-pS!KxS-+pe6$S;?xGvlAS?I<%bsq1tibK3OEG3 zSbpG)r8vwrJ5Zzlkdk6V9onZm{bw7ZxdYQKL~=G%>81TO+NFk4|8L%d;d3KdP??t% zrMrZ5Q2MP@fI~SEMI}_s3dYwjCj)4I9Tu5!#Cy|T$2G?;#5{Nf$FNAJm(?CLAkX4K zCpRcHi>5cN40l7=G8t`+C>=8Ur>e}n{|-ltGD$X_et(;`0m8(q3T4HsBHxdrGy)s)(6nBP|Dxo(3g3v;`9-pD;j45>1 z&kYCnu{M;w&)Ryp<1)bZ0bY$iPFolk(C>&*VIOvZ z!K{;6@aI`^mi7IzC%kJd!n=B!P2RGV6S)Ftz6tdd>bU0xczj87+ZRv9F7^ib;q_Ib zp&8}-RedTUc5C=JFS@ zIxu82fPqaB@qv}|2C*sv(0pk~XJQg}iCcdhc@5kuGOw%Tr~|AZ+s{pv=+K_qoS|ro z@rkGG7)d=k9?!&xmTKJU-BCkOLP9HLA6l-3YSO&%V_PEBxBVKqk%xBQ0itapI9<)Z zr5Bt&y|j#EY)0eQ*k+rKjT{3f2+|b9XbJ%uaXxfx_AbO1KqQY3c(nb?%1AGyC-!A< z*Zw*Q_1+r24!Fb>8l!r=MWSX+5Y6{A!!p0<*$f!&U%e%>T_S+5ozBQ9+?@s;AU0^M z%kYs9a^M;OGA2}mDUNne`Bv(g;`<>v>s9?aUnHj9Nd8diIw@n8c-Uh7$Ja@YxpRnjE}Zh)Z+W-8F_mp zN+|=9CO8y9$zJ?y zfW$0cd_EaRQQ7tc)J(}1;c2v?#J!v8%1rPNGAsTo-XV~@6RG+;$Rg@3{IwLmd=t7SW_v+? zE*nN`DTWS(Dz2UL7&MTY;#nchT#Qg#%FN9`_c0*19<0r+?d8|bI2aEmbtZf*kExB(Rl)-LJ7hUz~;c)_igG%?jTI=_vNgC zxBXJ07)QDHCGw_1+ZbRgqy$?rb*k!oEEVnMlkd&Am^m&(KsQr1oQM^ z(q00b24dvGO(u(rs2vww;6(8yn%#ZewjcyA{b_bVN;opfMX(xmGymklYx1Yq3PYe3 znVp9eGAy9`30Vi9u1tv{Xd}Y)F%$Qp(*gT^cTcTzO=Hp4jvueC;DYI1H7YOvBgSm5 zGu|QR`r1%}gpMcEW75&1@N??W`@j}pyH5&e?%B8;OrAUurJgI}2btSZC$!| zF(m)@uizA9^*cnI1yf;TVO{D$hVb9^f1_X+i(mDmj*<_wqb?AMHKIRwl?h4$74WmZG&o2UVC$hHF%w`^68e<5rAymqQ6n zp?<#yP_p!w4e~48Dkn3I8AyWU#+6&Cf*c7e51*;!2aSir+L7G_1JZQdAmZ?*nN-P0@yga&e`632te(}(2d7bhqT#5N52%S?8xVc!} zuY<1m4l-$OCS=EM+(zZU5zT4|Naf2Bo9FbkJKm*ZvGX{673W<$>n98^Xcj2)1M0}} ztjs^<-ci`ZI*%rNY)x9)_t(C#p5Qvtzuv=p zj~jXWJK9diSsTGZK+3!WNnmmw4rvw*4)NdRf!3*{oPZW^xWz#dRMW5CcP4!Y81w;` zghcHrSJEn$OCzfFc6=bQFdq4yK1DTCt1B!ptC$kLqB=IwJ>%3Ogr6QQz`DLDm(waj zp+EgLB7VY({4@0Y3t`FVjd*IG8(csC$@Ogvn>w31Q}Qehb+h0yONp&*sG0QP*(E^M z*N-Y0Jpu8Tg!=@Tzc?@+2pR2P-+cRU2Z&Kp5cz@&O?vskB?5&8uDZX0O7tZfx9dg9 zUhMOPbaIYRfI@>B%bYX~0GI6R6`RMG1=li*f)K@LFY2pr1sIYrj>s znY@-wMik5~D|`xF0=KN4hJ13sd5+mXkL6l$H;gYPcm>+y+^GM2Do-FUJd!!p~ zE@(G(xL68TrgiA$r5X4x@%Te8+E9(~OhAKc_Ah_aIb3PfAUnfk^&44x%0pvuIcx!y zFZ8~Ncrc1%thGNMFfvE+>09Ad;D1BLkqRNpT@G$3iS1EnzJ^iVRXDoBu|g^}@lOb- zWDNy8g*5ADCR+z4TBrJf&(Vs8mk4Y>6V)C@uQyv}SEcxUHHi=!M0($RjGt)t25LvL zFj#E`WZ@&!x;_CqhRwaFG@3zM4AKYg6(XeCQqqVV=fH zgmB08`DHN=nlpaQxuMk!ceRPq!;TWt0Yyz2Wb^fpbhdyqUQPZK;=OfK!+NF~kVc3xLACQSl|TvMH#yZQ270uc6#Bvowph$=-319xi{?s zHT0=*jd_?s^vkhdE=e|b8x{vBQ4xUtgKw1C1v$Q1VZmkHo9Unr%Fa{#7R9{cyj9!h zmkw+NgAx)OM8WS_CBgv(9TsKw+hiEvgo2-=aziizVvd#lsTHT2tu+NcX#5Os2djWn zM1R8%fE(@rC!FNYxVm3uaRlCi44k|VaB1xi{YIUx0~O#f72ftTC1(j1(TA76|5*L5 zC#qz)iu(xGAOenqjc0vn!7^Xp zrs|UtAJ}7^Nt{yKST$N#wK>3^?S|H`II^$+e`J-LU|wkY;vB(@JH)K((mtJ?Vk)qL zWRI+`(b*u1O?3QOU%!}4(KBt@m4n%9KP-jKxejF^!~IoAePj_V>Qbela}&U4gup)5 ziqnaOqbU}$)>faUf-i+5)Y!Wvx|l?Drdne3P&%UA!Y_lGdQKPn!!yEUXb(2tb3K6p z9L#XE0dpniclyw$hvw|lx^(s)Wn59>SN2&ZF5!PR8g&p(G<3Bljc0CXY_yl`6`VAp zHt{!c7LD93vRd$$>{=UIhjWJ6SL)lhon@Nn?J--qLPf7OFl@NeH`k5fqj<7vH3ti? z56~>Mv;WvS$%U=g*sVAswHey9Xbr6c^cq^l*S0HWTCuv;ZnO|A(puG%f;yKmY#Q5} z+O6rMTC!BLjgZ}qCPy68|Jb%cKzdYNuNWg+cua558K)_%(?zW>W5gaab!|@QAY5?h zRxcmS#M&%3r*CsluVb`i+2L*OyEnwJ<89fktJp>H!fI9TRkVOR&_l&)55(b)Zx%|dI4VQoVT&zMuU`kH9VzN&?OL|d;db$GpGF>}1oy=9o0 zdyAn}XR^O@8pB2_xXICsoz5Jyj5lcb+PcfcDSX?mi38F}R#)S{xn026XiwcJ9MeT@ zOq-YV^#z<>tJ=&wWGbchuC)SQqilY!z=h=VCD>2QII=EcQuvL?OFUk^get~3x^ine zt}MtDHUaI)R(>R$shU{%>XYf;=D%6M;;eeUzS1D8 z6b_dApK*RdvC6vkzIR(yP7adZl~dN;`rw;2?T1u2_DZN#%-O&%v^RoH%)g9PPV3`; zMQP5E-?UWbygpg+g@jP|E2zYu%2EVMdllPVn(8MW9F*Q2%n2sqN;YxuyjDY~cqC5S4#LUwSo^_>&0_Y2s zlJi0|#D7ij;I+olh}I=QE7cg7N{EP-xGeD_GMT~Jb*G=OaHPmd9pPj^tJOeMGfG|I z`j4Jal-f!}XTb@b(cq!xi|PNbycM}%JT~9fRbTm<#I_q_oUs~5koYnda!av`8v+~I zGP>-IFrN@84K)e{${6{F%Ee(`L@ef;WJDqGcGx%$NN`UZqMmUr0NBolS%LAQU8wvH zi$alj{S%4aMjN&{2sKHSor=be{?3f>V-s?v$uIx)wGpxDpItR1H1s0$6X?|x8gx;-)Jy)WD^9O#8rX6-- SP!KAaAYkq`U~b?Mi2n!d+olx& delta 13642 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 OAalM}b3X79nEwM@O8_VU diff --git a/src/Nethermind/Chains/automata-mainnet.json.zst b/src/Nethermind/Chains/automata-mainnet.json.zst index 928b4ed5b16c9d7a77febff19b62f9532025f5d8..2596a2a70f43fcf17ea8994749799479c4b46a1d 100644 GIT binary patch delta 14652 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 Uf+Q^;oSzU7DjF?sJj~Dk2fM(>$p8QV delta 13637 zcmYLwV{E1k6K-wWw(YHL+qSKH`_#5=+wRubZf$MbEw|>@=RGI+awhZR8fAXWWRgi{ zJ`SNOx1j*KcGeF_-Ag=W$hHh{{RS;Q3RNWqCsU-5LO;hiB{+Nvuy!kFhrif7I^NGD zOz#`n_?Qrjka~~?kXlfFUC>MO>T5Cx?23P&5ff#Y9e*O&S$};tk899 z6*)z>h$Io#;4pVtiZcmK4uL43$m4XF$gGQ5;x_?Hr`27<3Ed}|zISZ)&4-P|U|xB9 z9nzp++2$u6E&?2d3rVv)=4d#7Nf3{Z%HJwWzb*{UGY(;V>?3Cn&%|f;<8p2nR$>wk zTc0<~_?o7)z7&hvMG4|Jh)+j4DzQV!TWHA4vKii2J_)_`kNO|Ea?M2TpM~BA(Yk^*e%)EgOMQlBjEw zC@%z(5Z+h_Bn(E{u;_IlZ+TgnC+$A+g56|rEjvG&7z8rbaQo_gdGxs7>vJ@g_xmvA|yn$fqEHagTLebmUT51^G$|;j`|H&ty+u2@^2o) zk~V%)wb|3OP64s5jwu8)Ee8rp77Yywn(R9`V%7Y2C{<{LZ{M5Y*?uG4K*FVgqcnl- zrO^ccaFvtJWZo4ytn93j!E!ky_?nR>H*<^ffglfQ?d`Q5-Ue15tH! zB0g1GA0?QvGS)_vP-wUWp$=D#N`9pz4v9fZfv3Y3OPc0E!a$;+t^a@kgByZ?eFuXm7lTA5Ap^eO z6p4aCAd7>8p^=2avfY?Mz(TD3p!K(wj$5F)mr+2V7?0V|Qm2!Tp;z5=MD--Vm5*HYUYADUC=Z*i`XheG8knKHFhp*!Ji6H50FN z1<}oZ9tyK}o!R+D?&7GQmKOP-z&SQ`f{x4>hU8x`j(qSktRef4sU|N9uWd|}S?n8S zU}#cuS2s4c5}95sWfBMBXmkdnWH?p%Qb%eH1t!Iz!*om@Z*f$b$f)WlIwv4C-tsHD zl;Y6u)aRB7mBi^uN&zM$%x~EwQZ~H0368S#Y&$fx!vz6#Q{IwEee~$v>{LiG)lI09 zkmTF@w|vwLik)ew)aHn&NxEraF3a{E@W>(~8S)?DX>1ukq^a?FDe9^$$>c@wTQj&O zp{vn@y$)&4X8)=%srkupNqhtPs^FwrqXcg5uwv*syGoW-$3!t;Fi4bdqMCR%yBpMd zFeAGM9P*_K>C4u2ozt3e-a7C(_5;Ehw#UA{qD;av-B}^5I)hTSBRVHUQj!uk=@51aO%HqUP_}7xfciABfRO|nP&{~ zxlYCY+@^)y&Z?=v8+5G2HGz)yv(wa6XF#sRVi?0Cx<<5m2D|#UlBW2hxqdMavux{G zg%V3=MDaBwSe1TKpnJfBXPQg+@M2FdKb1WuJS?@ ze7(w3DDhK`hm$|k(u>V4*A;(Cg?;P9j_`kem08uil9fJ)^%((O35^ycyzrD-i zm(CXrr;XwmF_W4-KL~bQc|=cs8~3rqWG}$%Lm}ikNgq;6T1M50)orFAaBE^mAb>#0 zlo8gNF6#bEbeRUgXsr}6PRi;^S;paQBudnx*4(1H_sBa;?o3km__tyK6Nz2i(M24( zhSHK^68@w!uP8yc>><;NF_=N1`P$dJ!(X`5>yK%OS9B}-3e>`Q01bFiPL-{;D4>&N|TR{lgp?8rA-j@R1*fqCnqAa zTMG6+KC1#v%}}?dc}k1oBx85^VpVCzJbmMvpXyvco9d9L>X2Pf&URI+Uu=+O^Y!i4 zb-CIeZWsM_^aE;EW4)pe+8^Un@@e49m8CKp@K&knRCo^#MEH%OsffCxMY#1f(70E} z*U&Iw)dB^8f@MxFv$}}T2lTr#k)`T$7hlrYerW(7yPYe&4b8mtERg)7$^e5EqIX<0>K*3ORZFcc}Df3YQk-5PfyN$uJ##SL%7>F5Y$MY9W^f126X(267# zS%dtdZ*GpO;97GkwXULvuxWic^SU2lH;9HPlxkQs; zde(~aSngO`YLTl;qm8Aw|L~EH(0yd<<^Tw-Malu?OADUOZO^nR%6OdTI%VvZ6E3XX9#ZyyVd9V%wMHlDop3oTX_PKEIb%eb=1swuijUsXtai-?fi@zi20OMps% z>IwsfNTMuGj|IA!U6P#>mB1jO0W|Z+DP>jexkvTWEgj?^NqO%`(;dX5uIdgNjo z=Ule9ujC=XL2>3m(U7l>O#WZlDcKg^E8el1xP+Eip)P$(lpMC6gq<4bGHiy)nEOjO zVSoyYgHqZ1qOA*oD(se4gd#4P18^xci;E_Y4L9G%90%8lO=y&^@FzBqNlI{gFb`B5 zRU(=Z{+vi9J#$H5(zBw>w3M|tC$l(lMhO?`Jm4at*Ga?ENjdc3kjg8LT1z9B9fbp# zJqcAgPaF?@eAOl{#(mgo?YPDbl&YgXvq8DU&1)6-bu!Fq*|st=+!N?_3akHWp^Qn1Z%9WJUVJOcAca6q z9`X~8Ln{KQ)ZF~H9(uY6&;iH%qmYd!iv7w`l3yfdJ_6wfk8y2`dX)YU>IxQTrw^ay zf&KH-g%G!G2Vvo+;pMKeaW;Akp13FO0mWF&jDfpyI#lK|OOiL2JUKsk6|Y04CT$!s z2nn5HL?VhQicw?Q)hYfY&}JMVVs0P#$I-0Pj*$( zr*9dJFIY@B?u(Nenc+1)=C8|Vcq=Jm4RRk4R?z$r5FcC#rjDY@WjsJ?Cx?Yv+(LQ2#Mw}R~%19>2c`2~O zLuWuU9ELhHX~CHU!W@r^a??s#V?2SRs!fH3x(6>DX%-9&0t^hY6!SY69U4;PsQ5yX zW|^`G78q=RD~rDCgPYEmjmxZ*?)e{D%=QK5rv@fy@@_yr(^ zzW~i;oOLy>kI^@__^HmLsqG)p(GC$ja38-~cJN#u^{KtOqY4?QPNg?Y8D5?gD|x95 z8R<5$jmuOAs)^0HbU(9d=nRT>p9*PSti^#Te|>Mcv^*)lxE0z~4A?GAjgHsH_GF=x zr|%TCzb%p6T*Zqo+aw02P-c#T&Hxrs({=T{o#4-C%S~&J5R%t__}qc+kxkh6R^G`Q z$OhV6$JDWx#JPWy<+?zZMnXW?5njSDpHZ>9REG2UHj|9oJWA6LaKJ|8(65Sm zlF`z9uj4+;xh!wV4Mu1P7sSKa#(y|TU{S^}7(ZsG+Jkx{w+G`W2sPnxWTB&rGnscY z!3v0E`)NcoF&XNIq{`li?GFnPV~z;_xl8l(ci_I35#pk-tPq(e!_9Akj7N7Pg zgODBu_-}b-^MPsxH?=Mi$AbB(I1aRXqC)1AT0U?wk+msJCw8)vf5x^yuKFNyJjM%j3o#5v zR-1H3EPfU zQASS>Z=3!WQa??!Pc-my#!rXJ$aam6Ehj^CFZp2Mhs~FWJUf{>TPavK73!v6>QggQ|gjG*Z+#x79LH{0W7WN}#mHTXz4uUjGT2sE~TCuY6_H+70$!cVqvy zNdl|M;npcr^i!s1Bu2rTwnOz1w!Ncf0guWu$IqM{(nK#a++ahiHJM#C{yD~u={ino zRkyhp-zO`$3IK(D72ZuKQqZgW2pPizrv?8(cbb@C0Wo%U*Brc=w!2cQoM2rm7@_C! zWRyTMBJ|Hoc|9#jp24EVs<mdnfARZ;8{{em?9;oBRhy+J$DQzZlP3CbP96W+No33!>bCX8 z01%~T3<9AINElvfvK%bP@|vX+=5#Bv4{G{ClWyAFa$T0NNFD6CHyw}?ezrUmw~v+6 z3zgzIIsat4@9I7MVsBZhdxM#y5hv!`eIj7C=7hDKz47?17CrZ@g}9+|l@;z3x2?gL zpJ7dNK4Y0zIbjSjj3zEX>@V|+Z;nBh9H1u8Y38nKtCV}Y?a%Ffdy=L`nn19cX^`1D zN?2%mK|ko!s?;t7SXSoi7*SYz2rsp-i_JhEmBCd6|2m(!nMX37_}Qm*4l{v;x=x!| zDR!amwB{x2WN!AKh(o1~#Z{Ab02S2Rr0i5shb$zHOxOFyf*22Tq6>IAE7O)SkbeC} zp)U%N!jjAUFL$5VyXQivp|k^RL&bJyX)rV8?>Cxx=NaQ>#}p`Efs~D zP}AT?r`nVcCuEjZYf&HA`?9m068Rc|h_OYq+e^b2hS`pcbMe=706wkuY}wWtM(Gcf zA{@4|s&OUso$~vfGCiO*t_W2Ez{%GZIIH|682SC5A_DJNr%5&R-t|B%iCJReV5%`m zg`cYhY9Fo5e7Fi&+Y`^3Tth`+xsu2+7GzyU+r46Kv)J}U`Sxi)L~^JlOU%kDe+||V z59VB~8koNh>76diIUB(`=)X;f)R|JUm=m{kwBr{BmM+qhOhIaAAAw#Ca4*dv1}mWW zSFx1)c|9S`WK`Ct(NTn3r)AlI)TIP{m2k*?Z;GY34`yLA_jaUrH=^kfJ=m5k6ZN}# zF`syR_`yOdoyshD4r?<`BF5BPmvOncBTEwI6yFE09K!3!JZ*f^Qagj(n7Pp0BvPgG z!A>J;aBt0DirnC3r+dE>fUYawwKy;s*CL30pI?sMefB=A7I)>mwS{AQyLT?X|D9!5 zvn!pDu<8V>Xk3r)Dnbx$1}~0w-BSu{<+o%qT`NRm<**8hug2LJBE;%MHx*<{!j)b3 z=7qKYOW_?dK4b@nNYG9ZF%n!|l3d^{Vm^6NrG#=I%pts`QX+y6unK8qG_}7-M+0_V z)~n`eD10Bgf#-N9Sij}rtKC(0jxn#Cl1N0+LtZx7LB@VdVAE?Dn7<7Wt`R2bX)H`tlDlifC{2w<6-5rLe zy~ZE3T?_SiFp*{?O>G!BJ#!RVP)8``UVir-q@R5c4To|&UTXzgI{ioQWn_s(HLOxG zHDmn;iswsTQt(dq_Qa|um-qbFm;3o1Sb_(yuGiNDk9<1;@Mj|H=eM0~tLz5%&MYZN zHwa73g68}YhI&Qeqe&HKZdM73Kg!UJNsKCE_iO7<$69z$b|vomUcHrX!9S-}{-i&> z)SpLi`096l-p1cPB%Rx7%}|=op)sNvp%C^in=LiN?NtwyFdxHGzi9XirCIp9ywOQz zFbMUa1ew4R0qm^(duZs%u4YOG{JH}D&zThq{Qf;-QZ=sqTm&Js>7r-KE!nXU4GC=$ z6R0#3`G?teFtrLhe)6tSvVR;n00qKcoKg2)-sc)9FR?)yJm~oP zF&1mmuXP^m=uV}j1F?G6Fs|(ja>y(^i<1*>_%#e*GnvNRgORmJpdDkQ^MGG6PFM*2 zJvi3xA}{tHLH&9}K|c+AP%K)C@Q(zJFo>7`wQ^&G-9#H*@a%_>WC1NL_IgWL4CGf* za7^zAKq2Nt2qxn+<^4z3SP1JdnV5qVBl*630qwJvm`sC4|D{@&gSoOXCsi}U7(plm z^+ikNqnHNk{1Q_Rp>W0E8}$XlFUQ%hHwMRC-CHnTIIH!KuU94fs=(g;EHUTf z2i4DE{Vv>(;bJ0+Ltx`V#wh zpcl#8aMkU^u=xkn1a^vdB8d&p1vCNldXQ{&!zi_p)iYx^t+VXuIHhD)%Sp?`NJ5m5 zO3p|z(LSQB@$WGyo4*JTsLeWvQbm-uQ@O+d{u&0s`WuDTuZ9k?|i`Fka5y1vXrmT*!q*=Yp{Y@gFr> z{HG+mcqN(6&d4Kv;a;ds8Cv`%;eOA``9oJ%VPQcrcJ@>ADWY5~+&l0cZaeDJv=#rp zPme5*6!MvyScR;_qPyUeEnCu%I^{TAg1G7174tAQbM8smE>fn2+k)S}4uJJnY%K*; z^A5WKYz*%ck)-g;-0a+Q@&5f%2PvKpM3s4lix!gx_BOE_kGB{QPltLP^krsY$t zXfu`E~YKw4I0*x5r93o*weM8&h2FjRms#@Y}XNDj#EU6p4UKm{(f%v5w@$r9=3Cz z5hCf7k2u{l!ss4aae47!c5d^@K{It%%;^Fx>AOPU+H$57-motcRmIoXoH45<5w>S? zp9c6Kc#Zh7hzrtQM z2xUcxLX7jo1(_!P6PuNfl)Fq8SbUpBpH@(B)23~FlyPt*dEt&w zqV^)(w4uc>lS8<~KdjyrT$eNDrm!_VA009jp0PM?D>`vo(w=Y#l_<@osZTr|dS0%k{6@WIbzxQKy!;FS^D<9(B<^Eb}qfFF{WynPF_ zF!;Qy@6K3RtgTEfLhdv7J4>>fC_}+;W1n8{FZ!2cxW{>9HLG^gIq78$;<|CMmT8>y z3nM6ge1044kJQ{@I-zMu%d{*{N{u${Z6X(*+>P63!&o)7?+FZw13d5F#PW{iF(A@gcENQWngA^m^ z@(|B(8D`JY$wy~Qp~FhP(h46%f8cmpBt*dA;8ZU(YepOQ9f&Qv&*7PP>7<+HEWt=B zT*z$5JG`=19I}RYs*#g#3h2JWQXR+cuIQ@)o>d&h{ZA>hQ7($siH$I!;=I{6tR=nI z`V0%RUDSvX#rk?HQE7t+8KaXd+@8zhQ_LvkCkQ2$%em|ksgK)iPu$3I%@|X_v_lwp znvjUAla-M(a}j0k&KO1N0*=G}j@7Iuev(?>UEJ&(-AW{GK0306VmkE_UdOgSBo31U zyfCUx<;+-iU$C+1-qa$&K~^H~i3H3;v)`mK=fs02Z3|%y{N)zS3kM;GfPv#C&4B?! z&xOaGgbr-2Q|XDK`t*^n%j;nPF&36TW2yXpoGe=r>`hOf%%)%J{%fKE3odYfK2x3$ z|4^BV@=#x;IK8uOj~iY(@s=>oT|x{vo6T^^&b)4^IVqGu@`;2XHSB93N_@0h{bXDc z7tK|Aj=c?}rq^)^X=R_C5Izf8C-pWI~?q*Ecv#P`WTe{r` zEBqxYeql6b)9+WcRFAiYj8WqEZ!O8mZ792&;i^XKx?7oq)@G z75UCe`BUiO1hxa7f*rA!%=^D7AFb({ok4fG+m1^05p#95{d=GOSCi+d{hCl5q-M#% zgccX69&-C2ExVnRXU79r*@K2tK3*Sh&J1QO5XM<msMBYSsLi11YG5k#krRRzIxT;6y*+97i6h?L4|S^|5^wjCcali2A*B# zc{4@vnjdEExkO;od87kdav8QnW14pgG_w|NmCIh3h(FkM#eXhah<)Ct?JI4oVGD0F zj6C=5MG4H6J8(h7}r$H&2Dg#>c{xbB0-xE%qn&9-*4^o)}+M)mJV$BK(&EiHGb)TK1!(w zhMi=Dp1Mxm8vM~HVKcTi!Bi+IL`4TV$t%C(*}@w^&s}Rsa=ZXu+VPdx4e<#2X!HJo zsHLJ6MNh3Xrw%~8QkUfRQ+7m!(MTLfiNN&XFBOF^A{!go*0ycd)|0p{%w#S-2}2@W z1oOgX&29^f&r9Z%7zC2x`!^Waw91{uZU&O&0)LA0QFK_e$M1+i6q_}P)Tq`1_)9!H zft@cHWMg)o-O`;1RigT5lUh3g;lh`Qk*qBVTC>9@d2YVrovV4A&G^{)C(v2&0Cf~E zr71{-vn6+V&ep3pPv&^|@%P2+*Xi={dZU`~xwD(#Lkh!3-d_57=_>K%>?CBu-!bhk zGgc!p&v1nE#IIt)anDeP99_j!b`;9IvHK16kpO32eZ~R`3S9nLeIgOTn+eHv7x6Xt z7&ZWe^Yi4mqK};*DQ{$U2I?}-k*I4RFW0TSi>ov=o3XyX>XhE24k!LR3^(R?iXoR> zWYN=w9V7OehG_c_ePITXN#QyKD{V3ysxSv!h+yhX)=EleQ=Jk=x3ea2K5>$OkZ0Py>nvvp_g(o=rB83 zw&pBRi;QHSIi9{nQ!6u2j=V-%rx7xKkHEJ7Z6H4!m*PFJ(72*frTZ->w!co;Y?a|S z^UTpC`zji27_F#Dd!ByoFHr%8zJjOw<_~*IB*-o1Kec*}ZU`3s3 z^Hh(wW%+XRFJXR1zmK#gG3usqu10g=FD*#R48A%t`f z=RkB15t)Qr@^lqZe!`D0aZ~SHSzWc8ut}w1H)X^yp83tTC3(h8S(Y0aBsg*-nQ2H| zi2Hw9s-h?|9|r!`>ab4rC|J8qnMz)|XgI8jF6bI>JuYU>;#fC9;{{V2jE02lTFmM5gHUm{e8J z$le)QWBIK?Uq>57j|ZncmY#V?-|o!JX(YV6{T*ZK2gbeCVj7?LMLj?3plk44yGGXm ztt_IZB3;=SYVP%YOTpqtc)KF6s0BX0e(Lg=XOJ|4bC2#~VoY!67%UcbaFbDRx6L z=&3LvjM7QH&COo{!;Rpx5-_pvZ>IXYmCCGzt=)goU$0nuT1_bd&Ad|>sz!#GU*uQL z^FmkdKNp%-MtJrTS^(rXD$=Ue&mqC3+>)4IPv~bKhBpYUP&)d8_wW-X)WSNYMA%qb zRZCRKb4-KmP5`!4^NAG!x!>~}wAus)E5C@k`Q#L%RY$^Dv~Dbx8Lhq%4g3Nw#`T2v z8wFl}gRG08KK&MZ9)~#=_APT_)mbWDaT5yLP&tQe##rU}6aZpu-F($R(ug$ZdgLak zYct8LG5MFRdXc=@n6roYTz&+}5yrINc48tN@Kkqi1&y>BDY#j!)yhC+D^r*7l=@_! zy=WUhPl8W$xk-J=yS_oa12KqnDJ!`s9BHOoMxEzf?8|%F`O1Zp+qURYZ`&cA=(zd* z1RKiWp5RUB1C)&vMTlh(#LA(wLPiSihr~;JsiK`epaHYQn=(mz`@0r0V<*dSOU^AE zY9zM0EEcHkaK+wc>JF7C(wJ61){{xrayJO@IN=7Y2-D{tUQG9`wJ+$ zE0GyXrppHio<$%S&7oJC;CWLgNVqlV~m^B+=+_8%w10#DaM z6K1Qo0xoU#wMUrXRP^rPrT?4^^@rH{RU6_-U^*gI^gLrNC^~5jtJ~B3yI}F$a%d76%#XnKN1%AQ0me1*09eID}2pkrkVM4kIvPg8zv2Kq)8na`P{yUa+ z3Wh@&jYg9WE9lg<*&@-8|B|YG#C;-idAiU#U$`Yu)8@Adnd*577-OeO89@caJnu0O z?i<6W+mn=Ane*0pP>;A4b?m4>DW*Px_(C!ufTyS+wvpCCc>!v5&nga+QNlUKF+{6| z)Gq8OBKSFxQIVJrryai9NSuIxN4adg8;zETlWNm<*e>ihsHQ}jCJ_IZ4LPPbU3w+G zQ*C(|^Ws-~2H|Bc^oszAH9N_xAPf$w9R6>aoPTyL&Bm-t2>eBfxBjg~^`Rv4-U9tV zfRG_S!K@0=<)Z8AcD(Tqycu_Smo^c8_WVwKw@LJ7A}5!B8)@$VVV%9TD&=$3@Ap)7 z;f<=JaB`Df#_PF^^Rfs6O$7_r&ZxjaO{D&Q5|29A^R3gEHy=DQm2Q{@A zZL6UhdDr?|CQ{9zIu3n`qFd27L6{LwT!X(#c09=XTndAB$87$#Os9DaVx(TLMH=Jc z?IW-^_m`3Jejk1E7Uu95Abb=ZbJR;F#*jQsc)S^2O_b?LkZwuwwT#-+lh{e-ZRRo} z84fRf;z8)aZFzdK{xjsXN*oA$p%X!5s=1(kn^339d&&?Wt2D)Pg%9i2_XV4xf*HMf z+eS6ZN>e0oYz$M3ukGi1>~81XF?aTy9hW}Ng(lqbe(qM9nK{#n<<7v~IggS0xvs;= z)8d5UNzjq8=fY&ITq|&Z#K=>7jpIyXU^EKv#HiY+I~(Zj_LI2Ix~mglUbyJ+>B`+~ z7&UIG38}jhc;47?1q^b`>W(ZsEd#_p9JMfYLmW^#dd@yuc_KEp=o2jJDPC6?U~FjD zj2x|&ghm$?I}^8vmyD(Ew_EV1t{Mcll`C$OsdLTED!VH_X3ndyEoPTio@6I#oH>hozJ|c7}{w3GO#`(0wf0#ry5xt!;8g zb{u=7`$p|yI%57_Ejfq3Y%StjJJI&;@Pyu`t|*yWtr3;2%xD4#Pm_duHl8~EyoBdb z6YhhUxu9SqLMT>rz3ao;c5{Dht19Kjr|5PC*nSphq#=<|)Q#eM8J)isx)+7_nVoPY zsx-^B?2~a6DTT~Q<%L-;50vC4B^hm8kGR~+I%^I<+V>+j%ut`TWQ}0%dA$X72xW$| zpDcm7`if5ZBJqHtibDLjafMpkZ!|&HA*zeR8~5TimlO*LW`MUg=EK%I9!}^m^LeJ4 zH0&I>^eCr#Hh>e(myc9yXtnxfO?hXQrqpPSdX7PzEE$~ZGBg~uM4KxC89n-n$^mhh z_|^DjY4EXR%b7!ptI}~gk~K*dLjL~!I2HS1O6hYx-U3LON<`pjGzj~I1p9ncBjguI zASbd^GmsfnyUBX*xhC=KWVXCnIFOI6TV$@<0_Ud?H$9@P;tPNop^eiK5E5@Lo-sDB zuh$n$Q#8BZfpt%B*kT>|nuF74>w#1Q=N!GDnfqd&4U5C!x5F*k)`{H zodKo<-x-_3l5nE$28~~I%m17>zOIWQtNVZx#G|?U$ z)=`?@sgQCJsu@}II`(b9u50;nWev&#u!RG5L6=hnkeLs&7?EaA^fK3k@ zcyTw)IlnCp=XQ0q!;PKT+eu|}GG0VZxd~XGj+BC{w7_9T(~FJYWPfnF-Q=>--Ex7w z&AT9jnsN`DBoo_`!+_yg!rM;Iw#2T^nU=H=l*~I diff --git a/src/Nethermind/Chains/base-mainnet.json.zst b/src/Nethermind/Chains/base-mainnet.json.zst index d78fc9e0a7d72014d174ab7f10ba89e5a79593c1..e901b7add277ba89779e5fca3528db60ba47f2d4 100644 GIT binary patch delta 4569 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 delta 4925 zcmaJ@2|SeB`=5=m50c%RExXLvhMFM}vM(hf*(KXZ$qY3KsU+QwqQy=(MXD>N&|OrA&aicoZ&n?_u;?}WS? zy3GY4;_E1`j&~P*xgvcQClX(*rM}*&Cq;YF!IbBfv~S;>76C$|(U(~W7NP;+p1p?S zV@e73RxU@sDRR5dGZa}FE+;5!XQPZiIQiN!L-5Q{oshEO`XHf|pC}@-q)X1jn;Wgc z<*Dp2Amv}CxO?pjExPO`|9&=E^!*9X=-n5;tlO&P*T9gwy;|jls=o0V8Fb%*U+Up0 z^QdrAv5%4F@$K0+eZ}JYGYfjhzBs)&_9?uNeIQtD^Pg&-i*4#Rx$;K`%SO7YuC*AP zQVP6kyxs!3bl(GGBje(Pmz3COi9$$9s(MP{E`8d$Nb-~7nCNBFMMCzRk$hiezgId9 zf)vAA5S!CvHmB*JqH+ZnK9r|Hj&D$yL)f-7Y(^T^4!)nBD7P7Ex?I)SG{3Xtp`Kf_ z13KJ9_U*{tf$}toR>Db)$WsbQQA$Eo*x1h0MWYOrV6mqRAr*YG6?uLAkw<4we~ylh zezWaKlfp~!v!4R#Z*?j*ln?bA>~J@5Yu9V-3Kh{cv~|cNgk6Y`sp!vGshFN1{fv3C zS0n(hFR`|cd~rj7Yr%@`N2_N~pox%AwA%5&-P!dj6osR08JD9YPn2vCCR?| zj;2gPFZPu{gU3zRo&`4QA;DhX5dYpKDemlQoKtmU&&#GK^bPji8pQf~Vp8Ot)A7lj zku~jMM~*aTym@uR+HiaymlhJc@JC0*rceiy(nE4>Ri%IR}mU4Jz--8Ou> z24v2Fz?paNy57)3wMLWT;%3t$H>v4|uqBMiqa%ws4}6zk0~lrT1PRIJs4Q z@a&f6K;6<%N24UQo)ih2-wWi%xHWN$TM=GIE9=kGx0rX)H&=lPOCQ=DhY=TDvy6gc zyF#o+Myto>cC(^-DW%c=Me_q_(PAN7^wYux= z>@l=%;gNUXiBrECgywfv)TCZ{)Yg3=ARraYGmP{9STp_Ld1@!_Q1D^_Qx_DJ?C#DH zV3xNTqC-xfd`551sXRiUofBYrTy#gZPMU}^y*E{&gsXD5y>*c`*|6b(uPWJTM7<#P ziWoRXv5xuhAT6uH>ytsM5c~4YfMZ&9dI3?)kScd%&sUfcyWE0$<&@>5r3u?8Z)OFR zYUKoXmZWIW16akT%u6eP`Vca+ven_ZN*T$?PsL$_%QKwc(@>(7$NH#OUrQ2#Vp}YD z4I*JT{HD&}ISl=huAm!V3otU$qkAT#P>H=CNVlBdxA_E}@hkLNJQrza(RT3WEt9DO z$7*Mq^H-AhyUo?R=$>DFe@&i=V;=N!IDtEm=6Wz_ zz)7r7SZ%^a_=Q1t`5|ZeoWqyOz$oUIO^0IplkFXE^lo(LYW_wnx3Qb!zuLV$n2gl-H+qz!aaf|v%+Y#qD6U7^?-!%{RSy=Axa}A=#y_d@ z5A1KzQm7kWo`ggtyd=9y|8N*m+aw!-qQPd&D1 zv!(i9sX^Bm`tc2lxZ784w!AGMVh23eD`xk-52}3krqq3YUf9LG;N#wopi0!;b3D37%ex!1N{54;O z%{AycYS6~MgpWHN)?GLzpl|JoZyG+^%ybj)XsT$L -#QMBKnL#BnxEHm)9-i^eQ zk#gllnP6n$Hs884^MkHUc|Tp) zMpJww)V*Vkg+6veqBNt4J~y7KBO_-_eYH1(lbr29XDr%$AZrqhQYV`NDjBYL@qvkp`p7j|

Rl-LcT|^Tt0y5HjQVLKgF9MRPAYc} znK$nuH3?br{6_E2wzfY0klV1hR~p-w?w>mz-^dtZh?55s|8l9`dL+0VHRxNXBDyK` zQ)*1Wk(U(v?$d?uFHa^-;?ZxkrJLuy5trDv{ON*akJ7Opc*oi$!w(+$98()(uBhd# zc4AFtv_C53C6l5w_6KitIAK924}CRf#IiHl%A2MAxcv_4{_EjB!sx+_E+RT@ig_>O zXwOVq=5bnfjgMk}{Ph=vxK;0v=N2vO0?fS$vsCFhS%VNI;Q@as6@5edUVQn1ms_TO zr<>FL#gFaA-`Q@Ia#haNN$Y$NG0o0;TFNz8*D5ZCapHO`cQEaiBJ+}$r#cACO_-|r z9W_u+x?hNF!XPqG=D{HZ_%g;D6O4_GO-#+qi58Z@A)#U65hi#Of{C%o@|wo@_0jn2 z@`{Y}Sw+)ui)IyM1&-R}jtnJvPnBp>na)sLpKUIc84bntF2}(OSCo^{#}v~a;+)I!pJt{& zoPsQ+X*em)ww|vkXuuZ6Z+X{8Vg*37lUVYZtd~>#XXmnBPBTOK--Y)iLY$&+5uW$j zejK(jnxceK*@ie;PiqYoekHB1HHXSJ!_j(MC#dZ9goQ?N5G!ItpC~4=oFG~!A6Fq!rsrX)hNzI2F>a~UtZ4j-U{Yv{DCg-@n3$T;#6OJ+FosLe+zgMe#(Yty&1zB{MT z%npN)K^a^ABup?qnDC=eA$Ya%M{{?BuwE2@{%eb-DJc-G`|r4%Mz3x2=#af~HL)-b z3~c}Me7atKZC7j0NNN7xbi&~OR8XYgaZ3B#YvGe9mQ^|Hkak zY!&gDen@3zlUUmznh}on@JF_OVy%Y?3rI7?H9WA*9kH>_^1lJTiki^>Hr8~>D2Y{+ z6}S{5AlfM`8DuF9mlD7E>mwDGEAD%S-{VrIuvXDjb~B0H%;c`a#9$DbDD&`$2z&$~ z!Z_k57Gc+aCs7?XH_wuu$&Tl{_ovfYEw+l~YffbbY%iIC5vDVwX46H*l-dSA!GBd) zu*Ijp#kZwDt6hX8pUQgqFg@^_%FXxudAfV5F^D$QQg!jG?&k|gsjQ4tg_X3vg3NpW z?^KonpQkc5L9;FpM-|s_I&1J@deQKZ{S-6h2jW3i!znCWksV|<&a6SS8=C>a4(2-o zPSMtkQ=2ac&Wh_GKLDhpJrI)EhYAY^X%afft-uD-2a}3QU{WGcB#M`TM$F@bgM)#m zwvyng03_ng7=H`e*_I2Q<8+bZ@GJrOk-vt0$m^03K(v8-lB@Z>&e~<4P@FSf1#R*sk4WKWz zYLyw>-QiXPw-WgGVXEZ$@X)j2(&yF34KaLU5I~8zGPtDTjvDI%pH=jbKHthl1umdi zC;^qg1FxZP#uIrM!bS7zD1u)_%XXSsGNG_2l8at48hC|M777dJ7Z`e}n1Gq;52%In zRrZSsAfBQL;GU`sV5(xie+cIPFj@a;Z w}uZGc!I2yCokA=@Xan0c&X$AtI6g#A^b0 zs^3CQcL6btA9xeuy_V%Ofd{`RselR%H*Df^?*Za6%0l50{Htn&sLa zfd=%|d$3{Q{OrO25>mmM^OJe{PeTaPN<{7CffrieoqWZH3!JsTJGoIi5%skT;C1v+ TJ{}-I#}9Su`fm+7mf`;g*-(P! diff --git a/src/Nethermind/Chains/base-sepolia.json.zst b/src/Nethermind/Chains/base-sepolia.json.zst index 2663198739d6dacf06a0a3721372126828c6b8c5..60c557bfa7b864f2e35d82c8b7d19f03684832da 100644 GIT binary patch delta 3627 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 delta 7591 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 diff --git a/src/Nethermind/Chains/boba-mainnet.json.zst b/src/Nethermind/Chains/boba-mainnet.json.zst index 98aead514709d50d3ac6bb8e09862c66a8f000e4..7931ec94f13c311de4360085dd82fdd3a0da30e3 100644 GIT binary patch literal 1083 zcmV-B1jPF&wJ-exScx!M7Ih&2lQx%ExPn5QjJ=t-m6i9s@TF=?ElAZ(sV1by@5H6P zR+^@{&Qzp|iHQ%?i8+A+;#ADF+$KDkC(my4Iy`Q)o26DtLPIrmP$Qp%R?$+A>0b?i zn9u--$^8nDk|4%qS67)!F6wW~x(K91oAap%q(t@ca1NWpxUnTZfRvp0ki(5BoRpxF z6DSxTB)x)|oFL`Hhlz+%Jz87!hJDR1x@vZOcFa#?yYg`i6iP;r@6>MBJnQD~zdVo< zrRnIH-zhJ%sqj!pMG!6G=3&T41bHZtwWz+-X!ZypX$|RRco<|1={_E;pP)7@PGy$0eNh;(-4in{s5;%OQA3sbSB0F@n zVYVm*lk}q`2v1ON?9kE1H36CU2)P{W(9y;Y=Iha8&0%tW*Z`?9xVL1+`qY^kQmTxe z>T;M7Q(C18dmVGlxT^J1=55k!ezCIsi{M#a2^=RTK7N=Wqe7korFsN0IWa*L4_fs+ zumQ;q9c^4Lom|EF~U6R2=BU zgwP-dBK<^!rr7G2qSQ*ZOOsOHqs+e(RA7$D*`cEaJA#yqm=lxKj~^w*4ISo~ggC+c z*inUms{EG{Yb5(w(}0H8*o_c(wyFI zddNnEgzC>$2Owv`b^gz*R$hQEsAH%M??VZ7j{5OOHeT^`-j>U~(dI^!TQ~$JZ;1Sw z!cHJpJh|RYvQo;o$)nI8y&)m@Wdb(0##A;W&pGe}q+lD^TmHJ;z}u4ByJ_AK-af%b zFOfpED#dJ78YDvzGlR$Y@i(AthCHtP!suxg6?P`_2j<15W+m37ltHlR%*JhKHmPk$Q!75pGQ&Tc zV0U(3G(Mx3hL_;nTTv_sXc^OpwTh1a^x$5&x^8Ig2P^{SYbqlGeV0XLYpYpyvE84( zd>rNnut-ovD0+lDzB)vEISSKkDp@b3hW;~(<0jpI>sBS*dOBTorJu%W`%N*Yuq;Sz B3-15` literal 1037 zcmV+o1oHbRwJ-exSnU{20|g)e({YAl7y~kle64u6QSIBlY>2ur*CcwO%wy8{jhE0< z!b&98h-uJX;R-@Pd5}D`VE8O~uIaggSg>d#zqC2o8TZw3fX5YXfX5Z=ws`!=Lh-7m zCi9|R{+xPv{K#fJ=Hc-J^$(99=)6!~AU)`Te%yh_k38#}D%(4=s>8>gbe( zE97C&9d}&82SRpq=JEJ}GV9vf+W2dlWyV&9%y@OXqYy3ppySvq>y>y;#ozFGOd(gZ zf=0HA@9(qcWXh)AaI(u{?bCBcf(QR{dwxPr9xS2z5M}G6z z!FjZGpqm|bRPllDK{Pj!R7a(%LlM(~)pt6qdaSt}W>o9IIj)!IC?$22>e3#S>~JEg z-W>E%x@0Y~r7xEwt#qXJK<5J&?aJhKO&>V$L3$7)2q6kcI3k52*cVRkg2F9Cfury| ztZ+UE0upX1nIz=&b&6CQvdS_j5lKV6h57CrMTxFcA=Z3~I_)5up2X&Ftu`7aJgzgN z<6ku8occ=NjvF`99@XP{iG|wZ$X-Xn*kAl&F)YJAVmhbQcV#@jR@6 ze&F!~&m7rG{au98DNT70x|U@AtIz^cu2AwoR;o=zg)l*6B5X^_t(f?x}BJBHC}j;=pU z`WOVJD7b!ES`80~l7H(>(Y)$_5aioM5D&$I@3d69toqx*Y^Q_}dT*dX+Bg*`=+oq% zo6H|+JLo>B9PZyAX4hPECOb;-^v0Gu#*Icob#l?*7nuB4OaiqAV{l}5x_elyMluB% z3_Pi#n!UMWty`RvNA1;BiI%u5fqjVe85AhA7|kBtjfTh5Dv zvT>~wwjE^4#yF6wAIQ0DTwL`p1OD)#i%PLbNV<$1MY^+dBQ$3DZ_Wr!@fLW!0_kz=ct3qH$%W{Kwwe9 z>>YuGR(gts_7>5%-i(!QABz5gj5ut2)=vrhAxXOx5rP{r9IPC!D=kOPIP-kpRT{^6 z4qFY1a#+1xFMI9~O`0Tof}!Jk<~rK4h0)E2!X-&G;G}72$jA6h-(v}5mt$J*(e>RU H8!8k5ZJP^D diff --git a/src/Nethermind/Chains/boba-sepolia.json.zst b/src/Nethermind/Chains/boba-sepolia.json.zst index b8b8a2f5a4f10d0676ff1d8a3a737c1515bdf433..fe7db661c33caee8b2c8ffb935dd1fe1d34e1b07 100644 GIT binary patch literal 1068 zcmV+{1k?K{wJ-exScx!M7X2Uqlk}2TxWf4@Co(QuESb@OcH*%|el?Vu`W;VUTF zIUTi}B^5<%V&VgJVosodI2Cg(w+T@@&lLIWTs_bWh3f*6-wU1cr_ zqy+W1WnBbPqO>`mihTr9qHqqI!?;o614zk<4>{bJ!bu4#Ie~)lLDDOT$q7uX?QJRj9`6Vky#AR2#G}6jQ zf(5Te&RG%@;eqf%%BGM$-M;FR;r^KpX_Z!<7o*yP1RWZQ$Z3(0wIPWOk5P#|$~q+L ziXDX^&7;SXbg__=hBRQe-AYy%%!uDgyeim%Dke;k_Soa%2UGwxnH`FtX*$^ zJ$Ph@6)RU0ILs1{lz6C=3`ydlMn(+D$cRxR>4$pbhe^o^GOMEnJ5E+fkdYt?{ZMi| zLA^1DaRYU>Nsy#MPUJ9APAGxHhx+lu#33RDlk}q`2v1ON?9kE1H36CU2)P{W z(9y<@W9I9z<}f)wY@nl!9p$=M&(yhHq&G*UEmLW2s^m*v(@A{iIcif_G_8}AL7Wa3 zuWi@=s{chybzcIt$H5VfMkb`Hu7>A9|paFoQ#Si zh>8M}oTL=>5LpTDoMSz@_h*{DCZd>e54Wy4EF~U6R2=BUgwP-dB7IJLN-3$RbZkmd zDPOkDS~th!?9kDI9YIP)%!x_r#|ab^96H|6VU9_N6U>htRS1Bo{Fer7cf0uWU%HGB zssGf*o8NI;P}R&v1#SHr`YR%M4%*?u8)JK^=ZAJo+)Z$C7qGy2$RF6RH~BB%Sf5NL zcOnA&2JpnFw@$=Ry>Y>w38*=pagmQ^qWOHVba>2cER@Jh~c+12Y~B zr3t%C>Au z9%jJ6JneuKY=dn8xBPFrfwt9d@7lZ}xP2xYeIOW@Uo5`}Uf(cL=FRsvc?yS>whJ_Ame+V zRv+bTIa2}FK8)cF*o zjC(c>U*QTuKzWcnv|#uwd9LZXf>^L4TVA9N(`ak#D!gokU#rcy_;t%9yc&tZqw(OW%U2ihFv82wEL z?{7yEI+(YyuZ}v-We=iln!-8i=uBuy<~Z(eZyj1s)0-W0V2|3``@n$@(t{X52vI=7 z5h)bGzHoXM6mB639EIm$h4VoWkZ@yWOLnAvCQd6fx%ZJ&4O4l*Rx#sYZ+Uo3>qqk@&(sO zhzKAc2| zZ302Aj^Ss|{6olO^EP9U!D|%TXstS{@k;YqQa{oBxe=-xoGZ!QzV1m6Vo0N^4S-V* zV)hwKjv3ddW(dNyow2ZZDOr`|OpdqrO8xL6IQ-{_|JvjZ%cVcw^4CcmJP&R?^0e*Z zhPXDwaqhVf0V-l)-q>544Lv1^F;GfaY1kgJiH(a}+fGDB8My)q-ww!SV*H6hujJMG zOD@1A6nfcB+HYpx){naydiy}?)))8z0sevDz4}?96-o&mnkLvNYDUA9MyMh)>AH|0 zxGFTvLwfc9Ix)^4MRU;cusmTHXPy+76S~-(2N*m2Im$WjpmNSkkTx`s&|q^Wuy9Ln zfz{~Z@;x?n#qC4eKa(G;;Fbzh3>-<~-f}{0iM$)2F;_@22=8%Txi3vRwS8C9G<>TLneN4F~Tk(j+l)OU|Oc*+He0w9$D diff --git a/src/Nethermind/Chains/camp-sepolia.json.zst b/src/Nethermind/Chains/camp-sepolia.json.zst index 427d2a858f946c02196ccc16f80af63231a7c94b..3d00fc10b16f2504b9d354405a3d2ee5ab6f66e2 100644 GIT binary patch delta 11395 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 ZKtKYv{TaRa3zH!<%#c+xm__97{{h!|IVb=C delta 11164 zcmai)V{j$Rx9;QYc*iy-wr$&XCbqfb9ov`~6Jw%@ZCexDoJ=se@A;qe*1dJBZr%RS z_3LMKJ!`G5>QCK^!!RQQFd*6%mJev%D?DZBfH4Sy>m)J?)RW^*D*lR2n64~ ziqqG=&(On(>tE2_A%#VSP>?E6yO8^k43E*)Qs30a@U%}cXJZ6Qlh|tJzI?;>l_s~) zEm9F=xJQnNGm8+us~Kzl7bp?&2N47J^^#?f{s%xO|He}Pg|L6Y{a>*77c~9_iGSfh z{HtL2?kF8fag+=%V8h_*w^LQuYLP4oCpAKYsu=_l_E;JYjV!Cm(BNBvw)JO&vU6)S zgQs4W=tO9vDAq2>6bcpzlUcQ}Fc^th5s$_&OH?(gP%0D=7fw7xJOVykc1~bNiH?qL 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 MvZuL+rRV(r1NaTxhyVZp diff --git a/src/Nethermind/Chains/cyber-sepolia.json.zst b/src/Nethermind/Chains/cyber-sepolia.json.zst index 00151e80b876231093c50cddcf5b74bba8158db3..dcd39dd4c308f58f8812f853fead3be6cd23d97e 100644 GIT binary patch delta 11582 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 delta 11476 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 S;*>sNe5hCZrk|`8=l=&P-?Uo* diff --git a/src/Nethermind/Chains/dictionary b/src/Nethermind/Chains/dictionary index f2966efa857578f555dfd1710b36901969167764..fac0accb6ebabc0521c9c14cfb849396ee8d994b 100644 GIT binary patch delta 15931 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 delta 6738 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 diff --git a/src/Nethermind/Chains/ethernity-sepolia.json.zst b/src/Nethermind/Chains/ethernity-sepolia.json.zst index d6d0797a3cfd3e2b73ed062a8687a8218ee2f70e..10e98d7be4bd150a1da4ba397c4db33fe963a9f6 100644 GIT binary patch delta 11356 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�fMi&uU~p+Pc0`Dw0g#BCJlv3-1Rsrrih?fM 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 delta 6528 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 G!T$jMwNHBh diff --git a/src/Nethermind/Chains/funki-mainnet.json.zst b/src/Nethermind/Chains/funki-mainnet.json.zst index f57bde28303341cb51c5d975fe35c2ae28e2cdb5..a519a3de5b8b3008cb7fbc314e5bd18accdde120 100644 GIT binary patch delta 14602 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 delta 13584 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 N!R9o6@9^?J{Xd>(AU6O2 diff --git a/src/Nethermind/Chains/funki-sepolia.json.zst b/src/Nethermind/Chains/funki-sepolia.json.zst index 1ede536ec8da9fcfcf6f087632355a0a76ec46c6..908998831d26218366cabbb6b45379ee8dce4116 100644 GIT binary patch delta 11599 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 OEaVrtRx7sNv;PCI-XBB& delta 11500 zcmZ9SV{j$Fy0v3xVmq1G*_qh3ZQJ&aZQHgp(Zsg7qlvAFGx_G+d(WS*x~scu)zj-& zSHE4g`o0~iq#X)K)5iP>sda^`02#XurUUthoJ>eQ=05Ol98K;uW^uiA_jtVG`U|Lm zKr2F?wB@0W`Gd&|0`6Z^4}M^ilw+}Bt&%rMiT25waO+l1j!q|ibtZjXf!ZuCC6i~R zo9;>a+W;Gbob9E-o^d^35<-=aHDms0)Fg~C7kxa)uLZQ5A8sk`j3j2@usYCQ&};uM zJRdRwBhN>l9rN^ma5BHv|FT9X*aYl%wN^}P|3&`%AENSKMCrfC(*Ge-zCB*G=sDj| zdRw^BELyBwXF^YN=&TZPf!3+Ryu4F#49$X9`whcA+X=@ zY5Jjv*-?>+#Ynld3Xy}Li6i&>2O!`_jS4L|F%}mVCVuBm$i>T)4aB=D5gGn|jIdq)hl^Ae8fcUgrEZC2PAxI@M zYV3pk3IlaGJW`nZlRGEbQ^vQR8nCfRP4Y&7?!|bNK6)t z!gsJzd@CW2Jrqn*AS7WR_#7dWuJ>RqLAI>R2x5eX+%qbr+TAeH>-;h|k6Fo%b$Y@? z$$B?obL;LUHG54qRHzUZ18M}4%4X$h-d_JXr55ywj*>75=JXL(^P|?-CT-TD=8vVQ zMdlOjW~l=ubfl1`uDyQMZ{Mwm$Y5YGpEa0#F@mIws)W)7fI-lNEG(GQUZ^loq5MJ& zdtd`ZP+(vXaQ#7oN=EEPg~B1QH1k4&xCnfa{Ze3H_B2nr{ob?+%hD^m<&9$p4y!iJ*9jiNja7%BU3CHR03ZMi!Z>HbuIC)!?TkwycNCW z!;F;KL_>`oU7SFu4_=AF+w^IQHk05<+~CK$Y)lL+H2T_RpUFO{%K zQG1P>?E%P9)LZwcZ^ou8M^lx@QXQ=;pIq1scXYZ?!TFLoD&=fgUvg091W|-6MDIoL zX}d*emsp)>Pof|WSHX+cz8_XJl6C1UAVDxMmtk%aq$aI*UpQuXV^TW3==M}<5k zSx>dT>sdpZEzZ*nb)zBz<{}20R7am~Xb5Zo$AQVI&R8qOgW+B67A z@9z9rSMe+~L3U_cp5B)nWi<=v`(9McoehOwUZGXw*-XwZ*cDxeJTu3XlAa@#F-3m{ zB;;YaoH5R~sGdFzI2~R6kfCIzex4ld-EIH~njE0`Mt7AE1q8TEOmy|cSmww~CheFZ z!xxZDOiw#jsYo2ZO-5k+lEDfYf=wU|D}o}6Vc03g!_}fr33J9x#i@RUrvPn*j zl9aU?jSgZvoJVF~^rV|*p^hb5U6a)TR?x?X{N(0^&p`g%P4FitYH1q^$bXYcArBb? z4h<(>ygX2{wRMyVxq&irvzo0-J%0DM`YHUqS-!tFeMOJ`IyA{S_=qz z6Qz`os;7(k5x{LsU4I~0gKfA4oMgRjn{O> zh)?DZ~?Dec683N;zW%s)&s%QLybQ7vm%iMoFOk1zZSed-vKdur|=qrnzP{ z3z`E>C}l3(S4LNUc&u<(xQla~|IpAV9^1X(?94kOs>YY4mN&PlXH$ci13~nSD`9Ng z26ssXoDGQlD;Ij_Ske5I7d<&-)Qupc@+{+QzKykM<6BNV@#7Q}p`R;2M^yR4jwDfu zh{R~iCJ~y&X6%{dzAR!Q%EEEdCyG^k0F{|li&R$Yl2L!4tH%RjQsDj6WY$)NR)h68 z!DSg%RV+EBc4UIFT{6=C@3bStMGsapMtsL&>Uscxu|N?mFO_qshYV2lUA~#UYp)s`JYCvxag^Q~ufKqH0Kp$P5puIdsb@jx~#wK-n|aKuvJ(R`2^Py70)~Rspnt0`5KVY!PZ6^VFT*b{Wn)XQ85ZD0z_5_lQ`aAVwhgj6{<)15zm$f(dD; zFlwkVE|f6pzy5DMjOrwvat!H-YCgxZg!qVwXTrJr<<@KOvEUga+P(?MvIgYkb*$ zS!3DNx~}I*dLjD+#eUasodNs>mfJ|t_+z_)@4#4&R+n?FB6oOwLGzwYAGLgc*nE25 zL8$Z?z7aXzs13Jx*Zkx5w4JNG^x@4V@-Rbu)=JpRzZN3*v@u<~f0`FumCIsQwedF) zhaLv{NM0*V0Q&rJ<1hMnv>T}NbofRF>-OOsUWKmy!ub@gNI*=T+AIM0c{s&)hx7GP5Wqb@4(Tkx#M?TSLQ%iw#(LDS(zJy}DfG@3P*h z$JoA;&g_!(>jovC+T$LEw0?td{ctEbTwkM@JSpmglw=*tlsH1AxHJG)-_NX^*l;w?Pw;!^4hd_*{9JW`Q_4 zRTLxhiVrCy{&aiS{o2~btTDcyJ0JYJNw=CUj*qiDAMonB!>+-c=j|KTTeo?Ifu!|M zfe8-l7^f9{>{We*f|mRD{LZYo5TC*R{&-`4&R@^0>T{P3wnSkj4U8p0bhsNW6Tq`S zcNK9qyXFqc!~!`KMZBBlALj0jn<8`6T1U4R_BVTlBD;~dT5q1C9on{aF6>`{5dviQhLS$ zl#!A17BHI#3alSpGgjM&MufsS=zuH{=|Sd5WfrLes{6lJH6R?du!ZCY@Qp|$mut%v zQGbF_wNDx!v44Zn?HgZDaG1{=kXXI0&frRkv_oK04p=yE4)Nr_ZHOmG3h7vduw64I zi4h(c*JK#uNWO|5#f*MmV3QlM8+ugo?#I*M)=dC=YdfQ8LX4EHaYQcHg9I`qeF(Nq z+*tcNhei;;wZ{DxF8CJNdF4(Ww#MPP;BM+<9FF6lphs=nGhAr-3=dXJCyM7^fp{gm z)$>_+h}Wf#8B#^=aC}QI5|HvXh~bP3;Xy@G96w7#?P`5``wVT`hElN|(H#}N(69fr z&m?2OV1*g86nI00AV#AC7z5slR4x$C=v14Ka$16++c#sII#zZ{giDCq*1?e+o_a3-w-M!brQ&5*te@z-ZwROi$LYAutMrSJNgrjv38Ek!;V~;v7 zTmA2MI?M=!cENA!>e^o7Y>1!hMe}gKOS?+=p1kBdCa@%-;uh0Ad#JOVyLlD*0WC>V zd=m99I37Rtonka4nIz~7g~gAsbwM1vK;eLlVrg%$v6zn-FQ7n^ImrK@|0uiw+%KB) zTC~E?S-KoKo0a;{iLaP6?U5@9S4VtbfluMx@%GZ`xmXbTH*|{d%?^fH>ZQI`Bj2}x z-l{mltzKjKu(5^Fm`Z3WTo%17)34B@ zm|N{acas_NPC#~^UpdYNjM7DcHEBT{!o}$ z+^atd5Z+}fyY5b-A6{}A$gZ$=)_g8YWyJ9eBt1#*gY@ALv|Mu3e;T#>*l9M2DXL5M zs|jn1zeZ;Z1_(9Zk39c7aUDDHZ_IwweRd!B(7Gg3vcTybR}Fw>B+^?+6aT1$ENLg} z<*lAHK7LeT(Ljg~!ZjS=VHGo3O*L_vdVI#&b#3G?J_zhX`P*p+|6iwlvqIXBqF-cE zo@=UCn~_wGmdMVe<3>UduF$UzCuIaKC2#KyQeD>KNUm*&Z0Lyx6a&l%htQjSEWefp=l6lU(~Az>wP|)p)b># zqZj*C^*1!;$FUJUwdXj)t21YpJK0>WeGebLVC_{sj~2n7NiQ2cRuZ|;zL57BXOv7T z5@v^7rW~t?;rUin8lvkOp`zFW(#daOUKVA_3 zT9C1$i*;YSb>ZW-Cot+`*{#ub_B%rT3^2WIbAucqV@G;qW-d3yeaNMcdk^3sk^kzM zX)lH`58h5~sVS1*`TA{~e>;@JCv$f+i53@XFcajWxLZocet2rU26-C`{soS8WC7i8 zD+K)HZ(G5(GG(VUJd;feG$<9Doh#GUaL+{vTm?c zdU)b4&vxjHZ1Z#ORqQAxN-f@aEVQg;5(~N^K_vYLu-KK_IeH zhdXwWjz`rGU7X33&c@J{OLb2}QR(2?F#0KB_|j(|_doGzniBB$`-E;PG~bdTJ*f!!o(sR9o*paN{V9RgmiQL3-U=kCIkoC!0i`?2D;Iv>6M z63R&B0j9!-choA1j64=Ru#npJ>M2ssy)AXQ!1<{P4~ghnk%=>ZlzCU`%7_jjc%_ET zWDsoyJ_&egH+O1l>4l|7bbNR-Ahmn8y+b1W%;2y39r<$>>iV(_w$!Oe_9gbS zxhxQq-5SAPGUXGwKC!%-^a8n3pwpxq`R9&MKVqGb-j4)U355oPBRmhH2`=^i7D>r3gt@@O=#9jPy&5_-S$JOKOK}kExQ_v;))V=*krL7`5!D z_rIIfoQcS;>nQ%LG{w?#NyKJlx=VA`t?+rT@xj|4AaIS!7B@UiBev~jc3O4saUWVM zynJ*r=uWIO*>n*~3IM{aVDxcumRJwFOjkuoH15>?Z6XcNYB!K$x6HwYUnY&fU0ZMYaUnMss|S@ zvARp{0mwrL4=*@`-dVSo!&wB#O#A~670<^Fvc&JO%wZ2q9zZn&1>}$46&m-y^-BXD~JAxx+?)Cfd8xovw8zKwS3)i_=%<18rM z7RJ{3#c)nt#QdxOB7WDyq5+RHa{Lv=5XJ3ew{N>zl91jxzM}Vwp~BYd7D`np=D9ja z)0|Pbj5998FgAOX#Y?3;?b)n zQ8Xq6w1k@dCSs3m^cf>MoxdD_Dd*;p7hAnZ)HS}3(rr4g8sWh_a=Z7%-#(0tDCj?T zxvC$fIfN3AAC+#ji~$*wJ3J)EL&`?r7g=t&nE)LKi2E@WL_6VvzI~$w8pfUl0mSwCG-a{<84C{v5n1)F#lujw1%drNKy}|8-{5Cqq(5ex-AX?r)(MN`_GDeiSN` zm&~~*$hA5$alT+}DgN3o@dRJ|b6K!>pi$7qjjedotCS%xL6ol3tNT}Kn}6c+1fR)k z#SQ4g3^u1+(D3|Z0&JlwHigqmPlF?Dq!L}253Y80R+Bz)2$Fq95iR}{#SbPBY4`-rV`rIBR{Tc@CACB6si84oe%_tm}G zLMpeMu$)tD~!fXrmPrYyCjn zWgnB*utU(e^mttDbJ0ko@%e7z(3Dla^>SQ0vUz#6Tm1(n)BHbn_)kL}y>$e-iSoOk zb&i{&U5(2un;vjMeaD9C4&tpw;7SkeF>$wbcbwx6{_5=Fah=aip#FdSR!snMTkl;h zSR0R^gtk90+4ds^HLC=-OV1u{__mG6hM+Bz>!yO$t4xbp<4-&L-RfuJ_2z$e7W^JV z?Y#}Yy5kBWOSDPIOfV|^cO$+wc?Mffk1x$`LD8Y6WAGkWV^VE*-7|8e^ zzg1Jg+N+$drmzn;P<-1n@n-u-Zq+fr)6$a%{}e;|$JYVE9c2%km*I3=NU>0y5KAio43rc zjHjcgUQX2tZ6eNlgQqjI96}0D9;b*W(S* z2)HhIfSipVaOiviCx&*FyHp`KHGQsoD=#+?givN!GVn#ljr2B1N=l}UV;>O0#Vkrq zw_;s*Cjf{0aT!jo{SoneWN8ujnCTCuF3g1mf$B&t*lKD*ytB|+p}=~E#SYZ`h8X`p z`|9*AV|Ty<(GvlYy{;_($kcS__|u#X9@5o}@RKYm*%&({1l64qD!OkhX2UEnWZU-S zyNu{G+aVvc#(2haAbjGWC17MBu*q5wQw~zW>iLMR`D{q(2$H4j116pL5c*-RLdmk)=_jQ`QAlJO)qU4Y z{2#T_7#ebsuQ%YggpRBuPT#1Sm1DaPfVkJHr9nxDS@Ky~&I{m0swDC*%WczK0qoN( zqL8(hu*2*WbrcmANZKvmycbZBQO$Msa7)39^`Od=V;6&LnZcQ)kOtf(&Wvm_{t$>k zmc}9yhLlf1W@DK7fbkj$A&r0yg7t&BTuN_kIo;2qWBFuPNcmfS@(yCk=V3Ck1JORC zNjt=TERaiLXTxRTWo6CKyb^U(Y6nsFIZ3Sq)l;>N8djEwUX#jUTa6Ql5htZfaVg$o z6>Y;)2x7O?wNH{oC{Ezy5|7-X4iU<^jC~=TR z(eRP_%KwI#_{G0$0JPFtmX?y7Zm}*O8o)B8*PCk9&`C<=Bl+c4w{;)Z6ZM}0QXeDPM5 z^c%wH9NAjC!O0oJw9!}4!#!)OEnL`mvK7&=dECpS3Lhf4S6bxm?8j2H+76PWfj|kh z@P^!2VhwQ|#ny+U(o4i6SQ?v|igV-X=Eff?94x1&LPrD`Ko`usWvK>AA2j-u&Rk(+ z?^332kV8lF8W5!VkT1{A8hnKb( zswiGTS99V_CN#u#=ym@v!8P}SfRlMYfeW;xh9ejI6-1HhSSNnvNl zV1Jxpmuv1YcYm~RElOz?$KoflZu0jOIbxRj7Ui_;UdLDinLfl z!Hi!ZF~CF+E5M`0P`?YqnbN?Bz>$fe{To72MIr%GY4XxM41=90lA94{S3}qDg+)M; zhZh^J79nAzW;)F__w`bH{WKq{5ccwluUYl!o3u>d?jlQfinn84G} z(F^waMN-BWYWj5NSIJ#!t~jvjKX|z_{6Kd&KQ?VJd#$n|P6ip*t64_NqnJ8W2kU`8 zc2bF>-ueYmR1On=iU`nI(sl0dDX}w-dyd4GBsn}ouCS)lJ$1WO&H$a0miX#R@T;E@ z;SE@yHrRhNxq`hhxd#w4qY_QIi_+uZ3^c=@^3hMb4NaV-@AYaislDV3H+A5MpkYTu zYS_bqR~*l}EO-)*Zw(>h77=?w_w5AjG73Wr1fcxC zrVtR<+AU_e)7iyh^vmaqkow76JJOP$n#k@EZVRulf7g3t8LY3@`5S>StgV10tVCsH zdE}UN+i4GZl*5k=ge~%D3=N_aqc`|qKFgV0CTzo-`5C=;t5}x9p?SFH9Esmegrc-D zEv(V?Kf7F4&aEEWFmn(jjt76-5Jb!|5)X{8 zZp{w%XgrZ^8ut%|FwS2Q&@%>FRCsBO(%%rtz4zv|X{E@x1;AT{3s-$cghc%N)F6LC zZtdN|M!Lv@Ge_v(p`8txzgb`>cF}X$ShJ;IXT$`-h`Wt8UDw9H$=#1R(e&Bz+`IAq z$Ku|L>lmH5!hr6=JlF1YYjO;;JBnn!cWhFEnCW5Eusn%_%+XFUo2UX9Wz}*p`P7a! z1?0<7cKl;G@iv~STn z_yl1#HAp|_u7B<`Gha;=Dohoz zABl!c|Dr5QrsbFIkeE;CX+hCN9pUuZaiPdU!_$tV9L>NcBY6RaN<^*p3Swk02bp?N zMIhw>Q#TpTDxB~-$Qa~W;`w_<6nignwNoEJ;;$sw(@HD1TPU}Q6ntiWbf1NB@(?J#-%2;Y z__9O#HgV_ddX?nz!seOiic1q4R3Y=Y$*+*J)tR zR|gVZIgWK}ufY4HpU2Mh^G}P`j;qVe@zu}ClEU5~*H<946*biPK-JFF;6@Lij4~7v zCgAlc|MC54Wt=FN{JQAy6I!*2GrpMgS;?T!dB*e3m!_fZHx2vYzxlV<1Dv(&Z+v)C zNXWR3qG|qAozdO(Uo6~uF@WlWZkxJu*O2x_hsRF3)AlV^!y;B5PHTvXb3A*kzNA;0 zOi_bzC16{2th58NvqM!c16DC4779QML=Z2Z;};3XQy3up)Nai|2EQ=a;NubSN3l1u znB~+yl!R}aCP|tNTZ3=bimUS^&?nXFp=Mnw<6IB&yWu8Y)5L*Hn^tcnk3e4TO2X;* z-w}w@(;`5@^rP0_*jg(c#gqsrTva6Xj+dRDJ>a+1qc?RbILGjx^*uesAG=YsXiF#_ z`jW7@^C#wAkpT#e#BoD5I-iK$BkBONRo^p4>vXPh)33}5~9y?`_XvkNe-4H$fpLBh6WllU1Tz#q*1?|<2geVKy%Af12 zN4zIB7bn}9Jr78?8D&r9Ea~|llGi=KK|o97KKgRs6Hb3P(YTdAq5-iVpCBYVd8|D= zw7e<{-~$54OGFP~8k%4fM5t73;*e5AmF^nTL1KqxUwCe}mwd^=-Lsy7x z_^J0>WmsCsQ2;uv=OdY1;rj9X8fXce6- zlAIhrgb>`3FHW%k(u4N#2U-3;nP&)tPuvU%U7)dG&r55n1U2^eKRu%Gj2cM=e3!-> zr&Y5UXLl^Xv$r|{~?hm-|%-lD^N~p&+VfJ2X?Mk6o}>2I){|r zi2$)zGNWE)XX&V{QCOoQg5N(P9q2nOK*CQ#{kKAij}v7ZFL~VDz&<+U-_OydHSFw7z)$fN=)? zu^TnR!QG~uXima0B{UA@$n`A)l;r02x<}bDYm3zESIfYh8#qZyM+1{=!iomo-;QcX z{vJ>JK~G!y(MyP+u99i3XU$URi-wW54lfJusLa0)C3o*+O8Exm>-47z5o@47q7}d$ zI4QKP50(+R?qp)E0@Ci4mSKHo&MS$9|5i8N+r+WM~@vV-2oS`M@(y z3zNujhifZnPE6&r{{TFIVrks;ixc&7I`(|}o|I9~l4aJA+?dwkR~T^v23E?S+cgS* z5@vn28yEtacv_f54YeKS+=ilR&2>XlN^El4VoW$L2>4h-<~&rMyQ-Tmpm* zcv+e`+a!&0MitskTL(#>1XBOPMES0wW2!L@i2T#axX(;atO#^BjY9XV=Qe4l# zE8oKS`k;Q|voOgMlT%TjQCV8W25%G-@7J){aA7Lt+6Y81_coK*5gc7JdLqD2^x(;mAn*Qt3lcAuWWwq1ig>z$JlzmD3}1*5crkEIACn2}g!%n}qXt9$5u^SUA<$o!P85dZf= l%lH4?=i83*KSqs~@9_VlTnaXWw;V9cLx4NBv@rKw{6A4v5QhK& diff --git a/src/Nethermind/Chains/hashkeychain-mainnet.json.zst b/src/Nethermind/Chains/hashkeychain-mainnet.json.zst index 93644fb7cd33d7fd2f51cd07b29d1c7704603bf9..18753fdf32d95d02cf67d0776928ba25ee1bb489 100644 GIT binary patch delta 14470 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 delta 13558 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 z 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 diff --git a/src/Nethermind/Chains/ink-mainnet.json.zst b/src/Nethermind/Chains/ink-mainnet.json.zst index d69b5fdd61367d623e7cf66e6dfce0c1fe9915d8..491cc7e769ac04a36bee704400e231a70bf55c02 100644 GIT binary patch delta 18800 zcmXtfV|1WR6J>1Mwr$%J+qOMPp4hf0wrx9^*tRB^U}EgMd-m)8bE~Rv)#>_KD9(pG zFNFkXTA4q=wWC;cutGaPb$8-~DOeKZ9CGd9$Dpl*5lBO6U^2Xp7QUXotB$8`b`6dy zGEh+=p&}u=!JEL{zH!JTBSkk+Z_fF9{|e`u6ym&B5Zccu;>V~n-E7A9ccqSXr^V}m z>sBg1-F6hxsRV}!golix$go_68w;4mWQGB{*2`4Y=9sM+NdV!JA!0LnrGfwBE2)3) zl!G+|!Bhi!EstJ&gRex8T)L~SG{xjI-Au{kiy22^cXF|tk6OIf?=AT-D}>FRFNyc+ ztKw3b(BmWqy~Rc0>v?lGK8pB*>hl8eqgTAW>LSInwZgye*VPK(t0ls6q#^c&q!GaR zlf)(r+R!jxg$j$WlC zc_b~*t3Ys+h^4n!)qTyWjKXzj?lKv!o012O3TIGoNLps55tXU}T94sMWJdVtDYUao zyh(20o%bmI#=q06R9?Til@>bCzYMT@_p#Q^-I!{+3taGAUZ%#~J&3}vtEVm2UYdm} z6wsEhl1XH9NGzqYpdY=Y6i7B|)kV{|GYU7|aY}Cjy>a)im!-v2RTT&8Y@1ca|BC3` zJn(KY@GBEZhc40Qq6JF-2TJ}2ivI_S{sX}OdsO&8mEHu3$-gKoNg_t`$cDF(X0kbW zT(TOWyPAoVFa%W1U*4L>gJR(@)jtI2@AXN=LszKtF@0+O$JY2Co9_R!6aGKjk^sga zgFCCZ%uxnK7g=z!`u*o=8RKDKO5D zjCdBVohAA($=kKp(z@JK4XPX<10j@P2?~KDO9TO9P!0k=CEuN9&~4UG#7f$}KAPni1wpgC*G;w&smlNlBn2lsT1Cm!FWpg9l_dd0G#%N$Y}& z$l`*k@*N@{IlxC;!ZML~NJzZ*g}e7ejceJ9(s00FzM!lzLPi!#+)2iRpdrA`0}BV8 zMIwuqL=x=5o4t^+SlID!iUClzF(DQ_5=6W!a6~)?8x{%@xWxVczBj@~5(tTj0gb^? z5C{Vs2|*%)p&TSB!up>U2?d!3XCw%Y;%}h9z#teI37Sj;qH#kYD9DVl%Kl*D04Vr> zum7*iBO(wv0LnK21_jbUlE$+?Y`U);U3N?)V-|?SK>{O+f($6Y>IOlJ27|GH1VZw` zC8Z}6NQ%?Uh(Jv$5S}~^d2gGZZ!&1(x)~~rMv_Xkj9F+>vD4s@L&I0>i$b6YpvV*a z1%(L;42H&JfHV(=IL|{@4ur<~zs?Xqj0bNecpFh`l>c9RV+I=#NOQ0v&?$#NqCk<~ zAYkkyCHeq3zo+*NXmFtDfl#8^DIJR$hX|-mV1+Ru&HyM*g_Qy+aa2cWV=)+65CqZ_ zD5!HF1QHg@e@VdLv2MV;(jEW-!Qv4K1`{x*)OHRMH?P!+FsG1Yi;qaTEg+@HH&-tt zC5S3ZK~1@LwDFV1w`Hhxa}#Du-z?upq{SuHHwQ)*2MHd-gcEQ4q{v!}Hy9K0q%EQH zW#H-sBct@m9AidYr;+f1Nfu+^>2LC`{>!QT1uCVqr$Hd^DNJS);i$_UHN>$nt zssf^=5Xp}0rlNDX^*E-;U?g){)Y@D0p5{yP@e+vhPX>z--)vr8i#kDJ4Hh4%%f(Ad zQ-doLA=vZq9hh+itpC8IR9f#kzOe8b;qW0ZnSaEcxeMsNSSX!^l!_m*n42n&;gOM< z(Y&8y`cF)FGS7;1!?CTJClXF`s_>3DKmhb)o#Ge7rqPs9cPw&O^^Od(a?qTpX*r-rB|ok+|YB`VB$N#AetV* zvT5GGD*WwfgOeY;1M0MV`x=Xf8eG;R;wrp)oY2Ch>z||$n@q^#p$YMN(&kxk`vE~k z_W<2uA|;(w`d=RTQhwIHG&MtG>=;8@a#CeXvbJdY zBPJ?tP-rp(s@B%D)YkGEjk;+4Zol6VO9&1gAYt1n7lmBIJ#m|~lX=Nx=DCmW+-tli zRpyc)Qq=F2F7pcQd0Z*dDIkh)6abG1PU(MOZ(Nb^!_g!0a;LQ6Vo=$?_m9u!-T9>d z>FW%yXrG-u(oIlv#_k`akX2zEBP+gvDh?rHiV2zaOR*n|D5NIp#1tK;)o#^_ztQVz z{A$1SyDB-~+IgxTOvBfVMXDv(!PO;X#m~dF#dCOCkYpw63YnMM69$yVr}}c@ zW2y$tVCnt?N-DsP0Odqn!<$dF_lQbi#~WcaYakhxhH+0%|(a$NkOioZF2eXIai zynIxwpoxN(H0BSsfYo)LzCG$VgZ^=Lu35|^Rwx6+G7PwdqGMC}&X0>}?dfKeyc@GJ z9sBUK?H$}=Wl=$uDo=F^E8vmmMCO#!1TwCYb#T-Tw7xXFZ25;8;1Vmi6VP?E(s^5R_??D8J} zG6F?jHZS<%R<6ll8s-eWY$JIS?JMxXcoJz8)VnmYnY^KVz zd8z(Urth!|geE$jW-+iCkBRB{WSrlTg`Ik&!3~Y`qw;4Sc0ih1s}Ke@eVS0mRd4va-V{%0 z7V683>Z)wvaeer&o-s7!@oaCJa#clF2U#X$;Wn3Ye*J_slwt^ltyTu4Wf&OZz6mL@ zLmgVSe>s?^l>x=;IGKaSagPKa1*!07dc;90+pk#iqy?PFG2(Q$)nwg?N|+W-#l{pm zUi;tw$--Uh|Fm;x3ur8zy55uo}ND>uOF=m3IHYXhY&0Sv_>+u*6oaolch@0Y)wXq$i*h(Q= zr14ZE3FuN&9kGp-nZ*{5os&?R;c!&&k7*%yg2^97NEUH7Vhl;La!h3&vmv09p|CfT zs7%yO9;fx>=*psC+5E*h3d14C#4w}C&U;YG+G=w|nIf0#myff_$`9Kb-c%kWmVn$C zSqNi^f$J(g-mVXs>oGO)OL;A(7>;Ez8@WnW1yI4U(u2}`Nedzz%>`a7F@Np3*lE~Y zI~Og=WTe3yIOSoEv;;8! zUOQ2g`E>7yww3E5#?<9TMOaJ7VP`ZDP+FzPI>jFM?PVgGjqZ{z?#}pRtuVjXA+U84 z1R7zFZkAh8J-2Z*7P`5q_V#)jZB+0qMDLm7R9)_U#)7iPCP}M`I%_M$Zo^sek8E}} zHx{Tyi_Ci>{@`3k{!7lU=Ew5SuLG@~J8ThQdpDgIr5HZZh^mt>2xKk_H^r47ix5O| zYdxByzB*2mQ2cZo&+L%3kGl34kCFTx37p3%c+{=JmXw&G^Sr&r9;Nwze5W9jxqZ6C zOUBD;W=*iUE@je%)3|xzd~~8IJ3eWn&;YKJTAdwGB2+45^=ED zk-w3GibCrb8;ZOJEio!#RpeM37imS!B(09vvgah;V8xd(3MbjbaeNwTv_6Y6B2&1m zxUe#aQ}WEzCNf#m$1^AF-#i%@fW%P9AS+3V2?bKo$+zYrdz3>Vs?>)fsI*#xtqyHY z6t-n7W_9)%{mx-hc&$=>UjBp%+_`!EG}n{+iAYKls0G2$2n0z3CWv@!XQFALfE;WbfLz*)5$kabn{Hj#V^r}+TJgQV|z?4kO@(2xi z9_)@I0n?4RD$f#y0GUPbf}o$;C?_RCR!w4|V`E~ZH@ZsSNfKcg&78rM6ixB8VdZGr zT~q3MyBIE~F-@_CpPD$XbaHmivh}n#C^|Dz>sr7}8Z6#`v1p@Ww{QZ2>#?ZUe z?ftW6gF>xd;f=$OT-!foz{$r4M{TaN3289~d*?_Jx@%=QWmJBm(GX3wUbQ78I;{L8 zFQZvFL$TpSNMCH1u#5Tk`xDd!ktA4tL);EUUMu( zBh;`R{IoZmws^DsbZRc|n7nNT!6mBvE_yRATFc73k*e-026fsUU}0rJuURuyDDYb* zOSo|LvUrI!1ZoAQN_k4!e36md(;Sxb5Q*+2n&clo=1ND7j8x$td`e*rpV=w_0*%5N z0bO;bxAEC2oT^azMAis9Coip}{c6`&@pM@TM9xtIZ^Mm4H+cnnVsk$Oe|)%=EG#yx zzMf25N8bi9Db!6q^!Z+L$Q-j2iOam1e$0jwQ1a!0v@m zC~%&;BtTazCn!=5Wu_s;fq;O4fPkl<2a=FrAVh=)9~7vQF$-e^Li&3$1oLquMwqIw z;2=nm!hnk+1d||ulYk7cpva0AR9YK@T>Nz+p4k)1tXI8&9pW{@+HNJ)BpPoN;r~%~ z{L_i1P~>KH7bxAAv@2o@yg}uKDVGO;7xN)BdI+rZ3`S5P7DP~V{3A1?4g}@t@X04=VBm`YartKn(yK>x4vy}_ zt+T*YWT}b>{}=Kls%!a(Mq+1jPftQ$sVwMDCnxhvEr$9ikv|;@h64sUew4$R7X7(7 zMdtc*hSG-$2BOl`A#Q4sqiBorvjA?ty&r280GV(AaZJSHwKUD%v{rZCaajRp6MdOu zYDZ|3>B?n;w8LU06FL#n{0b0 zfY@-{V=Y=T_^8R~@BO0Wc{i7mm;MSAfi$W9u??Pzl^qr7hp{xio@+%+J$qqnI}Fv! zWAseX_9M{GTB8&kL{?IIk!MvlvK}!7P!z^gxnqefJj<%wjMK`|OwPDBjgF%U3%ZW_aPHu(7=NV&oV%$V=jfTu?>oZ<*AnhrSVYSYDxZP zJ>n@KW&}&5Er?c256^M*%$vc;Pk_4!N^|uRdLC`3XgI zx`l7sK%Ngh+zIhuw7=hnHNs1PQm?>{_V2-Br$~u5QGX4x*VtdQJ3_Gn6fexvDN6D; zMy63h=_XGjM8Ha(mV`Zub&UB{ltaWy7QL{`oq@^N-NIK*xAYJaBo91d%?@ui*545< zsS%>%F{kp&_&AH*>>__2Vin(oz}KCKdo477(c*n68;}Q7NYe|KT(cTr51k1FtV+HI zj-4^W%IRTZfS+Q5(cfR!A}07w{203?w~eP#cVwUlBe6`uR4NdKm7@>lPqd9bk+?w(ch@xtnO z8s-U@!38_#Dg;AhC+NL&jb|u+L#=3r{X+)fbQ4F*DA`Ydw!)vpO3m?;(Hg^H zJLZHp%cZw!Dw_+ON|kS7(jqD_>n^QS3G_8lcJ#1s?e+-8Wq>_6WO_cY1pLDfcIl~s zzL4&Yy_dC#TkJHwTcdHp;R6ab)QBnzZSQ$@)`OlVrG0v$E#kGz%ct-_w;iD;R8Q5ZRbzafE&z~$#_`c-)(LBu&5A0fV#hbwP zmY6jn#-7ZlVq2}Ng$%%R*6_a07naTJOSEh57~U|srR{BAHfv)5k{lf;rqVe$n)uKIAUyZg=uL~j8 zwH2CKnsswtVPzU3vKudZI3IYU)92u@E47#eQk;hF5LIgFtU!k=SU8MlLwj=pa)>rC z{2S7_@{$s*$a)C>^#SKK$gD3An{`_Le&Cc1y%&(_T<_SgfW3YT-pQI~#{3!_k0+5= zQKdL#w8QwGJz$m<6d++j%w~T(ABG&7)^RieL0oDKUqcWs;uN|7$v{US*gzG-LK@ED zF{*FDmye#enFJA6Wa`fDefqbk@kT`gYc00l7Sf~j9nwAL5%LnGL+R@MGrI?${?o#2c zzgu6G#9lGsYhqZmU5kF9ObW-z(P*UtO(ddPbemvcDub^Msg0*)# zc5e(^Sa?6JGY|&=9e#^?$CVdT7uZYhNYr=VNp@wf?D`;32{_tD7dLL`g)YUR3cx9A z`5HS*GALcCl#!MK%ZUSmq?id8RfA`Y7#cqrOlP$=6$m zaJ!*>%ZijRer^<`X68zO^(Rl^DAD!Q1qi)-1L}PdM$YddITsm9Lu^*L=fOIR@%yje zLfR{3?ypaDq;hdYG*1zhuj`2j*Fb^{wUa8oEQr3hq{=E}3qk&vN^>nCYEz{6yx`9& z5N8mhw^eE9%}7w>#BDE^i~>R4=?DA;V&UM##m?t>ZzN)n6$sB;@3?zs|5@H&&99h) z6R8iMr=V7`a0Wu7VNAwLzj0o;xsf(+GM-4-&$jR7li`2@mwpYM?2%J$FTimp?VU7U zINx;k;;ZrP7pVKiNxKYws$FwzMeW}=XfD3pO9Ky1cR{cC`{_=Eq*m3aprTo{^W?A_ za!`Mki;y+tqbS4r$hxq+bK$HoMngokNY2X;YDgnyYdvBpFz9vjPn9fFOgrkc9<|>1 z*Pf~|%wDVTVIFh&gjd5C1b_mbnNQKDpbk;c5N$ME!~phG3vm?s$gre>A!%__4-EmEa;4_^JelHyyK5Pk zq`Fs@GHb;xm&A>Wsj6f4UUPX$haNrwV^Y2qGmtKgoPVuZBZE}m-GZ~!2=l0}i$VT) zzGSs%W#&8WL|sRbsG^TIRRZ=i)h>|eA1OzN^7@{p=cDY?GEfRDN@VI|{ebBRx;|l$ z#>ANO2h7}-lcopk|;-ur6 z_ikC;1dj#0?m$eiBgN`(CAeIil!Xss9heWol8Ug3xBJNhA)(_jw=f=_UdwhCq&*}f zy_&uGSaK#$mgyFp6wK^z2^jK5%nX&mo?!atr)03^+S3WfZ9UT-OR|cEog~Jtt6zPn zm2HYi!mXfUbVtPDYvP2vJLF#4;ZJid&SJpt*h3{XJAnC$WUZAg|LT?HZ;^OXX)w9e zO+Ej1vr&ij52gU{RX8A$Eyh-Y8rOo z<$~=&9B*IzwIqZ4M2~`hI*&K5L4l9PA3jwS30U@sC6{s&!2YVXxT@k;_I2Jz)`tPz z85BGG7-eg|AsgWoYKQZ)v54j^C74Qh`&33Dc=XNZp9ruVy7Z^IBK7#VbHV!{Rx>C!ClaBrR z2B6s;p5d%nLG14eED3(GxWC?flX-7+bZ_+!Q>`^x2`9^r#xqJdKOm+H!M~gL#ktGS zjr7f{UNEaL&=dV_@Y(cXWQE|<;PmA;_fAjB<4RfSyL|Ny+}80@$a8PRWs$SxlgK9s z{uA6p`I}zUL6A_icF4V!b%BkIs@bWF88{lYR>P{E69q^x0xpzZe@5XE`-(90xL_Hs zw-fR3g6bw9wA+a`+~KL=VNnM}jKS6PS@L_ z#?5_Zp6CqUFvKL4*h%-=hG_K1yu951`Q^jC8q2sZ?ZT#VcD{nYtdo5g@t7FQ41~{i zKg(GzLLVqRf3E;bw4R6Q8=KZniHAgM*t%{lph6GU$YJ zc{Ebv-T`Tm&`kt*dr!gn#Lg|GTV;df&mZzq_#dqt3NemdlL<@q$+HO-XOG+AaeeGdr$z%06GZwbV664< zk&LL{)ag!0|k4@Ed}*&T__?$TW+jEAn6`9V3L%u2hijUe0@V_ot5g> zS8~lPguC}8v)dZerdVaa9sR5tcT`SXVGmrSMTHcvPGzoi)G-HH(m3*0LN>LXQkWqq zU~p)pDz_$WjePYRDEu--OoHZF%uF)0N?S9su;vhuJMY*3YfiCZ0en8_g2K=OvnihD zJ1Ge=%d}_fe?cT7-RA_iX=(G>YhyXLT|(P$$a~`Y^6inI`(jYgZx}J<_$&IA5^-Vb z44AOKk}6sg-mDEch-Lv6qj~HxnV|T0eP9iTrC?niaWfy(<<~-0@g_P?murz?%-=$$ zhZN+aaSCVH4xt1az=!O|O4U2d$*mB9c}bKT0t)CYS}SFOtr7Z%%Vk2V5gD2`qWk!7 z4x`DjwxAS2e&32B@w(hzwoZs=%k%02x3y}Yrq%<+2&Dl%hXc-i8#DAr*#1+VKh3uV z$MJ_VO;-gaG(V>gT3aNQ*(U`T0zwoHLxkr~vQ^s<^VtREc)Lkw0 z)cC_;@6Fz5H{Pe8%E|y>o)w1xRfSLFU1`Me09Ir~=Ens^?@skYLFU4fpdM%9MDT;v zm#C-Em_?22k5h*k?1z$XrkApqR?c-wKrZ1 zNt)an4l*bf{p||B!yd1L_eR^JnST2Pm0j1zjG)L4==3DKyhNr&At&Ne1^i@QCG}2; z3$dx&`ukdrM2va58odFIX3V@{w>5e^3TWZTCNxaFeF!@}by3#fwd#unbaCy?9Ys#} ze+G;h5(a0dUUfImfwH!`kG(0+6)P7Nck6|(Jo1XrVqG=_Q5!X8IA$_HMj+TWY_W}^ke zArp)nJDqwhVuIxoHz01^bGBo*VZnFSnx>!_`1zUJ=OR3gv!aRiJ;y6QiOYWN|M4-U ze~xyRf`lfB2+`;CXp{7@U@56ny#9;v zb1AcAu3i!Np=7fA8_VC$qk`vq3(#N%SX9E1Nb`DnC60-bLp4;S`>`LjpBSQ_EZAZk zG@y+zUecoVXn!WG%)}oTrr#=1K?w#!y=Wb1xZ92u0d*Ds1|Q#y=u>kf0;d=QyF=Dx zR#m+2FWntoR)x!U3tHqM9N+(3H)|0OGW>|O$UOhAb*kFgz z%yIDcdgjvWt;J8s%YM6>ToJ~;C$=Ci^~TPMg$0a|qb~&PL%h<$cQ1THjZ<5WUgt(F zc351aFV(;My&z@_j{4j3^^A!&{i#k zq1;t?D3!%!J~dqj=`-xZqC_tMMruyRyXB)T*LX)j^}4v6sv+eHh?oNIG+(wHHpCSd z3EcEZkx)Q>@WEo`YV91%SOpUY)dvvm-o|Aon@%GW34d%x;f9U5D%s24RX;CSNlG;Z zXg97-tlD~R_i_-+Bs8`#dZ?s*k%1NKALEQpzlV2x!$P`^fq>v!@NrQB{pb+(?~bvP z+Kq>E$8cb#T}X)qxlwb5sX}B53AbwEB@N*BGBzPX4V_emB`-J?Rpa5IoJq9w~w{iX4uB|W{tht9* za)OU$J+aJ4K2;d||5`Z!v~8Na0xPj}n3y`#t_OxOTq#I@j%sN9Q=j@YgVP(OiVL2S zN?0@Zty|01yY@eGL7^vq>D!)?xUq*~^!!?9XUb;38SM-o{nMqogn2KBx$Qx~;#OkI;M+b1x+kVD|Im)!}yG(6VUd=4u8Mpt>Kdq0tdw5j6~A`* zA_+zYdwEjQ>v#|bTr$0ZJGOziaX!kLW{N3~YvAm6xlVckchKq^Z61?egBMMQ-7Xr{S#S}Kre#Mc~ z7dW$2lQ3inPQV>o_>M@Oa{i%9uYv;a8I(9y)f5qlLUOqU4(lMQtLjO`S=kbQtoj5= zppTodFzXrIo4ov*zVxHafElPFvF)0D#q~#p>QDY2954#eQZW6NP#!vqdUCuV#*a z_S8_gC{*|cE{I(E_H0rW=@)9dZ9TR-;L|fy8~Ox%JeR5qdRD4f6*#payL$P~vMwV3 z255}iE(ZH8stQ+4~PXHB4c2%Z@gE+*W^C>g;x+9n!n^hsAQx zFWOYPgl^`A`-#$dcR(&egKBWgs{0 z)xFuDvTK5CPwUzS?9C>eP7Idv9l-?J3rN9N8gMD`MM=uBBF;yU-mxNRWe0eJ>mhBp zkx(5y5M8(d?4nqxpBM-?pDzFs(XaptxK{uR-U9qj0`{!TUM<}55C^vv9>>3$xv$n7 zkRVzB`(#MbB@I}Ugz9~JzyCWVSBbFZF%lc(qC$79?|I2p8Qkl^tkJihw*a&O2qXCi zm2m>hAbCYeu%?~ljC3pes&aCGD4KD=^WTt7)>K;J$lX}7nc?1I^vh7{xtc0%BtjJp zHLYR)#@6K@-LCOG%_%Sp=q+5Lp6D|V7A~m3ipGxp37Y<|B(sK@8FHq_z6R$!7gvij zYPgjM_^jU*e8sz#mJ9yGKNEGlQxqhYan-97j!P9dP_oyx_`cMXFU#EUd%fa%@f8AE zG5H;Gc4n&Kw>mWTcOO;QxAkq7VCob8hW2m?{vuqX{WuwICp94zcHwEhaX>#PWQ*1S z>MDsSHS|)$XaCWIt3#&A?&1CC+VhtA#M`yv{rdre%ZF~%#X5=s!dFmtvV7@+)-)}l znsa8W@Pd0rs*UAb+4^WxzL*=q%on)`yD7y-ZF?q-^S=t@x-`L%om*i&Vn7E`SVQ($ zO$Pmf-DvqYPLIc`2&pUIlgp=?{?rs8rj{lm4GFPbD}iz6R`ZjZ8e2)7eico_(})#p zSQW;bIeTRNMp@JV>&0GUG($82xAiYen zLtFCMPc+W)ANTl;CGd0kcj9Nv@@ksJ`Ow2Gdm2^z9!A7}BWVjb=8iLfF}t4Xb#_rn z*KgyH6)_2$;qTe)f~mThmT=V3r{(I`T(I9s2wMCBVKjx(m`DMBqthhCw;nK|I%+NP z=wvVB8xX&5k{H>|OC+#M;uZLb8 z!$W=P(k8jF87-H(R;|xKWq1u!$D3`pgT0+!#+4Z7F1sF$y)DmYzE#KnKygvYC4N%= z`Zk^(aZrsZ>rKuwFd&BVxPL8fW|`blQSi_9D28koB)DBlxEFJ#==X#N#3ubJgWN>m z1nS7v1LU0++;T7yal(-`3ae)?MOdDTuYy*a28U;``BrnnOCJ^H-!F}Rl^y=O0y*Oq zYa>8)CpqC88R<8T+2P-4s=v-~1fuZq@nnKBMA)iz{|&j^9RIev0Aj{zq;rhr7z7IE zADSyhJ6I8KfStX#s^TtM(f0dc^22ab>ROS41K-B-H2trE1?={ zuuYb_P<@~#GMOVQH&gh-Lu}XrLX<&~2EH^Lja|Tjr!5Kp4I^p*?C6sSj<1L+Ml1X3 zg7YvsugULi|I0fBDVofu1M{L{CQ8#wB9#CQ_<%OXilG(ab~=JNoG3U8G0~=gKKQpL zykM>EQ)08rM}#&7itG5}+F}u(vsIbIOi!O$0DWCvs(+s?g8nu82|+A9@UA2g^Hrij znWUKGO{^?n9jjgy&^OlT)GOlFtUky*aw;vx%WRfveC$4wc9DE_;T}$XAUd0*M>`K8 zn5vpcbQ>-=Qnxu;vTJE+{=>~VIw^aUeu0mr0^wwgM435^1D96TXqECW8q(bjo+ZG+ z!0B5ST87zB9CWN`_~mtl@@M1xQ6xI(7!~Z8K+T;q(vhDZaMz9!D~{NJWJanMcp(f% zaLICJ3@PJ5WhymMJ{Q)KbxT>@5l72%j1(`9KCr%D`#$! z7~KnYOkkAyY7%$*a^0fXqqHGjt{;V1v*uf9?*QTsDQ|I+8(E4t^n-$&0!!6-$x>Lw zVov;r>FTM{lJ$10NQ=H|JtXbuh=A&Enb@CN`_-h&z;RyU%B7u;=B@e3yg2pJ^XN{9 zJH>SPIsB<=G@HrgezcKR^|U3vI00-0$$&C=M$gQ+ky&He59YAuAy5vv23>u6^|9F> z3{#JbK?kkQrjgFTYZG>j4RhE#ibpqOjw)y7Q;rv z!P6+wat!wS%sL_OA>C)#MzaUhyiZ|);@(4*LCdoCw|r;obk+n=%Yxj$vf>F<|yl%goC6sQ^;>t5~czGk{)&P5`51o!j3f!7{#4gp}E^+xilKLNDp}IkMm_Hc%QJlO$ z4jpNR2Md6q`Q368it&jG!WpvWBwDs~K$#Bq5cpBK02v^fQ1>U(VJL7W9EuYkw;$2| zti@JH;vCACGe-GzehSJZhGG11P2MdWPq);td=<{blO3<@L7A9%>WXS49FI6hn0T=~ z+O}LRiz%($uOH*zV3}UZIX{LUZ)SNE)r0h5W8ODc6X-&#TBRV3qk)mCbUr`0W5T<4m9B>ILsq; z5h3El2Z|=$%ZqFQv6w!HV&(l009Jk;^F*;Uvw#N)t0@JB%Av1)h{_mCIZEQfk%wNv z3oF~u=kS5Wy*FC&^uGXHF|{y~2{}*aOd$?NNw@Zs3(wj}7}ab<6Zc>qPGRF^Y8zAM zc#s2^i&r3?c9J+5lroeef-TP+Rd4X=K^khv*)B3L5^oxEnMRbd2iReN9kRUH3OYQy z9&Y;S_Pi&Sd6og^$)i2nr8c?!NC;w^UL1;-q3QRts0t70Gc%7f@ zcZn)sICXCVACtC8mb*;*>JqtSF*7zu(jeY zimn#hY#TbZ6uf?8HRdn^t5+z^ouk=|rtS6)WrN$TjH@jb2A!q~*sb(>H8v{kwsLlQ zEe7_@;o>=?4yz5;-Rq|aA)Xm+)#0PpH*jVh9Xk#th%wze7z}nR+(IH6vcuZK^89toPcDxwCdR{LaR5gJ07B&$h5?>)f%iW2%VN z*zGXu$l}%bdlO)^%&21skJ(&VU2W>vQoPN^YR++}xmIqzOt;k?xp8p&FDYRTt1X!Z z9hM5%%`t77A)`Bv(RNLdI}XjB5m}=eT9&!ait7o+N5w0ynF z#1m%NJR&|^HTU2@VU6*u}O$h?SQrsNnY)YK;fn`7bT6vIhpvA{Q6TKqOcUci_GN*Z+Bo#0J9xgxw ziSZ)^C;dkRiUpF24;4AsmRwcV&+u~D>Gd?>xBtsSEiu+jRrZ)*l<3#|(n#3vi#UA*liL(Wx#L5;Tp47_TzBX72?;%|JXpjfM zRB8Cm-jaTfAB){ZrN>!@;mO$|L9fISl0NbUUDigBvWm{8V`%72b_)9jV!`)ZyQ^~& zyBt71VXWWB^zy#_J*R4~qV!^G2aFFRUV}|Q0F(x1Wg0>cN1c{1u(ZZTa4XC5PDw=FTh-Jnx*|OH`W@BL~&`+vcByF<97P zCm}Z{yrkKg>P{Raax$b%=i!{Tr39 z1!4rH(b~Rt%RX=ou^)1GH%im+2P!p{{6hQ(u`mO3Z+036gnR5 zi6)|q0wocMLID9Q`rnwISRe`s1g@yqJivk@p6CqGNXi;;nggQ=u7-jA_E)?K&$|O> zA%aj2G4S3EH1?j_3`u#v1=P`eXzQQolgU*G72L=YNX|N$Jf1S;aj@1CWIQVe$Vq$w zDK1FhR8eqG@#~{Wc8B^uZ9EoAM(0>5aOG1787`ZGv?O?=sA-g5i5%3=CO8{H6Cj(l zq>60uF_U9{%4i=)99+8-R>8vb0tNi|F&V{7PCD-h-4y~6!KH!RIray5i!08=%xu-k z=IpDOBEBn~rB9EP1$nhMW^oLbqu~e`-l2R}#7`OtaI;upHvZ! zhW7zo@xb}}=L7MNryuKW*hkrBCHN{V7=9q-6;T%ZfV=E9_y#aW{h7-`1 zM-v{!rSzG7*A9?2kPeWHl^AcSuKYK3;VQYzLv$0_0iumb#|n>Fh?E!V-eV=n0XLkd zOLZnkA9QF-vVCeKvQv?$@K&j%Kk$eZJQPA@WDF*lYgD`u5zdIbvx2hf_kc{ymE@zf zUAow7ywkk8f{NFFg;@L2)ArCg6J+>*12RrHfA3E=9ElV`s6eyXV{+AE=Ro!FoEd`2 zN;t0UVVXfA#O2#jp@d%bCX{-sF)@R$FfWRg=#g!a;5qJUtdExnu&j$9-OR(a?vuXH zr3zVzh%t*WD*x-Ib*2PowE_>iiSa0?(O_J&T`s|Q`(ko>BM>gb+hi15Ep`pIF`lDG zzX`cbK1KXtk&bJE0DFH_8xRtrTF(4wJn6WEeS;+werv(h`6Z^Zbg^J~yx={Aot$Ad zVY1$XY|+L z*DFWyhE_e)yqRRfpPgXGudCl|9ba3$GZCIo{ z5YKrtd7Fpukm3s0TwOX;Tv=Y(%7K2g5AVN{d{_hbZLn~bd6+w$`5+R_bA15=L;pCLNqttH;8}2Px z%sjukTk|fzc831U&jQ^?Y=CH484zE$SUfwkwon1MT@#%T(|I{7+Her(wAOG zz|2*(%OMb1iNbzi?OdN?+*Du^c+IO{Ov2BV7O4LlBBP?w;~J4t#q-*g+ngIGME=1s z#MN@gZS%uo7lW0@g+6!Nmj3deGmwdlo0amAXAoJB<0X=l-_^GihSl!*l(QDEV=xT2 zCUym629Oj7FsbWuHu#Hs2K(JW6NVDyZK2ltCi2|7o&C243Z`9eYB0TIi6@y6kWMK_ z>&HG80u>I4mT{oXNRqdF)>j*z;!vm_??R{q4V7VGhNq8=SJP=!rnho>hEN=omf$Tr zvR{?tB2XR7^%DRVxc;;4|%cbI6N>JWve{x90kjvD5UqMsP%aWiToOiH-$}mExLt^^$)$5 z9E{~*P&HfG2g|ckbK_@~q}Ok3wbs?Zd}}{m)8Sknu`=`dz;q!f#GZ+n6cWLhD9{EP zvys7&@;nkl#yu^&arC!c@K-M;8^b!7<#9~AYwj|v5O|N(^_+reAsAppL?9wW2OMij z1K+{9Py`+1cqIpRPYE|EB{XC+6+&O`VKo;S?EgG~6O1|Rc3-RxxF;o5@@{pxIdLuz z4}{y>Ar;zxG0t~>HpsQ{+~;L38p{KE*-(KRMA%S3p(V{RO{df2x7>?pueg?}1@8I- z^a6QJYlbBM;mPCR*%9Q z|Hd{rCBnO8bLkZ<*szwt#%c|*+i4YP!VM9`q6nN7tVB_`eH6VClYoDWE8ze(iZsFq zcrRf^B_aLNVL$l!9M;1@MWNDLsxziEvGLSQ@CcYRB;WZyU7?Q*+1!)wTd9#~_gGZt zd=c3r+?j@=$yANIb%*IBy2gJEVkgxzgBm3^rcfjXOVomS44X;uL4x^4HwOq(-!~nKnLn~0Bg2NA=j171Dh=azLbRK zzBdf+u@D$rEL3MYD%r0PZ%#YxnUe8IrMwhu&&V#% zQEqtqlnQq@ZMwLfNT=9{&`6?Z7fA=^W53qo4}WYNq*ciAwdaVcPg9(IZW`KDY} z)B-nYd1mmBqNz!7$ro0w_^hC?@zf;GL|uFE4VZp-`k&GKR-tE z@zBE6YkJ^F6yp$zG95bN?%0C=a{7?>&Kl1_oj~aM4Y~*LTtzGNBDK%3J&S%r{GR~) z2m|*bQ=vp((fTLw6t*iuUPT*6et)z-p@#G?EHID{IUn{Y z0?Ct{uhJ{=O6+-+`2SI3f`8O@$t*QTPwGv+_g6c~a&c4=?UX<@p)EJUgMWg;jv&cA zeU#G6QYzQWNW&s@@IoQ=ZrIRRmPzC|D9WXZp=@Y}daQ3&zEL+7LW9suzBo`Xs9XGS zX|J_R*VunFtkC_l*P&`vEPvuIsq)=Yq9w!j4~Z^MG58UEgfbUj9<(+HHRiGODl^)S zhFox;fI`hRLB116#F#a+!GBJ*#WPxr;#leH(MlkE8dE%khzcD|JVv0hA1g3EEuve& z7dlBZ9u-Yt?{6Xo@x-i$2&ms&Q+Nc4$W_yK@$h_TjiPCInD>GdD55!U*~EGaf%K&F zz4f)hC|^M< zNVi{3^C5CB_?QN}l5;Sg2CW=&hEy=Cr#K+?ad73hF*Pp}i;~lD{Duga;~;!8Oe0lF z2d74tK(Nbv%E_{!C4UN4)2RU6M)K!98|mbz^tV7@d-DD+82kGM<_9c}Ye}+4KMNW^aw(E3pqrtKOgtN4qR!rS7d*r?2dx%Z!LYuHy!3!N zQQ(LYG@|ifvbqTcObXnhsbnSu6P3r~Q#T^aG9tRZyb^ZRE3%e(gN(*%#6G&i8mhm{Vo->2JVz*ETEYv zE%3Qo2|Ani%FK15}bNh17xbCi47}Q#|Gt8=IZM4A;$A zEj16A`Zuuz#Wasvv{adt3>uM+APC+-ppB@eOwz_A27lcfNbm>B9{{yVNAzMN*Y(K( zKF>|ZPs!hjS&Tt_HePF{Og(i_{nEYuvM^Wm#Ikv!NkTQ*b!s#jC>}Z{gjdy+p4ra& zES^|s{W{GgR0TrEOhes-o-8Z|_FfI(X}*Bdr<(fZJmFa}ryrn~`77`QHeYfInX7P` zQ3fc-kbm}%7QmF}cx9L#(EiBt@wH>EG>l_985M#UUinc#*pzYMXKnbYTIU+b9C4xt^vKK%Xgm~dup>sVR_)kK8K zeKHB^risEAoa)o927y9y#;TpD$Nqq2A)2sgz<)Sw=AV2!J&Ep6$tfb>0&+593FysH zy*>*V3Yg2BD^a1`5$&qy4>$xzM$jkDNf3&Zd`xaU$P{b;NZkIxs>DH6 zwSPgq))i4s|12%SyzL`;#5&dY!Im2@c~yzTvy6xl2n8^*Q{E}e3$Hd@G>~!sD)~)a zl0z^wHPd8*CNW195cgI>p@{JJ4v7JCPv)p5^%qFP4DAC?_klKjxQ2cBY#(ac2Ws30 zj`!iMeOSXjbg&O>+Xpo5!w>i2=6y(OAAfkT53~@U;cH-h1&;KA#(hZhKJc^;H0;AQ z?89gKP}4pTEuug;d?nBZg;W>-XQ z_W`~Sn|;vsp=clc_o3N`+dhc);eUT0n0;v5J|stp>O=1{1iqlOkD;8Z>j@+NU8eI^ zj8nCX1LSLEV&%SWXQDm1IFKYLc`lZIWLD)$HgoowTkA&hNWjzd3T(+p)jWQ)Y{!~p zx!^euaXY2@#4-$sX9-?s#%LdR?J4OCQ60;~j|+42{FQ8w_j_DitYpLiqkr%+=(smU zzR6SJZf;k(nn1~G$`LYge9PfK8Jnf5@6VJbnCu1XpeYY{Ou%-u5_xInIPT()OTqEY zMN2J&;85k0qK-K`z7N;Ru}5K@_)CDkPQJ~>w-kcrhx1gxBN(T%~M$41)qG**c z8px|)P{@g29`F*EKb)UkuAsM%%h?gFJf&%CgGC0u1yM|5IwiI_hLl~xRPg@iyGVL- zr71pPQc8*UMgP~)ATq3{d$a1Vl2=t|d{YYJz#x|5RoRNPecqwepMSuJloD^TQOp() zs=|J8J@T6p6WX@1bBTA7hKjdR+re5)#hKxZ8v}k-)hWUlzRqM2hkSQ{B3dTGx<{i& zq7_;Xi#*<c1eyHYgKPbn68?o&diAQN%6ba71uvB%;HQ@qhes6e~O zJMopPd29@Y20sNM-b5IIWmwKtkj;`9lm51{e=x`VfvG0sDgJ7*jzl3gDn*noID%?% zcDJT=it|^_;_09?f~e&~JNOs^&6N-=R09C`Ha3&JTO9=-PyqmEld)Jp1@A-estU7I SMIr(MA*6$NN4I!K0jmc<6pD@j delta 17862 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 P)n%P_Za?iT(E$DrFpKZp diff --git a/src/Nethermind/Chains/ink-sepolia.json.zst b/src/Nethermind/Chains/ink-sepolia.json.zst index 8b6ed84f486918ac5e12c6fce5e53a5f45d42026..855d939972f55866bbe90691a4009201adb8d8f8 100644 GIT binary patch delta 18679 zcmXtfV{o8N6K%4wZES4Ywr$(y22X6;wl=nHCmY+w#@Xb)_ul&E*QxG0)8|z8ub!HS zJc!g%2!N`E@gJC0B$GC#SSzT^7LFhplcTJC&NOxoVk`jyaR?Q3y60hG&&)&E(d5mJ zWM@P{VZjejXYe+#-(aO)(3{mU?E>h1Qqpm!?YgI5%wkc%!VIC0`8g+HXZARIpW$lj|do;~|p z6xe^+)Xapekp@ykAlF4i5f`o_n^DL@!rhgMjsC_o7c^uVCF;6KN~_M$vIi2whZfhn zL&t0MEK91odHhx6F>5P+tQfTWw4x4=G{x`4EGDn*+%y1#FeX*NOt-6GU-w2XoQI$x zG~v-mmBPWelOaB3UKMscUAq2P$iEo+2apyl>08>qbbGJr(U*q)l;saT#XEezVz3Y& zOO7k9Q&`6q{29U|s!qLKB_J^lp5 zpG~U#-v&H3MNznM^u@KX8jMven&tNj4T-QgBsBu}HRG!P1ET*A0RM$p{}&?tA3*yb zXbOc#(a87GI9d=1gRWNOqkZU3ARfFxn~UPp9!EBQinJ6bq%(`Ce;;llnZsZa)ABpe zP8|CmTlIhJ!vC?`|3BMilzif7O)JE^6wsDL!cCa)oe#j?3k?3j=Oh#Wg$Q}q51RQP z3E#7%1Vfh05`G%i>b{5@5#wX)BJUw$2ENI9(zn!tz?Ii+o`Q&oCVVhcsVB9PC7sMMzd! zwMP+7AfyIIGJO=J3SlDce1cXd1VN*Oi&@@ZEC5Q!bXbd?BJB!lLWG|NHwbouPp3`> z!Ut)I$of08SsJ2-9#LgLq8@E(3ZzslY_ty zfre$0ObZ%ADI)ci3-c8}rVL?-)d-o3Y_6&=3=91z%z1w-zUJM8JweAi zG65z4LJUvl#55oyL`Wudn-lN@`u`T32LS`I+Vd>R(Sp|ae+uUNwH85O#=)`Yr;Y!4 zm_xvY(Fkorjl)+B17NC_DhZNu7#Ym?2?14%T2{6?IRiZa7TqTCf0mExPI5E11< zm8T@7INn}-jpJC>(m6fxH=}D&9Kcgy5ojNeP+v7Am=-pC1;EZ{Ey+}Pv$h}Byv;1` z#8kYlh2@S=ops6Lbbllj5vR}x;|x<_vcvK~PTg$5DatHP7{{%*ab!mD5qQg^-oj1| zj$;Q+&Ly`C^9g!EL*$DlEqW|#!c+$#nVqHEjo}ne%U+*%bV!8u^NLgHXfp^>XGvv(+yo@_ zrRZ{@WEtmMRz4GZ!n%?fa%MF}-d+1cN4~~qd~(V6oOw(4R{QDPxkzb8w6vNUc-v(DEA#jxX;jk(CHAv)s?L`mH!0q@}%CekK+F{mHac(O^0+EAB@ zHA>!`Y;C=ixUE*OMX=p`^e{)TX-YN~!h2eQA>rh;BNDqjXsvpsZk~n>($#BLqE^Uw ziU|!#bCyA;E$UjZao?^zi;uAc7-6wP0(N3OhknUSe7{;aZ4wahocYe?_i97JCSI?t ziyoJ7fhVWQMuWGSN45jeB~fDxj=VzTUKJJ=cWIU6J=}rNR;?ip3sqtw1MH>+p^zy2 zbz;QmEY<{}A88_@vfRSDRZ%NRuer86jzq`M`HWKS^oh@jtj$viBT3UJ!a=>n@#Ur? zvT?uc45o#Kv3a3X3(Li|HQ6eZ3bSx^L=2F1fHCZSh~H*;CPGa(IiL7h3a1r$w6^WI zm!CNX5N{=6D15#uVyQu&h0=lr((Q#J&eYxK~%YaY31{D&FoeHF0dznL4q7 zGUoiE;y`+I4i|6i<)ftG^2KX(w1b3Yw4iz*MTA%dDgQMrD=%HRG$c>BfjxzrGn+0jWhLhq7jr2dtYt0t!Ko$KLt`4_*@u3K8D<@k zq_OKCw=8AP7D-GnFq^Gxt_Kd|=z5FgMq?^gVq=0mn85au8BA!nk~)(f)y%myKHWOM+=c&Zrm2A7ednr`@3K zywr=7uIbvtRyqDOXU_1g3SE>5Xxvc2?7(0vj-776oIiW%tui-%1)qegPj^1&R`rgz<3;w2YOc1tsHVaa7Tddd9YB(EQN+ZNm+7D3$nTthpY5@aHE>zt&F{UU>qcVdoHRoR0= z&G+1X!yG>`e&=6Gye2jS#nqqJVZQQ!Lz<; zORcF`zOaAA8kSNDuOrXTX^Ip(yOzR{w6itJSF_nxjj{b6ROYe^GG?Nxo3Mapj4ZT86qmn1JJ)64PP#m%}b>L;&NGFL^Uuj1-E69zS z$HhTg;fygc++-&@ z459KdM>#VEWmu-6S$~pRq^Cq-*Vn_>EW?5FyOADFDAv9LpK-d?GPdDpsS=$vYEDVS zu<#`{TxvyC;<4iiy5eChjK_6plp43U*uQHu$YtWt*R@;AU7-Yhq#cx+*- zFLZHI?Cy304c5xI=E4t*u`13F-lKt8qZ7ncMIE&jBDZ18c!$kAYkMP}XMmqXOm zil`>^gY8H~tm9@B!Y=M+?xklo8R+z;6R-7S#&sT_Zy~weNfnjA4K^BQBz;5AjaNej z4oXjAMTJJSU`< ztstr+9XU0%;YttrlYqlD7!t^POjl7Ckwooua`O3360M=eDpDK{9I-W+!;D*jGj zS^)**)-q!v&1S5REx-~~BU38OW5XCCW>qln|7chzR!X^3$JO}DuogqYPAo%Bp}|9L zRdZ&iC-ImmC1`9_L@hGQB8u%@U!(c2C_N&X!;%9t{bzEnsp@zJ^D0$5bK?5nYb`Az z7`PvEQBnz+B0)({mg4I~!+vs9r{V}Sx?Qb+bAt_$Sp~g8g+)e(OSmXzolJ*|2ca@+ zUSS8#@#JwLitHeKkq<9r%hygGmmR!RetL2 z&02?he^5k%+QKE0l=4VLQ5Kb-xGw}y)@ak1fu%rAOA^%?h1ZtoS%mV#aR&}6$}H5M zeeCUVYD4%wS0rD~<|6_bXL(RQ}4|!&1p4iCJXsyq%s8yS1*c}h=UbJg5q&R%^#fN~IlG@`zWRQ6uq&CEESSCB88!~T>O~|}N{UbFTroAQ=`uA! zq>IZdibLvDCCCeLQ^P5bXv_dTdN0&ocsFwS^YX6(-%3b*0u#A)0D_he&YX+q*81UYgX1qs?CNbl~>;{v`VZ=RG49ClpcV+;o$Os@H;2;6a z$!GygMCkD0Awl~YYDEl!=m8Lb2SWfC8%l(UG7~m@F>;tOHl#2JBq#`o5q3lg(V`k2 zHi+JtA}%-x>V}>iom)?NdlioSsIY(!tW`d`c7=>w_X%8= z_`9`r&0K*jlImpX8Sucq<>-=XsE;h$pXs``eryXWjapoFdi+JCK9&crs9N@3oVbMMpO5;{ zA`;zNZVQZyz>`*4IEm*`zzfuV@<TNgV3Ks&(kjR4%{EE3)CG%OP`$SU#{ckYNn9cI9WdGgaB# z>_X;3=$z z#k({EoiR2{iS*$MMTlXdOlajsM6ur5MNGT}QU5S=t0%jVT~%?DwDh#$GOq!hcPGuK zXF^~(eE^UJDW2ZYcgZ*)J0s-?{ltt&7g0KAf*K}vNK|kONQoCbcHHofoD<-_E=k^@ zv=K?UK+6%cj~)^OCmiW!=CFDo)syo!YB6>lDroaUJwyu#h}SGs_fU&W0UveW852Z2 zEX!BhxlgJ*Te7SwE3HPLn}7pNzaH(&E`OrY7Hcdyh%$Oq5m`ki zu>yCp%JIKXnJYdqs}a)NrwGhy-bK8Lyn7Met8d({xP6pXhwg2i8`Ifc81k=sGrEc3!X=)(dhT{ zzj>dle!Xb}&8`OdYtY;*I*@9L_v%UJtW#$eu3^^Zdgw*rKPKl^MAwA0ODf}tdnfQQ z-;*L{I8W6Mim>NbBm~|Q=L&!C^U$Ik0FN>;L_&9u)bF+*@Q1riMgy}uwZeE8)NAsaF~KsCL(d>w{st?C?^^b zgJ`UtS=MiMMj0)#ogQ#aOpowlos4h$FZPl&)wwU2KYIVyMm+3>1t=-f_|!Fc{Ofy; znzigX37GpQJ2JZuD1vpayNgz3PZz*4lEgRbi~;t}SN4N}efURDaFV|Zw;}SBZW+PL=B!~JBAoaaYA@p6sO{ISPtVt4#+A4&N>CrEmOq{BSX;PrHL z1%wr?vDZhDR#Q3m;PHRd8wGndsypBGbQtzh(e8HHwYuuH3fVACDt6-&&JjQW&bv%n zYnI=Sq^RIN&rj!TfxW|EuyE4^9Y^yKTjsG|_`OUO-qR`_iNB9h(xl=Knx``#Wj$*Co1*&~+*A+8@SVpog zr(vLLrG6p4Jc5h!YB2|g2g^?^<_6jM z?Aa$uoirEbii%1Y-d^+*;VA9WL6Xbn0rPkM)h9Ka&( zQB{yF5*>r0AZik?$4w3mI??OG0`u}T-q`t`|B0=UO7s5v&OYY!Fn9r#xlzQjuiw0< zI$!aWyCHolG^4*AA_*g77Roet#hmzwi)VrzT5L>?7`1Iz&n*#9>CpgZdskX5zDQ)l zRe5S?{yA7TCkTkeUo&XtWS`w^)UH~g?R_f#<7u<{hQkr3GY|_9H4&R;`mb#%C*g_o zP_4BhtK$Jx!lEuUFe>OpD<4^~LHLhtLv@+6il3UNvu#*!=F$DTi)CdP+X(244e5bm zA9s}fK1-UDhV(pm1pFZ@PQuo3cfUlK^KRNzTpBicqJdUIe@ALkaffXypH8J8CUAGz z&|85esoz``A#rhMD<-<-p#BdT&7(fG=T;31i zIg_X-uQ`O(sBLS9mk5f__|__q8gk6Pf|G}N)8|l8i^TY$Q@7{sZV)1oK2aWy{H#f# z&XHb1(n=B1GnUTmB}M3`N`n4jU0$$PRYYag@FAykLy zuU^7l_*yW8*}>8HKUY+1h4Nxf9JeHEO|EI>;(HGj%Q^KGhY(rNIEUXS&q7mJ%kPsH z=$`+Q@CRV5P+b=CDBiwL)atqd{mF!8g7aK?{A*?{3+Q{Km~1jj9A{e^sK>todvyCR z1OZRP^{g(%H*(MLJRO_?p=*msTMOf%L?W(?vrW6B`@aG;QqxQd&3~tV(d6l|pyRmT zQ$mDbmGH$Z3}-rO3o4goOxj9{?o8-F5kINBz5(Jx?)WU=77kRtkTu4+4)}yr_h>&i zBTak@>LeekJs#H)gmT%vOYl0x&tEOBr-9!L!MA#Z+*Hqs#@U^b{jAQ(lfOTfCZjvG z+8geUmj$K=(hPAz-v2ea4mixsd-ht|+0r3-8_@ybv)v4MQAuqGyMJ*TxZwbp(KagD zge}IMvXn3Z``^Ys{=o%#LX`}r3|hahqZ*jYTS{D#*lq@#p+OWaOn~W-sDba{c3^Ui z^=^u+>`$FiG~>&HPiz^dbKr-Z^7x4Cc#$4wPOW6p_W-j8Cn=0vnsF)fjQp_udR`~* zc#z&3S2Gi_oK7px&+NzM2|b<*KGRONJjX4^qeG(eu;LQo%V=t;L(28oVbCgEH&Q?=@sgo;dv7jl1f3arbu_oj zaRWEZQo~4`Mk4SFeMFCCD{*sf%p4>|?;Jd+&at|(ck`olGrNH#5K{m010YWNq#LHA ze<1TgcI;z@RJ>t8o+-EBWgPz2LEnfjrEFJ!-2Oa(M>M}Ah4K~sZF|+_C;Lh44?9xn zTOVajq}YmIH2pch&gN6$Vh8$o>zYobX+7U|xKB?V-lQ4mYJqqCtsEB^3*on>RMM-& zrMF)wmqZ^@8+aiCw^Xpf3=mH8v|GV%wgiJ#KS$Mzq$?g-kj=_*Hl}HUlnL~fNWt6R z^oC~2#N^3+vUP^cNVNS+mJ?59*BiD$kF1z{HO4lqu&B+Q4j(z2R<9;=>zE&x&JqzY z7Ie~2zaRb%2lXP5DL}8Xm;c6v zC?K@6_16)wby7w4#Smzvkkp@#bg%UqZ#d@+{Zg!Jr)xuQQ6GNiv{j`ZJ`dP@E4))# z;J=OOLxxD4+*P9VI)BgBLght|loWlp!`En`2PY~Ed6!RN8F@<7gkAP^p&cD2H-u={ ziXDTEkV*{NldKJJ2gWCj(@5U`VQ)b(eV#8g?@Q7)hH!HwNU!l=wPn-2bA3wrEp4^t z(3)0v$h=*CD?Moiujq>Ys!SK80NomL?)#D@ph5eW^y-Mn9@dU;A^L!=Yk+0VO(Vw8 zL-2H7%rJ-O0_B8+_^+Q5XTA^vHG|P9lYK`dC1h$POR73M8|XN$-$Q=}BOGvU@azuu zH>3E<$$|bEe~7eWE$7d+(lg>*)%+wTa1d}HRN7ZhZ&Gk-y3GK2g4h(+gv>)43+R}j z5a}oSXc<-iG>Li2<8kG~e*X>0VFqnnB^?-2q4f6C1l-~hwN}E_MG_K)G`J_@d#P}6`8CrMfs?q7W+ax zH5Ki^bYIJJTZKP6xMCCIAUqhx?I1tS7mn2p6Bn;O*V!v}rP8`+`5tS|m% zH26};TYN<=9rz2oKt5&8wwrcJa4? zm9by}D`Y9L$$6kC(3^hQ8uh`I|GfVbC2ygtt=UyY_eT%dCex0;&>bV3h;9U^Xcv+j) zlHfaw8Kkfnaik$f@TFI0>&mz?Us849No<&`2I$hM5^OcF;SF8ZpR@m(aoT|rAw-qM zV#*@E6Q@%;qS-$(oBBIrH*_r%UOzcvUrHaa0>nFsamq+FqDPWr9=6dD(T`XZtBUrZ_+jBs8Wll#PIQh+Q{;o8oe{t-7BCUQ+YD(zD%+!V<7<-uCjGXC79N?d-=4` zPZ?hSS#H5BJoPaBln2XV=?`meZ1+*jB@_q`SXCX{>$6AK;!sY zV9+@_PWjurQjKQ)7lC1hgQK^OB~O((fRblpi@WP>=c&`7C(8A#5~H~3?Rw?Ip&<@p z^#}LzqR_5}^ADCkYDgglX%Se{*S0WLGz#*!jdl&)bp6rslg0JeQql1n@kM-WfV$<1 z$SJ`B#%Vy|8y{!Iln!PC(=j~Gj(p{gq5TSf<^jr*%tqzM(KDucNI2%nL|J|hAc$j< zCXHU&T)gsUzcC2>&$p?1oLIUrb>r&DZT)R9x2Zp|xE!)|{)=1ebwbp`cGyMc^=-1U zyIyAhD(%>DGnMkyMt%+mF$L&+@#Rg%Dmjbd@6Mm92A>bY8o6GNAkIs52lU)9kLs#_d%E0Jd1gBxG!YB{i#B5&SAEfshgV(f$?k^ZBIu%rL#sZ&Y_*h{I+#6*i}U#UK(jT#dv(`6D{p` zTt|uL=&8+xy_YAZBjqP!rXEJx^SHm}2$z$L*g6-R!eCU;w>%8*Kk=Sq0iyfZ{Av34 zNOh5&=>v@1{4rGE3N)CJ0pZ7l1;OZz)^l(2&NU+JwT+CR^_3&Jg}7IoDy^IXhk>2Z zndMBdKGF6+6!O(uDWLS^UiR>+y4(FB7K1#rl9K0zF70)vpdY0Q)d5f@o@K-s=lTUc~ zy2$hPOte>3vY?^lE8bPhBBOQ3A}zn$mRt`mTKFP>;Y-dQMBoBH@bWYyZh%g1z=;P=Y`5E0{%(Aa zM4`BO;SU9zMgNTr(vNux;uW=mZ@PQd;z9Rj7eM5_VrV|qUy0X-Q{9;?=9cfD%XKQ} zb8--MxVv2rY0#2?J6b*^5Zw4y--u%UOSD!WxM|2UgDtZl8*@wC^n%e6XD$2^5np7h z-J)$L#dB9w=U!<+Xa3WqbS<%hr0s$kQozY(a%}kZ{s_~9&(gl9D zt(Y8;@tN9)m+M=7`Qrd`g03mPl*kd6uHQ#SdBoJXf%izoXMv59IO1FO2%7Xa^KADl z8S!rS=bP_GlH;R&_fcKp-J>&it9CBPwdJ?qPQxx6NhL9&7!HTFF1<#Ot~(6#M3AEU z6!S8ad<7>GbMHO1tvRSQ1RU4M?UjT@5O)v&;ZL}8+mM~~>zHhzYiSiPHi!F~tfdiE z=7o}l;mGrEm_Ro4j_})s)}HmbiUF<(?U(B`j;p)qMdr!n4%qbVvNY$9-gas;O@Bf- zt>@h}vXrq4e$w5nQ8xuqVScm(Pv`z_7Kk22hLK^4ucUFIPv6NhuZ8b51@&Nr3GE`F zcSGmFDEIv1kSRkdhJ6Sy`P>v{fySirs)!qMM7mgD9xgf1pWJR4&!k2SWvULPRoNZK zmU819YS$pvn)O&t!E8;I$Ue^m0+0@~zYO z4v!mqGav8k$Nb^HL-Up~FyT82lavXRRg-J495d-^1&>;O^8LvGE_<2liw!Z2*3>-$ z(CzbJ`SA5L(}8mHpjFe+If5hap)#7w(5O_bwty58+)N4c;wd?j zbozTDD{kmiLIUJDr;c+$C;VWFynC!N*Cra95N>>70jA>6F;?r}fGrO6Y7`)hvgWtM z0&EhrAsqWJ=Dfo}S*Wg3^38}Tcnh4za!r1JY)OF@(m}RNTWCCjg1ur_HW1Qe|Dr5@ zm{IWBFP1@*?+kKRuBD3X*3&1f6H?!{6|A3LWqP3r@>g{ zsYH3YNxiKC7dH42tQp$Svg_(BtJcSr>w3wvM>K7de39uH7}Upb$a+ieH```kM%^@} zh{{2Q-zoHlM!F-~$abz%Rs!%duBy2b^i?#c`?KmTTMqxyk4>j%`hk0XuZ-dn1PCN$ zGn~IOjN^q3RWDNv$oc8BBrDfSi6jz+tmqnkyRI3pI_i;_U6DgNic2AqKA4FC(*G7? zIfWbCu-4V=$Q(~Yrng)??53?MSqnEj&JucJBNR)AU@J1hT4f+uds#DE?d z(^M`qQW0!M)#dE=Uqp4%_3xs?oi@m67ugx^v)EB;Nm4%#%#@>)C)AGM1wae}h{{OYiWk$HqWlt@^dNemX(7i+Mz8 zbS$c-QUP-(PhNELADo2OK)A`?r~>SO$1TXz0QWL?jen4PPSvSss0OA;GC}R-xy)bm z%SW_NK6=Zpydx3y@H4%k z@O9R?La(JuqvCDMLRS)UG8Jfu|NZ@1UNawcTOr%hdR?2UbAPDSWnV7ij9%HPQgzyk zx`F;7)}2S9vp$vF6Ax}Wu?j=Jc(gp;mxIp1H3c9_aq5>ZgypxkUH03UR8+M6yMQ%W zpxp+%aN!Q|ZuT~5>wDSLhI&PmEqvoEWe-l^IRn15DSJW|Hpe1KNmv#oJr^M}lRwqffZJD@H>Y7Sw%LQsU3 zmdmYnEM`8v({;oAh4@kgk20SRHq5vL+!$qSK4#b_(m!8cfrLq9p|gera^ zgYwu6Wv~6o)+FXREF93P54UbQ)-QP|hnVviy0YDi4 z#4M$nQL`x=?X1W`|mR+!Fq&99)RCg!Cqd8TLn7MZR6pO}e>h%7EHLqqpbFO~F`ERj`T0LSvNdoIdqw0gH57q02N8wl$#cN)sl0xjyh_MeZ zjoYO-Wrq?c3OmAuBuaKsO};`UhtS*vv9&pqQms#9ZI+^kF9@L+?fZm6Vt!6d^ghX< znhODa8XpTwG>qve;Qq;+SeBwOUpw}~eFK;07x}N5Uq#(17|B8r=^MJc;lKECB%%m9 z)QML(48L#;J>GnhcD36qRp!(MRIY=1#O1+GR#tYsPV3VCIty@8uQ?|6!rIMpvfVJ< ze4Yclcl^Wb9@Y`Sj2rnX9oj9g_nsdC`KJ0u@>KyUWW*O4us!8ZZnUQMyeLDvg;!+d_=J~QeBEdZMt7pz@AN=XuChOHiwH&^2n&(7NZZ} z>!_#3=jBOB=eS6`mD1Jvg8P~i9yd1e?i1FoRq-FfnrEoRMAES&)gh@Ja7VIK&LMH( z4Q$Z2J>XQt#*HA*X8W+5*-X}ym>fG7l-4qlVASR9EnOU`1a0j%WdQTpIpa9}pY-hM z0S5&~pgV9Ub~;*Fc+-I(31D8wQ{{^Y62(P}tM-@LVddR$n1mzp*GAp=bd#nkse9WB z&l0>k0iCVoRtUar7(CaZoGl*Ot3Z5x=sNGTis)mgdg>jn7;%t{!@g35RT< z&g?<}_TFy%^8QkMlfg0G5`98PX3SanK^=?SXTZKa4E zMt*^u=udXvaY-4m{eKc;2|C}@p=>9kGzqv{bDPtnutp{fiI9sR@r7Q_aHYU(GQzci zPy(j&WW_A#Lz$WB&h+qNp?i1ii84B)sZJ`@{`;B1eQnQ}(A*eO5Ib^JFa>FFd$Yhc z3$W%>N}WRt>~3Nx`#9uqXbf?&jS6OQ5KC^h$m$D zY{8C(3tS@&=7RIX>o%LvGfd41+TQ$tktYb4g=CYmt8^?ssqLJv6>{WLI!B%KWdD$* z8ixdOJY4;*c_Vflmc8UdaCBRfXXwYmm&wGZ1CT!txH%WG;l_?*a~L=N*8*V?oN*bk z_z+uz1vAd12frea@X6aSkjd$WJ7+o@EHgzw-q!KVNd2rt7Zdv&3DaaY1*AxTGP-}O zlM-o-t=Z*7mCDFOx4|Qk@p^J^5;t}$)cl&iCqbs={7YN9rirT3TeYX_T3yqGw`Md} z>)W^W%;B-x@LJV3O&pA~Y;}fj?3>C&r+4gEnG5aJ}HrecSgSBNHVd85o^wq~q zO`W+dbS9j-+(Uae7PPinTMq3Sc34etn>E%bZJaag^d>K@+DpV1yVolw%w3xYbdau| zx-}yv9-bpwdeb-d>Il&t+sk#v|K&Dt5m~!*b^lZFC(Q!8yKBP&AsVQ!wjFgs@o1UB z#oS*lv!jn*U-4LViCEv7#KmmOuFWxa@*HZl(Vb?{V=aqb>-oRtHnUH%FdIHvHKT{7 zZ!m2e{xj!{8QjrDzxtm7Pj%-1%C`PzZp*>uPyK&6dxY>z{Wi6sgKL{?R`@}E`=;cv(vPv=9Zrqt+`+Jf^lL@>2 zP2&`;8m7u02H=gcqTU}Pao1owr%4q^ArHoUQ}%vPc2_gQJ)&{mqY;YZoV^W~`wk8f z9-8}@aQO_<{u-F2Rzg%!M`0F36HI`dWAc#O3Ke$(j+Ndvd%?UQS>PVtV;FLi1{)Xt zg#DeOAKh&U=s{T+j%c@4J%HI-bj|`o!evNS!S%E`Q&7H0TR5KZ?*AY*EmiS8_)$Xb zOmv98pb7=?-tf}w-nWQ2F>p@GPclEb$b)M8ARrdp&cmSsyj;8r^^?p74$V7Wzhnx| zAfNjHVVJFgZ%%A6-@DO^0jm+_76wu2$2z0egI@UW&t$~G!)uB|jk~SwH@LFhCWQ7~ zkNZtHJ-WgLW)Bl*rYq-jPOWRz55`}azPwSwCZ00#wuAPys*go(+Kq5s3uWfxSE|9& z`&*gOmC`ksd8;~OR&b_8#RP`(l%r_obH8K~UK4 zu7(hUSNjXZb$>pGV^FRLr6j?n(O5FGfTqsa_cP|*dHC)5wfiB91v0TEkcW*XK&qVU zDVZPtpw(oM!hyvPw%(&D2AN<%XkP?eK~uSf+UE-0LmWpF+8Gndpsa{w-~vtY5dv6X zlt%!i@$7%T=a2HgqY#r-i1y#)mb-fx~d zZW_QB(zta<74;i)h!)Nv3~HmF&ZvU2;9G%A>dwO<)E|R3|25{4UrL+abLjwS18E1* zxtG<~V9ZObD;HRauR<+*71Khkm-J}FvmqcIAp4SL>`+Cy1Bdr<$ED-+MuV~-@jW0i zK}@mIvSsV(oezi-JusyiMAZPC?UP)+p#LNsZY7J6$2X4~h{d;BP^a9!Ldq+9I%YT9 zm7cVP%o!uWJ@rdDV&6R+uR9RRgHV8Gu}0^p#>|20;yTd5eP(RAXQSU16LTE69q?7za}1VZ=_eg+pX%fj%UDpGg!l6aK7?q9X=m5^c_#5_qXI zw0VC+P$$MAqeT7SnC)~9y5AF#nUc~S26rCXA|cyswyn2`_82*wA>cIrC*%i%cvKSz z*!iJYgAftcvgb|NNXEwR=`SJkTJfjMFENy*i3Gvn2JOOcXAiLm(j*M48j(zj?&b(f0(|Uj4)+$HvVjs*lYJ%2{ z$v7lb0uV}wIz{Sz+m)nBKcO)4%g78NO_j~EQs`1BOM6%z*fC6~sGUzKsynt^M z@Rxnk@KwW8UyNQpXf$tVy$=mM-sP}l4{Cp1r8Sqt0MEKC!$6_c0?{3UlfH^eMF+#9Ov z-wuVBB2EJqBx4GIZUPS1|H4VMXC*;DK`>Y>_50-22=lsVxvUQ%DTfeoyCDdq5W=%v zD+1IbJn=_mV3;Uog%yl3#<M-5fZ&t*tb%knP% zRZ{F4R9*{OdhPn3uQ+54f}&Bo`Vdtin{|l4RuMP`$VDZ~JwY@6Gcc?8G-=~_M06}R>u`~)JRv10V#>s(-Fbsn32Ll$3hJJb zo|eB_`TDiyc7%ifa;8=Z4yM>^s8U%&BG=NA{KY=F*bb(-sPWlOdk`5JixB=PpQ$R& zQA(?@1-jp=gZ`vICzu1@u|#4i+mK+$d{ZE}90d54M`B{#Us)RPsA~Unzk+$M zxE3x|p|o@6QI4CY&I`8`d;VrqPe+qv^2`E-XJPwA9@|o~A@?ozmYG2{(wW^LU`1<0 zlt_wy4&_qX``P*+)5=}F5!mIbZzyHK9hUHD)HVHTPGe#3pKaW%#eJGCmQaT~KsdKs zFatClG}?sYR^F&w#yMAMFXf|EM#-Y$QzMw-`w)6vPLDiEytVok{(AAYbvnZwG<34O zO`|JgFbg(e)04e5Zb>SX1JS<6jpqK-t86`!_9?23tC~&DGmfRCXGB4k0(Za?qHK)U zRg5YnX{G9_0Ip@b&`@PC)qF#v~c03GUis+^NfEQ%4ZO*iWM;orJ+BstYUlf!OB0>ocSj?KfFN8=HEPPKW zm$y~}hp+BDw1h!XM^!*4wg?Ssfq>rh{s$6&=%Kyi7H`zq!M7~6+bOS!X@mXSdI~sA zSe@&5m%VQ1<&{T);eMCS2gXG1DJUOyngY{m$w%E|Bx$A>o8 zf4o4akmC-A!o_sMC-I*7SN86meHAs$81R*aB~Ya zH*!&YeLKt}Cxhq8<>`2M>PJ9(1gEpstXQe~u#gUIGr6-2)wx;fOd(C%-ZkcUx$ImG zC>Jn$h3#(=sb$7G4a6WcD-2lCo(Z5{L zt+Pgp)IWKpk1g$XdRv|WJeS#BIcc`t%?zJ0(b|;6!vkWHNi1j z4L0kz@FfYAcn4yRU^?Q`oOS(*r6R2a=mmb|_V^dE~EA*OVFm%u%?vGWYDp81w zA%KUiHa;QAd$jt}uw~iKvyd|dcOgj*J{od6bb-x#_eVs@^3D#`FdN-4Fa)C-*f zUn@$V9TXz%N)C;6nnd!2qLiR9loynteCwOo-Ux(zkf%4ZN)ALKw#5{emb;c|LH3`J zF|_`SkQ`cF@Si_Ts_eOx==ZRlS-Iqq4o9NTd+6e0k4T$WjTy4hDz|@bhlgBNpG1Y4 zUqQb0CSu&0OHZd&(HRJUI6t&{j_(IKYAJPXhq5?s;sah!?59LND-dl>qNXH8@$TA9 z*gYN`dx#48MtF*skcfPh&Mh7h4$=Wq8s5PD%J`E75Vs5jxuw?LcdA4|P*j8I?pQMm zCah974>cno4jhLLiWGlHxE+ak&AH@vVK&if#K(t*V+;cb=;O;-yMqJctSXR7(YRTn z!zPlX+k{vG+esK|6D;;7KN(o@ayw*L^+|TU*ulVxG%}O7VWQ*nfI_nJhj#_}_B%T~ zgfN4T@7h&Q2cxLR%Ht^HFQ~;A2*lb2rb|9Azgolaj;)Nrjfn3gDc>Y zKroj1Zp%{2OTS6mCIE6H=|In@YbIUgEbywmGng1-B(v!Jx~Gw%?vlV~7c$AGC75BM zOl8+F)gUD(3Vt)mf~Icz%-NJBx>jf@z~~4iUE=CEHE0BE0|oDp!A5({!Kz?nR)eI9 zFhBp0o{W4Zn5CXOY7-5YpH){O{_N1zkBm}Y>Jo(bOw;_(}a6u$x< zaHbfHCLYmR@{r`G$GuO@6iG8g%?L&&4)iXO{^EA0KE(V8t(I2-n81qEX7Cc8fNnvM zXb}&%)lDg2pg=V$CCAvlq$`X2gpiSt?QI-%8pyu`%mRP7DMWglfrbvSu#zUiZj*!p z-A41IWH$kmT-us)m?_=}i4D-S)m(TL5YFaxYYkW5(y<#U3#a+`(&_=E5hr_pum7o@LBydc0oADf|^<^ZtZD0E?lhOx*EM>gR zk@*IP%FU&UwG70KpW&~NO1p$p1TzNs!_)|5+8UZcXHY%dQ{rPsz)>d(`B;ZfulECw zlQVzvcA|Q<1D0%On&SQ?4ch%fxYP3;Y{|DH0$#hV;z+=Kj%xX}<^PACyF@w;7)JPo zU_H@dDvBVZ0Bsl~a42*_@a3ruz6jI!h=WJQr>T*IWC(!SBjAEmM1*XX0*)~-eM{U#HM{u41yplmzjSVOdcf7Yb*>X|NDFApvrepFZYTlDtB1| z|ww;Fg!@xid@SOZ@xKI%h{_kn|b=x`r+xDOom;RpNh z$v$+5M8afJ{1*TN3l>#XRaI40RaHbpL_|bIfq|-t;?HSt^1JDwo?P%h`AHi`Fp)J$ zV1l{wvzeLPOe$v%Elfg}#A3-oNn?LWNxY=0L`q0lNpwl%LL-oHWN=21M#L^DA{POG z@2D_wngdYO=1{M75x_kKH_F^@J&Vmu`0zmz3mUD#cwc zF-c!nFVUU?d`c1;oC}}xV?QjkTJi>XpR6aOQb$p28?+8B~!tIkSyA8@TX?lNByUB4=FB3V2 zn8kPo;BhtP2L0dM^4v)>9iudO!{$?6?QBNQThTtPE0CpMLD>_(IGQCQTsZ#<3WK{o ziq4K`;weir4i<5cDToTW(UaKi7}#V96JhtC*&^xYN>Y5nw{a4?8xF9e=VVyV^Y-$u zl227=WYhe_VF;Dt)yIE|rv2Yd$)CW2aS~s>Qp{#zRE1^YdRRA=MzgtU=aMKK4W(|S zuY2`a5Z3P2NFX7 y>@vXuR09C`H#U=fTO9=-Pyqn)lR-&91@A*Yq6)JVMIr(MahroUN4Gdf0ni5Kf$%Ha1_BAGC=v7C3s1NmE`OOd4kH+FV=$Mq`(Gj3-I;eJ2L4zy^#Nj zvmuzsAA(zeTY|(C(ghslWj<1Rb#h|Y2 zfdUoGlmsm&TaCBU0-0zG1+MTz8X^ovmoR}})W}*AnKQLw2mjz}*)X*eh1MB^F7wGk zPY0r#a3#Xv$&DW49`ovP_v4K?;}jNg6`J!!5yB78LaK|-&A8Q>8#Yx!*I(AVWeCWB z0;@D}n%j)}kl{w`24Ep*;*hB<*kTOXc~2N>XzJw*wEnGnGeHpWpH$o1v!?@}`M-n^FlHBQynGk;utM!-ZS%?Yw{ay&(Z|G4Q%WIPKetC?WY7&^ zXcW6tzG>5vTRt!821zG|SZ3gv2ND2y07i}5oU2VtP5Dc1(ySIUVY7+}MgE8-hOBmX z*`u@BEBW+BTQCCZW4MJx&bDX>%-c{SnbP|I0p$OI*|qg|HSjB z*<=*MF(d>AP^GtI^|us~hh5dnMHQiJe~H+OMSkqh-c;=I+EZzU@yNQ2}e8 z@B&hhfn!XCnMH-;k6|Hn0PA81MtR@}D{xNk2gbfbCz8&ANdhNoTrNz)a%(0u2ay+yHCrpsB-U)dGV}q?ZVPX+wC8cxDb}iXK48#kbNZ zNWz6y85;7bFa7$k++9!p^T))&9dw#t#X(Ck&(9KU$veaU?hcISkEpu| zYZGUyC25E3JnHIQxd&I?kq)`nGZvZ(TC11SIrXK*x8U+TW#i&@yxUAMaB3UNnnUf{ z*vJQ!K`F$m(oS^I%wphAW7+SEaUN!Fu6FppBW1{V-o3weu0y-(tyENr-crpY5@*Tr zG+}Tb1)}kX9)e5bZgtdoQCTe`{dEI8C10RO$sL{P=`w^Hu%t-LxWdpGwZhX3K)_H_T|%)1WbOp_`tic?%%Qsp_HwDJmx z2jYqk4wk7Xs2+ifZoCcENP-evE-W&7PeKW!96{z2N6 z^99%+4C+7lLeN^ge5ecs<5~UU73;)kPcf@OzcmGKB%FQNT(85`r1phgkRE%-sL#g!0~?88k-{M2uPNH=Tv zMa`(T42@fid~h}3>P<**5%)oft>8`aftVOgSplp`ZfZqmQb{uTED_{mhRTO=E{j*v-Xf@hTUcD zxvu5$)OtbjtqDQ-;-0IMKZO+NjEMJH?DnyX)G>(=9;v7f%W~FZI4e;zA z#bLE%x0O41qXh#LS)C{kfBxLQN{T8J%LR(HDnxMTa2*hftTA&;0~uhdi&@ypqf}OE z5LPu__9K2RtdvBFLy5x&acL;5G8L1c;XZ`|23PDHUZ#(z$%TAQ>ZVejE*i2HE)qS} z0&1sphF=p}t`VZu69u@@>N(QnsVjg-ZiOKY9)^S@omVu$=aQXlvG@puoSMjl34pl0 zgxE7OHX4G{kiGNfMYEU}6W*;+bn}LZPjMaEH1$lr4R* zha4+bbJ#NA>Atz2b=g-7YFrF=h~I6zNscQf2C0@7$Y~+ipskeRJKp7H)rh0TYz^h& zRnvyy*&N!0g$L3IW&cn*$IW2T1P1$KQ`wB3sOoFutaSiw@*b$^5don zUFj*8Rb&Lj^wpqnHx<-=Fmjd_=SLy4xg1MR;*F&JT=L2?B^ddw=g}_4iD@qx;{;En zl|E`Zs1DOv=HX4jh6g#Hrahy>t=5|5mS?qMV4bMVGOGhTq6Wy+r9;FJ0$W*XZ3ANX zMPX&y?mRlu+96QeB*X}{<({zEHJw^Y_>40`CXlp$ zpsNet?mh~S^PA!ykGYJ0IxJTI;<)m$rk`JXHHA9}%ZW~rK2vjoF^4m+|L>HW5Mwxm zlc2j)3Uirmo11Eos!E~^0|`$3eGvg6>-rB zH-+zNcR762CzsE-zRUX%je7>)X)^u8B>i^Bccc8nn9GrWkND6Ic_-3aJW7fI|^P(_>a+Vv+yu=#dxJ5$Q+{BmG+eF(Zzt z8N2)#j0t+#-qw*O`Prf1LAZh-r3j>k=)zbdB1#VRpU}Cd>A0+tnN!4!v|(xOn2nW1 z>c#L3Ta%;#ZUf5d01~7~E{EhT%3s9@B-+Gu$jRmSWxIJyN1dN&aOtSj{BFAXkZ1!h ziNvTQ(&??UEF(j4!=m-Ku!nw?5~Et=YTYr_0~p?LpBpA6vhz!0E-uqdaH@^-q-iCl+}oD zQ-wW`9APAo))mG!nN zY=T%XC}mFx2Y(3X4_iSNv4o{qupxe}h6JrR<6fwBMEWK_0h?p9mzP_P3cFBq`$l(n z7aKVSYtSjvkVJ$=YU|%DI#{N1MB$Bjn&7`dc{^1<0o804HyAeYFa%`M29lZ&dATw5 zObrSfz5v;F-(q?5RE-H~zL8`$Ow|y`W@+eh(N^+M&_Rg=o<#})I{txEs-AM!=?Kz9 zMqF!c^zc@{7q$p{kEX&HlcbZ3B%%8iTvW5i5c;P)r;OrZBH5%nWylCN-BGa$8uD?r zH`!?gfDdoNozbKWx>~Dz)a{I;c}aGjE$2~u(z!swge(8HXTI};P*%HS#Nnq&hLG!1{hdX@q%a3L5PN48LCqfRPdpfi=%i zs6(UXL`AxbL03T){w7cEIAtCJX(zFg=1JdG)KsNIoqT6zVWwBvuvV%=%PuFeDW#m( z_;z}#ma9lAUS_Tw&PW_DGdKf7VN-?*p1-}Ra?VXx!5Wm`FU9pk!(*mGfI@?bJ{AiT z*#6$N(5VJFg3t_(YwG|t4BQ;iZU>6-ku1| z7>9y6j4UZ!RU@L2KP^9d@35JUX0RaK?V{JtD1EE1d2ptmb zk5ea8`hnpG@0Feu>$+>;y_Tw-=W|d1bb1$a z-zDntc+V1131Gy*GNTc~F&tKpMQy>{X!*X@)>INeN`#Ar-ss0yj>C3W<;bZJF8;;` zl|~rN-R)@+-grZ$>D0}K=aR@V(W4S{Bjm?le+?`P{|bW*EeT$S)n3Xioey;~BYd|< z0`9NJ{g|HUZqM_72n+?!G!u&hVIAfI-q{}q3FFG;+))st64DZ>1CYMZHdFf6mN4@B zy8k&=S7gEXdDpjvbhpwKWb9R(jo-E`++CAQgl%#M(Tuu>eLU&OJh_TG;p)i&7PvI#x!&1UOfLSwtV|@@A7^|>wnPp5)n7Qo6B-4Q-Be@hm@vNWyZ8E7IYqk! znSwJK-)fbJAASelPBL@x5mukBRz7vkTV1U<%^h;?T+1@8m;ux+hcH?$d#p>r&g3kA z(SEv7j?7kOq3g8^8|nPYAlT))=B$I6{mk|jWuXVyD|iHFg(#Z<88qMBQwEq;;^;Pi zkb0qdkkjZxLKN$;C7K8s9=ceKkq|_pOWa4F0L4*45z{FwU&tA#tLSG_2EW@zvt8@E zb5Qq|M$uWQ7sS6joE( z5lKwY3l3(mnjG(?Ly&e{e0N9wlFmO5lI6Dh$b}#|EHQ6OtangeuSUbdePYL^P)XPd zPP2IbULdw4t|QvlI`lA{!{jVCv-nXsM@!mkYE~kKHT4hBpX+gN!C-XzH?Ors+4hHD z!i1P@XkN3*04F5iopndAraWLgclV5-Z?Aw0yVnj?keZr|-o=!m0UqFaW&SyBvCFoxx z>_*&7QSux>C^LmE=+3x&Wh{WU2OZ$uU?u4`nx~Xm;mIBuk6J%L)hCpd%hPSS_puxL zpdutFQg|D}(f1k-7XOGb%DPY+P1ztoAWd$pNyrGr$&=6RC~|2#X_}sPe-ZF>%UKow z6v_~zO-pZ#O)tM0UmB37beq>P1K3Hi{d4g6@f!;;Rm6R>a3F0jl}+Vxa@XMA-??K<>_fjy2tE?Jo_KIp zMDeIC{P>quWcF)B&~>67$^6c_Yf-jg3x(H$l~I1PbSnvsQKdbHqhb`GQc0h}Y16=!C8O-{O1mD2rjmyQ)Li z8ONuzg#BRJ(jbh+_EXwsCh;7rQ_1$57EO0|F21M+c;$~wD(S7*d9n+qmVx<5*EtWs zJz4l`7GcB+l+NO^ulMo!iT)P{1Bw&M9uq}^et{t*Y~ z=#>t>CaxMv z0oR)A=&xsHCR<|Jv$@+l<298HeYN`j(Kemcl_&XuqnyifSVIN(lHLigOjb;_hEy4t z&8G7&sqR5XZCrYqI-gG@?8{#4s&+~h`cU+AoVyq@j`6?art>|N8{X009zX-&UZ$4b8QPkN$B{7T=ntGiG&vjQnT zYqu6smjd=~A0ElBePv`X-1ReEW!f!OCYoRYXUb~UVFJ~DTyJr<$VsbIa$2;Tlt7g4 zwcFKDA_nx-k~ds4akhWL>Ds_)@CWgGw)tx7MTYctpJU6aFl(lO@FaafW0>q5h_l+l zemq9wZnUFdGg~}08P!kJS&y;n;vWd%n(~rvM^pBiXV?ikg%8?+d+Z93#N6BZrpwPh zL9g-om%q;AOK6CFgOV01=x0uLkC&DGFr{#|b#Aa4?v22pOMNTZZvOz+lZkU|!;GvM zy(3CmPaD-TLV0+<2USN}rWaM82fgjWd`|k}qzvEU2y8B4_3q!R5)|3+$tk@cy)TJk1wyoJ_&;GlCr9=8( zwUM$qwk*=;K#>+~D|ihsK>xDErD!1Yg7TGj4#G+gd4y$Og^Q=W8`6VNxfl*`?#|@J1VSAKNkwPquf#)a2k= z(6cDi(l@in!}YkoS&%1-AbinRRoKQsGdC;wgJJ0TMH8XOzBC(mkQpKZzqDGNmCFOIeRJ-dBQgrNGdeFA-);j@?f^z}E!tKmS3@tFS|B zPoYPe%~z8>JTO8Z&7UOCFKdkYy(1{Bx?DCI-y=jc8?YgQriaMV=`hGd>gJ^Ikoj>4 z{pLxILo+)&_-`2aecR1s(#xnhD@8(5XN^Qtkn`lZq#G<#;p<;#J#yxdxRu9R4@7V( z4nuKkeg1m-p02Ao-uWcC&h$0V;(G?ap4JeQ>bD&@QheQpX zMM__JQcT@t=Y7;`7T}<%X`IH{VJbtg#D{C50Oo31`P|MVX9SaL;*!CM$O+p?jk6 z?rG{aYL&^`Xd_qkM3cCEPZUb2@f@S4CF0{~IGrRrE7h1;;>w@;6%bHbO@ks0i z#T4e&9kGMwMBIUVA<#|PzhyyRLruV*tUl$KYikC)NO%0;*}Q}E?n_tHboorC?+bz* zQ+iJ;#438Ec78NdqXjdeV8JK!kWg5n+@8j9RiY5!GzJ;nW4Xk6qlmm{&BzX(5$0DAS7``6op!!qd?rn{W)J9J`9p!9a8;+;5GU$`@4~ivBx7}wSxVX=|pjvUFGhTThWdqGCba` zY{D|^S<%n8abis27+ds=JM}dY59nI`ryepx%K} zsx43VF|o&`TqM+^jh+Tu6nC-3%=^4Z@l&T9QB;=+hb8r0{$@gVMSwjeCaU{v|CS(?Zm+O&}qt7 zVjLVpq&3Sv6^It5U_4j_+2!|e#vcREI@>j+efkpXD?CoWAj_KQiH3Yn@Yz3QKu&+= zJzeKyewSX%k+EKZ1s2F#qE^f{R-TB8!C12G`VYH);6<94^hwhIV9uI9+ z^{I7pa{L)?aZv*Aa&=Z10d3+m>s4*v=O|1t5o!T#_Y>^nU3R9&Q`|VkNkbh-FFW*l z-{vMa;uOygEMY>3!HD zf=hSf|8S)|RfqS)qmCQ(-#%sWrPRSFp%WhzM7&$~Fmy4Akh(4IL1Q0H0o6IGY4e!G z|A+FuD;g|lz+v;sY8msBx9ca+H(Sc;l~s*r>rTP$xOZWV*p+lwN+J`fgU@F<3)Vgh z7E(hbl3ryKm0-3G>ibe%i9nr=+~k7C#>sD&7ly1=lx<<{({X;jC`}Vt`h^qw=d1He zR7bzBapg8a4_v-$>>{QoAk}LDTy3w%@p6PnJh+FrpJb(=N{PucDh3<4IHhKeWPwUM zt*;ERNa(;{tw59BzV|u)rt&?sb#?fy*u!9zzrV7 z+-1H5bbYZB=a|avH;;-B5*((6Hf47z*WZlj$4NSH@-HvEE&tr*Sfa2{k-SHM{IGzKRms=Qa zGgW40;peZ3da)j2rXC+=!;nWGTbo7yIFKr(J_2G--P4E5F3&7)w;1;R++lkD*@kd4 z8OKP0zr6k5OoX4RJ!4FNin9PRD;&|S7sDL%Pa-7XDSBJSe-;)tmEe+ zVCxniY9%^;qds^MaLxoc`l_$)yEKKO5R#vt?aorP(4p?j639xtgFDopTO#b!Iy<#B z6%u?tw!XQHPSJ}_T-&Qn7`D_8`okc@*;Bz_Zr>4!lo`phnKxUEvK96>iZ`mjt=F=? zJnTpz5~A^7%X0&R=)w#v;#Fv-K8u%gV69@z8O;JiP!>;xLa?S{=6~2)IN^+A-1rX3 zuq)W-e0BZs?zb+~P!9Vz4l1F%WEv6OEyBEAO|RRNtrJ6;`Y|SB@p)wme#Gv5zrZ|_ z^y@I8Ab5l%|E{<+i`bn(Tc=QV0sU3SmmQ$elO5&(b}0^UxXCp^ZfH4jN%F!2kfEq^ zpu)esI`2B4&m}OPr&5OX%haJGNN75V@_|BxMg#1pJ*yQy>zG!w@ez>?$bS-aI;Ceq zJ^vj|{lAiRs=L02#$<6WG?eEW6+- zsoCwK<{$tzVceONX5oPQA6IE3z5$sPJ_Th)JxfFLgLlP6lzY0=1}21iD?V;$;aNou zh`B}jcMarp*KS7dI|dOF?I@P)IW}mRr6#?i;8uvQ-uwgE78|3H^VHR0n{P#35JQ%~ zzm+^nAd6RJ1p_sY13H2N3aRaWn)iqhYKmgl+wB7HrLor4Y%L6YMdn=+==-SK3*%G_ zKX<}`xWmZq8C@z(#JKUGafMeD`{Jxk0?mFW;*k`6$8-46o@%RH<_EmP9T?Yt1AJfP z`R_?ugj8r}0^V^m?DQS%@R=rPW4js(D`K|O?ZcJ!y-D!$ZgCQdU8uI#x{MwyuNixp zYRy2DQDIG&vNqz^D53#_yFYW#Q3~-I$iO>;8Apoi>g;mk^-BH@9MTSUuE8nztqn~H z_3&x759S;zKbu!~2KfI>y6*DJBHJ|%x{Mw^@!n~=t zAV7Q~+Qzat_FJz<`r;=1KsxwhCAbP=!=hp3t>c}M=HYE_VYWX-m>!H}4{(Sr!v}i5 z=)XsqQ*qD8{ZK0x!hty8F%7LaloIRP^%OQE~a*ZLIn(IQS&3)Q~Y zK#@4HUH7nIbaT9WBnm5XC-~zK842p{I;P1_l?Sale~@9O{+@%I#C~{sB--|s8dPXwq#$G5k85@vfKop-N%w??|-C(CO`a;bZ`$e8^g$j zpuS5Git$mywU~RZh3eUA2TtEm_gnoSH%Dyd(9CXfKRT7y2ND7ZumqOIhe(if{TCVR zxYkD{9-d>{Ic~l7=L8h=(GP_}<2^7-$0}~Bb|GLDW9PYX9UE0WyV~6OpoUvBzH^77nUk;lW8-x>S4gHf%=O_@Tv=Wr;YOc^S<(-w6@;pH z9p_74v#4_qduOPe@@6uGNm8=?$w+XmEPbszqS_OtWvsVpZNsL(_Jd7e#lf3RfoYK1v;YX>r-SPkwtKhKXB@9KnV3@w->Dc}(at0L)z(#Y~QDzc{Zo$RQ0a?J2 zyV{fZxY?O#5-3{wlDe2*aFjCXI8_;j5njc&>A<~b$}iX{B%B>wn@T9u&MkWc3q!1t zv~UfbN@;?po6|HK1o-5O1?ucKp@py`dxGdP*xR;K1YE10^?(QI7v_-0{r zLCk0+|5tG96Eh$mXR9I&Q9{~Mmzt`|E&KtWl0)pu z#qr0Ex0gaLUKh4CMv>zPZu=YRJzlN3WtzQEd$yLcU<}XnpgAOR@cp%PfU=-f7J<+d zoY9=Z#zrls{w)YAtnyq9$C?jHBikLYKnxLPd52XCz>&T`L=t8|dfA24l7`DAQI*9@ zjZ9p8fheME_n0%N!#I*+=VTuGn6*O4+0*NmF68uJwXN3gOECK0n0Md1PDxxZFBFWN zb);Cu^vj?#pGlCY)9J=&@&=_DcC|rSz%%|Dd?Gn~S>KwP{JZL!b|uzNE5-cdPv+iv z6O7paKmtq2l6Z>MQYT$kw}yyb)JAbnAwWID=;>11F{6rPI|P7p)tK#R_Ofr}1?Zqo zI4qwcsGg>P55XC|7GsXbR^*eYU%sH3lM*OHUlBfn-NoE7^yJNsFXqffEy!hrQj`?q zGcYj(?5GS%iwnGTL>xlh zN;GtA?($shi^$rC?^g{&%pTtDi6W3ROkH?NH3|0|eD~GZ6`DlP9$l61Cr=K;<{?2% zJ=}nO3l7_2Vvuct_?h+eV$H(?l-x;hhO#4pU**oEGJ0@ZMaRX$p!FhxR-(s#q+1Oz zOUfWUK&8XJHq@nuuh`xVg?;(1leg!>{+L&snNEbt~6s}YTG-cp8~%&@9EzYKoQ?!}Tx5H{v?!&xLA(yyaP04l#I%@XA=wyO|;bf(g~JEx&Q;iI^^f+^(NB3ie+x_PX&*K5ATI zuLqak>tzqe5w0xjHRdBax52WeENo#dUio+r!k@8QaOb)ze_oQZ3{X9Q!d&${l6tCd z9?!r8*=-71%X`>L)Wra}vcXb1#{9GdS!%D5ih7!xC z*)ID;ck|f8ES`6z=n6;6HFS$t!4d@XM|)+;h$8pKA> zutZTA0C1fFt8!N%Z90757fr+gQqLxKRla00$MyH<-cG#ss%5n5c_qE6{DsUu$x?Z)H6 zNkfv|NE8?!a-_lnstol-41)AUMe$J&KLe^&{&1Gz0#cMDF2*`Qv& z$hn>rS4wmc-pC8E^)U-WmYP!ayebMS(Tx3-K31jxi44zzr^j5^qcUJU!=T40U+`+Q z#VbsY<>53Jf>G=hD8)Xwjl!K$02)kM$!vPDzAr|bn>raVK7B{7Ns6GvdOS$qsE)kD zeE%7|SHCY$0_rnA_7!(cQNIfIrl+3W9t}k*g^1y0?8pc3psd{2SE;)cXr@{Ym)<*~ zN!85SEa-*o@48*B{rVW82m*yYf^|tCO?qxBwPmo?V{K&_F2STN@nS8X9jguw4H_)$ zDBNVrJ$(BP&7bEPoFks19PXNUZ`)qa=}iz+NX?j18XC7tjZU}l=h%4s4-OH0m$;!tnZ;VrqMRQnrd zC)6_yU9{Sf0(BmEZ~M8N+kh52nIYn9?c}M{Ha7tD4BGIX>*rJQdn;-7_)tEq91@JK z@skN$JhM|fJPwa%nFsiQuD4h7Bh%!~LLgB;R4EPfvnvt5(XpyQYDO!eC0(UmsA1QP z#OqxBE{TqB;%Va~CaThF!mf4oJe_uj&aHJa#oO&INBWm46nI~?zceD)*;VzZ{V~Sw zaX}4SH!I!8I8yyEwW72nvMTxuZbpTCMzvcI-6dBC(wyvFwe?r8o=$3)ie@(TS~FNZ z?!FI=DEH#YT$Q}|9%j0cqwG0-T*^htj#aS1M!sMHv^Po^Tw>Xt{W8)r}nc|UI z9dcD~vJ(vD#B)Tg+QppD9}!_^=Ieyl*bsI^XUgLd?WH?HkUY75anhHHXQb6Aso(zq z?2+n>Uz4&2(CTLu>K1N27w2wMqu5uyg>oZOND`zBIt<)IwPQyjs z$3@K!TI`qNRM@`_=L~`5sJO8-M7~1qqc}l_5j=!?g7#^LI8*aPr*{kB8@d zb7`l{3lCmG-J+`IxE{iMb5Gm>&W$j}wV8YjPhi_q;ro2&oImlV&qx7|ght+j8ju5X+_ zYc0>8AHDJYe%kJ@=*Svxk|#(-1(TSSSQ3WVEB&uT@@ox!-%C2k@i$}yz_w{-MmwG~ z`N)nn=G*ru&8&@HyoZdd#pPQk-kfqBZpL0Bc6)v56Goe{@W4&jt`PWkV| zHwh}7pDj1UOPq0%$Q9E6fUc{)S!+k6dhj1p>&l_VD&+UUnJO>wJTnh7tm5*5H#_?> zq8!+hyZ(W`q*azqJb#*T%%aI=;Uk_}m=H2v&kgSpI^XJtcw|Z9{l3*Vv&4S>) zF3T4Nr+2l`th@)2jsPnJnR;!4MRTOJ>6iK91=z0lF-uQIRQ?Dn5J`H>=~9`tbgQ7@ zBo^)9CRUxBFVC93FVEh-A8o;is6!-{X^b|QX3mDi+M|QO+M6$Lvk+2_mxyPq--u^! zAjY*Vi|EiHgJ>aOPQUfRIG~=0zoVYWKE-3+nD&Zb=SjufMJsPyc9c1c@_-vbOT`^U zt7)G$LK~TXY(}#PD408zq%EjPJy+2Ux76|1aox* zfg4#Y-I#4K-B>k}wdOw}$RRY-rXj6(i8%HIjX1_aVywdxh$gaB^jk0H+*95R11^a; zBQA-!D{bcW(#MQRzpMj9QPz$_{lvzBB|)s1k<4JOZ` zXtJjp$#dfVeGm(Ogu57yH&qQ-qi8~yTgn?zFFj4uqakI&t`7|P5Zj5ul-kiC= zhpo}@mrVOcnpzZZGThVt(CY+*4Y}*{vI&cv1kmz<;ZUa8sI2JXrk-gWnxC zC0K0V`ElGqc`5IsQ22100DUs?u%^UYV*&kodM{&Qm-N#CZ9r}G-vw!+1V$nOge%1p zH;p~#Tzb1~IzN9B0Fh*H-QC7nTHpboaV{GK?UE9bCe6Swrzn8T`AWgUjXfNTA(Ros zdyDa4E!JHKC0-H!{V!~#an}S3f*ykK-?tEP4%1CCh~*#XcQZ}|a@u+t%QRsKmZ2Fk zLAR$Yq#?#1UjU_>!LPt? z#0GBd#H>JMj|XV7;Wf>fv|%xMpceclYC*=?5aoH>^BTHQyTze7hnIf9$XF1P)*qi8 z!nhuM;~>hz0`LSTRv<}o{^dNHd_gZi>f)QDT5g1y*ULbcqb(Mo#O4&Ru$tTM8$D7lArLG;@bu^45$ldXfu=_z9)-n}sXeC-kXDd(kfcZv ztrY4-bIhsVNaXdb2}o74KUbc~$bTyNR1j-W>gT8S5y7q_Hpj#pqJ0;oZk5BhBMln- z1SyVun8as62mRrQ!YZtOfTdZ$DqqXYk#`Wsvzr!C7o?#tGeb&nB1Gp=B=Jn<*~BTA zpHY@p09@~IS*^=XJHX}+5@DVD$L~OZ8}y7dZWCl0q2=*5j`0q^WaYuoBJ%T-GBl$? z3B8Uhc2{Cz23%s&UWJ$OGRzG%7Q`z#Yv+Yyn!B6PB3I!3?Tt_jyKCE*SCK_EYktI~ zP170dY}wO>R~049Cl4y{J6eq1;(mApb}QVbC-XATslp<;ikNQ5o>37N0}W4~>q zB4O*i{WwTET~Tew27t$xLQ%rZrX3$M#}o=B?#9 zUXp(sYfZgycmvbQjI-7XP~%Ae*@S=q3c>TDIIcqBIL)bmdFU8!_B#Q@;ekt@qdx09|Q z#npV_O3jJme*2jK#xF@sw-o+Vi<(;ICW4StbthwC0*;K)Zfu2IJqH)6i@e_=iREfe z)>nnFK2Jui(7vMYvkM9@|A@j{1IHk5{k`T3)9iIk7d+gY7Ue8*!8s+pY5Acq-*OIi zt-z5`s&pg1e<3g)3TTv4QvJS`4@UjMO{|^9Sf#``vXCluoYl z=_2V??pit`bkzRzyw&=-j11^n-D^*m1GnC8#3hw z8tIilb)}et0U7Q4KrQmSamTbkb+NnX=Cc8BR$8cX&ssC;kwLE3RD)%7J%ykF5l3BOfLMd~z0V zD+5S6|8#yX3X|Li2?#87^0su(^|bGBoTz$1zYNJ91I;JB!=mpBsrTEHHEkH(U^iSyI*EcAV2pbN?I7tA;&m#fw6g($_pK z$#O&hVyVp*)&FmVp62?*r-7agBVrHw2Tiv;M899zS0uWcy-6uPf5oV&d33@}Mq^D~ z+xKok?vGGP3a}$B;3_QnWJ1c#&Lkho)|U2{Er9%>8KvMphCN9{J$0;^@r-v%A-N&n zH$H~_?jv33609-iG48G2XCy5sQCQF(EDC$aTURk+xB8-}KeEKjpGUYWTzG0H)q{=P zF?A>M#Gd4E4jFwW0Sl|AxvpWP#)-0`L_gw@X6_tD+*BOg<)!t`eeQBdK0`MR3;mZt*UT`gaT@ zBXV@7L=iX?{~T=sIA8lr*!&FEAXuQ;sEm!2$U5R`L*P*Gp3&4C=6-#Y)XDEs{EqV9 zk2bSc{|anb+PSv!jtcW^Qs!wqE#`@j*|wws4*2&1ia!*;l>T=Ah9#xp;iuVbUG5B5i)ARQs2roN-X7R_n&9v~%yhnLt8OS) zay^m{Pg)89uU%F$yQ;|bX=~P34&4eu*|C5@9$LIQ+ncaqkw95X>Yo(xR1y|2AO~af z=j}bjhGoV24<)j+&EcT#g37s)ZNLDWQ}S;+n}otn*oDr+dfA;cVSA$&eAtq;py#vm zh0Vi#qe9d=t2i^+2gbj;VR}#jTLCY%&^MK7hJP@o0(2zG@g=4$HC>6MKrv{=qrt>s zduokeoiuVMT=xdQg)_iQH=}}AGtIkFhBlmoNEO!*`mJ)XtkM4sgtfwQqmjzk6>1 zH%No>(bXlI5CD9H&>Loi)KV&A`?kc*(H~VnzqbGL{|x-YqQaj1Fa!ih-Xw6b4!k*g zyy588`+svV+$~WGh=4<0SB4jm)P?j3`@^Zrp0_X?<$~d9^peWpz4Ex>(a3`4tR~Wm z|H@SogYGh;++%-+F>5{Z3b;n$SG}YPyJp~&HTQ8Oz9I!HQkjm`@*mxKBb*mF5Hgr* zY)$#aYhpVh8ZU#JsSOY{8%afM#Bv0cHNsXi?O*V0Ixdm4zp@77`YP1isRVW5XQQYc z{+qlna$@&|RtW4G1O;~EG^%4I4JTTJKzNhEX*Ix^rdgomIBzF}r%Z)pSr{CD@SJBU zo&@`x$7!aC49W&1koFog?c<0=8!2V5&(YQu_P}QTI;P!e&;rQrns+S6u|T@vAzb&L zv?&Wkie56N!v%i*%Kh}{j+i~peA|z*FvvS`pKcAsZ%NBbRP%!Y$6Z*M$oi>M#+v&z zGY0rKFzR_$!ydf(Omq19LJ%Ed4&=ZIgcI(=riJc}p)J>yF;IgZ<=buKR8sxF((V19 z2?PKDxOp_wvZ2W9YB%~w_6GzmdMR@zvDt`5ZERB#&P#N@EncNlp{3YEA=I4yubN0yW zr3;$r?64s@gH({-vU#+zm>!IZr|ZMD5;6%<0iMNAY<&g{x=5;pZ~Bb5V0D|gaF^wi zkqiXIwCWsJZ=KJL{5}{I>KdvnepKhK@KZ~%mD-RJQFs&kpcyr4@BO!Tg6sK>05>H- z?>8@mGqlC>X8onb7dXKDF0&m`zd;FpQ;Z8J>rsSk)Fn2$>8hBTC)y7bTGk9+0oS$Fp zVU%Go@*T4L{@#N~y+XB0wda+>(4ip*BqChLl9x^WQDeY*4{%bVL!Ft1-L`J>_aW-k zPVcN~7+6rBPW+PW?-=QC4MEU8C>YIR~xF8pDb>?B02vH>$EFVHy=z(=rON>{P>8#0sI z9QJJ!A}9xYS`~{_H7?@DFyA(Q9ciLjeYQ-p#OWlO3_U6vE!=F~eBz z1CQNRzx_4rla|9jT_ToQuU72K(WMuTPdADCODScwXV)IH(Vii>6j2LMFMSN}C%jz0 z-JKc3Z(-%YKA}Bl!+E2ej+9d)?NLv!Fj_v_cp^aUI*V09A(1tIWsiW86nTrL{(}Bl zP0?@Zb?{4-ku@;^^K+i`9XxY)C@%oZRJAFw8&xO1D4lAv)k0;b29~jpYUj6xT-KYHQo8B*NjM`)^4)qOIM=QuQPtjx_w^zf$_k? z72Lhtt8tl#i9>=eB|VgL`1)8_v1OymLj2p8<^vmNlD@N)WB&Z?$3r)Ks`*2c&EYD3U0MrGPcr|KW^H;6zT1V{L%-=u!Mb?kuG9bp@r$0DXlE2>||SU?n{ z_&<>UA9N*Cv+EN4iUpVc4~*pj#E{w;I~f{{|LFfhAxGJ}xW(a?k|g4}@DaydgIOlb zqXA3)t2%giV-1FcN+Ho= zeSWAeUp(BIN}fwTuJ=|YZFDb^C{BYP+_an&=La{7@g<)Ch(FlBFXPibf#}09Odd(t zp|3NNl9DO?{d=_(s)5pd2hxNI2 zb)(i$6Uyf0F#J({cw|>?1Pw!^Y4N<2Gf-vhL@?XLTiA-@$;O~I)tSxaJCm4%lbfF` zb||s9>WhpJkBBkrLztPN5L8rD3BoQ!i=t4ep>SGUV8~?=pP;(CxGZur0xB-rfBzC9 zq2Q8};^5@4`!^!IO9??k<^p1qqoXhYf%078iwM!KGw%Oaii^uogcgMyj#?)E7YiWh z9*%;`APy`|+h{0#v*L2m5SdbMoxv-i5KFAWa`d`^->KIe{DZugv05+>d542VE{G*T zY>X&LN+~FUizAPCe~v0|j)*9MM9&r$N{aR0vJkEgREZGeK?EdRi+)voZLSV?6_f7L zQ=iggziNyaR6>AqJJLH8#6O|>xCp5D_k{(L@_QuKvfm=qqGD1?Bne-Xz`KYJGer^% z2ng7MGyMpNh!7-n9CE^8dSB~yD*71D84(% z$#~ilRWhf{k`spq)z&K2$LWfg_ZJ3%-y$RDcZ#xK<1l=ZX!{K=)( zU+vWNvPmQc30PEpk~PWb>HP=-(1jdS?Gyu&a&@zdYmFOZl$!ZpZiOq?q{`yCf7!n?8`fpby~^KQ$YIg&BG*W`Q%7* zFg15*79`Theu=TxI-Q@RwDvr2SSOcdb}ilUc*fCzsJD1lFjD}8|HpNe{T`a7nBi$8 z#}E_CRxqC0dC#8OozmhJphc+mak16+OW=&E3jeHjt+JidSM+gu1E;VyUH-F6YcF9w zLW7arfM`RlS{*p&man!S^zJr7ca>*p@4FJM3gk_Hn)Z_iy$hO!F7YA%?w`t=@KM`G zdKrURkjuw!OK3cRrrpPOm|bn_y_}YJg}=@kt(Mjo*7HUhpSHB2VIdqBZV4kFN6E~X z=qYtNb=(1v>M%2a(_498%Gu}?pT#6z52MpB?xtolT@~&l&pg+ZF?T$3%(Cggvgw$v z4w*0KR{ws_>)$67TX+;_@U>*FZ8tW*S?JiFU~sR-P_uT9TQbVw=UF@YS4QkBKK@Br zwwgI$sFZOhYiY9UEWOs|DW8tX_lE6nt-edL>EFZOrUmnV9=sn|WAdYl`ZXj%b$3u& zR`uw?;U)Y@UzqQZmY!Y}Mow2kpLujjbOcGBRr%mfuHu(W%%n1`k3o?xx{y;3ErWv= zskPW0T0NI>1IuA4t=?tZ1DY!A4Lv6+8mwvTaV0EJ;Y&>gTt>Y{_xhddeq!YJ0Hxse zSO34$ja7Oan@8VXTXlk4X&3fj6xKhaoaZ#_t&m|+8Axw| zJLF!`STFT1Y2~LdUzM3;&|FPLKyzvPVtHNKUGH;{-25281pxDV^^dZ8bsQhN2RW!c zF1|_<=m$}>u-Fd&;m)<8)82!^J@l6fl(V=pBzw!52aL{fnm`&O@Pi|M&FM#zcRK|9 z*J7SgzT*b$|7mkW4nc8C%2JI)Q zDz2Pj-X;yf7L>#kJ?ZKrKYJaLzV4jo%~|g9k=lGyh?CvWlB@mxTI_5wB)wEvs+Qij zly_+A&zabqM*LVTPZ%4?4<$Q+0YbuAvC=x>@r%zj~@X4bA zI{8(PeI1{q*(L@@<7fF6#4+1#mYpzxWFPvKZ~awE9^gV;yULLL(%h=*;7MT{3pM7- zO))DsN?xi+&DmVVlP*wErCywbg#RfUA$s}NG-?uI?MD9BqLVd7uff)5G=*`kfV0no zNVM#sgpeiWvccL4X)*0S`I}dyTO^&$&TjF#kauh4GYh&CcJ}B2WJi{JA6(TCpVGJ5 z*?AIQQZBZromakg@$I-m_u}|5$2eVQYo+$GVp(yhSk$oLt5kFrE%+L=%g%eszp0}< zE<9c^vh^iDoJ+`a@M9~(ne*ZW`k^yS^IXq1dKI$ZzrH<==F*d{Q|{!?`)D z20Zo;j?>aiUr45a*;97Yx3r#?&R~+|o)+cSi=j#;8B5Z{*In{-4|;jq#A{#!HYm4z zO!E)$2RAGHBpv0g(t$nSVh);JeWlPgfGqe4?g} z)e$T2O|GvFL_?2&>U%{UJb*s73+&Ind#Ricq>U96IjcPIvYC1=D#13L*NjV18IXTW zX{*`ug|;o=7h=56J%e9WfSwSesjEtD%jj&CS@7`izA`9y&J*@?F%#lMNn3t3XF#o| zAqWY@lAASP$0_B4hLT1|;6{X!qDbKWR}m7V=$4RvkV+0R3$K{Jv`*yb^N7_Ib$ZIh zSyl=&d9*xlV(*ar-hA@84y`;ttDrdq69$Z43WLOTQ&E%|Bh;3d;TQ+=%@=d;dRp-r z7tt5<6I=ryY$~%0a+BXaJ|UUeao3E8iEX8BGz(1t_}V+~G&I97HniXAw~A%r@X=KJ zchV35C%zeV_TEO2=MXp7IS+-mNGmYbXQo#BcC*8k#xGS`-q-?MFN-CK@u}_OihtgPv`Q7%@b+c-(N82q zsIxPsC@!$GNVqy|jSy2}#W2I|Wk8WbzfQoYGv+oN-*v+&NGRVyd-1j}eGAfZY9XgQ z_w$pA6?HA^oU`)UnlRZZF&KN(XE#oGU~VX!zwGIysGL;#7D0);*1V$oeOZxo=KdExFb#x6C3xF4V9dV0))2e!_f%qy#9(vCydP3L@&vkw{uG+YwcLfUOTB z$8nMfMHie+o>524E^ih3grbx_js8<+b;u`0tTt-Oc{ZsFx&#hxSEw^fmhTBUwSdD^xqZf)Auj)58Ml4P7{# zpxCo*qznz`6 z6N*o~{Yv5z%x<5eAnc{*X`iuKQQpq@ulO4s8;Oo}62kyuH z=1G5v4gV+aC#<^B)MP8aAY(i$q9h{5#qQPD@cE0ub^Q4GstQ7_qZxtym907k)6OM7 zJb$0Gf`qkg@6wj#sMeW3&zA0Tyg2md=dtnw4p8lgYK?4w4>u~x3y9(m>Sc0w43s71W3>5LfQxC(iOOEDLkkm3%c@~5{?oGRmlYy z0Ss37F)Iok5KbS6&ZDj97wKzSM4OL{Id0u2TGNl~_^)s%9pb7w-vzqin+@BolkM4Y zd{72MPndOVwBIXis-Ri94tds$!!TGd2Hr|Im`~bwoCp}dtozJvr|rPOc2Hm+Ls6g* zp_>payl}w~63VR<>xlC2>j8l6f!mT(VsP}Mo!M_2NR#JzkT5YV*`LWivKo@=5lpc) z_t7xuQeX@h`Q4ausPYRPHATP5=~rdb0CmF{ujCk#Hkn5WC#3Zq%VBGP~WZta$OohW92c z)A@G@1V)H|)(c8SK9RysX<^E0(h~L2v44uZ+{fdXn+K(8S<5r)Nk2|eJXD7yoTeY| zI)B`Z>np^z`a&~2IH8J^Yq_(ru94HdC)OxxcTx!}@Qe3SpXqc!So1<%a+10Hi1(k+0%Qo6+rwA}oYo&TfJAxl$kq zB8|`7Cp)!)=!QfC@<(uuBRc89ff9?o+ezGeOAH!J@`wFeWc;lnM!xwZci3Xb zJ??VN=2^$<^Fk`eCQX!OmzektN17*u#-wFXKOy%xl0MtSaCMwIPJ9sZgFq?jIq#6O zn_eL9TL<+S8*NODPEXSX?AX{9ejd88%TbiJo%MSEJW~jHD`R>$=IIbI_AU5jSkm@i zAK^?zP^8;O6B=vxzz&vwgCdrA%#v&CE0_*}m-veniX?-yh;J9)awgsD1T$?Rp#UHf z{z~`AO~QwAX*Md6p|-7^GH4(!?ToSWWwKw)>L(?A#d(V3`8RenyPh?x!U)=GNgSd- z;@95t3h^2ga_@OlQhUsn?lTvyteET7KZJISY6cWbT-@e;1KqSkVP36x!i>b(gvvV} z1Lm2|bj@?CT z6ItKySWbx<3*>veDOl#|6^eo+k}5x~aFkEhgmA0zmrr#?Ak*!Tbs8sUiX*)&P5x+C zMZ@+JK5Gvav3eUwyeh1z7l^kI&p=L65i>n8AzGqsS`Sr&ZZDQU&M85Hef}AFNT}D2 zJnfmrwm)IWaO^=j&2?u=?65vn7scw(>L5vnfm)$IvmQoNHoxJ;PQ9C4MU#-m=%leI z4JB4Q8LVZUxHpY;Eqwh+?smHnDO=?`U^J*T&{0+hM(_=`L9`V^-lgCIbz3W64~N!> zms;MUmfihPxWd6BWn_nVbh;Z{0U#b@wQ7e5iAiaM!OQC!{_LBDO?|MUy)(w(_|4&1 z@ZMI5Kc&s~W6P(tk(kBOeCn*yJo=C{hw>b(`DDX_Hi zs-s|AScE%L%^_aD$e8zg zHZEUAfiDqKbZLEuVRLn>AP2eeQO-)@LUv(aC4Pt7XOHPa#?gm~kzIuONNJ#!A zlJ^ibk(yc@m)j31-Y_?iujweHtk6G{>iY=|dn6&ZnnA`XCYtlHLPZGV0~(qTRbBgL z@m*m^{=Krnr(^rE`hop)%jcM~t1%t8bkaSL*3TU(-=uwE%0xiUi{&b88AQ9fiFM5j zS%v*d6{?ypA5V8Rhj+4O{%|<1h!BIg8E#u%KLyTG>7FwOy5)cV zJ?{IIp_jre>8|GpofyVUi@sb=&pt~+2AR%99I+OO0M^88qp_b%fBwSIiBD%<+vBL= zVf;j{GH)$GhM>)q%kLWZfn`5e(UUUQNAIFFz$;8}VimU=1}?7h&z7a+j|MVj7bX~Y z;d*rA_;EszYp}6)-bw@&%$$DuWpV7{X#XfA%$C#hutj7*1_6;H>0_q|pl1YMa-fm6wSfd!3d7e9Z&e@2AEvB1m zSbh!eYU6*9v3i1CBM&e=ZN>jaLy`7N-l&X4%nYY9)_|hN<T> z2(3~YR3&9KtSHo-6r2d8bJD_I%oeT^mhStHX=X|&g~sPjdnD=#LN6cJoGb3TWSXtef3S=ihFy6+q);gv@}s={X`_VdvZK6n(&{qY49R=t zDzkj|Q(@mqXiz(qVD%jIneb*43sh^}RPR!*Tm^$Uje3=mb#ss{A-ZEWqO~faBvqi| z@1u2ZtL-_ky9-LGryfF88>gT%DLIh8D3{I5wC~ma;*1X$3WhmtissSmfXj6+*{Y0U zjvcDh>O3>kF9WJ3gKqCj$VGI^sO_G0w)n<&)B+otI}hPX!Cs=~nK!2`d6_2ohyzmw$?aV}dZqeKR<#_=PQDTgSs zcfW5UNA6kh()RvpVfnGA5+WLDU;B8=fWr~)ul0uUx$71v$+Von56N#Eobv);)$zGh zStR+DRD6x5&TVz+Kt${HwHSvK!Ava;ItS3Q9=$gthfH6%9Gehj*>8F*;#3}QH$qV9 zRVeOOEZEpZm!&LfRmfdekeOU4u6`FgHl;}C#m_9hsa z_sct}QMIi^sQtp$=i-?k5%uj?bW#%`ZCxwdi4t|6Ym=q=>^#@DgGLIuU5f;TQ-5}F zc|s$!-<|is#QuCXR5gM|+H|`i!OniRPJoP=AmFfJ^{%ea$`=02cjdJ|I6Yd(~)B%OMhA zzoIxFMR7UfKp{(g;NbvSk0P~S!6Z?_{tW;Aonv=53?q_+=uvNNSgq(~epvsdUG#Vt zC!|EeOYYC0Ie;kRkUo*CNK|{`NZg~y0dX5CE>pUon_(~DRSk?P$$d*;&%bx9K}Z^e zWaDZKQsUSkfcNbl+ow_7qOgLE-NZiBi=pP=lF)V^)&W>Lc_ko;{G;c;01I6^2mU{N zz7hjZ$U@B&quO5DnS`D(Q_Odl!P4yJ&_>-zV3YHE2TX9z_gRFm!#(e>rzy$7cpvst z+|=ECS{S9Cwx2^=U_jr8L)1E5yuQO^9S>idTIU95R-14!;)pOU5LH<3lX&crejXl7 zHM{}+yhNJb@Ds%4kE^#QM>4S!h0)acI`40Mu!~iRMb$DX-4sG?cF0i>OuFVG@0Y}6 z_sEQkX-#hlI&Hk|HtXuA?w^M&NUO@hy{_@g90X4@CdhE&7bK&9o?HOJU9KX!*bQTo z^)^#Q)UzH1BjB6yE2Va^;%;NQ}r;^ZNW0&7UvRn1Ieq-w~<3Y{~Go)SmuSUn8tAg@rK zbPKMFjq-R=Vm+w>nZ>1O)b&1*)t41p$R`NeI_OQ#u$x~&|2wegPwn2_&k zHqv=1yVeyN8J<1v3N=BWAOZ{DEF()xCX~(EZK4#&xj;@pf0fom{T%MSot)s=EWRSe z)_(3pv^E}sER28U$mi$k`c@24gyMRie8D$=qvreVys=K{xXQl@Nqk`3G`+43?Z%v( zK^Mlzyt(zfu&gWnI5YG*m*$B41qB7+k;^vKk%7vM4*2zOo9f-aX29PwsbBZSnL%(j znphUfB0y`GV%C?o(32^k51^wUx^XMln5nkVJJtB{V6UGic};-V6xK~_;Z+fqBz zhxXYFhlrf-{JR~;YUm)Uswivr_5SeigB0%&*9s&*+(gOpap`P^w-~S0kB}g0)5g8xwoiR^*wwK2t1I~TVNJ`43 zu2E1aQXQ}TKD1fzfwgVD&MP;s;&Li%~Ch-j3c{$KzaL0qrIqzgk)VPVR! za7q?9Ym6;9Ary1-lX{KO%3I%fIlJ&cRC@%O zo#uKd5ChQR6+kDv6+47eb#yNzvdT1+G)R&n;yh0#S-9${TJ4{93{X_3elHRVvN{Ma z43+HI{uR0z*9r;Bs{fS}ju%cnt@q=W6VPL+4SjnW?$n zk6T|{D3RgV6#UX&0HO|KUV%o~xhNTQBtP;U422^7M1zT4*?jr#ylBz!v%9ViH0J1;o&AM_$3rMmmjMR2%h zW))shEA^Co|*yAg$`2}?0;y%8n_g^(82e&g)rV`C` z*D^ST31QLFfy4ps5x{8LROSmamiQ=Zg)Qpt`8=by%hE>jF*DBD?A>0L(;rMnCU^JJ zlrM^7k}C`0xg^7>UR4A9)t?4&==mi9@jF0+4cgSJRHRR`?1p!y91qVp%zt1-3(_Q- z93%aIreoq{glqif8?>{6>(xH)x8(A|IQ3UruwWLqwuOBZv-Syg7@D+=iWN_Cwriv% zxC?x1EY7nko(*w4+}3=|!=K-p>CtvgrtwPte&Z9mG@%AN#k^p#kWTbL?*~& zMW!_a?YsxS(-9J ze+t}{9S^k;Cc0q8znB$ZmOs@?gExTdi(ue6I!uFd=)02AS8JQ(wQXV-%QQVWMmGm( z!$ITdxW?36o(}WY&lQ=T;W`#Y?f9LdzPHJbtpJ(E$?qO+4 zrfMf?@qVplwt)i!R5t`4`et!oy?O$x<&YIHSAH2+Jxs0Cy7rg$a( zW|5W_?ZXf};W_%Y8&m!%nI(T!#Hbu^l~lT4&fH?baF{~mrY*8jWVlmZ2N~wv0Zfib z9};BRydi+HC-$sI%%^Qw5@Xj<%c(>RifUogkjrvbLCJ-hb@PP43ee!t8;nidvxc+~ zP__-8FLlJGd(2(59c}j7&Ag7u9gfzKSV{7&R_97~0d6ETCXIx-Y}_vpJDZvybhRA<g2_)!=y&m zT1rOhBh4VUKbX4g?VN}(jo>GKEvaqM`hv2DOxXaZS(o>;h4@`+oJSuw(#_;vfowEZ zaxEnN!=e)qN{@*jY?Ljths&--CDR?&!jiB4t~; z4SCi|X;D!M$su$UTLgI!CIalpFq&X}h+LdFevo9G9IV%#4O`xgpkD$#6oUQ_L%7gG zAph(js~&pQYydN_cp}bhgkNBpFWvatKv4;6=~tIP{1Jd>A@uI3>L)09d1n=CNCt2S zd2==6lVy;)vB?W5RlXDTlpHCZG*C&EB!Nmh{WA2}NYINXnCls3gYB(q%^T{E)whi#=` zT%rim(I&NdH6a@HX}kQn)AtrovR{b>>~vV(CmOLR?vE7JHHDljSRfX*0w( zpJ1!Jqhsq-y|`~kPguutyma~OG@SD}zZ!Ndk_fDFE0^%q+8$k%DOncQxL|YS6lwCY z#PZ+_Cvcfcgfp3+qS<7A!}E5)Bi}Pr95{ z9Jt=}ewaTDL0|1far%6x7zAg!mYhJhilqj5KuQn((7*BZnJBt3b7?^j7g2UtN`nby zOsJf>Z5EfzZ8^+hTojDACIY+D;SATF2gBNjsTEr6UX&H8Dw&zuT#Z+2FQj2VhUv*f z(yZtW1?HhcL!Z7}R(G*iY3SX*h~3n6SGIh-P)0IeI=;_x9!{gg&W2OV5i3vgeQRT% zwmM9HegW&4tBNz1M~+@9Mq!Sbjr!obC1#W{ra))ws)%83XeoP56#& z+}@vJS+!Z@SZ$qHrbAN{vy|SJmC_QD`?Qf~ToV}`s{wgC>jCyA+9F6?Jnps`%5hbz z+mu*6Zy|(!JCXzFN1AJ7eQU>znshZ#bvDw>5_p)ajUJuQ;47?;Zy%g5Rz+%dU6n66 z$+tdh%ZHN=+&Xx+H1XS_MZ?rL4Itss(@_rdY59`-uNG`zIhQT{nd{&$&por>MaD^H zryjyY${QIr5QYRy9F*zx z>w1+p(sbz26U@lJFvfRVdb<170vvl6KLhimQ>gNvtuIX;F5MnmQ($5~6qgFFDbj=D z4y}b6`<@YI%?*Ref)#y5)Z>LObxP*$*~zS(Cr6j%REdtp%&DOWgJ5LIOeP;(HM{97 z?e>dI&)!(!;$J8PEq?P*a1w43k<2zOdMezD1Jftps=`BVFpk*(zD1vL(jVLO!_o0(jwR5ZaD(iGHVp5p`PqT{1cuMTUgF<`F z>f%2YXQ#kd^7NJDAuhDSeO<+h8%&JGVYoNGQOc&Mp%^jE5}%c`r=-~`K2DJ| z=2q`<=~+ptL~i>_QO2s(F&!BPv+4zB<)f8T&j+OXFW`uco#I`f8U#`-^~rhFJufIM zHXTdLD=_SaVTC1SUi%d-H>n5gZCLluEtrH=c5?BW5LGrU-nHWKFW5y}*Rpll0&BQ; zVA*eenTOBsaOEt}*YBBrLAd5&#B)MbrAxB4Lk3dGzF!((SpwZ>_R!oxV?|#x6ET&W zWaH7&lyWfi_o(Q9I3PMEA@-HFO;B(k|JG}mdcR-|$l>msM{Ffu`<<~%e(+YAdUPG3v&&c5v%HC z@`1elE$h+;9XILFsgnBU>~6&1LT8yWessHmhkm^3&z4!=PPoDe$ICvEM*59Jn8Q;2 zt_;i6hFBK1Dq=qR-G_;^yHDWEYZ648z0f73aZA=|d9aRNc2j@9nMdtPt+gdY#1w4# zC{%oL$vv(45H7^(^7|9iW+CxYN{Ri=2QK~c@!3Q{uCexoMqbtLV#HE{JKa8JQy5LE zL9+P;%56*3wOSZ^N30|+Gft*ixOcGP>tkUri8_PN6Iu=x;0D<{VU~>D{FU#cyw>X4 z>wo{bNaWo>2#z$Z4ok&Mmjai^EgaF)ZJu_l@Sx&-saDe{wvXmeohf9E30C%{F##$R zcDKK+f!jN(h9MQ?7M(%MlAxgzYzqG5Ix#g%HPb&%qbTPXLq~TAU_@P)q%@eO@&LZH z1W)~xehb63ab(s(FXl+@n!!@)9P$s@!P=uub6dU3U0N5#{VGN<##clw;YNpq3fVqOTN&fyfP7Tamx{DJ;t6OBi{gH@A$k2P_$F}=d+@u-|j zLT-kKep;2f(mbBSHiz&Z7#v;TvRUJ9PZr2rfVun4v+xPMI!|M|!roxC z;gna6QfAOPiJsHj?V=!q==5^tAo&v(V@(Pp3@6e5zP3j%v%}Z>qALO?k&k4jyYD1@ zK%R|TKY4oZ@K+p+Rd=mYvthuI0 z%N5{&nKmRg_t1+C2Uv$r&z^jZJxT^3hJw716Ej+aF%%< zx%*s1JKJqw@Etf4DUm^3Z|ks3V2X9dyW8bdVVX+BWt+B>s^-=rc4zs@^a%3&qmAR2 zo?szu+;i+gFn)jJZfFJTuPehYMB{M(3KHx5MicqBWgRct3@H0&m$;_34*31%Zlc}Z z`@ypvH@5c=A%lnb58OPJ)+?X0*F*1ngFo@`bh1{#6e6@#o`_lfp}1?a%ndabUit2F zk0r)Vh9Tf|AHCIGb;}M^*KS^d?PCN-RiEYg)8$%;Zs7V+!>i}*y9!S_CaW%61{R|U zN7}MnwZrjWw}m_HcpJ4be9~_;3XPiynMW+Fz3wSfekIFNDntSj0Gi)0UFB}Wxw9B5 z?GHm>rg}t#0-UxV6RLJugyZY{yIUtCF$xT}Jh{LXWr4e++fcPkW! zqCe}=>GvddmJ<`Hf0Gw^0|<80+zrtFRyQhlvfJiGC(4(gA$P8g3K%n*?KTZ*Meqf4 zTXC`D(LHaKP=}4YFLrX8h|lm4siM38xvM}1D@U54YIu8qk&!W2^%HEPKO(9~8?>w^ zJ9cl>_VEah_3-v-rUic5fP1s(V}G5gGITotx58(t;|#%PN9a_)$l3b(4n8maCozxi z?YXbbU~Fo6`OOG7k;-^-IKiIq?BEg)X+7Ch3|$|Jw;c z7;DsF`6}Tn2oPI9`9y{d)h5%cl*PF9Tx{`lj#=7V=dOhNFhLTCzGt&cVC60Ad-S%1 z@k_Q2gi4;it<1KVT?AeqD$yqC6{T21&uFW@Tsi;)Ilana+RBh-KRgdY4!mwUhGNlw z_Y+f5{$2S&xF^67qArf}x+Xg)Pn1pu%O|c&{zj0WK^paU9>z3+P>yfF`E}qFzxNC^ zYbK`@bqx2H$U8fl-yV{2pt-htY)O&hwEaG>8U+S7fwvq2B9^o31W<|x`}TyIDe|-W zgPl%4Xuhl2ilHAgFU$0Kc~ci>srJG#yAJ!gX>j3_E%1SV@Mx{QZlu&zP`8sGHsiz@ z==^Cbf4SJ(VFzVUPJoU)o$PE z2bjFsT<{X4Y-`+H(1ubx1|N5J!M<|umzM8#dOOzPn5|ZMxA$6mUpg+wN4gkZyT;Ug zey*MGcAX@)4+(zsr`DdOi1Vxom)c-JRs!n{Hz3Vm*4lkf;~ za!-`e^jx7?I(s}uaRieN23G{NeciFKGZI4gE8>seRdkk7AJm`Xo^v(kXC93(>Ie&Y z`DSn(s>>q-k!`8=o9fos<9zNXce>T%3J@@o1T7S<-Yo+kJsQRgN&wGqB%Um{nk=mO zTnS}4K5)Cl-c+$VD(O<&qg$3JFu237#L#c+9U;@kigbcasXExOfH(2`8{v;TA>4G- z5W}!0Sz+=?+7flHq0}X#kn|OGf5F4gb6Kk8#~SYw-wN8qrUDUF?ayf_+8L*gQp_S{ zh3Ud7%SrHBOM3kYg(&7^K-O&S6d}%m;6_LwwWFceHrBkx< zVsBP~#q*~_W#Sw#Sy~sac-Jzp?=63ChDF*aibaC6h**UoPu$Y9|5B|wSsb}Iot+c8 z_bRlSX70q~VrT!FBzDo4&G5D?6ioUAL`WIM|6jcY&dJXrCC&P$e?p#b5Jh9a=EV+A zenblYij%O2t!cZ3#JFi96Ug{0%rudFODf4cv3R#thaBc`a0aAz$T1}qLy@g(~|3drb)QV2Z%u%8QEdL|LnM-0lR z+Hb{irn02+qH>`+6tj{EhLD+C7Nd4C?>+=cdth}qf7uVku0xG;9}A!UoKxf*gv4oY zzTbZe>pua6F@f?CTLgz18#IX|+Cu@+9SZWqJv$|qib70HYnY)lUZ zD3Q4-b){r6a4-+Qp(`Kq?=@_J&0@+2j8AyObZ3FQcIK&8GMvE!cD?k!II3tnY=Ay@ z5ypIBsA28|LUMBmI#MVlv-O^!`i#VF1)wl$ho?GJ=OI21v1gxzX6R?7e~LC|ZGGo< zd2oBI4;&r3Rb%qtN4$FMK!X|;*n-D*eO@RqgKzy5UI*+7bk2CcF`{5)6KYOHPU=K6( ekq`MGZ2-cZKnjSRw*Hv{8Gyv4To0h``}==HlR3%& diff --git a/src/Nethermind/Chains/lisk-sepolia.json.zst b/src/Nethermind/Chains/lisk-sepolia.json.zst index 62dc3d9c516ba9590e025db505f614929531100d..b32ff1196e4baa1463770d72d254d341ce827927 100644 GIT binary patch delta 10749 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 delta 10857 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 z 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 K7J-UT8Nm!SGrcMR delta 29565 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 diff --git a/src/Nethermind/Chains/metal-mainnet.json.zst b/src/Nethermind/Chains/metal-mainnet.json.zst index b522efb98e3030c2f737e3459054b98866af6230..f698bc9f00303d99a94be03e67735c71df6cdfd4 100644 GIT binary patch delta 7797 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 diff --git a/src/Nethermind/Chains/metal-sepolia.json.zst b/src/Nethermind/Chains/metal-sepolia.json.zst index 21f6ef6bf7ea89a9b7bbcb7fd09be3c7a661cf2d..788fcc71cf2a33736d3b9e5def87ad67b8355ab0 100644 GIT binary patch delta 4429 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 DC-Iq? delta 7562 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

&7fT@bGyJ|d`D`u!Vh(6rG2 delta 4914 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 b7Ar*2$3yn#?6Mm)QQL#4sl1u3X72wVsdl2Q diff --git a/src/Nethermind/Chains/mode-sepolia.json.zst b/src/Nethermind/Chains/mode-sepolia.json.zst index 987fd93c08cb21f254e194e7a5bf5e9f6ade833c..0c252b0b0113648e2ec2dd93ccc6f47190c0f5e2 100644 GIT binary patch delta 6690 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 Y-6ltc4X9&k79;V5hSq9sBSi@PKN;@XegFUf delta 7123 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 APyhe` diff --git a/src/Nethermind/Chains/op-mainnet.json.zst b/src/Nethermind/Chains/op-mainnet.json.zst index 22d688630aa1adda33f2c1dbee1db777a994853a..f8127f7c97d4492b9b16f4d817f3d6ab4eeb2959 100644 GIT binary patch literal 1197 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 delta 7777 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 N1UnOE7V$ap{{cmN1Q-AS diff --git a/src/Nethermind/Chains/orderly-mainnet.json.zst b/src/Nethermind/Chains/orderly-mainnet.json.zst index a7f7146e31eac7a3e50d2553152508a542d18574..939e60d40fac1f07400d84e4431ab5249c84e247 100644 GIT binary patch delta 4309 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 delta 4905 zcmaJ?2{=@H8=sA_kKJG#`x-IE-q>9wi3mx_kV%E6Bxb~9Y37zKj_{Q*UrLLVR8%DE zMV6^lL~hD5$r2`7EZ-T_y*=Oe-SdB*d7uCP%z4lITi*9HoJWilAm}=G4HuC+Ca_zP zTvwRYj=iF4M()CW+@eJzlG1Z0)TXNj3$Y8!%Z5(JqUQ^SG#QLUA+dL`*RcDrO&%mW zd&x#PQUH_g6dEYM)xGEw0>$`*7Rn8*OSSB|jY=iN*`sK)-alZEmKD~qomu~Uvb=c(#vo?iCi8>v6>e+Uc zQm>OG=RGNpQvgCqoP;7FEln(w(Wr=kiHpOg(LycLl>8z+y7TZA73Y0|ppk1zQ$v{KGZTSo;bure0P0|rT z*&{3!fOIB9SiqQQk@~(4u|M$WwYQ%FJsgvg5G?0?HWg(zZlu*-_9KUdw50l0G92_R zWd9)h-J~~0>Mb$4f`#rEe0bCLZbtMV@o-)Y@)fqV#~~4)S>GS-+VgdgGtr10xpzd3;88`CaeeX!6}7 z@&QN69x(A>$J!I4 zIu+7fbd@f}JxU||8Iufh>j1L))M9U0`TtHeSwh`90d(OG?ICE-7mXdofoax8drf zz@z-Z#b@*GjTr z?T4$Rg^M=QPxZ#s{RdkgI=9&msv9=VV7=!y{i%POK^GSLt-);Yw201zTOt~E` zyX`llKA!|NnZfv;{!FCqrc3YqzKFBEBfp0_=$46JDvAGo#8^#_lS63j{oLTX>G$+P zhp(PnMfiqeD7&Ou-erK1kAKV18Cu_hpy}$$3xD+O)TGP4EJ;47e`Swl<&GVPG%2E3 ze$87azGc0Y#i{DIBDneJWA8<#2Z3!pM7Dv1%_w@VHST8PMCo8p-8;c6s-bMr$qaqz z7D)~(IbE&`Su+B+9%c2NozoS6yo4L*e+1)bvj_So}Y=m^)l2s ze(QAQqxr(r&5q;9928e9sk?OrEJvwe9}^h&3lg=E}|Q?Dz}DQNTQ-7FfJ!F*zS zySGg~le?B3o3quXR-4ol9O|h!e8fQRdC~Ho4e^w3Vdh2twfJM|muEPPPS*VaHKLYc zN{6>Fl^&$+{RG~W9BD;%u?%}0(;aj2Mas6V=6bN+`+pQi$MuyRof2i{zj?gNM#kxp zC-FQwjGBjR*!qc>8uTyq)Ibky$BM!$7 zxtvv3?bPN6AI^mPy}x+fv|d;4+oc2tb|&oiKCv<7b6Se0hxDOujpcQQrfIoTYh(Iu zTTQdHG#tHqV~(`SGJ)TAb4paP=Tw!D9_)ph(|xm+#K6~1g|t&-w4w}kN~wK0c$*9SM09U{-{8=UH&lmFao16-=?>|k#ClAE7i9Lwfu<6&hv4O!!HT^P7jQ{?{hlP5I7U zw$f)M4`+0+zjpVw2t<42JK8_lV(58#&R=((ed?Xu()uQYldoIOy#3(u_7)`~f%<2e z???*l{p9KN-LAr7Y1j{E3SvtWMQSbtxr&b5Igt@qMNe<9#uUfYKPR^?&{Uo#l*D9W zYLV2*XfH6&i*%sz&N{JqIq5^sD+t+(Cd73ayJ}cAdz$AO7BX{g^=qHIn7=@XADhyW zRljrR_*I6FO}x)b+vH6z`-%MW`Of8OPp(x+?jdi~PMkAq)f}$OsTqGN5_;zV0^2*= zL$|32Y^IxDrIu5|_vz~gZ1&N#1m928c-mGAXfF2-)y_R?@Ep&mT!@lHcP05}lt%dX zcQr134wGsye9)}RSIrGPAJBErsZy%J8Tq=gxv9cn^fxcR`$0l)#J+?CE}*w@dkWib zJaop2S;urN-FPf~_bBE<(y{Ck=Vp{PN`h4dXd2NOB5?hf zHVpZWf6(&>L1e=c?qfbf{406W88IP!N{^-Kj=YlEo>v-4UwzKa&rCSV*`1L?(}Pvc zk`8H+e09|#F6KV>ZiipG)FK~LH?=#2wlErbowY5!y7EIv>($#X_lCBdiRlh9k=v$r zoUqi)q<2qM-q;hq#TWkUniqIt_#(khxU*VJ+4s5i?XS)f)hJjp!kiR@hc06yW4y7k zF~P*t%-q6~6coHSgiJ6Z;0eZr)id?+^3g-(*tDwi%!1jXd18MaGhoy{V|eh`Op!K~ z?FvM6Ic8AV2Z4yr)i{vPv;;=%Z&Ir)F*T$1m|2QCm6Jg128qdigY%!t`DmR<1GAKa z0Htg2p|hZD(MG{46k}VP*nHsx3N#TUc=Fyut-4R-IsjZPOyv-3p2)#t%tu(GM290Lrkqu~Y>dL^x^A&ts0 z#n3t%Ca4@f?{5!9K^q}M`a~hIe=|U9<>3kjXdOubvy@1H)|CYCaIWHo&Y=W4n95ei zn^0zIl{LnCg(Xvr^{D+6wF-}^8L{tLIZsW!VCsZ|Nh9!Iw9~sW$bY5 zqCx~lv^yG(+8;9aZA(FbF2Y7WKIfR{*O>j4tpXm?PpIq^V*gHnW{9CZ`8!*`u+~9^ z1f-c@Dq9>ghV5T+bBJf(U$Xbt zJ3h!>pLKHA?xN2S!lWvRxg=o`#m0f@qF2QJd?qlv7DrgWs$GD#&SLgGNeWm~xkhKl zvhLAh6s!?p%Ihv(*Zq2dLpT|-3Z$g%bvSzbze`yKe4bk60?cgzxGI>+v&?}fNd-fL z&NJ-TzYz~IE3?p0OEz0`Fs7Bl?dW6xaxl*kP>Hkgw9n7L1EM`W>xZ_CJ7c+3HEC5D{xe3HC^Y(ZPuufJ992IjD3|UTw4va`7P*oepue=Km z^BLpiL4Gt@1g~Ip;ScT&+>|6yG!Q;?w zlD7lLC8H5RAz+A<4%`K+8EDLUyr68h~!D`tbkW!)+!S!;hkTxQu7C{!YSw$p)jYfxtpddYvUb`~$jx%1`LZ=r|ERSU1uF%v6yD3snRNW=3ZC z|GywS=c~&9cV7Y0t9DBvO?C0(cwZQEC=pLhG=V4Q)rUXi)cNnGT9q>hpzQ#-@1(z1 zz1EbX4(UcX+2;hJeP9TKL%gVn(8uDYnB50vu0Uw7H_qWPN!BEH`b0c&7Kd-+F z%~M)!DoaTNjt9SCl@!)GZ-&w^!)}- zJ34Mkh8tC{T Me0nN=*Vz#AA2-E=7ytkO diff --git a/src/Nethermind/Chains/ozean-sepolia.json.zst b/src/Nethermind/Chains/ozean-sepolia.json.zst index c94ddb78a3e8ead58d300f4ba1af4f99ff7c8246..5bc739ab60ad9071b0fbfb944a69b1572ecf8412 100644 GIT binary patch delta 7348 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 delta 6913 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 diff --git a/src/Nethermind/Chains/pivotal-sepolia.json.zst b/src/Nethermind/Chains/pivotal-sepolia.json.zst index f40661f81d5013f079e4ceb3431a8b00d074d658..7da101279859151dd2c0b08347683144fd8fc0f1 100644 GIT binary patch delta 11331 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 JjM?bs{{!WVOsxO_ delta 11070 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 delta 7574 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 Mr~C#^s`k_W2fz4c^#A|> diff --git a/src/Nethermind/Chains/race-mainnet.json.zst b/src/Nethermind/Chains/race-mainnet.json.zst index b912f3ca3d1bb29104ffddf0114712b6c12e1f8a..c5afd00d6214f48771d8adfb1eb6d994baed7c7c 100644 GIT binary patch delta 7286 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 delta 6777 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 diff --git a/src/Nethermind/Chains/race-sepolia.json.zst b/src/Nethermind/Chains/race-sepolia.json.zst index 8c33463cde1dc2b643529fbc27ba67c1c6b282de..f375ab0a29807a976ef649642102e1e9628b6257 100644 GIT binary patch delta 7340 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 QrQ}3JK*DROp;7zuKc0jervLx| diff --git a/src/Nethermind/Chains/redstone-mainnet.json.zst b/src/Nethermind/Chains/redstone-mainnet.json.zst index 43b0b9eba19416bd93cf71217885b60402f950e7..8c2aba2c4cd2f2fa28b0d05b7ad38aed61011736 100644 GIT binary patch delta 7667 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 diff --git a/src/Nethermind/Chains/settlus-mainnet-mainnet.json.zst b/src/Nethermind/Chains/settlus-mainnet-mainnet.json.zst index 5f1cf4f95b4544ef4865a88ef6012a9ffeb83c3c..6e2e6dc20daa6699fff830da3d79fe064c4a64de 100644 GIT binary patch delta 14610 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

H6GyQE~h5UI_@b{1>8zCWnRoEy{yeS|XG!HKY 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 diff --git a/src/Nethermind/Chains/settlus-sepolia-sepolia.json.zst b/src/Nethermind/Chains/settlus-sepolia-sepolia.json.zst index b9a8fcd5ff53765fd359c61fc46a52d2b879c687..1a9238e73a38f7f1160a9a5294d67193d7ab596a 100644 GIT binary patch delta 18621 zcmXuKV~j3b(={@|gHr)kCh3sYRcUXK^u&i}pi9=Te%W;t{MjW`~X47_iLpl=8 zu*Nd=!5Tp;Kwn{b(wIq9*qPysrLsTes0oH%Xh`c2M;TR;kGb#GIstG=BqKz(P@d0u z25*G(4N9^8D+nBCWpUy(n4b3IhWawcy8xN-THsnWs!z`yr8KHR5rW}C6DTq)4^bw9 zM)4UDdN!LB^`_{p>52Y$>-zA`sFgZ_kFUf&gHsMR6a@2)D2-ftNiF^&A#z#nTGHeb zUv!HlvoB_x3H`~%&K~OV?z7v{Ay$Z62SCxc`pcpUnaGn=I=ywF^zDL~D-T)xA)xxA zK=k+>XTQ2g{(Qag;q$gy4s@+VP=+|fu8=t5;zeu=3T0@Rr$U*@M?z;|L#|WT04aP(d4nfZvfALPn3{+8gA%`Kd(m6Xm?NMib$Ems!Mc&Wwrkq}6x^6p0VBh% zf_>8)sc-?DhQNeJBTWh${XvHK9KgIL?0CL>`(4Pt6t*rcSkk||d+qj7)vGTJ^(D(6 za*liaal>FCKAsX^T&J*!B}f>`B&trmTO}Yd0haAzLoZSyEy^Yj&B`1v2(5$Wds-DK zvi?MhYv@|?y}nJAUvI!;QxuI8PhVUMqrq6kqFMf^(3k{+O;RK9STmst1Ni@u=>Jlz z{{y7|1E~K4&0%oJ8u?xtCyOHCP}Pcjv`;;W#6wr8^U-|T6G+DYqAbM;=*%J;K1P~J z=FwTiwET~>lg9t2R{fv4@PF!#|I~p0ECLnMEHY9igJ|j{mA;oDh1Og}&VK4*? zq^H0=ZyD)(z8-8I`0uulOfjSvV0f&RC8wN?!qJBnTyCRS>!VSh$ zf51KSFS&&VW|Wx1L0HCkm;h)<5O8b25OC>CSSUzPWKIhQK^wk7Kuiw>Y?*i3yMOW;w2TCK{cu1thuO-yFnZEX;WHxhX!3{`7Ws=N=aM$$wPKBuHz$Cty^j*7%?hRnriYIn`UECj$)-a1 zKr1LTg1lD8?zxuLcv@Y?^A$a(B|45H6r%AF44d}dkHX79H>~vFO>mu-e}6;Sc!TR^ zSYm~Dj}v;hSkt!{VzU8xJOlxLPsS=UcK;6rk6^7bVmaM)+B}aUsQ?>4nuhT)Hq0R{ zIVnIjgNz-z4q4AChTYDT10Ccjj2RbRtYRVw|EQsY8x)$%h?=b>6}6?bN{c>fzw_)H zLM8s;Jvek5#hQ>?v>Q&FZW0ff>;m`6i$|m9q=Hh@{W`~3Dh+uVCoElxiq|hJSfVoz zRb2*IHz$>*T4W4UYLai1DH?m$!s*G?iU*Ka>{C~BXjAjo)d&3~1xMoHK^j>d<|%^W zJCNcq9EO;%(XbfXg@{6CqDEZ#X=?3ujrbeAwrXD2UBE--`S$K}WiGUGb72aeRw6

iy+_CjdZ& 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 SNFM?MVUB~^O1Iid0geYinP-#g!( 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 diff --git a/src/Nethermind/Chains/shape-sepolia.json.zst b/src/Nethermind/Chains/shape-sepolia.json.zst index 3eed325e08513b57d45fdc721504488c3b2bf85d..fc3fa6ce2ad0c9528b97e8680694be5f1be10233 100644 GIT binary patch delta 11590 zcmYkhV{GSL`@LQJTidohwQajo+f%pmX{WYr+qP{@r*@~dHP7|?CwKBBXLeRrvX67W z+Ar2xXobpYg92zWDD(6^|lS;JZ>QD~pm-8B5XwEgw%{)yH*TJg>5_691pz_@AKopI8b(TIkO7 z(t6kv3$-><6kvF>Cllwaqt3L6w)0>ovDhjk|bd?4?kWRZYrF^VwbqL z-Pc_h`yWRAf0%;*VY=hVfd6-0DM*6x77PaYha3zDB!zK%qrp{kMY259so7;{co}sT z=pBI34+D*aPmIYM4+cSuFEJzzS^eF_Nggr`Ruq%gS%x&&3A`Y8>65RB_V;j5x}vA=_Q`+8uQ6kMBg+aM6gN*PXu!%{bOTmKtp zvAn!6^%&PUVM^Q_x5uDe1^zA6Pzb(Ec*9NSyCo$q1vp+1jub>; zem^1tf&%6!L?O@*5f%zN-~$CiD3BZqg8&NG5h0`nQ{4qu+65B@heSmN!H9Y}_Xncp zn}9=`4?tLw?tvkji3Wioh+y)HsDOb)cxgpQp@f7Xhai!Az`!IKA0zR(L{tUl6Fc&dwsDme7pxLdgPF`N@Ol^ml7^CFmq>g7 z)-oCj1P8evh=wdeYVwax!`51NFaXbb7c3AQ7KD%a5(uk%GY_T<76<_c2Wcq+4sr7< z2nvc9NKWCh`BMAzJ09yGXCE`#ZY^OppF+nnm@L`0&2U;^l#nYkYt^+6O))>lD^eK{ zRPFN6ptRC*i6qCXvBBmn9etSki|;NEQl#sd;bP3RtCGvo$A`_xIbd#YT0Q)&XIqx} zj;3cPk3eU$b67Cb(EI6UTVshAlR;{`E^UM} zz7mR5@*Oo4i4w1sR(IyLW~~#36KfsabdhCQwt5UgX7fslTnidi3RZRra1#`|qs=Xq zHeobb8)OB4CZn#2@H6$qbvjmxI>fF*qM8T|Gm8r{>KceGpGF=IRQuUJU zT`BhD*DDh@$kx^5{pl$kT8qZAQZG=x`1gMlnx)K`ITF!$Vuj8P2@pLV7ZsO#xiGo$ z^Xc$&UXxJ_m6?Ii78<60JVpKh#!pJEvI9#Q#&?rMy%^Udj!obUJ@K>+gOK3=X5})BoB1(<<{^ zQ{MB9LD(UM!~qU;cL2|BTv){Mxv)>q2pv`#d$qFdbW=_&jJ$M9aYc6qJQj~x)xAi8 z8gD6(FNyG%Sqfa(H5Bj7rJd}OTh)F)pFI;PQV2H-VjABb;33>rQBiE96$_rOp5Wk{ z#cZT2x>Fd%t=VG~kV|`o4>dm7FBUgo;_FAEcOTX6GDS=lWtH*7yAEH|%aEjv{~O0! zx3FrUbd!iDJyIIk7!Z>OW`B-mc)bWHzEPUMkEO`}w&6HLn`ccMHqJk=$K1}!Wh zVJ)0jPh3r6~@xUYkhg}-CoObM@Le}9y;izQ8S*?p0eVhcF`zzYeR5e`8rDDvjA ztBA*#*q7DP@B9@3V1n#~GKMM`^(S!^LXr6@)^a`r?(JRgEWh;GVaAlctCE{FKHz}z zxD`0lI$91$GNchd)=)L}iNt+a

KyAosAD(NmwjQ`5*G?H7K+7|Guot&iOD^u5S znZv~95|682{W^=Jea*_r>WZb+ds9~&(XIUas&uq{tgUqd;;R}b34F1(AM|W^o256X z)XI19&M1rvXW0jhIHa)D?-I=COiBDHplw_ai}|XPX#2 zdd0GNMa?LGezPtdEXpvh}XTGvodp_?Frjg$v;@x zP@gZ-n07*5#VMW{HJp{Xrb}-9Y`ZN%^Ff;_%APd`bf1bJdf5y8CFp5V{IOZ4tQ@I> z8~L%1kL5B%$sz5Fx*D7~qh@ZCpWlm4Uh+k(Oa7Z-bup3O-F1j(8jdbqv5aH~!{Rvk zVSLV@V~C7Fd-jULcHWUEub@h;)_@pI!3So+rp?1+Z544swUSUrDkbApQCf4MT=d6s zW@F)B0E83MY26UM#NnYNfC~sppy#y3Nj4sF>jtl z8c=Z*Qa%}|>h^q<0<1&RnI|DV9A>@;MQs%yVwi8G38fA>L9=h+`LXsE+Tan{Il$H0 zX8XiB>)|qp?Uq|}20IS_}AMpye{h8F~W?$Z}0s#?M5WcSo3=0lF~uMzV96-2$xkE7NuykXF?diJD~fzZFG-q_@V2MY=FkgUjyK!%m+4TSbHID zQ(^Q9p_vz|%n4P?6EcD3J5bJ5esYQyg{Q(KBdd~PzQwvlpo9+vQmN5UrX`DT`XptMmSzf}(8N1-m%uraqA(uWjhg~{qywc4qr1gXE z3U}etqTu<*Y-70d04CsX3NZUfa$)@m-CKr`)HCpYX!|)!Cw~5NJ5XJI!Dgg6CSnIC zALGCG5WQ`KVAxCc!ak|)MzguqgScz7b2lh@^|zh+A6`%|;_FReIBz}e5m{fJXh32i z#Pm&dS`YMHSJhvIW!WPE=KJbmQcd;A2Kt=~ZknG;V_M7|+%G^>5S~UK)K@>^bKdh` zTkeNAn9MJg3Y@II6ta=z-Azcj16}g3dTKjzua@6-7xUj4oFJ8|r7o^cNaLTPZX_h9 z!2_nQDukRwm!mVc(wnA+gGabQr)P}*Z;`x;wOJ_fW?GZlhr`%uZh3Jd(nu z^{Qjm$cLW;%ziO<(|J2ak{Jyu{j{ZUP6j0;0lsa9vgVr$0#6@3LRhXu4v3M3>*$W2 z)KD9S9PKBaoVq`$W-{T#|GG&P=)$Apk7yELPVMY@$N`+n{%^bt%$OJ-DqcJd1*G`# z^YHhNRzJl^d&@jmW~9ne&eeW8>l1Xzx9XysQVU+}ZrCzX3LMiunoWTY{c*6ZhlX!q zB&w@GE=5+sk4jpP#8!P=h!Is(Q$)!p@4#OSl#flG&oa=@_+~ne* zv(mXf?80|fFhvh#jnB%4Eq(@v;$Z5(%#wTMm{uW3rm(77aYj>`pd`+cb$!mZ3tqC{ zA`h=RhF=U|NYZTMU!B}6zmc4|#9zs-sGYV@3j>1vQU+IvudC5o|KNSNK9V2U7Jh2-pmqt`yce{8wm^l! zIAGZI_WPqJo8N6xoEz@%xQ|}0jU`!bp(lRGaw~f?2%N9m}#gVYhs?*>%{Bz z5CR;q4hYKVVwMmdw%D$;J!7`%rM7Yxoj>vEF^sPwiF5?}X9n5ww>I@%ztt0;>8kk+ zR*^361^RWe1Xn*>xA1PUa!U@=w423T`X6p1Iu`dePp#p{dBGzGnM4D`6^%<9rQeg1Pw{=uU;Z`C)0$8Ld)P73gvu{SZxVQ1TM76q(0UsK;A z=CZ#|zrwhPZR-lbP8ZjWE)kd)2)s5278`c^I{m$TSL^v(T>IbAq^FO0oT(rFc>uc~ z-%=ea{HdM?;JcihM4fhbdC~6*hJOt^PBxQ%jL(;(Z+EH6tiP^NoXpn<$}go$Cj|8l zb<0=eGSu{Dv6jB{u(%lu$vv8)MQshKu)zv{R4s@x2JTHMb%^TPTUL+%7p=VY4Oh0I4=CeD?K1Mlvbe$&8)}}_F6@xT&Lt*xxk@+{^c()FQ4mJVtb>&TaP@j?4;Hp$aH;qE7zJk z8oeU6ix~>6Y!vjeXMy_nN^<1>Gr-dgW98LXc-W;v5$4E zDw)5wxDiK9yBU;)V3=$eKH$saZJuH7=wWrQ4Lys2L*2cuY5lty5M@;3gPV2V$oW$j zqIv8;5)`<92NP#y$x?wDQ8Hh~N8(_-3^Q2x-R|foob$2uCT!w3GMPvqmq`Tv(_Pf( zofR;_#T}Xh*9v9I!-$T9dl?!4dL z1B_f21x0ouH9YE$De`#=WyywSqsw=3_m-p~Wo{WtYRo*@494z(KQa!BhJaKcPQE1A zr2eh(wxTr8&(}em#w)#+cfH9G0ql~ z8*Z?-EFX@-UN!SIr#W4i4iX8Os}|4AB7ui{9(`eGzB**sxeeB~rH}afB%0#3v~J`a zq42yImWRmX)hxV+ae@zPU182$wHYG^iLJ#|lejqpFeq)NA9bdpDLEV6z3j%fnRd5D zTY;dNlZn6>@>j@F7C@(Y$?~K!kM|3;+Rq~uXZtREn^GiFH*pem`Cuk>yWemk*EYYN zQ?(POyrG39E;_&gPH*1Vbxu1vXvFrFmeT=Sbhy{!9n17nj{9(1brAtA@1==mJsx;l z7fd%@{K&Qs5O@5Csi(Wr!ulR2uRh1^EqGxc-oRkMDvr}$0NCPT)jDZ=RflN$rto1Q zUt&3wG6--oZfX*6>mnjnBG6DVGIChdhExRpI|PDNW%X0b5FSi2Sjoi>Z#(dLmf8;| zU3qng2s;m&e`7J9<`9N+X;mPN?krwguw)H78z4-n*yJp@(Tk^i9=(3nt(UPY@JAj| zA8ApGy*SVt0_<&L;Jc{Z2QU=o%aAYY#Yv9#VpDqiyjI|IQ|i^lD= zS{(i1l=!s{TQQpEp`#dzC+S+gJGj;}RkTMT z;b+NJnA|$n{WP4C>Y(2gzHp;Q}8W!_+nx6O^epv z@HycIq>DuJypd)yZkWctLTO%qj{GYNElzU6Vt2fhoe0|S&w&hu_zH~eVkI80`ewnC zi~WjBxuYC77X*2S4q@gHr?439!(_HeOV_hcAz_{5l@e!#Q7SZxqDp_12}@Kcx9}-e z8K;36h|4mG;agN6D;~|Knxv=@UZ|UX5vV`_tgbSayyMkkAGIebnc_gj(1@DnXDD z^L$vhipL%sP*P86`xhM(zec{18DiTkG2pug%_yP>lV z40_dO!%Y&5T!_l~2e2tqI=g+xC0Sc_`FmPzv}nb>5U;%P%&5VB4R?PQl6MhM6fklFr{LVHSsU2THVkdf1!M%GFDKtSNcGr9ofBu`uO_|;Hm7C z`hc@@f*xoL64}jmvzxSJ?%@0qP%I z-F+*_l;~c1fl+T`Tyu!JsiioMFC%=1FT3)M0h$C1)3D0fM?TZa%Rkb{Ns(Q;ysHFj z^&7F=LkkbCDys>jL1_xwozEvg0$6hTUKu9;Yca< zvV?fYnag1zO$_hwW(aQyX6IcH>vEiQQH#PoISA}wX{2Rsb@l#Tm-LqZ8&5whJ-nka z0W^rgS6(ci<(-d2w%r=3*-=vFyd{$RnP5Dz!>2LXtx|d@2Zo%M0a`$P0D40ko;Q_Q z9$X_9YOhDCGnsp#oTRu*u)Do3G6a650pz?kb}?OY{~Yq?vH#2w>v5h%M6ipzRZ!py*P z5r`u%58|9}Mv-RX-W{=$qGunMu~R10v0f}I3uR(mY)&BNHcu(}ON`sR9!wTQ%xAOI z4(p?0yQBgM^0^#T8zS~RjBb7!4g^A|AJ;le5TnyM&kBOH z^u5j+z!|7HisPk~*17iw#FMx|Tz>-6YME^6De4%Rc=|<_ga~!5=jHQ8ndSouQ*-&O z3v5Vo@mu@DWs8XU(o?W z);s#fXc3B%$768~6LfgMxAbOgu-k0?fp;KAZW;f60B9v){UXJJIFhddS|4rL+@N5R z%vs}0q}a{dnLJXM|B1ytPUnJO0t}GTQX=z@eHe|Essbz`-I)g|eRq9#bacj3Z1uO7 zVD0f@`(u$3X1pADfSeI-6)3X+Hc*vWWf=OcgBO#}9*-oXVVsqm$g-3jt=D7sh9s-{ z-KN0-$TxQgOUP=$G63Z{)FRSN`tD{RR{`u}L{a2fW zz%@-HuQP3Lu+IIfzUF;He|0i|x>nvaPJKV$9o8|jC|t`A3Cs);_y6jyVu~Vi^1}aG ztz*L(DK*8|`f1WAJ1o=1sE`;=7Q17s;}=;>|7sp)C3Ey%jN*D3W-o1oTv{4Ssq09f z^1>a@Y!lD6!NrufJe6rgqk(A{$>z^OPClJ)BmLVco^|%i_`mVvCC#wbG!(>slgro=2chRFScEbl>q_V5j2E>yV#|1KxuxSu91)KxjpLHZ3f z%HmlnZ6!kmP4@IKB>~T2y*!%72QA-BY|Dag!q7m-g%Yk$nEGGm^ebMO;P>7B42cP{E@pl2pR)39&5{N%0%QY@71)Ge z?QQxS`WNe)Fa{aH36Yt$q;Ovjof_4zZ6!mdNPQ*W%9qep-E{K*>sTrBuB5fJxI?ws z??^s(qIaTMf41Op+(%YNGEz>4*`78<@zbSqvB$QcrX|Lrq7~47Kk(a<>8__Ju_$IT z{nc(#JHdoWwpMBwq^S=yGY~snwZosop2<6tT7f>y&ZFS?_3Zp~(crm+ej!}>WR|&b z3?u8IP(3t9Rg}c<{tDgY5r00epN>PIbkR(Q1J#mS#J9&S?%zxf^4r80U)MU&9MBA_ z45|#y547(QqR~;<*Ga{PUbPvAM|tXRq6*ks{@xFPzF6Lu!9xJdzdfwEc-7(ve)f64 z-55BcxlX}xbiufm5lrPLem_eh$c zR`1uYB2)4Kih`Paj+(1Vz90bhJ=I!fehp!+h#y3L;t#5lA%fo3XW!K z#frqO_w2;PCBmb`!;SE(E`dHPIJNS$Cg-;-ve1l8g?2T-MND>i(`39LWTJ-hmX*8y zFu%9~O5V|n>Nc?woo-EJP_9s3i~^Qi1zsA)3d$x}u~zAV+{zB^m$>uJ#HQ?%Uivcu z$&+uBWQWaV%TqGi`*#!P2~1Nc#D1429@1TFDW(ac!6KQuXjLRL+HkU9)L(G_9b#}~p=8C=rIbW4105(*e_&59gRY-V zL_A3ni#*1yGcdzuqXTZ}Di@=q{2}C*+pgtVPKAIPC#EFR5eqv@s&2E>L_Z`y+>bXSF;OC}|VAs+TA!CjH7y@&oG5LKS-ZABdN^hGd=aYeiMq89>`cgM)AOcgdQ?uQAe6zkKyjPDSeFL}OpLD_YA%+B|c zMk09V)p#%<`6rMp^7_rsTf>rItJ1C*b5|Qbhws0zIY!fDeg&c`t#rGV15v~CO8@k=+y1{UMv7c{g?_YsaABzT_ zXqKLe)Je2wfi-HFY#I-Axl(spb?WB1lTHvUtD-V2X4dMEL=_hN(3mr$gk?g2`f|D> z*UgE%-=88lAxgH} zNdesp48b~V`yciJ26Nm$*9Wh{()nOH&)=w7SR|eHg_?9TU93922y( z3Q~y~fCT83Dz-4u%CbWFUUaeDt4xHUf^j+!SQfNnh^BLA!2%5$bVskLXOV#5NquM0qEKY-t{Kg}zAHtxAL;e`ybfr2h4IilI| z*m#k~nnn+42BywD>s2HFi|C+eo4yex`fGS!_OOU?IXrQsbMgrn(9h~P*&RSxE$IZA z6~@yJEA zvi2te%dW_d3FQ8r9=av2>-uCdEV(tMV(LPN<52v~qQ+uExxvs{W)J8xm(UNK8X^Q`R!{$QbGHaP6ib|ZFT_AvRz1ikDT@{q~ zxyB9D;YxY_NHz?aCA%oE@2~>lV1NITEHC#|U3XF1?XFb7y~DCIrKoQ3yNVNf7Veo) zbUZ$Vxl6NF!w+Ad4s(xH5*FJ}q#x`!bi)ntevHu}X2>B${sH{6P4?{-(69F4?_WOt zRR+BQ?lYdcN)eX^?l0S9FMU`j^xbXXS1Yu1$*E?OXTG;g0P9jFohbiSljN8mOU{;; zk#Co*xue)o! z0vsGOfz(2w4r4&?;F4@>eQ~rA;=UY+c-Zca)TVd9$l(EJU=+w`I0Ue=^;E1k1Yj8tAhQ(U*kaC>JDf&pL*rQ#3voRJe{fzOa|b);&i= zu`dJrS=R5jxwS0Sf#4D-;ctfic{#X2ojjmcna9)3`wTdrhaJ%xZ$TRycJ3@l%JPLz zYx=zyaq;;4qMX6-UiKv^oF4bu^!@HO@=Pt%ta^yK;iwZl&ak&209g4_m7yfT|KN-Gu`M#j-9h zXg6tj(eOI>`-s=`bk=TMW5&1RSw;pbEb+9J--edAoA4kh@sVw14r3EqSVz%(<1ASr zn8;n7)SXQ_knz*S3la&=fn3KMwuXb^5fNX+LEeW{i04G4V!O#H?B7McpgHi+^ts;Q zvM@j}@|)*gTV=)Qj&BT^>a#55+L+yktrZ2a;k=)jp;%Ep<2@IJ*~}k;gG8(#a_ohU zVVY8}f`~^cMwz@^vTB(Q3fqPee4GQbTM3l$oayM~K0$?rmJVuj-9;BV&fFVwv$-*J zbmMv0tIJHOBTC_AJy{RW3w^i@tOYD)^DMyhUdFqV?{B4ng%22358O{e+mkhcS=W6) zO#WAfrN%^z0R?HV=(j%g*5+=E(ddJw>>@4r#w4r*j99zdH5`M^d8KLvoLOBXi$@Qd zJ=3?`0A+!OByfjnKSeDtXW&%u`&vqAhia_QNR!wlZqYZq@8J{4xd_g5Qmoh`?upL%_tZ_bZK7RBS`Ah+IbLLbSUhKrYfj) zZ^%HfC4b;aOA#@8M0o4IYPh)L^V_A?v&+n$!&UU9UbJ}$Xzk$HM_2g_YZ^%f9YJ)g zpfXJb=X8=-aL|JLelCw+%ZuJd8w&WwYAExWiLJQo@ZD}$m7YB&(W=p!4kuf8e2Lf1 z4ABNdNcDjxNh%EfTgKD$p~{`urjr8FflG$=_I8y5X!;Fd+T;g2 zMKKY1pL&^!iM+O-IF{_TJ9xkocOtDx$_85C4HFD;{DAV{CuKPa$Pu~;cQ*^u=%CHq zt=bEY%S6^BfyKQhM|cc#Iz2NcOOw|)swZEl0MB@t(oup*R0i|hnzLQk`KRR(+iyh~ zA9XPUDp(I-u;Y!u8OG$}@c9eZYuv1MdmOAmPuvv(ao~*hgVB3*O9nWpAge|5l{ID5 z%C}}uK*}^v>~W}SF_<|AFeMv3y6-0-Nw24gHsIQ&rU}<;15_C@cQ9%fsF1B%Z&oO+ z8Fk&q=yJ39xzLD)42?QVhsa(YX;|Q<4FAmw4VsNca^@C$;w2GS5t zR(LVFy{3by$=?-;uK=gSbU2fF+y;7vzV>hRh*}MB?P!T$n`)}nw+yNj2_S$dmO6yo zNZQ`&9tNfo8@mzPFK1|ze-In8$M3Sk!ec$7sjZ+!IrmHYYIAnvtz!zL-Jw;xvY&}f zlSL1POlK}teKR9;=GH}S#XUcA_kMX-Mtu;5GV86&@!y{v3n-6>v9sfcee$T%3VFzU`J;({I%Rz+FY}wda z*NrguOYxki0gATw`fZ^^xV$)3b@=tA;;=94J!KHubjVnOoIh9bBD+jAlQ z|BU(`RA^Jo<{G)`YjKMK9T*6KS6EZdS1~4s8mLHOI#Kc;%vvl1Fdu4H1^)jB_%kK+ f{{tZATfNW!=ivNvYHF%rTz~*~Z1QFKeg6LeDxK_2 delta 11513 zcmZ9RQ*@?5)2?INww=ivPi$l2WMbQx;E8Q}Vq;?4wrv{|O|rjl@Bcs9t9#YK-B;Ir z(rb0Cs+<<6xn?MUu8H*@q}COlA|%xsSOw%01v#5i)V=F8-{M`Ij7bAH^X~6#_V+I# ziXu28X35*4JY_Zy2)O^O>@;5EK$R#NJB%!~#R>V6jhIBWMyRnk$gx_QSsZF)t4I~2 z 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 HJqP{+0DmOv diff --git a/src/Nethermind/Chains/soneium-minato-sepolia.json.zst b/src/Nethermind/Chains/soneium-minato-sepolia.json.zst index 11023bceb62bf1c1706d70ca6316f01c0c4e42d6..801859ffe85b35420e823d9881d5a35ea6fa6cc4 100644 GIT binary patch delta 14650 zcmYkjb8zQP^935)wvCOQjlQvM+t`?&*tTukcCv9c+SuM08|{65_tsl=yK1J+boHs8 z{->w9yJlq@D(Dyrplf6Kgw&2=)xmM=0MFiz5~gBJkaftlM;wQ>5=J5qrGv}xJX{O_ zrI_b1_V{|naX`RABEp41^+Gm7Qr4r6v8W~=^8H!u0+5m@M#-+>JRkE6UrFa1m1F&X zp>Us+$4M~YdOA!P8OR=P%TCmR*QwLJdu}PG(G7`_j0~9qa8!66AXbtli5W3wPTLfX z=IGx)CkNtf8p1cCe$@-TeI)i99&>YIpjfO&Y34FZX@4&kp_b#Tqf9>X#kO2B|6n7S zG?-fK>ZPCPIk_$y=770&1d2a3o)=ZA#O|fjnQhJsJgl4fh%qK^HQW}8?)>6zG#1Mr zE|p(DpEb&pMliTdh=0-HeWzr$wx`iP!r4|?Qh$(DFopx|)7cXbmuRp&En?*nf2N>p zT%QS6vl0sHPMaLyMWjH0(*hk2=g(gYBL$7 zTZ#{5CRDU4>|+a1#WIVkQyn!(Da|1i_}XyDmrBXA%R{s9CJLaKqx*hnh!@%YO^R#a zTl%_mNS)VWA?8w%K%Pin)P%0V)yS$@_NrKy4nsoMEb!7iqW?bt{2wC!p9=qf0R4Xe z{(oRYEF7*zNs#g0nj93mLYt56Z8(W$@)Ttykcj>#EWp<9La}C-j2PN)U5gaVGxG|-d zh!P?+Dgzo-FdPZ52pp8pDLr-H!>#2R=i}yu8HVUO9Iv%9ZTH`>Ooj2%rKfP~ft6RcBKs{$@sbQ^dx1YtQI%!ZT5_8im{$Z6e(`rj%YN(`hE z35G>sK=b7w3xr{yL!q-40Y}F`gBJ;;D};y%guw#~gdBxLfH6@Hf+9(T<<%B}5{H0q z2S-uf8%i7mha?lhS^$FtBZG~EMQ1I9BuZz#3W8BX#<&DZk09;LLi9T>ya$b7Eg5df zq?H3XiH4t&bj)m|kWz37z05V)Y{k(;$qY2BZF08~k64}-7M}AQU{6r4jlr=6BmcXZ zDLf=;AQ~KBi{~Z?wwU@vUCZX_{oQ)^T z8itBH0rt*ANW0!bE92u~%Ms%t5#=C!GjQlq@Zw+#)<8(!LhhBKCG1m32(%y=JTwtV zEMDtI>?`X)a4^o>!r-()a0tB0Kxt)Bs7VMsuRtgwGAkAvsmPxq1;fQB-*fddj^cVB;r6XvMG2h{<~rinI4~1-+Xjw zi0Cm)IPs64Bt=`v26IB5lqF2QG(yAo$S8dZ$CyzUIT2OP&}IwP5WKNsNzn=8jXd9d z85w@Q8MgOT8qA~$$_AMO0}~xQe30^AZw#KuQ&`lZJy*IP1SSh85NWkO!AeN%-PHIs zK&7>ZIX0HSWGXVLY&=?0QmW#nP<6B}(1 z@lXl!o6X-J#a-a=21}2$6`<0x)ZnT_D2_Zr2Nrxm>r1$ls8|h7Cmz4dTo$Cf2pjgV zaaVp4<`4FYhoPk+7d&=$JN8vHbbQbTAk}aNl5F>Nf%&bG*hCX@rClF2P3}mkjXp&z z`wvZxNhUTz#T0NilTqcrH2#djX1EDIS$z>7!BG%Z56Y;Z4$>dOkVWQ#BVtUvZ7kJ@ ziR*W#vG0;S|I=@pqS>?_ec-iFG^7WQoN~9hEPh(Sb+Mmn(RZ(NYBL&99x=>dF9;&{D>FC0NG_!r z;tED|XbN|jDHjvzWwk5`g2U!(1`*+KS&;=nF@=Sv{|IhZ$F8Bi6Ikor6`4jCGD>vT zqqwHDvd$onq0XWVhVloIC{08I8AMOH&S;sGmXh#R1d~bd?$r8XOH=s~V^eiB@K(IY zs?(Fsp}pq$rrHXeIYU$PMdxnu7hTQaHBEE#=NgGhws=D$v=Zv{lcd>?klCSx455Cb z0dba-L78;qEjSWWjCvh<5szA})k01yf7fLeJ9=)^1Tf1jL5w`Lc*ME@UpGf9zbQ9A z$1l#`S0yo~;%=}-as5DUe40NGF|J0)1cv(RztZDwypl%&vHtI!@uUdi*0JKS1LE8m zU!hau2ohI4X;g&7V|xyW@|Thv2m^v=CPt$ zA@pHlt#n=Ms^5S&_SJiUNxb4c(*`HUgxb?{oK9U?DYcpydkX)%B44t%g0`rct-SM{ z{-9k|5&hG$`pCWdasg)>6p^``BS@6EPsD!Ty+?S3($H2GA&-h8X6Cofs0 zpiGNEohLInNqNfaQbE$7orzxeMTTaQ+ZtOpNk$w_^(xZYAY?$wFIm%mn(m0=HwuFc z9K|*-`$e3a%k(B-HNBWhNtsmA?V@fj<#Xt>U7kTfV3Os~p%>#LcoV1eO zJXu$W@1SldO=uxu))`hb>7~iR&jI2oTcTo5=2L*8f6xZ;yb_RNnoN56T;3G5CE33c zR8Y~ACs26fvsI=lPWOv9eTJUJH`Z=7jfKkjNdH7m$_9YZg{?X?(f?lMZ-)F0dNsM# zPeq;DcX7#iC)yOceq+oedLOs9KyJMlMl_R+&xcN2^trXTC@LZ3-Fa_5?Gw`M99h-k zSn`*AMfJdboRlexilhXy0yVYS`dLqsQ%5BG0bPkxSt-LbNj^S}X=Zu-sOtc6Ewva@ zQJa+kc{zZE1@cKqi5>3Lvc2VG`KhdM9VfltG~u4$EiW1V!iYRXWBV0LnY4%(IZm4H zx|*yzSq0bHrlfXNDvP4`klS{Y@Xh10zca~ z2$wl?X$Db+dfF7(Jfz*r!eR1oP^OA|bH|!$eLkRAGO}TXL@$Tmn(gB_PC}5^MDIY= z*A?fj-QlFg*!={paNN&VmQw6~<;Q-#pw{d;+j_!)X(?O=%t+?sL^n^F-A`49+CPw2 zPgM0MTxe-ayU}EnY-*b84sWJd2#&Y^cHCt!6IAG1gHK~WWR0vkB^~>hv!*)E?;|Wa z*`>FY9y`@JWB+HoTsN6&k->MBq7E~~1>bC$ZCu674K0NYiQpIUVNHa75cS;%#bS;& z!hSIxfrb1J{BU^m$Sj>ix}#O|d)Xa@Ix4srPOsQIvDhSpXf}-5Iq#HF1TuhOw;^P{ z*VM!>C4&eyFnTvo4zw!^t_6h!}>>2LC$6( zP6fNq*X;gtmM{mWOa+JP-x3`*ZGjb0rA;nTF+=udG{d7KUJG0PYF!?&gDR8kxNoOW z?p5SdGI-5=uy}Al5H3{S7oN3}DIPU)97l6cEcM|CNkrH0yHiY$ds(2k{Hx1Mev7Jo z^ttz0>k>+JsR^Fw({KE4TIlQF6l_x07w-hc1XYc^IewRoJT@q`O91Ih zAHKr3l&L7VGajoTp=w_r!w_V-2ZsssC$*)pn?kmHFe~TbvV^m^`ZnB5d>6gyW_E6n z@Ik|nUc<6pOz%zOT?JquTvDbO8=F(+HKj(-k<7FkuQa74kvU;HL3b=A3nF5Jr!`#S z??=Tx_lzwfacdvf7UVUvB$Z-xs};-T6*Z&s@ntu{uN4B zmZ^Q7TG&+F;(|YGMe!+}xyYGe5zcyVtkdu&!GccfFlW#7O&FjNm?%$VGh<3%OWJt6 z*48G2M}(MErlGq>{^_QnRl|W|D>uGmsvL!RGWHzj{%_C)3ns~d z_nw0~r;1y`1q)b)7oT=dA*N5+z@{(JAfm^_x1iFsHBC*L3w7i{!F?g8&$YoINn#&5 zBk8X?$i@hl*PK-D(3TeOjiTGVuZ-kJP|5E}jZ>D)=u?ehJhY&1atdR&9aNUAc`XlT zkEi0|saj0G(;csC(5#w}mRnp}{-sJO{u58}t?0POq6G+hiQ758sWZ;f?GW4E%;#NM zRrvY$uZ=F>{;-%Nz2%Q6O4=h;B{_`m58ZugGxtb8cF*Ryz&kot?xEh}Eq~Re)fStI^eqQWGXi z^(3z*F>FVP)u*vVFL)TLU3ijW#nyOa1FG+HHN1JN#dN$|EA<}}^3vGU;kC%jP}X+- z)Kd&;9p6VVrN9x`M)%zIHjkaAXRZrPzIMNHV*%A1%;rpf-fSydkH%rKrP5Nf2B%E5 zOWN#pa4C{XDpK$U6|u5nTnwm6lNytqy0=t*_-C@&OG=-je^rsY`A0LG1uEBwsVH@) za?4|Pei9b&lLyDD@k?3AYH2jo?9T~AYM7fjuhZd1XyU3L;2ydC9i~ePJG=NEpoH3S z0tcAal8201h$ETj@-xJZeaSYm|F)y;$5JC*)MgK--1kikt%CX9j}ZS>`O8UxYdA9v z1sMzs0*nmC3^S0G3=0W%Ech-{oq|OeD-as+_!h{^i56*U!itAff);K<1|tdv1C9n} zj29V7wxmvo2bOc?L^?Px6q=BH20z@j`vTZ5BX!=^P5}`?MeBu#Z?UC==mI88Yk{? zK~wl2FhX(rI2_I(7;f+ezL)-rxo|}Dg)mwb-#f20i!wM?SDdoC&|irKiO>F*#`irIug2N&@8(cHWcxPzeL82P&?fZidSk{vwL_qd(~lB#u~-7# zlaP&&q*;(C_78s#+oT~6VtRa2%?!jiwcxCD`k-@Qfn?kLdeCxlZH|z_NP}2p7aO0_ zw#AK}`N`_w<+^@1>11UlxlBqjMFiw@?MQVb#S!L(lH?c877L-*vXqh#nTt0%;JX%j z?qXDSzKM27I}1pRGc}jW@rL34v+=flfmm#a1MB{y;DstL=+=A>h{rV%Kr5pdtGZXE z(22X|70|49`h-DYc5qJ>D9Ma%6bVftS8~DqJTP(GQ2{B?+B zzV;1l$6#MpDh(BQ=UV!+R1hH`G|+gi0Xu@ne7@p_lw!908gH?`Mt>>%ixEk$n`zRe zp3i*NVO2K2vI}uLHrP8h@E)jC`@5_31w-N^`OCE4&Y+9Zn%MtphjyllsPAvp#kak= z`SewXetuH zPl;!lWe`7%=`e}7x<5qxdYiSpc&3Ux_jozEzhGr|NIo*5*|T3hEh|tE*h+4L{T9fR zW-WtjcxvLO%E&$DT{fJK8DD^nU1-xOVc!t)O~MJzC6@Yw=ff9tpNUd^7rbf67J%!zd$1> zMRF>x1f7x0MW@?hloIxX>> z6t7rfe+LsXeFRFuZ#z)OB7QtV#X;~Cf*(*Kgf3q4PVf%UR`J3wur_fr<&yV9DDvmu zJUZWe*jar0iQ`8~foyW#8m7H6NA$U*8Q3z9*`vV$p4dZy1^jiHgaeF zwm7UQ9=#98^W)5JnT(|5T}P*!nN{XZt~l_J+B`wTZW!qEPY!7xXj%^c!R;9+0j@v0 zT!PS?<$M%`;8Zh+{`s9&bW^owvJriNq{PxdM)XHuBI&m_)SDc2RRLGOK9PuH`9Q^B z2DI%DHQb7TT7837ErV@%A&RW=# zOD77n(7Sw#sOY!5{i@xmCG#XzbU$A%{E1Rv{q&s|2)nZc2MZcl^Kd+P#i;Xx1wFn} zC*OX&sOu?eNon7G=+h;^%1DyzBh3d&LzzYQ(0Kv)LWX}x_nlDpe2oe^-BA7*L}&>i z1BR)Em?M`n-yN-F15S|m8#&MJX#N?#`QH{W#w?goayIg{90rRYMG3klN;(Z^I>gnO zGdE~-Qf-LacD1vibjw`58EBz)7s&C5{MRBI>)Yygqo(k%k)Lzi6`W_N^c_WMPNzLx zM9l>x;x9B_!?vCax9+euReeOVl+ELbTUD@$6^iEwRU`P0BjR_RfBLs^ba>p5L&h-< zBF&I-2eXJHRX@}k&M24vT;EmE9`a<5K=7yCU$@1TB2Rcev?m(DA}TfWLS?;Q*ox#x ztP~YN;2P!o>x*7CBO=i;?s#+AW8zSj%g_sK*ICr7#Bx(~pj))?)OMpZwdcmK+Asnt zb+}$lN&D{Ru&njGA>l5dpt!Re=M37(%SE3~OQ=1$mbWBo9^*w#g{J+e_9~p~nr6}W z6T@6uOpZgjEycV)_s-tYnTcX%WvA<*&A*ahv=-`!3h5H9kZC~C_(TMIC(TCHWHJDP z#nPSTKks2+Pcbkg=Jh>UDB|H-TuuF3aOTTS=mT4*OtL9MRU@L%&Lb0IsdS9qxX{<) zK8v03y6q8;Cy~gtXyFzGp?x%U?(l@PDMXX+lNPLOB4$&z8~Ho|{1jM`5*R!VI8=aE zD39dpL5TPR>l?_bXV9RpW*7dHuL;ON^jJ4p4_?I1T!mK4Td^R2V(^*dlIEC@|Bdgt zt4~Dv@5oF8hU!cihv8z;o3rtc8Mbh#LIDs8IIz@rKAtJ|>4l=J0XG6qPELyelR1`u zY9!k3D4qOWZ!2@ENloHC(Yj(-Z6tUYJQBJ-rWI~6zQ4i`aO{^3kO4v_IQfrfrw8wg}?XO?M5jlacdVeI9o{Ds2>?(bN z>Yc@(GGPqZxDl(0VbOOgHXD@=!B1Ev=a!Apc#Nb}d6n5(%Kp_xlQm}8)?@(iO}%9h zT5$*eB2YzQfzCl7{9{zI0YJ`|WQBpi9un`_9P7+D_)DW+o?MT&1I?Q0+LyXu_`*`J z;-&-3iIya$wizvwX58n`R90|H6li2~_*fpuYLkh@?Q^E~ZXpl8VZ_{PT`1<+Tz?)oYx`8zRP0?} za09`^uia6SGdfoSpr0Vmc7cW7*%0nRLSK9hNpN?%%boO!wiOX?!Bz1zVZ~muwG7vW zyH0;afq+T?XG54ZBTfsz4gj^CI5H2w_ZN9E77@{HGc9K8NK<2&!=^;VD16H=SdMOI zcoL79s+u(4UC<<1l zDH^s)yl+}6dk;d0{~Z!dM+13b%|Ae4D^&7=&_rWo`tVFA2%DGZUM-iC$4?=3`vuKg zRrg31qOJND1o=x|;=6!T?J|E`k82}lJyMi^1Mm&(CQDB9uEr%68Upong#}{lXM0hA z4WV83&ItDl@RWhFfs^sc1~!VAWBO>rOz`}dhwO<;!MzFq4>DM5iyIn@$5Ig`*zKu+ zAC^BzaOuV46`A23&nFC&r!pk3Wa>|3Z_9A^VI=RK7mUzn5z~b0G@1LJT#1Upv&|&H zs)EVz*V7&%=I3*{b_2rFv2+o-yEBs|V{j=S*SC`gKxINCKgJfm?i1!;q_mT`^ioGZ zui<(7u~ui-bZ}HcP(W+0L|Kx}f9)34Yc)&HAD7hQnIk>?tlhEyoY;srmBr-DW?Zv&XvNHDi9^hsxdtp8 zz$0~w*EI7Wu`0nz0DLfmynhb^^@!dqUGeIrEc}h*Jsnl7S<(&3NXtFcuZS=g?d0uoC|4>Qzcf=g(;8YPjyxD0lz%#=LfF3Y7*@^c?S`%C5r~m%LjvO z3E2Lra0FEZ$4;VY7zJ=_?SlTqejD|||5b}K9`^f=Y;w5YO8caRk+*~!TBnFtDb#?< zLxYPUUCY^5OMi(M%|4(nY(g&fUfz$Z8;-VQ_se@T8-a$2LibHZP3Ir0{daYafBlCM zWdO#miU8lEx>qYGn<2MRr>$P*F4P!xqz~oz7&QYC8ZgMozZ{d$JF8G#Z~c`QdsK5J zdY^mJLmq*~9oj+ka- z*v@I1MGDq>MZQM!uR6=|^xTgKg?{=`2~f8DdOBH+ijE$&3?@+=0YER{7<8dxaMA3F z4{$t?$#Rak#uNz75Z|0ir{M8CGlR326-8wA$5`c{AwMQ>Mks-|)M-`)2KF32yy;Sp zcbt`+nO*FF`hJ^QIg}L-`+C))7o#8Sl|!~2pe5T3P>RU5v&i6w89!r)FisN^fHG^M z@7qr9(5wn!-+GGu<69r`kl#Ypx!Ok1e#jxWb0X^51!B}2?($4`0ov)#K0`y9``Ky5 zk5IOv=aJXFh0CcwWLa5J7O0xt6Qg%h;aF3`zo&N&*fidK#4=Sx!jxsKe`#WznelaG z_)1Lh?7N}o@R{=}ltiM{OMfu40xKE!V?UJocu5dHcjM;FcYP7fA88IftofXy*qVFR zpc-&4(qMPkrmt>2g!#LCMsdhjZefU|b^O^;Wb;xe9EL%6^&8WlEOXgU8%T=eQOn6!zRrRdiu0Cf?;PFuA9{8itF@OH#-KGr~0k^=%J@d z{*V5&f5&mh1A!lO+_+E6K+jua!Af+Hbi5$1$607rwRt+a{+wHpkwkX99$8uzZ^{3v?2=BBX(z2M#hgp50As94Q&pmrco4YfA$b&-Q|= zWj40LX0^bQIA_#~jm-HS($>-AsHKj=?0AL+E9Sm8rY>BqD*_#K*yYY<^pkvTany(L z?q*^^HptFj3?~F7@VL+`?mNGsq{3kOYgC3G*o`+)*$6oj;Lh8^X4_=$AcKN#_^2)l zqp~(og3r00kN6MHEimJ3vx?}JJk)J*qgPlzSJpLtO%ze>m|6Hr(4g%~Q2g5MkTCXo znlZx^PB=fc$>xAZN_C!71L`uqimjH!a@@x(fK5zPg!T~Fewffu_IP#vnTYt} z@rL$$(AR&Ejd6$g?Tp*acJe)0H0O3Sz9r&4UfwZv3-YupHMsp{)sR~E%HDF9WQ_HSeO4hI3{}Z?;1`wPAu=Hqh}rYrS@58V*pJ-P)`R zM!AD9FsX76AEi<_+6>L`{-`}PvL`G(L=tS=0JFgH<=v$TH~p}i;=j?s1%LW*rQ(O& zkJGSs2evd7FO>}I94$v4lEcgc#UcFr5I67G#6a0Wcin|7DV{dY*bgnM!T*Lk3P&=n z(i#DEgEAhHmHbbg%s8uhS*5dWL)V?w*yLdYMce|BYC+7S&a z0=v5@*mSweE96L^@FjD2Vm5b|R0+`CO(P?b>i4W4tnlueU49JLQqDzf5Y1#O`*x4N z8HE4RZLJi_0OS@5vLY5Y{0q~RZLwU!X1{NuG(TzHKL&*;4Ajyy;$L@onA83t9D~*?r#CxbqDoHlz3(BE*vwp)kB8 zATPY?g4`(1L02z(JGegw4Na*A2fWfx&KdENJX%unu&vI@p1a89y)5cq$?<`})IO4o zQdwLhAZQ1@Kkd*n>eA{Np~#Rr|1^~bv>qi*)x>;|ERK!=C7Il#OM~m=NJ-7gMtb}( z_(-I%Xk9!D50mb-s}MsS7%l}T{+Eisetq#Mi=mX8*>;1pXH$>#kBLF6fRfH)G$t>4 zXGxH~2!GN?=>c{6OXBBZbZ|gtVQjC}>RWlK&R&U+yULSBwYA)aLM^AjLH8sPYgTOB zsH25pP|f;fg2tEr{%OeHrw)(G0ZK4OL$CtRmKI{Jk7oBU-+1VypEEeeQeBo8wBOdW z$u>jLg!c7jd#c}1VMGd1fXC1Ehu4`pi*9rMi{#Haj9nzN3>HOD6NZ{emp(D-U;jzC z(XVfm3fdYD2T2(HPXC}>eh)jQX9SMmL0StKl(Zh}y{DY7`4m`&uvK`Wa}$qEkZ(Mh z9cd7WYXWBJzm3|_m)0rfk%UFiPnAFQ;L}FnK0$*!?MH{AacM^!0H-}^fl15?yom4W z)8RIPY>UT-%b?ov6ZUir1}`^m1UAzLh2|Xj_uasUTQqQuiV6&v7(uC<@(4?Y?x16D z!;=>uCHVAXp3MaJ>rnsVZC+Y&Rl7=wrDE}Mv@a^hH1nTV#MG%Hkkr}CY%*X}a=?z5 zo}!D?u|YtcU?2hs!0$^df)h#Ta_+k0;X-o~Ew{WM zsgh{o&`tTbq7DYd;Pxe4YiVpJ3SyRwl$GVUtge%Cs8Dn?;74M<#}PwSYX@ng{W^5j z!!0DL<0rn3e$&Wl%}VZ?9@NB3sBUW)5$VQ{V!|%)ZMVV$Ac+%v^1_sk<-pryFEfuS zNm8KF6}C+NhOLeNMvu^7{h1*o`_}NiWj1rsTH;gs7S+{OSuZ9T&zNBTLbO~>g9|#Q zp8ph_N%=LF)S94-)j;lq>D2Ow|EZuk1iDf*lSMQ@_R}L%9UVs_u1H#3*71O7qM$%7TfxDi7G*d)z;uc_7qo8i9{Juy!y%P6Y?@e+SN=7WA zMrfi4e~m#lX?2>x8dfBn)wb}>imXOPUpl%siX2V%A-dbLdQGEDx!MI%Yiemb*~a2t z-rvt_MT=?JgTJ+OPhf{kGE5#G!y~ELqCm|+@OyOi zR#|U|?|u&qZ}(K4Luo{wVrg~603Wn>q3yrRR17&nERE8E~=T7MrO^b8b}C{DwOC{B`D}Zw~up`<3{5)zKv5pIeg*RR~pT#Ed zjYqc5Bzc=u#(JR zWhU{;(Ta=)yNOZs8fR9SKRvk|k80O53Qfg<%+2?($&P(kkFCNwy)5gC$d~8B?K~|c zW`2Bbyyj54>IB<})cdORA*%r`GPL_D>ka3(?#muveU*Vm)&Y()@+w)OZh?>c?dZ<1t zHN&x3D2b`Wg&P2n3k?n|Y<`*NON?wpK!5ANfg9}W(C$SC$zX+}`t8@tBuv0&61i~LJv zKSiY6+rNKrD=*iZ`P1nRbZw0}78MqX1-FmJv<{)*zB~=^se4pLL86dwgT?uz8X%be z)|q%bRqV_b+QgC86EAE@rvg) z)p#pVnq3v)kc+MAhj0?$A)7OnVvjj8;VLUBntE z?fr{Y>hch9sRwrc!^$a@)o^^7SK1R=9<7LyM=f{MJ}BT-@a_WGH0UL*9-mRGiS zj5UNA#%_X1p(p-SD4`yX`F_wg%(tL&j@1N%43THc(3hi)NEXK>>F338wP=vVkYLz~ z)I*VaUDox@4(_sR^8JJK)%nxPm+{b|J~x=^+7>dW_~R<{4;Qo;#m%5M7wrY&wo?gk z6()e3&T+)paZ?H|!xzNPahgXkgh#j%yz$g$1Wt9D*XY}^0=wF*Il271_|usqp9BuR z3N|BwAO$R&dv|e(k!K4Tp~Ljvesoam=ACXDIFD0#z+++VcJ!i$`T&guAH%pw!4^4x zTB+YFi=#jkdn!Iy(?-PFlW#If`S_+)`2!%9$-hCWn@+PZgN)~Iz7jyX9yJ+pbV4Eb z!a`-5DugPEYD0Et%0M!^RlG?G>iVK&ZbJC-@Vho1N05IsW2Vxp$S(4&6=yg2w`=TxPhp+6{lD=S7wt9IFyCE0qvY?%nt7foSWOLt}C~&!~+h~8x7**12JoHcD zGJfRY>5=ToP}bh(5iP^V-w;aMXP43*l9J10HK_#)-3n4xk{TXi0=@5 z1++_gF`kzMHWl>e=<}VR{Y918Z5vQNeY4QtgM8^}m8OYKg@)EU`UB=DjK2bfwZCA- zg|9>NP*HxgNtV8WoJOX&`ZK($gGaoGU|jpxWW71Yg!S!~L`_0PMZncwg=9KZQ6ig) z*maIVq+<0G+Lt(7crAKra&HD-0@w`|VkYl@9JB8-b_Z9wit?pFJaJ0x<=V(Tb3C7YWWDhs)l}nK8e`v_QBMCz z1Py-ZTR|(51`XG2MZiPEoFG^i*O1F?A3TxPaMk-s<9CK7d+@E+MtlI7O)iIYPdBMm z_UQ0XsoM&K=Qp>IU6S{+gDWbJUBAGjla0Y5YKGqptcWu4SfK6QCfyTMws`qc=S=le zC*+U}A_UaL7}g+uZ$@AZ1@#p3Upq1&OTT*l->uMT4&z2Rty&Feve#)eK#pYd&WSR5 z+o?RsNQPkeG^cLg3zLNahDYohj-tobmnXBlOWRhX^s*K@TMaNoc?dQ`+jcV7e#! z`E3I`9gMOXoJT5@;vUTAvy$68`s+pF!rZ;Jyt6vULy=(qbr)!w6m8Y3i!n8H(Z|u` zk*q)rXyB%|)+^bx7|w^5m-8l^~cFU-T7HI z)sDsOe>||+?1%2mylJV^jJ?xVKeqyn0p24m>&!vpp_dhrGg#YmTbi41Sy;PsDNsq9`KHAt1xA=~1pb%l%02GiG>+*-1&a3M`Il>^=3Lz%PcYuwr`92Ry2qqXJE z4k20Fob?vUEjg=g$fn#1P6{EcJvQ|Ytd<-rZOE%v<()VoS$*_+BgU3Iad!B>uFBmV zLNeq2vp{RH_OZin-B55RtuOBM3WZUM#->S|0tqa3}sHVS6W@!=qpBH<1SA~!q z2Q|GGU})Ah+KxR^N5O>|hNI@Zer3;cqji-#Qzz@56wmh6MyFcuza1|x+t!>M%+$}QQ`ZAgxq z%bn$-Gqwn8+?g9}Wn4%*Oy%9-qFH0=Ypi%J!2h|i^C-7h2+3T*`Y*_qobfg!TaV@L zcF~#g^Ew+eOP<*_1?CsY7i<)hj-kGql-sxN| zfJQ($-SBtw%h>t9Cq>0DFxAf);-W35&+NZz%Q9Rguo<+<8PE>1eTx;Yq4%MmhyXZb zzVc(Vlwlw?Y6m=Rb1rBKVZ+#?!&?6Tub}t0aj#S>opJzBvmRo7X?Rj6rQ7eiAZ5)^P8sWA0txmy$9xKqwS zlVe0Q-&nE)A!D$%>R2^u7E65odf&r}?)cQ~hgeFpSqu_?fzzPp&!p^ndPml08FKM| zZFTj>-GeYI(Q`m(tgrwlLIS`j;W1^T)WyZs|NHQy^~A+pavIB}a+}7%7$Z%1 zMX{3=#YY)QLP^v;d^xj>_FH!wO}q$-qJ|Udcq`7o4SCHX~_ zkpL_>j659#e1gU`MkOm9(Gc7ad@w5%LNJ;$6g+q^ITk3<7^;q(Eda>O!BdA+!$N!` z1C4OqI=fV$3Z)V_TO0*@9V?9!6%Lv}1}IMGorm0vY)7Qfp@~DPna0#E1ky9&wzDG; zg;*P>Ws87dPC6*Hl8oQ9{Y}<=u#g+s>70>@z?D6~lk+&irn3+=qM?GtBUaJvIKsiq zK!%)&Frn-;&PZk8bbwt@RU|#}9!oNJLlPba#?ewy>OmM$I83$|0mK9uL8kgNc$Un5 z*{J8oKLPkbsV9jso^RSFACo1`NqX8b=;CtxR#^n>3lJ19mBm3BrEr+=MNK8jM+H$m zF!Lp$6+ypY+qt0N3c69T?>14bHVu)M5ef9^l)W;G3JN!k7vY$wIP{$imEBU-IOzbw zjyns|w@ujf7XQMRmuA$C0sl;3ox}g^|FjYL*C3Yn#sUAc4WY+o)X!_s{Bu!;|N5@b zqdlq5M#R^1k<~$QEzGLcqde*V&*037^#3)0{Y9!mRyi1YV*m~X1@>ym`9I{5g_yWhZ-Qt(6^k z2(i2g0noHCe}ZdW;`{`!&H}A!?cgORagwuhA%A$aCdfk(CCDJAoE6+&(O^xY@A9dG ztS2EM0bzOuw*t2Xm#t42bF9Y!gALn6iIK8JZBl}d{b!n5?d(EGPAjx`SQn-&lm8j9 zR4e%Qkzkynao@z?6}W%uVwFP~59WuP_-#H9%$ zt#b)tu0CXT5U{%gG&n!V87*z8v<|Q~l^0wkRTV5@#CD4XbL-vIdM?7wB;5I{Sn!2P zAvP%D5|brCsR3pgk7xGI9--zj1J7IxyJgbP+$;U^Ma|1gSJs>}shCHD@Lv@&&ZzD`etX9O8>9Ea>|$$pt-hLA9kv zCs|S7Qm?*`3(Dx6qYa#r#WjYHMGLd3hw&UEqoQFjzX3%7`n#0>qyK}1|3S?EAmV=z z@;|U86$@FW&cpO-P9PmTL!XTjU^b1Ye;aNhQ^aBu*Yex@l?V-wOI9s-TRrX)ih!z- z@2PRn@IPDae|E+Hw}B`DCeu-|!FHCPRwxnzq74}Km_%1)le=_LDFw8dZWIIHY?){R zBq$fb2;u=Cuw*;|5U4l>AZX&kWhpy>kVlc8p5KdS7sM;4GwyDsOt3@=3;mXc==A{t zp29)U=mG(O5VnRv(0chuj=E<*NFgCghv*xh9!6J|?!l1cyS`=hsI7lMU%pzhUj1`5#B6ECQ z@Xj-hHil@R3LI(?;KWO2hUyqOxDgE`1y%!_3EcyZ1xj2zkgZGE=>%xOnNEg*;FyY# z?gvQrSR5JLmH^2hk~5sGZ5;t`zst_F(Gh3z3S@-#et)&fO2vPwqahTOVLdz+7(#+D zgf;aI$UosiSe7tQSY5C@kRX+QFtVNZdRrqTJb6y(>f|J(l~Je;`{n(911NSYo{)3$ zrqP8s94cn6oAGMnr3jKB;m&HcMV=1Q34^o3LO%;lV2e?y-*CLNZlI{0sl7OuQ-6-R z-r1<>SAih`NxYrI8Amx}BdKb3sxpuEXtD!(Bg7F43AD5lG~9=Be*ujGZ-FqoA&xJs z0SV3qzC4WsNf0yz31WnN{V>=b4GEd2VIVOK2nYlU2xJ}z*xi38QpTs&xmVo}!ju34 zA}>q=WbA+qgMw6mKoOz9kXZ^_nhLzmRqoyM+t*~JJ5!gXQEOaZYs(a#h`GxJh7HijM1#XWX<@({ZTSz8Ki z_FTk^P|95&DfygF@KAFLag5hN4s8E+AN)uHUL5c`$aNKQ0MQe%bN*5%mT)s5CqT-S&d_P+K)G)nJa1Gd* z=$*H0=V=Te3M0_Xqhic*;iV)-@8_;}e-R1%OF^gX0ENA;=tD|`QYD3zlw9n9hPGn{ za0M*s6B{HElkYUewt$$avqsq0_5vAYzry6xPGx&nm&BCne5T z$R%Y#bV=6FW7+&2wWWg?hBx8Di%?1==N~pwc7Z~Z?pLw2q@}i$Q*Y2l>vNd_-VsX( zcJCo!+b9&;nT`c)>i%(sKV-srRwY4vZ{Tx`;rovQwjTodFf=yg) zLRS3T+*rO?uJ_SnWhNVqg%p22Q&YmCrr^2qli9J<*b)=7ZG|xjzZQkvsTI%f0j)YI!aV8e{w#Q<htzf(CRF|;Z~c&WqX^%1fdg8o))7>VqzrC`HihL&4LuK4QD&?$DpU+4V~>= zjwUGNfU*#S_D}@oeAw!!rCW5!ZBLDiW#u`U7z)jn@XpI`pyT^u7Dnu3Vn=&D>K5F!Dy)qM04O7K1^Y|%U4Xy_n{QNSd+^xq)h>i;c zTaw5g8yOVaPr}quV|_`V%i(n6v*HE{Uu3-H0*jZbJL_K4X;d&F;+`(A)2$Q8Mk(oB zCAO?Ftlz_3ptE+#fU4IsYyZ|`Syc^G<-77?})+< zReD(b=rB0FZdd&_4PNzgF(=49;}LFI_bd~c+z71BJ*;>}!Of8H?|oOyBqdXsk4j}$ zI~rwM-wMXvm_+kB`m?&)^OICKYe*So!vB;j+mVr`T znOA^aS8Nz(T|rfdlC!*2Zg>QR&!xmnkF*S9$tTAYW3)%b>sOeywSzdEvrhc)X%jXh zydZ@o0YNm}*g#7GhU02VRd`;^z$dGyT(t=!o4ls46XR7AyRv{HgtVMR{oO)X6>&8N zfgA=33b7#IXH2wk4m)m=tWxs%X^9H;&@*3!W5h0sxmxbUWlPHM@>nE`{D#F@loAHB zIlijC_+w&DE@DbPy~l(%&lllBHY47#*SB*yK6Eh zJPCQ#`40LIcJxupLoe9-lSxjewNT=kE(&PHJ^|fi;}MwFZ0aJHdmN$bRPQl7N*US;r)eJQNP4Mg<^sZ z{gb9P^*{EeZKizyMp%3%pJOVWraHfQ^^VG;~GYR&!E- z6{DgztGtZXyAU1Vh2uPT4>3D9R=zVR$rByy+pKU!2 zUy8N3El$oVE>6N?W3kDyCd(1tJs_*j;DKADRUky1m>f@z2_KVa>R;UG#XDd(0UK-hLL!lgAt zoMFqd12U7?$2=zr3ayAOuIi{c?&YdM;IINU?4%VA`A(m41pj7gMbXOphznhR9YH>WZyUt zk6#NW)S;ci4|dpJ>ky$B5D{v9lJpV2uT!hNQ6qtp8|>V)U-ywQBHxZq9knxmO1k86 zQhi3}9civwbMP#u?FB?Y7{v)w6>iOF14O9V!nKWKh?QMF!4|3{KclbINn3c!zVCxR zWSaP{d3Gboaa`$MG{?lUK_#(&CEbb*rMhBb_IIF0$DF*#nY?d&ALEZ>oA(J3LSjJ+ zI5zHUd7M8`L7Pf;ElsUzB0qdvK=YlM-#~fKWPI2i&}YehY4n(cNisYCBZ35N2Kd_r zu9aMTNFZzA$`re!F_J(xEeRhd>r^psoL08K*t@s;t2LjxH$^|R=i_?Z_UN5_`4rfV zlvQ)M>om^QV4Mf58Ib;j4KBM`B01X>4yBLHLY5RMM1GxyF*xwT7($uxC*&vxD_o;Q zNsP*k-w`}jx^+cb{o?$2yW$LM2e?mV$J8Vjbmlbu+P4@h4myPED!CFV=w0zuZ~gd3 z<{WQ|m%q!V-zK$pO0_P&%09?B`J ztG0PTZfZm@hp`Uiz^{2@D?@esjGd$4u6=*;#xn@LoqL?<3FHIz6X)NiAAtkMU>Q1b zHX%ZxIqlZS2`^xAXcD4@w^fn1S5?ZCP%1Xt@UX{$hV5Jxu zR0HifBJepWV_sV_19$GTLn!Ov_vq!&h&g@l zj=huR)Rq`q5l}qD$|Om7dpweFEiGbc`QMh}(^W?!Bv90Uso27EFESXClM~cgg5RPz zRL)X{Q5#IBF3m%%`0s3SA4ttrR$qUAiXS0ST_aD6{-YiFy5J=7=&(wH+KaO8zze!* z_wPc6PKl1k1_*&i*X&Sg&kl4(zd)IP%%Z*2-6gNyV3M6%Z}@#FsFLay*TPF|cTMr* zRzIh!Gg)qtd`eX4bPrlx8QBP6F3&4?U9A&PE^l!ZFY&LD?=r;Eq}$G$cd)Cq$b4*< z4hg!f$ZU2JoGk9ABtYIarZn6qt)vVQ#njS|oy~)j0JKk=G=BlQ4wV&(LbZu^1UQN^(q zdpfFY2=SbS)9&OYRGoga#CF9W^#*BxkV#AM+xjyG4*`Fyr=!$W_Yg$<+Cwb|G!JhB zz_IQ>GA%Y?Gvg{U&?&NT?d@*?c?3+m|FLm0OY|KeKdrQ3;<#%8UC~8#e;E zQpuwy1+nAQ&X%cU*z$=K{?->>)zN99@f&?@7lY`(e&e9cavqIB8y?;3<7)v?KX)&9 zG4l^CSjKbP2S^*L$|L_X<2fqcl6PWV34d?ifApMX6YnIm4)z1IAP)z)zqA3XCy-G6y-AFVa@E8 z$Tv%mE&E?l!OGORgJ*>vmQmK}fAV#@T&BrY83i%@^y_ro@z_q+QDF;pF;=S`o!zpo zIUSeG`$r?F0%eSUZv(c54WecM?2{;WfBADhRpuv&Es>Sd#nm(G03uxaMbD|y@D0s9 zS=HD0J~m)6jCF@CeO^BzR*Njb;%wjzy+r5uFLP9#!;SZ@TN|IUa%teQ#kDuBscO5F ziiok$Mn$y*EK?^7Eoyb`7FdMB^ZS3)yaF`?#rXI!Qx{*%@I?Ll7~UcPL^`&yPps>A zmKDb>$1*2r=ns1sUZDraWQwz7V>D~~CK~0_2fsppXn2_M%i<-+_tX^<)Mxtn;u(s2 zZb$_X3gobIPzf3 z8F6$$1HJwnzABA$Fp#ETn+E^miNJ!iWxkUq|`xJ+f&S zzr))}TVr1b-8qY!5MAqQw+qGwg|6ifhrbQI88LyKr5yauu_b+R6@!h{ZYC)!}0awj! zANNm9_UX%)@8sTB^W7n8vqc0ZOx92slN*RD1DiKsol8NVESFkPz(*>@TGRW(dAN)e z7Ew%K`9TV5>D<9hlfp@BOaqA{cXF|GLO9ue$z@)xy%jG|QodKIb9Bv?v$Ey7tSlRP zy@j*1>Ez4``5&L=p_X|?a2oR~UnYL)@SZ%I_f+ZD1??g}4|38As5ZnJyt0Hp*2{5& z;r1J#g?ah4n?^#w48beyMWr)PC2W`{ja_u{iucnoDHJ}ae7e{Nvuh!`5A805ZN+;% z^9q3YDUtH;$?Dc|8M_^^?I}UR7)!Kd8ISkuuKcn>#ZB&sorf1wYJE{!Ks@x`ksgO+Uxl5KCQU>Vm>SP zk`X&JF)k#ftAf?PaHnsX`YmsRbV7_TTD z3BcV2Dz1N)==p1;pVP`{IyG`Soc*q6b{PR54eK;|V*ci~D`-3q%LB;Il@e64Zij#* zgkUm^KnwOGuoD;)d01PPLnXj0cN@^h;*7BuFQg=*Lz~5xoqohd+&QX^v^b}Mcbz#e zkAfC=RzxTmzmx>2uJe6+oz;ixNB-+Hw@Pl>lyZ|4<<1Wwm;W>)tcyr_M50NB8O>5( zx{2oh7jrTEw9_$lfds%3HAd7(fdfbggO}$i5`GZmtVt5CvoY*}$?X&}578~`_e~i} zQ3~6HZ7BmePqI38FX#;+VFgZP+BF+4RN-vjT|nmsbBh=&S=4x3Bq2QBvt=a`0>j$sBlPpmm9HZ>XfQMJ;;&o`kmt= zHoZ_4y&hKGUeC@TI>}WLLEz4DMv}eJH`3 zd1OCN^KKgYL(>({caiFtf*I#l#6o)YCaov)_m&(jh2!M@a}^Eo!|jdq z=^j)msiyH1+l$gQ#P`!b;K~m%i`nXn2V9zDx}$TAJ)SCG@v|rOP%$dvjkAi7G&Rw; zt0p=kb^N`n#Hj7O=rg4-Hj2H8R1*kFH(jj*Fx&-qzP1Vs8s}EV;sX}O;~$P2tT^Gf z@5OeD=1I-vU8k284Jd(RnBU?(wZ}>j>#BVcxJ6wNWzq+`Y#rjRa@(ShF>4htnYJF2 zu)!Cj))1(L`5V;?DoZtqq7T83KgGqT!79+F+98Q8EXWV4>*g0veTiM{rBRd(?V(sP z8u~3%C<7i9eu%ySTRyzXr#TNgHtO|qV>St6d zg8Mm$sv)tL;w|pLK;@F^AnglUg@J()boA{C>~ud3<+z&W z8_}(|i-8h3y+8$0VyalaJ72=fa!*b!w`Ae?BDaP>lzdD%bTyVbyolroC1FysKv-Jc z)!}WrCWdv_Q7V2EE60Ocbnxa0VF(5w=?;7Oou&5b_r6%|c0rTuxGCYXfLqVciwfls zV&e6xJHREQQ&wK5h_%=nf;UY(K9-UOsxjFxBFK~vY!CpRKf3f#`&(4aYlyg3ypun{ z^nwg&B_(4M_-By?qRPi#6k#WU;#XO7u%Q@kraBxO2YN;dd1962@|+6q(nYw~h-zQ5 zt^)63)PJ2Xu41GrqImU2gYOec*4bvd^tgMDJ%_}*GWFLJ=KDYNIRO;J-mP!#JQv`YMDK6knIJrmAegLops=Q%!ULKYiU>4$0b2p!c?;sV$VfY> z;}{Br=EicGXOI-rXgj2yP`QEIZ;LlMmcM4cMAra?P-8$w9ugrnODlWgMj=C8r!x9; zZAEAkR+~Gcm?>_nV+WRd{pCdgoeWx+7nR%t>c?Bo)=^R3zLtwG* zq5wd~F&X&@Q!|6sl$y7XL6w|r7Y!L6XG0{PkLu_t4*CMWVgTE_ugUf!tEY@7GWkjs z2bcFUq@n7jG+MdtACwe_uKns>r#QjSN>8}&?G~;%wMKH*G{CAwwp-HQCH!&-z9&PFsC8)Pg-JUUlW zESTb8e(cz+SmOHnbpR~C_6vTzsZ{h@RH`~|6@J}Cm^K_i@h8!=l5%x~klUwpm2C~r z4+@9E${wx`g)1B@%clupX+-a=|qQ@N7nWfCj-v`e-Q6IXryXZtU`Do>z* zVDG@UPYcmTYA=D^~6DnsIlD;kr8e4{XRI}wYfgWN|YgkZ$%)N^|8=_#F>EjPQgk%B8E&Ihq3v@JC}L{DZSn@Yom15 zo-wB-m=FZwVJ7mM|m11bzY1^@jGM4x=*c z;pzYNhr0!`E7>;Z)sJ))Y-H)qdPAj$R)A7yKrlE3S#1EU^#-UcP0F;I8v)j7e@{57 z@2=HUXq2wzoCPoM|Kb?0EVAVEZ$OY5xSDa~q~MEGWM^#bs!Zw?GJX&Xt;WrRGomsd z>{9JMzD)@TUk3`GY2O=uhwkzb`G{w1zo_Yb^6uR}2RSP=nZ_Tsm>7O_+vKB4A9$x# zse^f(ztn~lUOY}k>#kaM_^sr65(??DNBPqvJRck$IHR!$GM<=o$cy}bh=4A}s=Ygp zheH+FyN+N*{6kzGO*E-)i0DEx$2kY$?u0FT>S4~TGzXXji25?V^5=8 zlczSJCjspJ@sqe^jPUflSCTk?yXX^zEq}s4TiCEV#LDKE@*iV}e0i&Qa~Uz{TD`61 z+3Sl|-VG|18?ND6-JBRJd8IouQ-%^Z`CRn>R+L80fn^TsQejWs~R z;^tygPs}O_%WfrHduoqn`EPB*BR1NS-XX~8fCDmXs2j&lXXHG$OH_*t?m7DVo;AY_ z9?pJ4pb^LtQiU|dI$PVBS;LYkERT|c2*(xLzdSPr)pP6OSCZ7qExo14=sbg&BQZ*1 z`aQ`R(f;X@MA~cKAls#EDi{}G2|mq&i?zKv@^rFR^ZvIFe#akRszIILcyTOn_{gT1 zparB?Xiqgdsk@S*OP_O=Q5Nb^Tr>qXOiIq6ydt7-P#fG*TAnz$+SO68!=Qs_`_C0{ z!Xfq>VyxrIMg{V_c&C}L7?_%UzE@&$*}YHrR`OEgRn0c28raUgcD;}>1EYK&L zJhA_VQ-P_7+Xi!6{{U`( zG$mqvQ%yZmGpHwrGE_1HEfzTUiNy!VQYpw|16EIETEX%O;JE=E1LeS#=Qez0(3q5) zcI}0W%umkqKYxfZtX$@Q)hoE^dxbwBv(v}Z2MkNwY!an|owSd3p)QHYBmq7aKgX?~j9y_hyqPK)L5b6OH0Ykq;7 zf7W-=B?x+uha)!*9)HuFUxpGApH7N2$R8$2F}x**E21VV(C*M|Z7`!p2fI!N zqumQ?V77?!PLz{Iqgj!@^R*dU7gIQr`52vB>3r{3e8I82osP(A!dItC|E6D%O zMdwf~4UZ}<`NtYfJHqeNl8sOCXA)vAEv^+h)_2!|AV?LDx`;{QiXav2nq(%6JWYhY z58Iq1WgNeXRKZpAl0HV4s5v`ICt?=Dz>$e}Nxs2<*}RbCmbmGsqJ{*CFhbpAu!hDu z70$#uS1m{La3orPapbaJ8X-Vn%(^z`1%{2Tj4}jk&=dg*8Ze?!`7Jb*%Gq>h7nx9C zUg!pdu?0I`ZD5AW06m!2GfZZ>CmU6ZIiDyc^D;wQC`^A}lGZ9(a%RAV zddkj0v7H#OBl?#(+YzB*H{wdRt^`H7ZJzuWWuu!aDVnJ7=$wx3mO1c1#IWkSeF{H5 z^Rs})3SU5*`6$h?2V)TiA$Dhst7%9d-is#vP?zhzpuXYX%{?ixd3w*9N#FPbcGg%J zZJ^<#IREPqK)q=IKj)ylJEO<3q_osu7b#KA%Br;rUCg#9t37UlX*kvQlfa3%4t85R z?km8iT=Lch0|iQkCKXtT&e2$_%W=+aZ@tYO)Fe)%%4i;O1tgtWxPv|8Clejy^1|pb zcw(52;T?_#Q10}^bccUawnP=a!+pQQgTKToofBPL%?C0)D2grGK>yW30!xa6Pcrc5 z79i`U7jgMeeaU;t+k%IjPD_{mTj7?rK$t%a-zjQIDbq6e00xxPeZ@(RwBEUd@Kk&& zRO!dOBY-(2&imuG8}-38kO1tE>C2$&Cn$jLS77H=BFW ztC$(VIvQdHdl87`AHMw?BOvDLNfqxl`7}8lawL?H{^qb~m>An(ESawz!}@2Mt`MI~ z*YtgNCCjj0+N7t0?`)oDZ=%AFGsV*Kd=k_)9|2>WezXGB+r8Gz?2YW{^wyW8y0 zThF_@w2*Ou-?%7l)x!IO+qb)><91UF693`_2#ilJV+RB`&;q;Tde_mZg5DD8GY>j= zvIc&pAbB@@?24GN{}8O?C&L&bS8$6P>3p18!ca0>vqW)4*vcmgH}I+SWBan#+w)jz zRh%(FoE2_N6Nyb=x$e@TfXGCVKBqBSd>=EoBlhfxq#X0#^M$T+-J?WX5W_L@A3}9Z zZCeP&vjiwDQk{C*+a(ONlopilkB7=qL|m0`;w4Avxxq@SgB6|G6rHv73syi6Jyp<+ z#VPx_&(&C5x3D4Do{N|(-z}Z{jB1xRaIoB@p#w~4J+Vc#76ljhju@D~_U6@9U#o(^ z0it*fYv^3f$;Mpo7yqp`u;|3<_8?HX(HUQKc%b7u z>SL$QUAj0ZF^2(mReS$8Ix3i9N1WotAIHJ4`Xc^5rt`o8wx?vrH#Xza4?juNWpX{} zdcY&#mp#J`L1y0|9UoAs_&SngW83zlKcqOX(57&&&Q{ff%d7*@j_s^bs}yz_-`bPI zMPs0r5JX!iNAM+en8?o^?pJF4ArZ?NM{GcxQ=eQllX(WkoZi@}e=HaA$m(stkQOpR z&1vSpj##)KM0m#B0IgLpL&A@TmsKa|dw|t+Wc-WxZqZUPIrOnpRbxCmEapdEC=}6w z65HbY+7Rm2JV)?;HjWfXcpf>?*&BQ)?#l|wU*Bd0l+B-Eyq37x1m%VwZISq7t@tZC zh&%%_URR?7$=kvw+(wX8Ah+XO{pYI{2ZNCxo3l3kC=}UzqcSC*a(mboUqUGts=yi7 z9N}%T%7f^8vEdRlU>v##o2MffwY}`}s7TW(TwHce{!3Q8wfD(w&HFXb!9sSSi(A-l zOi5vT%`^q;rzR?3{D2~t`sLE!uNVq^i2n*tU_g;E5nb@WL`#)(u*g5dA^kv+M;mTu zc>ej8CalIluraB@;NPK;FqqR(4M@6%=cRipHrf46In3$;;QloFSi_LxatT~ySF*O; zFlq~d>k68lm)bBiVs)MW*0^B{v@_gI7xdS4yr`g9^_MNc!PZP+w8BoP=n4D^k2({r)&@|qW0!w(Nl0Rl_MR$C~=iz1s_uQsU-4ygDVMasq{Pnk+P&BpQyB8w* zishMt|Hg7EHTG}kvKW=&ihkK3c5=ohMlgP)QEUr~SmqxRNfv=o%q1la&J0xiQO{u9 z$p@$w(;+;E8w97!rg{L;&KjOQX*ZU&oixMV zk=)2>1a~Q+j3puw(WX0;Eu|8QvvD_erXaKxFBoT_eiT2YP@c1b5`XJ26ua6Y=J0q} zOScH_q*^fE+RZ3ehD4@)LW~-Y3BndinN~Y0f&)P?-U3H3ZsrI}EkJ@`)hQBd>$$I8 zL8`!>k%&8r6KqmZg*P1$#@;G|V3#$(&|wtIT~VkoyCcEYeTX+aSB5(rfnbp{z&Pj{ z%;G%6_@^L@V{_{5_ z7sT396?Yo#zhVXe#5Im!&c;Elt%5MF)PWdFt$jrM#QzI|nCvvdip3}-@eAFWo&}P; zH|751^6ks5+@|qQH}j_6zu8p?s7D$)j~*nxrDI{Ko&`sizNN(=Q)Ce&k^1NAg6r>T z#7!11>Q9d2scX=Oyx%wk$j#O!P>tZK_a5_F|7?*8^2Pv81f(14jqEvoy*}Qru*SF( zZ@>f)j;udnl~e!?j9~&>U4zs7j?BjZK&c;FA|@%Z^a~8k?uC3Q^?p-@S^)igse83g;w3aXpNS@##2=_A$oGMX+IFqbza+<1H6c2nU64YG}^p&ohlhc(r6BO`c*~1+s<4ZK}L%nPVq;v0lL&5Y0!h7QT@exm{ zrO;~QYz#1fVF{ts*h(OqQw^hbxoD(LW?c(D|+_9PCrIzi7g+-22!@ zxH3}j3%L5x%4m-3*T4EfJ0=CXK^du&uPX-jsNLl)ox|E^J|VD{_o@$n@TtE>IA4$l zoCB|{zXFWJz=eq;QDVi9yQF?n^?=8~gP>2K$w;Y*i;Ic<_dCN~-N1z1`;QhnqycYJ zWBa}~M$oP&)n0C9273^XYv^ibIcalCCuxKzthj~*mluP18AQ=uhx@^SiS0@|2Ag<> zdBv_>sak$4I4G2?QbdM}nE=|jFiphHcLWdw!xKb{LWVN{BPtg3k%7*t1g?q^ELcq{ zhbW-S@-PtA169?1G^iM6j>aY&XkfYXSol8oEJ6YoGB2F`m#mmWxbz52l?iN&1+QI& zYz}2DWq4d2gWnHFk5LD?2(&f^GA@tk74^*-SQypk_-MON?7o!MMilisR)X;cf;kX&zXK+L)3e=~CFol}U zMgu;8QCL&R<@6ujf#w{d5$yFI>EZ$z3rTs!-`1i3Hu)7i zKQ|(;ZVOHeU1SPAG$Maqip@S1ru+Tf7JRTJ_FfDBdMdPdpPLfAa3J<>Meex}1K#J@ zooIgthDPL_2J1f+_W7Nx{eLq!?^2BUJ>ZQT4gxddriUH^0_4R!*+81OiHle6_5T4B C&HDfV diff --git a/src/Nethermind/Chains/sseed-mainnet.json.zst b/src/Nethermind/Chains/sseed-mainnet.json.zst index af814d735c6ebd3b9be726c83849de0e038b36fb..80558904d7256ef6d8bcb0f4ff6cff314810cfa7 100644 GIT binary patch delta 7364 zcmV;#96RIKqy)vN1b-;CFZ}~pi7;6f^w$6y3IQc2Fln|V55RfpYj9Ywt6$Pu_h7vn zpB`nk`1tP=Aw>w&CY@POP*7C30v-Y#0%t{^?m~v()x@)+Pw7I2;MK&lq7UgphTzr2 zv!c)FLWbbg#IvH0=t73z)x@)+4|gF$@M_{&(Pz7mA$T?MtbgdEUC0o;ns`?9$u49F zUQIkJ`d}9_1g|EZ6@9J?8G=_6&x$_Qg$%)~iDyNh>OzL#)x@)+4|O3!@M_{&(dS*r z5WJdrRx>YLtb*J(nWUy}iWple#K5bu6TGMSu?X{OvyL1zl*x3^P!e$95C8`b2sm({ zQ#xpPFq(*mr+=zxb^o9q)~(v@>S|vO8cIDd5AXsF3>-8(FmPZ220S#3hKB~2!GgW* z2M!OTFks-IpcIC^`_$6v^YCU!X-M@}Ixh?aH_)(9N_6x2+4ay)KiM5Llp`O4PsDOT z4y|QiSP;87R1|VZfhJ*bFfhEzh>tu(h8?X0@&q1EKz|`v70wucH)?gWBtE*Fwi`Vz z+$s|TEwqtZg*HmK9LGF&8dS)F&(4BmQZN|Cm{^9LZ( zfFQvEhJV8YQWPE>a3~09AOM5XpaB~|0Rn;qGgu37APpJ{kbuGf0)hl|fZ@PEffT5{ zs&9)2mn{&FD$}xZ=n9I)sDS_v4h$MN3@!>+pnnvG2M!PXpbTK|K7a%kARtJ9-~a>! z8krgJU;qI@0)!z57Xv&f3J}27@vsFmRwo6y&^ZjsKx>`5U?EAtauk*y7(x;r6a$P0 zRzN@j1$(6ObD7cWXqAW3pg{v8005+v1{y#>Z~(%Ch6R3LQc434iUS82Kma#DXh5yG zwtuR$xh;^C**O-CJA0zsgqGT==6;6O+Lk6I6*qZkbF8m;KDAb}jL6KDd1=ugRvz=$ zn?1d~YBI;uYb}RCNPE+tL~imikKd2@{s#T`5wMeDpl`Lc0TGh0}lg;hWP!!6G7du2WwTQCr;%!HDhlHLUYn83Q zn!J+kLg*hWa)^#^q|GQosNjn=62}k84;mZpWzuQ8d9^lBh#{dk{w3qHRa*O_DLPZU zD(#S|DLxf<*pE8feV91Mp>1Q@s(({sT|r{l3@waYSQNkTs2HN@1ofxb65gfKqy%1f zxf8+{t9Dm9*6R=}(g`i4)uGi>y3xT(Dd!M2$3cY@iaBe22oU{L5zd1uX;4;wjSABH%XeRu74V-->{GNJy%L|p8k=#kRfi&L!dw{G1XR%WFbWCaSYJaEK-`d%*wHsO=u{JuiKDslsx?(pvGu%Ah{v#c2RF(BkaP{!{BDo1I0) z{n3BCGWz^Ducb2oh&f#;?$9iA&6*#Hva%-4U#g#f=Eu3BGJi+0yuy}5m+dV&xcgFX zwddQKO{8=>W}9t8tdp6Ckfz4HQM-0jC1+M~TCt4Q2p&YH$cXpn1nPDTO_$#08U~-2 zl1yWC_g1l)_ooXPf>)D|bEyJ*9DR@yJ5xe~^O@XA3Quu0;X;)Bd2z*a9UZ}QoSeK) z++5Yi*Hx2#CnqQuZ8IdqgvktY|SHDw4AF@hjZ-v`z8=*)pLH+LtOmVvJKVqMka6P;)Wg=KWn! z3Rz>+v72J%`VNPzug~r?YS3;spP{Sn>&q)NgNqnKbSi|36uqx^$x*5#*ra-9ep6Ca zM2Zj{wWh4-dBa7dKEznW5i@m6%*}_V{nUJ}LVvS9sAz-NwA9wJ$pQ)AX{%aphiJQ& z#Hp|dvmHI&v{QWW-x;Sao@QH|y zqD*J6NQaDWdd4AWx}y+&A%(}1ZB&w>7KaI_lQy&{W=tUw5fPCjNpcevpdcU=4u(Wx zp?_c`1gswufPu^=(Mc=}$8ih()f*=TjAP9pn6l1_8O_~FEp-Tyi1~Q|$ ze_%w(d*N>BjS!`*#K=q~p3NY;FWf(2&VmQ=)tDi3aSFq$pt`!R~*${bwQ^ zIuJfeJe~&X+6Sp?4FN)(=-&sdF7ey%(SK>%i=kaCkzBA>hHUFf5{{hIsI~g`VV(Pc zj(wm*89^6>bCDH#u%k*IiKUcCVRDS*DLhj4e|Jar_CTdEu(x4$#kR_Ob;A8yh6qUv??V7CSlhl?X?COzt6`!${zB`?yys3V$UA zvpp)8mhDQ$r+Ma%1H4dZ*YfI9E@=Lxrz~UT618=5b*gy1kA)w*PIbiLEm@Nj*_35$ zSD&(gf-6dchbZPw{`R`F{_G{=O7XUG0StBWd5MxBE9{oNzv}bC@aec`}=znf4xQgwH z)iVPDo#f|M1?V%;f=dG)9DuZAj))d1U2d5-Kf1`ut-(2p%$4t*7~gy`PZ9rYxTWEw zQ|W)@8gJ9hTlUc7;pGA^^eaICQ+>Knnvn!U)L+*Y4!@WxOotnwYpbG5B{N7B`){YY zm8j)&-LkW+9RpP!nLzKjzJF>?+1k&InUtRICv%0-!2y8+FTglQHGv5+W zGcddG8z3rikaZ3eyDub@SK~nDG=ET*rWE?%SS5)WT*O$Q0xkL1 zG&-hQGFuH35)=d4SAUBMKVR0&Ufl^fd7U!<8kr`-({4F=9h^uZU(P2(;^u*I;KTjr zD(6CFa4>^RwJcjRVJZRd(T~au;Nw0BWHY$Ulw$lkE4{N7VoA5QUwZxw$FX&I%bIf=>Qv6-`*%IH%YRp$pMaj@*L@$^xzNlc zlvh%fAJ55vs6@?wHey{}GX`C)3WNSFS%d1kDa>bst3~s)JO7=vgbmXx>gn~N&vsia zS;pb~%9WOI_f?zuTKHDZT0DjM*?&Cf*#~rqqo;wo_hB7MgeGVdprwJ*B??49$8nC~ z(i1TZA*;m0aewgru|Z+vi_IH+Y;}zN%6195fXKVJbn@jPUFN!w)*z$>*Yn)(5=D$^ zF2VWuqhJ3O1-NS<-=kl?4S&I%eKcSrE&Osf0Mtf2E2OJo+syV-q6bsTtE8th-%52y z__%lB6$Dn+sREE(S?0UI(1O%&A`8`iydGB?M^q75j(-X|Q9p~R3tcTdX!a(-f|3Mz zSYZ%MH`iOsh=zki5v|7vrem8`V1ucj?+hiAq+>yH%6muOAG1HLOd|uaz7w}S_;++# ziQ!-1sY2qRkpb01?qJAY>se=)k;Jk6Bob!Sr@cbhVOq4i9#=16a9=y#T(JDrTn&fO*5d$MUYEF?H{o>UWtgHN#0K&N zLRy=T4Rz00$!My0sk8w}L;vlIEtLY@_1?0<9e?ENz1c5E6o>jBa!vrPn@S=R6lKb! z7Xl?R+V#_!HKzy~Iqs~%yH@BY`y1h#iUVh>f)`T43}c8s2=tX5tT%;_xrXH^XSMl& z)@^Mj-!(-Vj=JbyO=G*t6?3f>SN>@1)&U(T0*1gof(0F=yu+EE8(&mlY~9lNhe?jL zA%Af~b%=t!LZJfQR~;>3?^>?MTC9lm$%r3`Y&Y%r?xSO;7LD38Yv0_=9&rVd<|aU7 zp{8wXc{L zG+{QXuCop3K90UWM7tmdSTm%XuUVsMCx6;^|C5e&_Ru?D1=1|_YZx3?3+!0;#yKO1_#QY$olhnMQH8X2N2&v5r4YT znyjYPn0o$`9)pvW&D~>2nf&K7p}YqVYml-pf?0OO8CboCVxATNh*1WO=W?U&cF_(% zf#vWH^S9TB{P~+T9@~Hny(2Vz^*@?3EIWpzfSGnU9y{&&;N>JW^nnZWL`4AQDSqWx zDB8oWIqfRG5I5SFn{;n7qlUlv2!9Hku?mdewOdTwgxC?M(*Y3;Ctcia=e0ba%=RX54o#HDRgLmjI%Q;cpdBcnW3~2^1YRWP+hw0W#2!gsf<~&DF-J zHNsG+Lr!8tV5h9`m=f&!NOIUjT24~VTS#5f{#;P0i9-<1;?rZ6cU;Mf`tb53p=MwL zEWG<5Bhmn9(F!4cSGV!flYjo|pAkhCi7XbUZ0kBWn?aP*gOcbqoyy}rk zqWBp^6pY&cci|mH)!&B{7sdtm7@R!(mCx?gs{9SPca+nj;v3(djphtbUIr&NOd3Dl zl;L^wAAoi~gj}p;fM%{|k%TIyOj5KKD`Bk%RZ_B07JH|)cttL@@M?=$T+$nbn6+56 zwwT3bEI=+^=qy$jZGZ6+d?Xh~@Bz%zBiLgJvoNZ_z{>BpJzZ(DQ)0ee07GEPZu?!W+93fvBQ}wUQ;er;ORj=DoRc_LTl;Rxc z$r-{)jrGDI`p$WFp~MiwY~vlo;0YwT825a6Yo2$vO$-fP@_z)bxgiKQLbHB$=!oYJ zm2M)i+P?sc@%40wR!DTN6$j|ioOp6gQj$3bq*SP&Z;!7-Dl9o7{PqmA)+x}?5nKr< zSYKK|iN*cvf0l~B98RgZ!GC=boC}%K=GmV=%f3&agaON4A^326=`3ggLC4VllGaLk z3l3M;c5eiu34cS}oT9G?g5EQW1JzyE?|<+flISa6-(G=?l7N57R6;xlR1cl)qaTq_ z=l!a{*_@hSG}w*D||>n$r9`8=gP>`?RZQYNWKu+o6s7#DD)k)X+lE5DH>f+ zcufKRQ9fsHz<3B4LLt~OE*KmjpKKk}p!A}hpDXWN?SGyRcmaJQYa_Fql=ppFBqso? zpAMS`yo8JykYzzul~QrdOnlSTBl}3rA()5u(^q7cmae9k77<@c;FV z1v>e$hMfXAlmjZa*aX0a8V|z{%~N6pSSg2iBgv8Loh&13S&Cg*D79=o06Fyc&YSck zM5notU4OfSYZnShE6u#l`<$p65R`Q0ootFqLZ6DsOEIA@bbj1{Bdj)KrUNqR4k-5_ zK?G$$n5j5H)FOne|ET{r4FOe+Z}@Z4)1HygewB_>3@gjg;XOQd42uxr?S~BPHLnYI+M1X z=Qyz9rt>#sJy7DZ|DdGe{2bpqX)7i2C4eB8%hIUzM!u#dkerE5AAYfG8q44iPKMDZ zO{dFzg)n;%=~r}f0zP_9U?R^q%7(pC z#1^?DW*yk8H?)~YjP)ZKW$8B!oC4MMp{uQccV>ekz)uAG6p(sD#F6T#NEmlP_xtTrqr54iY(u)6j#nAvH8c z4*LGk1FSa`L9S+n9HOXi@#NZAK_PpJc-M;}$eyS+1)Y$DNP?EWESGxFO9eQXa zi^dIGXoZF69y#*Dgb@b}SYZPr9eC{0r=bQNG-=aPgC2V6=_vyWJ8fx+1%|!y<-`L6 zOt>&&0Tz_-?Wsc#jkI*spoLaidg`G=UX(WOpaCmv8}rBm7d{Lz;D8BiRASgeFFidq z(4do+mRe}gOP`!{Y_LfeMt>}}$dnIH9C%=ag(DcKz-miRJ#^@$Nuv%Lw9=+g4|&kq zx1k0cFm1~+10Hzc;fVnTaH7I;3k`bd)2W9BnsjN@LJLju(Ya#}jj(XskVRHlc;bNr zFHB&h0mD|>H0q&;E`1tm&_Rf zI`q&;i=>D*=555fMFg(esY_35r@uJvAN^_0bXzcZKE)z|hADRW`NT3CC=Q4}py$Au z6T$|5sF|7JXm=xtOir7SLg#KUO7N};i4*Q7P@ybp!fXjjiSmzlPU{3#w48_#<#yC9 z3|f^Tz>@Q|+LPSlf`3#_09m*G02AFMt&}ly=wDPss|A(xKvz4|os&bT+P4GBK{H>nNP>QJ!Lf*#Y z95wD#Xqz!bDqxuoBIxiB9WJCbV;2ghY@Od;h)>NJ4S@QIL4T4AiHbW3eFyXIbvb8n z;1X_=b<2VEMn^~3>O#A9t#xiIz?3e_?9i|)m|f`Ep+KwhY`quR{YCsB-q zog4T;%WYFp5_2%h#!`0(#;x;MQk5f9`x;i3*_H3oMhCJ9)jWNdK=!lQsi6@eH1}ob z#BJ1F($G2xSbv}|zNRZ8_;y*Iww9Vj)Y^SBoSDD;`VWbObE3ymyuJF-S#gF!IqMaU z)(cU!-cM|uRsu-ex>|5AH-srkQ9}W=2mo`(4}}cDt4T*xL`2ku48gps;|Rf0kOz)N zDref0n!86Pnp?;8=%Sg3cP54sOp&9B?!>IgimO1*sCV}S+~ zFG9)#5@;|O48cFc5HJJ`K}N6y5sVQ83yvSXeji{T+6UhU?}PggB?<&+z(ipUOi_U9 zgNE%Ic(}0Z!-lB=DxC`t%s=c!ANt#ep6x>~`_SJ$^lTq`*@yk@L(lf1mwo7OA9}VAz3fAO`_Qv} q&8MH}v;zPH0x&d_aUveG=Nc0O0Xnn$9bNQiX3kIm delta 6874 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 UGaVHv1hcOkI0FHQv*;gP^tYDcFaQ7m diff --git a/src/Nethermind/Chains/swan-mainnet.json.zst b/src/Nethermind/Chains/swan-mainnet.json.zst index ab7de38ec30b063d1dd4d7bd50693bd00d30e041..dee04cb636328e21f4203c26f09903f0bfa2ab3c 100644 GIT binary patch delta 6681 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 Y&k3%4OCr_T%pin|lfBfr4az?KKQ|g{hX4Qo delta 6566 zcmV;X8CmAyj|A(E1b-;CFZ}~p?HEo2)Vu(y;k+IpAdgA%2eAyGPd=p4S_qvkpc3NY z0+J%6l++O#fPjDu4J-o70mcDENkf`qRG4`q{a+6rR%qf`(OkL*4=XhBtY|Ky2M;SW z@vLYr+=GV|ns`<;m!Ss_D>U(}XfE4>hZUN5Rx}sUgNGHGcz;$j7wy5r3QasKnoIWJ zVTC5170m^E@UTJ?&x+=9J$P85iDyM~u^v3E(8RN%xl|7xR%qf`(Ojqp4=XhBtY|LN zgNGHGcvdu*_YgUz9hqjmjEwYTLBb#l!~$W!kTAi5gbNcWFyMj<5(WtuCJ+-KXiHGx z!Z0RGsNi6X2!CpJGa(%vojlH&%;d;aW|4d*te8N;1Iihbi`CPv{;3-eD}JLNI2aJF zL>!nxKpSc$#D{@{2$hJ7D(E1Bo=gs%ih9mIq=9LUVL%Y98eFmSdN_MfV#|lv4;+*j zbihC#i2a@viUS924jL4dm}oG>WRmbgL%A>2fgl*11AhirYGcS_P-0_nonZ*CTVtRR z?0Lg*bVszVQGX5!a3C581`=?f0TK@^Fc;9B04WL_NC$p_0v&)r1Glp25!n~UJ2r)* zgS8ebUfAd8Eqj9R2E&^%Y+BBcI+f9aMGtL$nVRaNOpNCN*Oy&gi5azZW!e^z89%6Z+Z zrlrahoOP;0$Mu}~`+uQE?bLET}?1j8SZDyyj+mvhujub{Kf*&FMl2* zM0dDEq?1LIQe()DwCR=RZUpP@BQ#VEoR>Mn2%{b*wMlGJQ7vV@>G2EP;h|7xp@5eroj@jB_KTmz6Ns+-h5}GPSoPL3G`hiJY0TX@8`4W5Kk1PX6!I^73Q(B8>m!Vw>Xsj&oH;F0W(w zgDdevB~6L0Dv34zyS%|}xDNkW-7uVVYHCE^IQp?a@%~rhh+k4Aw0mbORiZm%XxI=u z*tOPi$Bw=3VeQUwFH{|bHeL!zMN8uwl;QRq#+sl3e;Za;hKpS|#Kthgq<>h#NwD@HH;M0=U<7nv^#D8WjC@Zgb zEjs2^C8csMQ}(CqPppR0dVgKDadnMdwT)R_k&Swdm6ho6_xeq4XL^gO#?nbsnVPE% z6~S{iy{9A_{WmH_zhx=sKq;3;!_Y+zGjo(aL^-hNq})~RDK9CHP~_&>^PzYt=F*1G zf3!6IUo|#X(LZ_m`F}<=7n5I3IzxV0d0)QdbVwZXyXccsq(~g0On;F-mk%Ls5OtAv z4<3dUnmC+<(nH9ZXiO--n@v&W%H1{KnZ23CV3BV!ip(c}tKT4+$Zvzi^Z2JhYnkSz z&LerdHflU;Bhi#W2hS)A_icCzmPtDe3KTeJH_s6fD8HO}Xd zG7>U5I&yg_Q~8vamFqCrV8ckwa6`Eoh-Ga@iQwUe-V{1qt!7)o zG+M*Z-5-s&>$Rv%h)AeTq&S9;GYG2A^iGb*&0WpZz%x4(RevAzP#>GL+sWvJuhS3q zx^T-cqkjq(8DvJd7{$k2%pe|f%(5&rgm;)x!=4q*&~xaqI>b}N&|-(dl4a@gS27XJ zdFGcSR5V8uLBsSMcF;Rn5t<)e#ny)AXO~IKO{B}^m2?grDE8(sPcv0!bU$=sYksAY zmy>&C<6iF9nSUQK@rON!x}zO_esamly1Wn1HkFhky~!FPK0lI~ncq^SjLh|w7bkp` zIt&&cJcJaA8VGsF;w_qif^{-^kS?5obD0K_M)_+THA%|E3x-FibL=+?i zNpkZPpdcU+42Fb4fmkF)j6V~A!OSM1Su6}kaS($*2!Deh2*WT4f*=TjAP9pX6a(>^ zG-(dec9C)v4P?fm!0gmw*PI?hUNGUjmZxSPP7i?)@m!23#0kw)gRp5}SJK4DbaAENmxC}Z%sfS_ldwBZ`kh~7BfL@Ka0 zo?vQM6sd(HV}D1{uql?1E>uC{oVYyAIYcg4D%^8b-ybN zqUXj+SFD-r1RJDBvsIkIN0`m<^TjR(#eu`F;?4x|g#W*=GH*D*?Qk(9N8(FBK>43a zQr|6DXwAX%nod+&u%JmXsC_A}G_8?b44tKi6$~r`VKxCFsT#(Va6xWJXo?4V?xp#;PL=GKpc7Fcbs)4i${kD;TR46m&{eg-lSodAzOb4 zcc(=I^G$t+{wDJ4FkFSj9U0D(lx?(&`a5s@Wn;$VQ14wp#fc~vy9xu#(0?2S?}9Nm zDFy@g`1IL^kVcVdD-GeD7TjN!Mr-%EqJJI#)$H5ReUAl~L`xNphf=-S$PKROtAAiVx=9b3FqwSDpnv?L zhsN*v6{0IA6(=1BMTsfyyONptQU**M$T%K@li(3SA^4bmD!Osk@ZPHVHK=L5bqFJG z8a8x*6MtjnVLZ{XdfjV72C*@9@stHhqoP^`K}zWND97)em+JSKp_$t2f8PlK8( z&%RAdvsX2QFuXwxG2zRn7ZFu`yyXll$sVic`*@@Oa&ntlwg#S`i`!haD(tn6+$ zEe^OqPlhIfI{dq&$65%%qd|yVy>J#W^wrJI$@6(%X@0vCQ(66Uz@V4x!@7ylXkcCY zkPc-<7c>gc&_L)A1>&JoGso~6)PQ-+x?3?Z^Ql{j6kkyVGK_QS!TzuyLtT>}4EB{3Yn8ORZH+j=;|qkD+N^ zv^mdxzyQ_DjZv){ihn8sm+|J?6>U!iDpse+BH-T_L0(woT|wXisL@)9y2)s1DBrkF zIM8MiRSQ9Yxrgmdy%1nu(f)qAiw(S?xb_|*Yq&zU18u~x{$}V}i0CQJ6+A63%;6fw zu$cS$c@sS!!}3L6b6102g4{oqE29^mqhnK^3QMJePW8((1|!hpdsFfRM{6RR%?Qa4wKH|qssO|n&7?~Zp-&M!)_v6 zK}WxxlXQbYis>rQb-gDMCgqbaRYb+8pYFzyPWa5{6fHG`1Gow8=sik~d_nH!sziQ! z`QB^ea-f=`4}Z-Z`25M~mw{TbJI)$Xb=b31`wGsVPZ)3#fI~MZV;be`+ek14?fhIy zEW_{iz~&FFla71#%o{AwWob4L80A6fnqRxOJ__=i(*Akqo5<#afQmx!){cx%8LQc& z=D9)BvNGRoL@~BUYHbe0W6V$Kumbrn(%`6^atoNUCVwQ9K?r{@sDTjOOhNJ4M1IvA zrZRhHA+FR?O+PWmP(T8U_0xrtUw~jH@Wv{cB7=-M4*!*Xy8^BmGOnsESGs-)FxW=t z!}SI-`f_yW6ve*SW%No2pfRZ?Ln`#u$;Zc#R&FFKr6&>p4d7PKwBOlAmC-KI0en6Mh>LAxX>{#j>)|@q{l{00Sk-ox>D~Mg4<7V@PYNu?XR<`0YtOMjGNX(7dtb_W01u zL7j{^h|Z`Rw z7ObA$WRF~5X`z)!m)^&yt7$A*tUBSo?JLiLUGP$<-aEqk+{cniioU@6TkLROthwrh zu7-Dlj1{=jVbTm5z$-(P%7=7MobMKX&IiC$PIT&n<~Ka6ul{%ek4g=<9?OH}m4D|@ z!q$@mQ8x?utHG&7FgVO$c9TiMdOT~EVb4mjtPHJ6yj?wpB-XrIT`}6#Sx)QV5ksA= z{x`e&^LlkLd)1eU1LEE41fW;fIkOmOFkzkSx|?}a_HZdlCe-KJx0wMA`Psw)}y$A`eQnaF9D1fX`c6+V~tISx%6dAAxsT`p!w@Ku7eOb$^m}=vXi4 zdG4)Vl83PHewP3$^kJFNp(t=(MPX*>h=19ZMi!Y5VDp=t|{W!&?ZS>`ZNW`8zrjj zc4y|(5lu_f9@2GexlOZD%YQ~)wc*`paSuA_2PDQngX7vT`~f)plzbw7-GyG`mbj4( zzy_9$hLY3ULEc_!w(FiLyq}dQxDX++3!X-ZzxtC;0~{F=CIH3`v<^H z3Q+ZtDQP@{4=_>mFZOwj1#$zX75svhr7GAoN|)I5={1PjjDN+tU4JOjShJZj7#D2n zfb;uiXttt%-oB@S$ z+e-?Z8I`|iE+SHv9+2n z6XD<-zUtf-ijc;CF@FLsE2t?o!0rhzJ8nZ~e-k}y^%FI#nU%S1qSMTMCg7KWwrVM# zraLqImM`#P?LLe!j)KeMd<~MmtJvQzWKAC>q9tujF%8TG{Nk!WLe&@fUrxxpycZI2 z6mLvZJN!sPoRji4{3sP+#lzLC9Poqu&~n-50Zz&zw`}m_V1EGDJ9b%iOz1p>^AO7S z-i1!)<)%4wGNxL7f&ozR!Gx&y^&V=X&qJy)e)3?T8h6sc*;AjsQNpTF6Tt+z$8D|B zQAXsm%(UBE^z!iZEh=}#_JsoDdB%R>Als|jWO^^_52}Ts6{wg3c0DctPsNPU=evEq^J|`)_xx9~e^T&Qjw(COj)_ z`S@a>Y;w> zu(8WNJAeH)*z;|pO}}>Sc(QM2k2UP|Vb3OCyEb^)Z>O(~_CBz&mOne~J=n9`qfL8# z?bzgRXB#{0wZqRQyS_Hq@^7bIkM?%pv6g*4?QQV0+eS}&?fTec-)9?Z__f2HC%bk% z*s|ZJT^s#&U}KkkcKU6w=i5e`e(l=vWZ%vnYk%15!=6pPc5U#o-%ei}?R{WlEq`{} zd$4D>N1OKg+Of&s&Ng<~Ylojrc71KI<=;-b9_{VGW8Jm|fz0rVM_YHla;eS~AHi1A zrQFbP=|=V?+)5XGRZ@^nQTi#gl;yJ-lf^ZghR3zb-1E7@l5!poG9d*jKPvwF3Q0fUu3Apo+kymjEiWq;fbO^JB&vop~>ipECLbxDRALw}tHUMwkIQ5rS0 z7)&oxaYHlb2KF#~ifBF=YN*k9Y-Im9Q3fSuM54QC2NFnNC=7!TAOxQfFa!)jkYEUb zLVz(0K}8ZEphARxx3CYj53>($AF>bH2ib?T4;e8)I1MEBL5F}f@U|h>2Y=IH#d$RV zN=hz#cKnli1BvE_2C5IT54sNqQ6P{8*b*CUMgy)a1&*;a;7Tee9Y+IGi3JF8-g>Tt zM_P{trkn^I!)QRtfj~o`QGO0axe+4KVT${xmmf9Ek~GV>BKn=r*Su(VO0)S8a)BrDFNbp+Ln zApxwM>G3phN-S`UqXDV}1*THS(lG?@^b$va($NTAwr?;E2vGVN2F`~Uy| diff --git a/src/Nethermind/Chains/swell-mainnet.json.zst b/src/Nethermind/Chains/swell-mainnet.json.zst index 8d16059d8bb18cdd1e2c935bcf9f8c068f2e4d01..8deb4ab15dfbaad721eb3c6ad3bd793db2ac2673 100644 GIT binary patch delta 14756 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 K!vz`!{eJA|GQf^tGfEC>*?y= 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
tBFR+p8o6Iuixwu7aABJ2w_i!<@Pr1 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 L9r{Ax5wQOcrFcx9 diff --git a/src/Nethermind/Chains/tbn-mainnet.json.zst b/src/Nethermind/Chains/tbn-mainnet.json.zst index c4d8389eef16f0e5e9547016c2f7630259422d33..b188c9ac4d3be74efed4942ed04397d2196bb95f 100644 GIT binary patch delta 19367 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

IM4pS-tu8aHUS{~MRs4Bd1F@|W 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 delta 11121 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 delta 43297 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 diff --git a/src/Nethermind/Chains/unichain-sepolia.json.zst b/src/Nethermind/Chains/unichain-sepolia.json.zst index bfd9eda1df9292780fb583574b1df276f8a936ed..656831081947fb1430014dba527d14b70d6c266c 100644 GIT binary patch delta 27970 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 delta 27105 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

rypGV_%Zxw>vR(~8Fudw{!Dad_u}pf;h{QZl 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 MgNARnhHnAl90P+n)c^nh diff --git a/src/Nethermind/Chains/worldchain-mainnet.json.zst b/src/Nethermind/Chains/worldchain-mainnet.json.zst index ed824530df61dd4c73bcd5fae9a3262238bf5903..9d73321b4f8d7761d0ca22863a6c9f5ce59a9924 100644 GIT binary patch delta 12292 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 delta 12452 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 delta 11638 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 Sd>_O?ewdigKGZUOkNAHN(cjSk delta 7185 zcmZ9MWl$X2vPKyoxXT0!Fu()?1PHFd-QC?aNN^c!a0u@1mH;7W7+`P@?(R--hj-q+ z@BDddSM6T)Raf`^wU62n!{LY!h6dJWB%KoyC8TX_ghfk1To9Wo=DV~av-b8=ac;ms z0Rx8WNyoXYtVhzyIT9%eNiqg9;2vQPp~f*4T`EFThbdEJz9sbjqgKtFR$Xx*8>XR+ zw=?w9+SRzXOt1_K7IQ=}uL<4;93LG!rrQ>udIT?smM9FP%mg0d(}x6Eg?H?^h80fd z1xb}wVsGFLsr>A;*r!bra}6JF8~FP6JcnypCxYlnQS9(bh|$n!0Kw0Wf!*F=-L*y@ z33zY~?=h6Jl$g{gtc!1<+%c1wn4s@RuO4%l#XR&bK+eC!p;yN8&;Dc=Ng1a^VLCzd zmm+gIpJ<@kOBY7HOh7)wwHJEx<3JbF}X%?ZOe)!1CmQIMjp_ARcKQdHoZ*RY)H$}(6&2G_G z^fN+?g_AOFG%<=GTD@+lc2W^ka;^0B52ftYjaY*H()IL`_R|JXIYGOU8RY{cIp;?c z2?n%_z%Py{O;3#)Ol$aECV?%jvv}w@+*rj7pA^>+{du;mx<^wxfsjVCY#?>z#ja2O z1f+{Y;8L`UnZ(_HHWIvT9ozQ=$ypn++ZwSGRA?38ulc>|<^Y?{EI8qQG;`3CDlUz( zvRST9@6z@Rv9!%j>Gk$@*Dr?{zQ>GS%&RPKZN0clk0c~zryMh}6D~c~$UcpK zYmTZo(ZfLtn=gL*_$^B;Q=9Nl)XTpzM#Tf=ta+bHeE+Xx2s>fe8Yv1gF+!G!CfhQ- zv?N}dKNNd&omZE?{+~qrD>ko?|BGb)jTm0NDoeLNggds6+ZHevy7x<>Y0|7_XsSN{ zXM+Hrl16dbz)&+|-LywiIpgE@-0f1Ue#O+}2Wz>CcRj3?e~zKqI(czJE@dDVsLd8= ztGXU6Kg&52g&jGd_JKAnBh_q(bs==-W|+A9#2%79f6$hi-6b7v08?=RU+MO-tUYO| zRZUo1DY3A;zw|T67`9839hmbQOxB%LHd}FA-OT~An^A(y?Th+O73?h8+bqn!_wqz%JOjQbQ;1W8Az<#;p@9=7)%fmm14i{b)(#z zCEY}VY3vI+A7NdofG*d+d(YcbPFE!_BSHW%On#@&4j9`LfNNow^;3h3eujgdkhw#d zd9UN_x(C#^>#G_$H)auG&6Z}eyGdc>M7!#Kf^53lf6HYV>3lzUKlw{dI6`B4C0!lU&)qUNY@780SfWTiAO`gJbX1nIP~>__~mE}1xU6vaZbv79Fnw8JRV zsskuBpVU24NI|eW;iT(O=pvGIIu1vL$-xKfiGYI|&I51uZL(QVF?iIokpAJ&jVe3& zpe-|ZxZ|(2n~$1h>a0OYxBMLlO9{vCy8Z3>=QXsgM9zDFP%+vT-XY{&habGOLUNXd|Wy8#`3mY$w<0+Fv%G?(Yw1LhRg) z4l@)9$cq{;mh(LKzl*J9DC3p(GPsGwaAPoxODUNc1u+Z-$iUhIj9Rcov zF6sFp;lo{YWlsLG%sCMh*9KO>d2Ejy>l!%W;avi$aLFf3CRZ01He27?fO>e$S00hE z!NkF)L67)rx2(01riBTS2RGQW`zk#egZuEN8^J{BG@SOvYfS?E$uvoqYany6r;NW& z8K<{*V>g))$F-8Pa6jTXJC%Ec!0Z?Udn_xAc|7RcjQ zAAeF!r_9u|6e(WA>M~Z5Lv~?{wiWG(9-FKql)5Auth;QGf zGg)`5#1uUKbNe@@EfrDv%jabFZ%bL=sd+B!)LhjEEuaJ?B`li1na!=q} zd}I+o&$DtH^A{l~dBQVPRs3Q#ty1wN`TUiqcH%H(e&?E09)Gn^?Dw9F$bJ5)CQEm> zwGVB$3D*ryPkNTce5$x%mW18-C0nd9C%c@ft6eC%f{P>nXOlX!RKKhMlTB zwQ#m9`%oCmmTr>LB_t#Vv4b^_A>-8km%1|?02jtFdbL$Tz6d7lts0XPL8 zh9pmtch|mR75QJsRG*K*EMQ=nO!=C=UTkP2R%BO1X&9bA#qytbZ-oZD+N?-FTH<82 z!Hzjk-j9o|vhm5{K^z9-Cn`&do`Va+@`D7HsZ`5Bm~a>wUEJ0&iTx7|!z3#Z*t)pJ#AQaXQlgku}ycm%%RxSjevaHJHRyk&Hv~@bTg<;%rjsZT7g8KeCmWIZ6mKH}ho8bwww`OT6 ztLLL5THb#=Asp4~MkgNL2hXJo2MwMI^-~Sk4%bW3G5XO|Mr3P1V=cWoPvMxKxn}_+ z3D>QQj?h~_jw!pdJFC)}(*?UGZLbc_-)&dzA3R!qwf}e7^Iwdux!ozdqr2U*iP_5; z+@k6usG-)46RVZZfxq#{&&hX7$HytR3QgUZs}QCYmbBR~S$Rg}{r~&m-0$t*2U=lw zrp4F(=fg5bK26<>XZKEF#NIX9_1~TUa0|e0;%q&9PK4A?JfPQ14IkgL8ZV625?j2h zc~ZJ!IBzAM{nH#^IARpl_A9uC7Hfrw3l=OzjhHYC61vHH^Zo(zN2z0Cvs8I5^mcn| zAM)HnBU`J}XUT;o;YOKJzGU$tBd>F+{zvuYg;e<3lQ0@zPj6O3oQX@g>MxZTo&70o2$oXOyp;8f zZX|1c5uvDW)^_5B{;<)F4GO0o7a-=?8*(h1r^~jLIo;;e+{gh0vVyA;vj@*_j4G&% zLUUe6E{z2?O(Spn^5=DD5(WK;GS}Ml$pchXR<4|s&3VMpARwUd=faQd1)KDbP~O&LNR1=9 zSW`i#V{zJEUgY(SsTryPxw>1T+l>N1w)mT(4@OZEL^>OjfW~tKbq9_V36?qvK_j_N zwS{pOpTQPBt+qJ7>ZJzr1&Q+OwGGwC4nFn+D2Y5mbg0osUp@Yf!s+T(NJViy+3M48@{QA`R&^5dWWH#t=TaNlcQ(9SCDaSj~m1vjIL<>VlY4aoWZpr}K%Hz;&<7f6g;hN$Hu zl!$Ziwz6Cx-K1Ruh51-Blh(y1Rtqe=?ZD#g1^hx< z&@KHs3enX6#YFk#v>E*f^-$iK+8X=G{3u!m3E|x4`?(+!sGv{rZ@|=)V5~l9aVqZJ zFG{(6+qdfSAov?>_?NKLQPT`6VwufKHheMz$sq`}3ze!Kg^_Oa*FIZ3?2<3lG3;!~ z|D3OEPQ20*Q8BeJGEuVDwSa=9O;l5kdLW922TB1W`G+mAkNH14@?OTPS}1aFUWhs;U7Bqq&psUE`cNy7rNLmP)x= zN;$x7I}~YJi^r>x6GqJK_oS5g4@q^{Zy_JtTrc=rR%)*P3g1UIe3ERg2G{l&XmWBB z_OPi-zEsw#3YiN;xMm>w-v^T%o)e?OU=S26kE*T32_oG@^`{%vR}9 z1r)`t9gjvJMKHbZM+I}}?LWVL0JyP3v3AzTz5^GCA{%4U4RBsw>*PYF7%d04K*YU> z4rVB*MreVO3J`KSJ|T)$^EUu7OcqMg@MtKBi6_a2crqJai=e1fJgp#R)KJTETH8fB zO-@=_HMI|%C?SOT)YN!rk)h@ZHq4><8@Plbh;n@!kt&JXDiI;nXkus}3H*PqP&~01 z4w;#ca;O~Le7F*M;RmB3o|pNMQ*W7m!LOfi53^B!kA}=$#?NMio3IJ|6<|SM)N;I; z94HDa-SktabnWi@u_edM`ByA1xpLZ7{q|BJ3885cH1@HAZB)X&9X0o<3*#Wb03-mU z_zN(9u=#=ca`p4I!K-`Dos`xOxT~jM#}303{YI$@F~4BaiCo-bck`Xs7P!-Xyb>6NI>NB@ zJ7}R^q2Rk@E93*eEbJY>j|1cetxc651`VkFv%#o=XJW@q7X?2rN zb1EYn*Dbgda^tS3AOz%g0av%f51+mgJLTb$l|VdE@z0}+^PZ!`T@y6)a~Nvjv-LS7 z+M8rrjh@7l;#Hp@z3wUUK8JZ7babCcrK=qm;+Kew@9j~BoAXPnD=Kwg0Ax46mr!RP zD5LzV7E^C1ucKOi=><{h{)Xd9s(Q^u8_c>;j9bMNz^LC@mMRhvxkvrVbPhDeP%1Aq zU0t%pkIl&_ML2P;aBu{nAW(0NE!6zTN}c59?x!H-I{QKZ;g*5ncrl?xeRipNzh_$# zv(vba$q-qkgK57|=Q@0rpTLp*IZgEAAfyCZ@%7Pd5vv&q3p^X4_sZJP?8uF_y5pmh zcEm&?K=L_xp!^iMWMV5VK-g99H+(|=)xHjAOp@wa{h(t5-cqhQ6ENBu?`>OaRQb%0 z8CoP4(=)#di9;F!$bh^ZL+?YHAG*aQbWN|bu4c(DwYtvb;?sT5=wf7ko+s+zH%7dP zc^3la90*J_zEN4!i1}o3!cp$cV~eQUs3=7j01$nX31wU^#(9oR@T*a7xiKiOT#3;A z`xug|2x{T)&b9YMxNXAQ3C@WGU7+SpGZ_x>^fF>Y9%~7R5=H=2mHn*pEboWC%~R@; zD~pc`JG0kUU+%4xCjol-&V%~bv9V9DqgrU%(S0-VDtQWJuR&%utJJQdAFv55O{>+# zdl*9^K%yJaie*>SPp%HuOh)9uF{aS4{a2sv2sXIv=Q~V$+lfN{#ImVe1S61_;A-H$ zB+4ge$5NY5*)yVn~9*1e(oNI-b;r=#7hdT#i;XxYD4u(>>N=S z+U~q6EK7%MUr)eP+V30s19yp(G3|(TQ{4;no7&Jg)Hmx@(yERqcG^X<>zu9cVsaPX zE(adrXzk%p?>jiMUu2O6Ce$~iQ8}aj%r^)rnv`yr+ny5qiSK=nQR(-n1w~XR)!*@j zXdoi%4C+k?5dY8|7Z{a2Rb(9<^%j@+)-c7V@WJH?8z$~^Q-(gJ9~NxJoc^( zo40~K=KC(KmnA=g6y1{w2G0vuF_r>oUH{7xCn7P4Xosn*@ zwo~)lQ%&61+J^G9T3SNVp;RimqgKFIx*WfBTv!IK!&jty@S|&8$0RTHL*^PM1amm{ zyAC@ToTLuiBFnmt4?v2cPqJ*XzFG^X~MiQ+3m{D9)abHW1A31WFW2CH_)^1cYk_y2N z7@QS|AM?eDf%M+3K0q{@|5_|-4b$_gRpXfRTc!0>&cuvbKIX>Tw*4Gq zjE$cfyjAX*9}ZKW>~CQBiBw~CjPWFclU8|<6SB(t$+VEOf}G9o!5Nw-!Rn*CZ=-Ds zCf}6&x@L#8CZc{!=<)_~R*`)EP`~7fYs<@a=ABEy)yU6bS#ePx-<1rPhSWLZmE0sU zR!z%plvAO45C3+#s>h~U+P6WK?#66jUrjU7bfvRxLc!RO@ee~XNwLm$4uHN3*80Ze z<)Oh=5}Y@H)~!)X_raGX7kBW~QESy$&2DI|8PV*P=Nv$ogf<0f_G%n1e+-A>HB8zx z2ByZWuA|JDnGKH+*yMTA!r5q)T;XCxck;nU4v-e7 zI$)vLB5p)z8FiR*4O1d!SbP7PTZ0|ddS2tnHH9e{UM1vduBRayOf0+Aovfyony(UV zD0t|4cW!2SC(rd;4`9g(@wpWwW1P-+%&@=y!H4I9itLVMckYX|Fp?Q8~w zTe6sd9rKCyT;w9SQN~0F+%(oct7MYS2FFLhGm|7qOb7+OM6WcU7%!X&e}pl{>my&? zN|kez-p7E?i6(HkS?X&>ZCJI3dCn=WRgx)P8Ey`rM5{ZHxj<-E7C~meE6XoY?G^<= z&Z|}c02FfQ()=Ro{P%e+={IqpGYg{J<;mHK35t=Z zONw2_bZ?y*S_&H_tzRZ64GtaVy*vx^D^A@*TpkaHo)Fr50dX;n?O2!TjZlZSc^>6nw}9m9X{LvjuoDzYAH<53 z3P}o`q_$%?!X-)@G8N(O{lymJhkT{ud)g+__Ujp3_>72>aNu`<%)HL=^!CO(5`&q0 zXgm!_2Z#%A)=+k;KwxX^OhfVfFpd>YCj8*T;~}i8d8uC+KpMPxd*QxjK98TGheRoa z(HxVnff6B(K_zK0Hv-8g@$<>6_dzy{?iP%jRf$7V7PV(Gp~(g%XGH4w zweRoZWt%|DM(ycdo*hpJNiDy7muz96My0^$1{cbF4&3F@?$%v++~vAIWuZ0YA%q*( zXf%X>4}R)BFe+I5h4Pr-r@?VKqTd??Iz%&0uKx!&H#Z+A58prKzc5pOLQQ(z1&H2Q zQa)sb=Z@D3)yDTvUJj`_&@gs!ZT3h2n*T#gS59w)JIQoI?_v_uEgza{qo0AlLn IC{}|12XLP1Gynhq diff --git a/src/Nethermind/Chains/zora-sepolia.json.zst b/src/Nethermind/Chains/zora-sepolia.json.zst index d63f50733803e8f6e495c795eb982099f4713cb9..f8c45644e266f9b92379f691eed4ae60eaedfebc 100644 GIT binary patch delta 4385 zcma)-c|6qH8^>qC*vGybgRx~DvQ)#hCX`AgRB8;PvW=9Q2}5EMB^|^lTZD>~3ZX~~ zHMVY22njQF$z^mS(eFFs*01~fVigA{CeuX(O!pC)mulukloFtm2g!4D&9 zRNc8()?%}@nnB|4rM`4rrZUs9-^_KBcWSbrgOHknRN1BDM~Z{k6)&2i&K8WPdRa#X z4BI^^_bYjck9u5rENzvQ>77@-4FgRLNmI;iQX8{Tfo^R1og>4VzPhfn8OZy`Q9`Sw z7)eN&b9_)I_2Q#=8zZcY7h7?I-NVta^CAxq-u!OvX64h3XoSO8$(Z_kG{?R3K z?-7wpyPp3ZnJFn)^_ZTdJ#C}jc`R)I!^5P#%9e*_Y%-=&tj4B zh;pqsJD~MC>GL_?GUWopw3*cmbyrXBn9nJdS}}x0)|OQ>?w6A3?u5ih74aw3H5%k*x~XD!KmGL9^b7fp*KBORE*-yJp?Enj z`0Lby$-%waOwyim##QG2{(}<-Kb(H5W?O%$?Dhd!X28853#ON{-`qi09iZ^>efi-9 z6R&M4RR)!JJ}D08lcwqUAs_wxX5SDzj^uWJZ~N#&bR-?EVV>&z*!eL!SVkgZEjz%O zN;<2*8GB3olo3M9BfjkfLv1VWRVa%&MLwfna6I@*U!e2C=U2aXYH>S@!$ z{OEm>RsF&B&pF?I8?7&X-zi%8`C3OP>$>lev>R)qIBKJ{2eMuqqSF0p?p@72bu>CU zq{*Fgtj3GI!~HDd?bQZa-|YRU?|iR@UM?}R?{YVmR(hi2v#;ryl9|xyxLa(NI;x~uWq&mv7%?C zV#o={S;*esl}DXwBYOyK#?p2g8f{-ⅅB1qQ2Nb)}i;KR8BUvypK@gnmdYsZ~TCN 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 delta 4887 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 Date: Sun, 30 Nov 2025 03:41:04 +0200 Subject: [PATCH 034/255] fix: keep PeerPool commit loop running when no pending changes (#9839) --- .../Nethermind.Network.Test/PeerPoolTests.cs | 60 +++++++++++++++++++ src/Nethermind/Nethermind.Network/PeerPool.cs | 2 +- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Network.Test/PeerPoolTests.cs b/src/Nethermind/Nethermind.Network.Test/PeerPoolTests.cs index 92e13cb55d6..cca52bbda26 100644 --- a/src/Nethermind/Nethermind.Network.Test/PeerPoolTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/PeerPoolTests.cs @@ -2,9 +2,12 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Nethermind.Core.Crypto; using Nethermind.Core.Test; +using Nethermind.Config; using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Network.Config; @@ -64,4 +67,61 @@ public async Task PeerPool_ShouldThrottleSource_WhenFull() await pool.StopAsync(); } + + [Test] + public async Task PeerPool_RunPeerCommit_ShouldContinueAfterNoPendingChange() + { + var trustedNodesManager = Substitute.For(); + var nodeSource = new TestNodeSource(); + var stats = Substitute.For(); + var storage = new TestNetworkStorage(); + var networkConfig = new NetworkConfig + { + PeersPersistenceInterval = 50, + MaxActivePeers = 0, + MaxCandidatePeerCount = 0 + }; + + var pool = new PeerPool(nodeSource, stats, storage, networkConfig, LimboLogs.Instance, trustedNodesManager); + + storage.Pending = false; + pool.Start(); + + try + { + // allow a couple of ticks with no pending changes + await Task.Delay(200); + Assert.That(storage.CommitCount, Is.EqualTo(0)); + + // now flip to pending and expect a commit soon + storage.Pending = true; + Assert.That(() => storage.CommitCount, Is.AtLeast(1).After(2000, 10)); + + // StartBatch should be called once in ctor and once after commit + Assert.That(() => storage.StartBatchCount, Is.AtLeast(2).After(2000, 10)); + } + finally + { + await pool.StopAsync(); + } + } + + private sealed class TestNetworkStorage : INetworkStorage + { + public volatile bool Pending; + public int CommitCount { get; private set; } + public int StartBatchCount { get; private set; } + + public NetworkNode[] GetPersistedNodes() => Array.Empty(); + public int PersistedNodesCount => 0; + public void UpdateNode(NetworkNode node) { Pending = true; } + public void UpdateNodes(IEnumerable nodes) { Pending = true; } + public void RemoveNode(PublicKey nodeId) { Pending = true; } + public void StartBatch() { Interlocked.Increment(ref _startBatchCountBacking); StartBatchCount = _startBatchCountBacking; } + public void Commit() { Interlocked.Increment(ref _commitCountBacking); CommitCount = _commitCountBacking; } + public bool AnyPendingChange() => Pending; + + private int _commitCountBacking; + private int _startBatchCountBacking; + } } diff --git a/src/Nethermind/Nethermind.Network/PeerPool.cs b/src/Nethermind/Nethermind.Network/PeerPool.cs index a49a7c2b829..659d2a9cad0 100644 --- a/src/Nethermind/Nethermind.Network/PeerPool.cs +++ b/src/Nethermind/Nethermind.Network/PeerPool.cs @@ -195,7 +195,7 @@ private async Task RunPeerCommit() if (!_peerStorage.AnyPendingChange()) { if (_logger.IsTrace) _logger.Trace("No changes in peer storage, skipping commit."); - return; + continue; } _peerStorage.Commit(); From d1821a54bf1aab97d604a9ee4c7b9886a4764738 Mon Sep 17 00:00:00 2001 From: Bashmunta Date: Sun, 30 Nov 2025 22:09:57 +0200 Subject: [PATCH 035/255] chore(init): remove unused StateReader assignment in InitializeBlockchain (#9843) Update InitializeBlockchain.cs --- src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index 0b97300a5e1..c0c8fd44f14 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -53,8 +53,6 @@ protected virtual Task InitBlockchain() blocksConfig.ExtraData : "- binary data -"); - IStateReader stateReader = setApi.StateReader!; - _api.TxGossipPolicy.Policies.Add(new SpecDrivenTxGossipPolicy(chainHeadInfoProvider)); ITxPool txPool = _api.TxPool = CreateTxPool(chainHeadInfoProvider); From 4746d4f27d08e4eac8d8b616aa104edee7d23b6d Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Sun, 30 Nov 2025 17:17:43 -0300 Subject: [PATCH 036/255] Increase precision of gas price logging (#9845) --- .../Nethermind.Consensus/Processing/ProcessingStats.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs index 52756254fd6..f2246ed3e73 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs @@ -292,7 +292,7 @@ private void GenerateReport(BlockData data) double bps = chunkMicroseconds == 0 ? -1 : chunkBlocks / chunkMicroseconds * 1_000_000.0; double chunkMs = (chunkMicroseconds == 0 ? -1 : chunkMicroseconds / 1000.0); double runMs = (data.RunMicroseconds == 0 ? -1 : data.RunMicroseconds / 1000.0); - string blockGas = Evm.Metrics.BlockMinGasPrice != float.MaxValue ? $"⛽ Gas gwei: {Evm.Metrics.BlockMinGasPrice:N2} .. {whiteText}{Math.Max(Evm.Metrics.BlockMinGasPrice, Evm.Metrics.BlockEstMedianGasPrice):N2}{resetColor} ({Evm.Metrics.BlockAveGasPrice:N2}) .. {Evm.Metrics.BlockMaxGasPrice:N2}" : ""; + string blockGas = Evm.Metrics.BlockMinGasPrice != float.MaxValue ? $"⛽ Gas gwei: {Evm.Metrics.BlockMinGasPrice:N3} .. {whiteText}{Math.Max(Evm.Metrics.BlockMinGasPrice, Evm.Metrics.BlockEstMedianGasPrice):N3}{resetColor} ({Evm.Metrics.BlockAveGasPrice:N3}) .. {Evm.Metrics.BlockMaxGasPrice:N3}" : ""; string mgasColor = whiteText; NewProcessingStatistics?.Invoke(this, new BlockStatistics() From 7f4e2cf2a425cbb64ed30f9505a708055ffaedf6 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Mon, 1 Dec 2025 10:23:08 -0300 Subject: [PATCH 037/255] Fast path JwtAuthentication (#9837) * Fast path JwtAuthentication * AI complaining --- .../Authentication/JwtAuthentication.cs | 73 +++++++++++++++++-- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Authentication/JwtAuthentication.cs b/src/Nethermind/Nethermind.Core/Authentication/JwtAuthentication.cs index 21c8ce26d02..9ea0853c183 100644 --- a/src/Nethermind/Nethermind.Core/Authentication/JwtAuthentication.cs +++ b/src/Nethermind/Nethermind.Core/Authentication/JwtAuthentication.cs @@ -2,10 +2,12 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text.RegularExpressions; +using System.Threading; using System.Threading.Tasks; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; @@ -16,22 +18,31 @@ namespace Nethermind.Core.Authentication; public sealed partial class JwtAuthentication : IRpcAuthentication { + private const string JwtMessagePrefix = "Bearer "; + private const int JwtTokenTtl = 60; + private const int JwtSecretLength = 64; + + private static readonly Task True = Task.FromResult(true); private static readonly Task False = Task.FromResult(false); + private readonly JsonWebTokenHandler _handler = new(); private readonly SecurityKey _securityKey; private readonly ILogger _logger; private readonly ITimestamper _timestamper; - private const string JwtMessagePrefix = "Bearer "; - private const int JwtTokenTtl = 60; - private const int JwtSecretLength = 64; + private readonly LifetimeValidator _lifetimeValidator; + + // Single entry cache: last successfully validated token + private TokenCacheEntry? _lastToken; private JwtAuthentication(byte[] secret, ITimestamper timestamper, ILogger logger) { ArgumentNullException.ThrowIfNull(secret); + ArgumentNullException.ThrowIfNull(timestamper); _securityKey = new SymmetricSecurityKey(secret); _logger = logger; - _timestamper = timestamper ?? throw new ArgumentNullException(nameof(timestamper)); + _timestamper = timestamper; + _lifetimeValidator = LifetimeValidator; } public static JwtAuthentication FromSecret(string secret, ITimestamper timestamper, ILogger logger) @@ -118,6 +129,14 @@ public Task Authenticate(string? token) return False; } + // fast path - reuse last successful validation for the same token + // we keep it very cheap: one time read, one cache read, one string compare + long nowUnixSeconds = _timestamper.UtcNow.ToUnixTimeSeconds(); + if (TryLastValidationFromCache(token, nowUnixSeconds)) + { + return True; + } + return AuthenticateCore(token); [MethodImpl(MethodImplOptions.NoInlining)] @@ -138,7 +157,7 @@ private async Task AuthenticateCore(string token) ValidateLifetime = true, ValidateAudience = false, ValidateIssuer = false, - LifetimeValidator = LifetimeValidator + LifetimeValidator = _lifetimeValidator }; ReadOnlyMemory tokenSlice = token.AsMemory(JwtMessagePrefix.Length); @@ -152,8 +171,12 @@ private async Task AuthenticateCore(string token) } DateTime now = _timestamper.UtcNow; - if (Math.Abs(jwtToken.IssuedAt.ToUnixTimeSeconds() - now.ToUnixTimeSeconds()) <= JwtTokenTtl) + long issuedAtUnix = jwtToken.IssuedAt.ToUnixTimeSeconds(); + if (Math.Abs(issuedAtUnix - now.ToUnixTimeSeconds()) <= JwtTokenTtl) { + // full validation succeeded and TTL check passed - cache as last valid token + CacheLastToken(token, issuedAtUnix); + if (_logger.IsTrace) Trace(jwtToken, now, tokenSlice); return true; } @@ -210,6 +233,44 @@ private bool LifetimeValidator( return _timestamper.UnixTime.SecondsLong < expires.Value.ToUnixTimeSeconds(); } + private void CacheLastToken(string token, long issuedAtUnixSeconds) + { + TokenCacheEntry entry = new(token, issuedAtUnixSeconds); + // last writer wins, atomic swap + Interlocked.Exchange(ref _lastToken, entry); + } + + private bool TryLastValidationFromCache(string token, long nowUnixSeconds) + { + // Read the last validated token entry atomically + // this is a single entry cache because tokens tend to be reused + // for a handful of sequential requests before a fresh token is issued + TokenCacheEntry? entry = Volatile.Read(ref _lastToken); + if (entry is null) + return false; + + // Only allow cache hit if the exact same token string is being reused + // different tokens bypass the cache and undergo full validation + if (!string.Equals(entry.Token, token, StringComparison.Ordinal)) + return false; + + // Token reuse is only allowed within the original JWT lifetime + // We never extend token validity beyond what the issuer intended + // - IssuedAtUnixSeconds ensures we don't accept a token older than TTL + if (Math.Abs(entry.IssuedAtUnixSeconds - nowUnixSeconds) > JwtTokenTtl) + { + // Token lifetime exceeded - drop the cached entry and force a fresh validation + Interlocked.CompareExchange(ref _lastToken, null, entry); + return false; + } + + // Same token, within TTL, recently validated: + // Accept as valid without rerunning JWT parsing and crypto checks + return true; + } + [GeneratedRegex("^(0x)?[0-9a-fA-F]{64}$")] private static partial Regex SecretRegex(); + + private record TokenCacheEntry(string Token, long IssuedAtUnixSeconds); } From 5f6d2ae77c83e859a71dda77f33af192857e2269 Mon Sep 17 00:00:00 2001 From: Merkel Tranjes <140164174+rnkrtt@users.noreply.github.com> Date: Mon, 1 Dec 2025 14:34:23 +0100 Subject: [PATCH 038/255] fix: add missing string interpolation (#9851) --- tools/Evm/T8n/T8nInputReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/Evm/T8n/T8nInputReader.cs b/tools/Evm/T8n/T8nInputReader.cs index bf89abf1963..33634083dd2 100644 --- a/tools/Evm/T8n/T8nInputReader.cs +++ b/tools/Evm/T8n/T8nInputReader.cs @@ -63,7 +63,7 @@ private static T LoadDataFromFile(string filePath, string description) } catch (FileNotFoundException e) { - throw new T8nException(e, "failed reading {filePath} file: {description}", T8nErrorCodes.ErrorIO); + throw new T8nException(e, $"failed reading {filePath} file: {description}", T8nErrorCodes.ErrorIO); } catch (JsonException e) { From c7327d62fc1a594e1f19f9755c06a317dca7d145 Mon Sep 17 00:00:00 2001 From: MozirDmitriy Date: Mon, 1 Dec 2025 15:58:19 +0200 Subject: [PATCH 039/255] fix: dispose automatic pruning triggers to stop background timers (#9847) * fix: dispose automatic pruning triggers to stop background timers * Update PruningTrieStateFactory.cs * Update CompositePruningTrigger.cs * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Lukasz Rozmej Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../FullPruning/CompositePruningTrigger.cs | 23 ++++++++++++++++--- .../PruningTrieStateFactory.cs | 1 + 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/FullPruning/CompositePruningTrigger.cs b/src/Nethermind/Nethermind.Blockchain/FullPruning/CompositePruningTrigger.cs index 49f20bb7e2e..8ae718f97ee 100644 --- a/src/Nethermind/Nethermind.Blockchain/FullPruning/CompositePruningTrigger.cs +++ b/src/Nethermind/Nethermind.Blockchain/FullPruning/CompositePruningTrigger.cs @@ -2,20 +2,24 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; namespace Nethermind.Blockchain.FullPruning; ///

/// Allows to have multiple s. /// -public class CompositePruningTrigger : IPruningTrigger +public class CompositePruningTrigger : IPruningTrigger, IDisposable { + private readonly List _triggers = []; + /// - /// Adds new to the be watched."/> + /// Adds new to be watched. /// /// trigger to be watched public void Add(IPruningTrigger trigger) { + _triggers.Add(trigger); trigger.Prune += OnPrune; } @@ -24,6 +28,19 @@ private void OnPrune(object? sender, PruningTriggerEventArgs e) Prune?.Invoke(sender, e); } - /// + /// public event EventHandler? Prune; + + public void Dispose() + { + foreach (IPruningTrigger trigger in _triggers) + { + trigger.Prune -= OnPrune; + if (trigger is IDisposable d) + { + d.Dispose(); + } + } + _triggers.Clear(); + } } diff --git a/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs b/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs index aa38226feb7..13ee2178775 100644 --- a/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs +++ b/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs @@ -109,6 +109,7 @@ ILogManager logManager VerifyTrieStarter verifyTrieStarter = new(stateManager, processExit!, logManager); ManualPruningTrigger pruningTrigger = new(); compositePruningTrigger.Add(pruningTrigger); + disposeStack.Push(compositePruningTrigger); PruningTrieStateAdminRpcModule adminRpcModule = new( pruningTrigger, blockTree, From 3653ffcd732360b984d817c007489f642d325e5a Mon Sep 17 00:00:00 2001 From: phrwlk Date: Tue, 2 Dec 2025 09:54:49 +0200 Subject: [PATCH 040/255] fix: remove unused IHttpContextFactory resolution in StartAsync (#9857) --- src/Nethermind/Nethermind.Runner/JsonRpc/WebHost.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Runner/JsonRpc/WebHost.cs b/src/Nethermind/Nethermind.Runner/JsonRpc/WebHost.cs index fc765747f04..a8ac6bfc76a 100644 --- a/src/Nethermind/Nethermind.Runner/JsonRpc/WebHost.cs +++ b/src/Nethermind/Nethermind.Runner/JsonRpc/WebHost.cs @@ -82,7 +82,6 @@ public async Task StartAsync(CancellationToken cancellationToken = default) _applicationLifetime = _applicationServices.GetRequiredService(); - _applicationServices.GetRequiredService(); var httpContextFactory = new HttpContextFactory(Services); var hostingApp = new HostingApplication(application, _logManager, httpContextFactory); From fde7cf30ec91a94726879f43ee3e3471fec8b2f0 Mon Sep 17 00:00:00 2001 From: Bilog WEB3 <155262265+Bilogweb3@users.noreply.github.com> Date: Tue, 2 Dec 2025 09:22:00 +0100 Subject: [PATCH 041/255] fix: use ArgumentNullException for ecdsa parameter (#9858) --- src/Nethermind/Nethermind.TxPool/TxPoolSender.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.TxPool/TxPoolSender.cs b/src/Nethermind/Nethermind.TxPool/TxPoolSender.cs index 231156f560f..e201090e4e7 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPoolSender.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPoolSender.cs @@ -22,7 +22,7 @@ public TxPoolSender(ITxPool txPool, ITxSealer sealer, INonceManager nonceManager _txPool = txPool ?? throw new ArgumentNullException(nameof(txPool)); _sealer = sealer ?? throw new ArgumentNullException(nameof(sealer)); _nonceManager = nonceManager ?? throw new ArgumentNullException(nameof(nonceManager)); - _ecdsa = ecdsa ?? throw new ArgumentException(nameof(ecdsa)); + _ecdsa = ecdsa ?? throw new ArgumentNullException(nameof(ecdsa)); } public ValueTask<(Hash256, AcceptTxResult?)> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions) From dc4050d151308ca7b1fbf6ae0b5e9fc555de4f24 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Tue, 2 Dec 2025 14:24:01 +0300 Subject: [PATCH 042/255] Fix some spelling, add dictionary (#9850) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix some spelling, add dictionary * Fix bundle * Apply review feedback: fix typo and simplify test string (#9863) * Initial plan * Apply both suggestions: fix "Since" → "Sync" typo and simplify test string Co-authored-by: flcl42 <630501+flcl42@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: flcl42 <630501+flcl42@users.noreply.github.com> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: flcl42 <630501+flcl42@users.noreply.github.com> --- ...mpicTests.cs => DifficultyOlympicTests.cs} | 8 +- .../Ethereum.HexPrefix.Test/HexPrefixTests.cs | 2 +- .../EIP3651warmcoinbaseTests.cs | 2 +- .../LoadBlockchainTestsStrategy.cs | 6 +- .../LoadEipTestsStrategy.cs | 6 +- .../LoadEofTestsStrategy.cs | 6 +- .../LoadGeneralStateTestsStrategy.cs | 6 +- .../LoadLegacyBlockchainTestsStrategy.cs | 6 +- .../LoadLegacyGeneralStateTestsStrategy.cs | 6 +- .../TransactionTests.cs | 8 +- .../Ethereum.Trie.Test/Permutations.cs | 2 +- src/Nethermind/Nethermind.Abi/AbiUInt.cs | 4 +- .../Nethermind.AuRa.Test/AuRaPluginTests.cs | 2 +- .../ContractDataStoreWithLocalDataTests.cs | 2 +- .../Transactions/TxCertifierFilterTests.cs | 4 +- .../Validators/ContractBasedValidatorTests.cs | 2 +- .../Validators/MultiValidatorTests.cs | 2 +- .../Core/RecoverSignaturesBenchmark.cs | 4 +- .../Store/PatriciaTreeBenchmarks.cs | 2 +- .../BlockchainProcessorTests.cs | 2 +- .../BlockhashCacheTests.cs | 4 +- .../Filters/FilterStoreTests.cs | 2 +- .../Filters/LogFilterTests.cs | 14 +-- .../FullPruning/FullPruningDiskTest.cs | 2 +- .../GenesisBuilderTests.cs | 4 +- .../Receipts/PersistentReceiptStorageTests.cs | 8 +- .../TransactionProcessorEip7702Tests.cs | 6 +- .../Validators/UnclesValidatorTests.cs | 10 +- .../BlockTree.Initializer.cs | 2 +- .../Nethermind.Blockchain/BlockTree.cs | 2 +- .../Nethermind.Blockchain/Metrics.cs | 2 +- .../Receipts/PersistentReceiptStorage.cs | 2 +- .../Nethermind.Consensus.AuRa/AuRaPlugin.cs | 2 +- .../Rewards/AuRaRewardCalculator.cs | 2 +- .../Transactions/CompareTxByPriorityBase.cs | 4 +- .../Transactions/RandomContractTxSource.cs | 2 +- .../BlockExtenstionsTests.cs | 2 +- .../TargetAdjustedGasLimitCalculatorTests.cs | 2 +- .../Processing/BranchProcessor.cs | 8 +- .../Tracing/GethStyleTracer.cs | 2 +- .../Blockchain/TestBlockchain.cs | 4 +- .../Nethermind.Core.Test/BloomTests.cs | 4 +- .../Nethermind.Core.Test/BytesTests.cs | 2 +- .../CompactReceiptStorageDecoderTests.cs | 2 +- .../Modules/LocalChannelFactory.cs | 2 +- .../Modules/TestBlockProcessingModule.cs | 2 +- .../Modules/TestEnvironmentModule.cs | 2 +- .../Nethermind.Core.Test/TestRawTrieStore.cs | 2 +- .../ContainerBuilderExtensions.cs | 2 +- .../Nethermind.Core/Extensions/Bytes.cs | 6 +- .../Extensions/SpanExtensions.cs | 2 +- .../Extensions/SpecProviderExtensions.cs | 8 +- src/Nethermind/Nethermind.Core/SlotTime.cs | 4 +- .../Nethermind.Db.Rocks/Config/DbConfig.cs | 4 +- .../Statistics/DbMetricsUpdater.cs | 6 +- .../FullPruning/FullPruningDbTests.cs | 2 +- src/Nethermind/Nethermind.Db/IDbFactory.cs | 6 +- .../Nethermind.Db/IPruningConfig.cs | 2 +- .../Nethermind.Db/SimpleFilePublicKeyDb.cs | 2 +- .../Nethermind.Era1/AdminEraService.cs | 2 +- src/Nethermind/Nethermind.Era1/EraReader.cs | 6 +- .../EcRecoverPrecompile.cs | 4 +- .../BytecodeBuilderExtensionsTests.cs | 6 +- .../Nethermind.Evm.Test/Eip3860Tests.cs | 8 +- .../Nethermind.Evm.Test/EvmStateTests.cs | 2 +- .../Tracing/AccessTxTracerTests.cs | 6 +- .../Tracing/DebugTracerTests.cs | 12 +-- ...GethLikeTxTraceCollectionConverterTests.cs | 6 +- .../Tracing/Debugger/DebugTracer.cs | 2 +- ...usHelperTests.ReceiptsJsonRpcDataSource.cs | 16 ++-- .../Modules/DebugRpcModuleTests.cs | 6 +- .../Eth/EthRpcModuleTests.EstimateGas.cs | 6 +- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 6 +- .../Modules/TestRpcBlockchain.cs | 4 +- .../Modules/TraceRpcModuleTests.cs | 2 +- .../Modules/DebugModule/DebugBridge.cs | 4 +- .../Modules/DebugModule/DebugRpcModule.cs | 4 +- .../Modules/DebugModule/IDebugBridge.cs | 2 +- .../Modules/DebugModule/IDebugRpcModule.cs | 2 +- .../Eth/EthRpcModule.TransactionExecutor.cs | 4 +- .../Nethermind.Logging.NLog/NLogManager.cs | 4 +- .../AuRaMergeEngineModuleTests.cs | 2 +- .../EngineModuleTests.PayloadProduction.cs | 2 +- .../EngineModuleTests.RelayBuilder.cs | 2 +- .../EngineModuleTests.Synchronization.cs | 4 +- .../EngineModuleTests.V1.cs | 6 +- .../StartingSyncPivotUpdaterTests.cs | 4 +- .../Data/IExecutionPayloadParams.cs | 2 +- .../EngineRpcModule.Paris.cs | 2 +- .../EngineRpcModule.Prague.cs | 2 +- .../Handlers/NewPayloadHandler.cs | 2 +- .../Nethermind.Merge.Plugin/Metrics.cs | 4 +- .../V66/PooledTransactionsRequestingTests.cs | 4 +- .../Eth/V68/Eth68ProtocolHandlerTests.cs | 2 +- .../Eth/V63/Eth63ProtocolHandler.cs | 6 +- .../Eth/V66/Eth66ProtocolHandler.cs | 4 +- .../Nethermind.Runner/wwwroot/index.html | 4 +- .../Nethermind.Runner/wwwroot/js/bundle.js | 2 +- .../NethermindBuffers.cs | 2 +- .../TxDecoders/BlobTxDecoder.cs | 4 +- ...thermind.Serialization.SszGenerator.csproj | 2 +- .../SszProperty.cs | 6 +- .../ShutterBlockImprovementContext.cs | 2 +- .../Nethermind.Shutter/ShutterCrypto.cs | 4 +- .../Nethermind.Shutter/ShutterTxLoader.cs | 2 +- .../Nethermind.Shutter/ShutterTxSource.cs | 2 +- ...entites.cs => SlotDecryptionIdentities.cs} | 2 +- .../ChainSpecBasedSpecProviderTests.cs | 16 ++-- .../OverridableReleaseSpec.cs | 18 ++-- .../Nethermind.Specs/GnosisSpecProvider.cs | 8 +- .../Nethermind.State.Test/StateTreeTests.cs | 2 +- .../DisposableScopeOverridableEnv.cs | 2 +- .../FastBlocks/BodiesSyncFeedTests.cs | 6 +- .../FastBlocks/FastHeadersSyncTests.cs | 18 ++-- .../FastBlocks/ReceiptsSyncFeedTests.cs | 6 +- .../Trie/HealingTreeTests.cs | 2 +- .../Blocks/BlockDownloader.cs | 2 +- .../Blocks/PowForwardHeaderProvider.cs | 2 +- .../DbTuner/SyncDbOptimizer.cs | 2 +- .../FastSync/PendingSyncItems.cs | 2 +- .../Nethermind.Synchronization/Metrics.cs | 2 +- .../ParallelSync/MultiSyncModeSelector.cs | 2 +- .../Peers/SyncPeerExtensions.cs | 4 +- .../Reporting/SnapshotReport.cs | 2 +- .../SnapSync/ProgressTracker.cs | 6 +- .../SnapSync/SnapProvider.cs | 8 +- .../SnapSync/SnapProviderHelper.cs | 2 +- .../StateSync/StateSyncDownloader.cs | 6 +- .../Synchronizer.cs | 2 +- .../SurgeGasPriceOracleTests.cs | 2 +- .../TaikoEngineApiTests.cs | 4 +- .../TransactionProcessorTests.cs | 20 ++-- .../Nethermind.Taiko/TaikoBlockValidator.cs | 2 +- .../TaikoTransactionProcessor.cs | 4 +- .../Nethermind.Trie.Test/NodeStorageTests.cs | 2 +- .../OverlayTrieStoreTests.cs | 36 +++---- .../Pruning/TreeStoreTests.cs | 2 +- .../TrieNodeResolverWithReadFlagsTests.cs | 2 +- .../Nethermind.Trie.Test/VisitingTests.cs | 4 +- .../Nethermind.Trie/PatriciaTree.BulkSet.cs | 2 +- .../Nethermind.Trie/Pruning/TrieStore.cs | 34 +++---- .../Pruning/TrieStoreDirtyNodesCache.cs | 2 +- src/Nethermind/Nethermind.Trie/TrieNode.cs | 6 +- .../Nethermind.TxPool.Test/RetryCacheTests.cs | 2 +- .../Nethermind.TxPool.Test/TxPoolTests.cs | 2 +- .../Nethermind.TxPool/RetryCache.cs | 2 +- .../Nethermind.UI/package-lock.json | 1 + src/Nethermind/Nethermind.UI/scripts/app.ts | 2 +- .../ModuleTests/ProposedBlockTests.cs | 2 +- src/Nethermind/Nethermind.Xdc/XdcBlockTree.cs | 2 +- src/Nethermind/cspell.json | 95 +++++++++++++++++++ 151 files changed, 434 insertions(+), 338 deletions(-) rename src/Nethermind/Ethereum.Difficulty.Test/{DifficultyOlimpicTests.cs => DifficultyOlympicTests.cs} (67%) rename src/Nethermind/Nethermind.Shutter/{SlotDecryptionIdentites.cs => SlotDecryptionIdentities.cs} (93%) create mode 100644 src/Nethermind/cspell.json diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyOlimpicTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyOlympicTests.cs similarity index 67% rename from src/Nethermind/Ethereum.Difficulty.Test/DifficultyOlimpicTests.cs rename to src/Nethermind/Ethereum.Difficulty.Test/DifficultyOlympicTests.cs index 478be5ef5b3..12073260d84 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyOlimpicTests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyOlympicTests.cs @@ -7,15 +7,15 @@ namespace Ethereum.Difficulty.Test { [Parallelizable(ParallelScope.All)] - public class DifficultyOlimpicTests : TestsBase + public class DifficultyOlympicTests : TestsBase { - public static IEnumerable LoadOlimpicTests() + public static IEnumerable LoadOlympicTests() { - return LoadHex("difficultyOlimpic.json"); + return LoadHex("difficultyOlympic.json"); } // ToDo: fix loader - // [TestCaseSource(nameof(LoadOlimpicTests))] + // [TestCaseSource(nameof(LoadOlympicTests))] // public void Test(DifficultyTests test) // { // RunTest(test, new SingleReleaseSpecProvider(Olympic.Instance, 0)); diff --git a/src/Nethermind/Ethereum.HexPrefix.Test/HexPrefixTests.cs b/src/Nethermind/Ethereum.HexPrefix.Test/HexPrefixTests.cs index ceb9e13da4d..6cf38a0765e 100644 --- a/src/Nethermind/Ethereum.HexPrefix.Test/HexPrefixTests.cs +++ b/src/Nethermind/Ethereum.HexPrefix.Test/HexPrefixTests.cs @@ -16,7 +16,7 @@ namespace Ethereum.HexPrefix.Test public class HexPrefixTests { // ReSharper disable once MemberCanBePrivate.Global - // used as a test case source, hasbe public + // used as a test case source, has to be public public static IEnumerable LoadTests() { return TestLoader.LoadFromFile, HexPrefixTest>( diff --git a/src/Nethermind/Ethereum.Legacy.Blockchain.Test/EIP3651warmcoinbaseTests.cs b/src/Nethermind/Ethereum.Legacy.Blockchain.Test/EIP3651warmcoinbaseTests.cs index 98f363a2d60..d65b7fc7e71 100644 --- a/src/Nethermind/Ethereum.Legacy.Blockchain.Test/EIP3651warmcoinbaseTests.cs +++ b/src/Nethermind/Ethereum.Legacy.Blockchain.Test/EIP3651warmcoinbaseTests.cs @@ -9,7 +9,7 @@ namespace Ethereum.Blockchain.Legacy.Test; [TestFixture] [Parallelizable(ParallelScope.All)] -public class EIP3651warmcoinbaseTests : GeneralStateTestBase +public class EIP3651WarmCoinbaseTests : GeneralStateTestBase { [TestCaseSource(nameof(LoadTests))] public void Test(GeneralStateTest test) diff --git a/src/Nethermind/Ethereum.Test.Base/LoadBlockchainTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadBlockchainTestsStrategy.cs index 1e9a135021c..5c91a45ea1c 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadBlockchainTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadBlockchainTestsStrategy.cs @@ -24,13 +24,13 @@ public IEnumerable Load(string testsDirectoryName, string wildcard testDirs = new[] { testsDirectoryName }; } - List testJsons = new(); + List tests = new(); foreach (string testDir in testDirs) { - testJsons.AddRange(LoadTestsFromDirectory(testDir, wildcard)); + tests.AddRange(LoadTestsFromDirectory(testDir, wildcard)); } - return testJsons; + return tests; } private string GetBlockchainTestsDirectory() diff --git a/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs index 9cd12eed740..135cb457097 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs @@ -23,13 +23,13 @@ public IEnumerable Load(string testsDirectoryName, string wildcard testDirs = new[] { testsDirectoryName }; } - List testJsons = new(); + List tests = new(); foreach (string testDir in testDirs) { - testJsons.AddRange(LoadTestsFromDirectory(testDir, wildcard)); + tests.AddRange(LoadTestsFromDirectory(testDir, wildcard)); } - return testJsons; + return tests; } private string GetGeneralStateTestsDirectory() diff --git a/src/Nethermind/Ethereum.Test.Base/LoadEofTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadEofTestsStrategy.cs index a26ebf22a00..ea99491f854 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadEofTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadEofTestsStrategy.cs @@ -23,13 +23,13 @@ public IEnumerable Load(string testsDirectoryName, string wildcard testDirs = new[] { testsDirectoryName }; } - List testJsons = new(); + List tests = new(); foreach (string testDir in testDirs) { - testJsons.AddRange(LoadTestsFromDirectory(testDir, wildcard)); + tests.AddRange(LoadTestsFromDirectory(testDir, wildcard)); } - return testJsons; + return tests; } private string GetGeneralStateTestsDirectory() diff --git a/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestsStrategy.cs index 19334b8606f..564f4a0ea75 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestsStrategy.cs @@ -23,13 +23,13 @@ public IEnumerable Load(string testsDirectoryName, string wildcard testDirs = new[] { testsDirectoryName }; } - List testJsons = new(); + List tests = new(); foreach (string testDir in testDirs) { - testJsons.AddRange(LoadTestsFromDirectory(testDir, wildcard)); + tests.AddRange(LoadTestsFromDirectory(testDir, wildcard)); } - return testJsons; + return tests; } private string GetGeneralStateTestsDirectory() diff --git a/src/Nethermind/Ethereum.Test.Base/LoadLegacyBlockchainTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadLegacyBlockchainTestsStrategy.cs index 63dd6d9ca0f..ad5d8a85b6a 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadLegacyBlockchainTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadLegacyBlockchainTestsStrategy.cs @@ -24,13 +24,13 @@ public IEnumerable Load(string testsDirectoryName, string wildcard testDirs = new[] { testsDirectoryName }; } - List testJsons = new(); + List tests = new(); foreach (string testDir in testDirs) { - testJsons.AddRange(LoadTestsFromDirectory(testDir, wildcard)); + tests.AddRange(LoadTestsFromDirectory(testDir, wildcard)); } - return testJsons; + return tests; } private static string GetLegacyBlockchainTestsDirectory() diff --git a/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs index 60f964c0d9b..93670a28c31 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs @@ -24,13 +24,13 @@ public IEnumerable Load(string testsDirectoryName, string wildcard testDirs = new[] { testsDirectoryName }; } - List testJsons = new(); + List tests = new(); foreach (string testDir in testDirs) { - testJsons.AddRange(LoadTestsFromDirectory(testDir, wildcard)); + tests.AddRange(LoadTestsFromDirectory(testDir, wildcard)); } - return testJsons; + return tests; } private static string GetLegacyGeneralStateTestsDirectory() diff --git a/src/Nethermind/Ethereum.Transaction.Test/TransactionTests.cs b/src/Nethermind/Ethereum.Transaction.Test/TransactionTests.cs index 5995dfe0203..062eb09c296 100644 --- a/src/Nethermind/Ethereum.Transaction.Test/TransactionTests.cs +++ b/src/Nethermind/Ethereum.Transaction.Test/TransactionTests.cs @@ -31,11 +31,11 @@ private static IEnumerable LoadTests(string testSet) { Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory); IEnumerable testDirs = Directory.EnumerateDirectories(".", "tt" + testSet); - Dictionary> testJsons = + Dictionary> testJsonMap = new(); foreach (string testDir in testDirs) { - testJsons[testDir] = new Dictionary(); + testJsonMap[testDir] = new Dictionary(); IEnumerable testFiles = Directory.EnumerateFiles(testDir).ToList(); foreach (string testFile in testFiles) { @@ -43,13 +43,13 @@ private static IEnumerable LoadTests(string testSet) Dictionary testsInFile = JsonSerializer.Deserialize>(json); foreach (KeyValuePair namedTest in testsInFile) { - testJsons[testDir].Add(namedTest.Key, namedTest.Value); + testJsonMap[testDir].Add(namedTest.Key, namedTest.Value); } } } List tests = new(); - foreach (KeyValuePair> byDir in testJsons) + foreach (KeyValuePair> byDir in testJsonMap) { foreach (KeyValuePair byName in byDir.Value) { diff --git a/src/Nethermind/Ethereum.Trie.Test/Permutations.cs b/src/Nethermind/Ethereum.Trie.Test/Permutations.cs index 61aa35185af..ce54da79625 100644 --- a/src/Nethermind/Ethereum.Trie.Test/Permutations.cs +++ b/src/Nethermind/Ethereum.Trie.Test/Permutations.cs @@ -14,7 +14,7 @@ namespace Ethereum.Trie.Test public static class Permutations { /// - /// Heap's algorithm to find all pmermutations. Non recursive, more efficient. + /// Heap's algorithm to find all permutations. Non recursive, more efficient. /// /// Items to permute in each possible ways /// diff --git a/src/Nethermind/Nethermind.Abi/AbiUInt.cs b/src/Nethermind/Nethermind.Abi/AbiUInt.cs index 56dcdf62c4c..38dd9f4d4ee 100644 --- a/src/Nethermind/Nethermind.Abi/AbiUInt.cs +++ b/src/Nethermind/Nethermind.Abi/AbiUInt.cs @@ -24,7 +24,7 @@ public class AbiUInt : AbiType public static new readonly AbiUInt UInt96 = new(96); public static new readonly AbiUInt UInt256 = new(256); - private static readonly byte[][] PrealocatedBytes = + private static readonly byte[][] PreallocatedBytes = Enumerable.Range(0, 256).Select(x => new[] { (byte)x }).ToArray(); public AbiUInt(int length) @@ -109,7 +109,7 @@ public override byte[] Encode(object? arg, bool packed) } else if (arg is byte byteInput) { - bytes = PrealocatedBytes[byteInput]; + bytes = PreallocatedBytes[byteInput]; } else if (arg is JsonElement element && element.ValueKind == JsonValueKind.Number) { diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuRaPluginTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuRaPluginTests.cs index c5d7b358c46..1959871bfbf 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuRaPluginTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuRaPluginTests.cs @@ -27,7 +27,7 @@ namespace Nethermind.AuRa.Test public class AuRaPluginTests { [Test] - public void Init_when_not_AuRa_doesnt_trow() + public void Init_when_not_AuRa_does_not_throw() { ChainSpec chainSpec = new(); AuRaPlugin auRaPlugin = new(chainSpec); diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs index d9ec5662e3b..735267cdbb6 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs @@ -55,7 +55,7 @@ public void reloads_data_from_local_on_changed() } [Test] - public void doesnt_reload_data_from_local_when_changed_not_fired() + public void does_not_reload_data_from_local_when_changed_not_fired() { ILocalDataSource> localDataSource = Substitute.For>>(); Address[] expected = { TestItem.AddressA }; diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs index a2e4c6ae271..ed9cd9362e6 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs @@ -120,14 +120,14 @@ public async Task registry_contract_returns_correct_address() } [Test] - public async Task registry_contract_returns_not_found_when_key_doesnt_exist() + public async Task registry_contract_returns_not_found_when_key_does_not_exist() { using TestTxPermissionsBlockchain chain = await TestContractBlockchain.ForTest(); chain.RegisterContract.TryGetAddress(chain.BlockTree.Head.Header, "not existing key", out Address _).Should().BeFalse(); } [Test] - public async Task registry_contract_returns_not_found_when_contract_doesnt_exist() + public async Task registry_contract_returns_not_found_when_contract_does_not_exist() { using TestTxPermissionsBlockchain chain = await TestContractBlockchain.ForTest(); RegisterContract contract = new(AbiEncoder.Instance, Address.FromNumber(1000), chain.ReadOnlyTxProcessingEnvFactory.Create()); diff --git a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs index 53b92c06e85..e5659fadcd4 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs @@ -111,7 +111,7 @@ public void throws_ArgumentNullException_on_empty_validatorStore() } [Test] - public void throws_ArgumentNullException_on_empty_validSealearStrategy() + public void throws_ArgumentNullException_on_empty_validSealerStrategy() { Action act = () => new ContractBasedValidator(_validatorContract, _blockTree, _receiptsStorage, _validatorStore, null, _blockFinalizationManager, default, _logManager, 1); act.Should().Throw(); diff --git a/src/Nethermind/Nethermind.AuRa.Test/Validators/MultiValidatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Validators/MultiValidatorTests.cs index 45a7bda8c9a..b3e7b235a9c 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Validators/MultiValidatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Validators/MultiValidatorTests.cs @@ -140,7 +140,7 @@ long GetFinalizedIndex(int j) } [Test] - public void doesnt_call_inner_validators_before_start_block() + public void does_not_call_inner_validators_before_start_block() { // Arrange _validator.Validators.Remove(0); diff --git a/src/Nethermind/Nethermind.Benchmark/Core/RecoverSignaturesBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Core/RecoverSignaturesBenchmark.cs index 2ec1cd60b18..6e9ef8dfeca 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/RecoverSignaturesBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/RecoverSignaturesBenchmark.cs @@ -162,13 +162,13 @@ void ResetSigs(Block block) } [Benchmark] - public void Recover100TxSignatureswith100AuthoritySignatures() + public void Recover100TxSignaturesWith100AuthoritySignatures() { _sut.RecoverData(_block100TxWith100AuthSigs); } [Benchmark] - public void Recover100TxSignatureswith10AuthoritySignatures() + public void Recover100TxSignaturesWith10AuthoritySignatures() { _sut.RecoverData(_block100TxWith10AuthSigs); } diff --git a/src/Nethermind/Nethermind.Benchmark/Store/PatriciaTreeBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Store/PatriciaTreeBenchmarks.cs index 0155d6a36c0..01abd043137 100644 --- a/src/Nethermind/Nethermind.Benchmark/Store/PatriciaTreeBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Store/PatriciaTreeBenchmarks.cs @@ -138,7 +138,7 @@ public class PatriciaTreeBenchmarks Hash256 rootHash = tree.RootHash; tree.Commit(); }), - ("extenson_create_new_extension", tree => + ("extension_create_new_extension", tree => { tree.Set(new Hash256("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), _account0); tree.Set(new Hash256("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), _account1); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs index 17d9d5a0bc2..2b1e6c244b5 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs @@ -623,7 +623,7 @@ public void Can_change_branch_on_invalid_block() } [Test(Description = "Covering scenario when we have an invalid block followed by its descendants." + - "All the descandant blocks should get discarded and an alternative branch should get selected." + + "All the descendant blocks should get discarded and an alternative branch should get selected." + "BRANCH A | BLOCK 2 | INVALID | DISCARD" + "BRANCH A | BLOCK 3 | VALID | DISCARD" + "BRANCH A | BLOCK 4 | VALID | DISCARD" + diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs index e07dde4e3e8..cc79815311e 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs @@ -89,7 +89,7 @@ public void GetHash_handles_max_depth_of_256() } [Test] - public void GetHash_doesnt_go_beyond_depth_256() + public void GetHash_does_not_go_beyond_depth_256() { (BlockTree tree, BlockhashCache cache) = BuildTest(300); @@ -319,7 +319,7 @@ public async Task Prefetch_reuses_parent_data(int chainDepth) } [Test] - public async Task Doesnt_cache_cancelled_searches() + public async Task DoesNot_cache_cancelled_searches() { SlowHeaderStore headerStore = new(new HeaderStore(new MemDb(), new MemDb())); (BlockTree tree, BlockhashCache cache) = BuildTest(260, headerStore); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs index d6706b6a5e1..20d90ed8c3f 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs @@ -75,7 +75,7 @@ public void Remove_filter_removes_and_notifies() store.FilterRemoved += (s, e) => hasNotified = true; store.RemoveFilter(0); - Assert.That(hasNotified, Is.True, "notied"); + Assert.That(hasNotified, Is.True, "notified"); Assert.That(store.FilterExists(0), Is.False, "exists"); } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs index 27771f99a91..9d497daa7dd 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs @@ -121,7 +121,7 @@ public void complex_filter_matches_bloom() } [Test, MaxTime(Timeout.MaxTestTime)] - public void address_filter_doesnt_match_bloom() + public void address_filter_does_not_match_bloom() { LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithAddress(TestItem.AddressA) @@ -133,7 +133,7 @@ public void address_filter_doesnt_match_bloom() } [Test, MaxTime(Timeout.MaxTestTime)] - public void addresses_filter_doesnt_match_bloom() + public void addresses_filter_does_not_match_bloom() { LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithAddresses(TestItem.AddressA, TestItem.AddressB, TestItem.AddressC) @@ -145,7 +145,7 @@ public void addresses_filter_doesnt_match_bloom() } [Test, MaxTime(Timeout.MaxTestTime)] - public void specific_topics_filter_doesnt_match_bloom() + public void specific_topics_filter_does_not_match_bloom() { LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Specific(TestItem.KeccakC)) @@ -157,7 +157,7 @@ public void specific_topics_filter_doesnt_match_bloom() } [Test, MaxTime(Timeout.MaxTestTime)] - public void multiple_specific_topics_filter_doesnt_match_bloom() + public void multiple_specific_topics_filter_does_not_match_bloom() { LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Specific(TestItem.KeccakB)) @@ -169,7 +169,7 @@ public void multiple_specific_topics_filter_doesnt_match_bloom() } [Test, MaxTime(Timeout.MaxTestTime)] - public void or_topics_filter_doesnt_match_bloom() + public void or_topics_filter_does_not_match_bloom() { LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakA))) @@ -181,7 +181,7 @@ public void or_topics_filter_doesnt_match_bloom() } [Test, MaxTime(Timeout.MaxTestTime)] - public void complex_topics_filter_doesnt_match_bloom() + public void complex_topics_filter_does_not_match_bloom() { LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakA))) @@ -193,7 +193,7 @@ public void complex_topics_filter_doesnt_match_bloom() } [Test, MaxTime(Timeout.MaxTestTime)] - public void complex_filter_doesnt_match_bloom() + public void complex_filter_does_not_match_bloom() { LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakC))) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs index 5b1cec3e995..d28cf1ab7be 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs @@ -103,7 +103,7 @@ public static async Task Create(IPruningConfig? pruningCo PruningTestBlockchain chain = new() { PruningConfig = pruningConfig ?? new PruningConfig(), - TestTimout = testTimeoutMs, + TestTimeout = testTimeoutMs, }; await chain.Build(); return chain; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/GenesisBuilderTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/GenesisBuilderTests.cs index 75d56ac9c52..cc0607a1d8e 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/GenesisBuilderTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/GenesisBuilderTests.cs @@ -22,13 +22,13 @@ namespace Nethermind.Blockchain.Test; public class GenesisBuilderTests { [Test, MaxTime(Timeout.MaxTestTime)] - public void Can_load_genesis_with_emtpy_accounts_and_storage() + public void Can_load_genesis_with_empty_accounts_and_storage() { AssertBlockHash("0x61b2253366eab37849d21ac066b96c9de133b8c58a9a38652deae1dd7ec22e7b", "Specs/empty_accounts_and_storages.json"); } [Test, MaxTime(Timeout.MaxTestTime)] - public void Can_load_genesis_with_emtpy_accounts_and_code() + public void Can_load_genesis_with_empty_accounts_and_code() { AssertBlockHash("0xfa3da895e1c2a4d2673f60dd885b867d60fb6d823abaf1e5276a899d7e2feca5", "Specs/empty_accounts_and_codes.json"); } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs index fcf32a5ad08..31dc8039fcd 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs @@ -88,14 +88,14 @@ public void Returns_null_for_missing_tx() } [Test, MaxTime(Timeout.MaxTestTime)] - public void ReceiptsIterator_doesnt_throw_on_empty_span() + public void ReceiptsIterator_does_not_throw_on_empty_span() { _storage.TryGetReceiptsIterator(1, Keccak.Zero, out ReceiptsIterator iterator); iterator.TryGetNext(out _).Should().BeFalse(); } [Test, MaxTime(Timeout.MaxTestTime)] - public void ReceiptsIterator_doesnt_throw_on_null() + public void ReceiptsIterator_does_not_throw_on_null() { _receiptsDb.GetColumnDb(ReceiptsColumns.Blocks).Set(Keccak.Zero, null!); _storage.TryGetReceiptsIterator(1, Keccak.Zero, out ReceiptsIterator iterator); @@ -332,7 +332,7 @@ public void When_TxLookupLimitIs_NegativeOne_DoNotIndexTxHash() [TestCase(1L, false)] [TestCase(10L, false)] [TestCase(11L, true)] - public void Should_only_prune_index_tx_hashes_if_blockNumber_is_bigger_than_lookupLimit(long blockNumber, bool WillPruneOldIndicies) + public void Should_only_prune_index_tx_hashes_if_blockNumber_is_bigger_than_lookupLimit(long blockNumber, bool willPruneOldIndices) { _receiptConfig.TxLookupLimit = 10; CreateStorage(); @@ -340,7 +340,7 @@ public void Should_only_prune_index_tx_hashes_if_blockNumber_is_bigger_than_look Raise.EventWith(new BlockReplacementEventArgs(Build.A.Block.WithNumber(blockNumber).TestObject)); Assert.That(() => _blockTree.ReceivedCalls() .Where(static call => call.GetMethodInfo().Name.EndsWith(nameof(_blockTree.FindBlock))), - WillPruneOldIndicies ? Is.Not.Empty.After(100, 10) : Is.Empty.After(100, 10)); + willPruneOldIndices ? Is.Not.Empty.After(100, 10) : Is.Empty.After(100, 10)); } [Test] diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs index 5d782d07ce8..872ff2e15cd 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs @@ -457,7 +457,7 @@ public void Execute_FirstTxHasAuthorizedCodeThatIncrementsAndSecondDoesNot_Stora PrivateKey signer = TestItem.PrivateKeyB; Address codeSource = TestItem.AddressC; _stateProvider.CreateAccount(sender.Address, 1.Ether()); - //Increment 1 everytime it's called + // Increment by 1 every time it's called byte[] code = Prepare.EvmCode .Op(Instruction.PUSH0) .Op(Instruction.SLOAD) @@ -578,7 +578,7 @@ public void Execute_DelegatedCodeUsesEXTOPCODES_ReturnsExpectedValue(byte[] code public static IEnumerable EXTCODEHASHAccountSetup() { - yield return new object[] { static (IWorldState state, Address accountt) => + yield return new object[] { static (IWorldState state, Address account) => { //Account does not exists }, @@ -783,7 +783,7 @@ public static IEnumerable AccountAccessGasCases() }; } [TestCaseSource(nameof(AccountAccessGasCases))] - public void Execute_DiffentAccountAccessOpcodes_ChargesCorrectAccountAccessGas(byte[] code, long expectedGas, bool isDelegated, long gasLimit, bool shouldRunOutOfGas) + public void Execute_DifferentAccountAccessOpcodes_ChargesCorrectAccountAccessGas(byte[] code, long expectedGas, bool isDelegated, long gasLimit, bool shouldRunOutOfGas) { PrivateKey signer = TestItem.PrivateKeyA; PrivateKey sender = TestItem.PrivateKeyB; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs index cd97053ed70..06996065534 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs @@ -14,7 +14,7 @@ namespace Nethermind.Blockchain.Test.Validators; public class UnclesValidatorTests { - private Block _grandgrandparent; + private Block _greatGrandparent; private Block _grandparent; private Block _parent; private Block _block; @@ -27,9 +27,9 @@ public class UnclesValidatorTests public void Setup() { _blockTree = Build.A.BlockTree().OfChainLength(1).TestObject; - _grandgrandparent = _blockTree.FindBlock(0, BlockTreeLookupOptions.None)!; - _grandparent = Build.A.Block.WithParent(_grandgrandparent).TestObject; - _duplicateUncle = Build.A.Block.WithParent(_grandgrandparent).TestObject; + _greatGrandparent = _blockTree.FindBlock(0, BlockTreeLookupOptions.None)!; + _grandparent = Build.A.Block.WithParent(_greatGrandparent).TestObject; + _duplicateUncle = Build.A.Block.WithParent(_greatGrandparent).TestObject; _parent = Build.A.Block.WithParent(_grandparent).WithUncles(_duplicateUncle).TestObject; _block = Build.A.Block.WithParent(_parent).TestObject; @@ -142,7 +142,7 @@ public void Grandpas_brother_is_fine() { BlockHeader[] uncles = GetValidUncles(1); uncles[0].Number = _grandparent.Number; - uncles[0].ParentHash = _grandgrandparent.Hash; + uncles[0].ParentHash = _greatGrandparent.Hash; SetupHeaderValidator(uncles); UnclesValidator unclesValidator = new(_blockTree, _headerValidator, LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs index 5db48531903..3b2e7231c45 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs @@ -388,7 +388,7 @@ private void LoadSyncPivot() } SyncPivot = (updatedPivotBlockNumber, updatedPivotBlockHash); - _syncConfig.MaxAttemptsToUpdatePivot = 0; // Disable pivot updator + _syncConfig.MaxAttemptsToUpdatePivot = 0; // Disable pivot updater if (Logger.IsInfo) Logger.Info($"Pivot block has been set based on data from db. Pivot block number: {updatedPivotBlockNumber}, hash: {updatedPivotBlockHash}"); } diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs index b0f41e95cfd..74434364f79 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs @@ -1057,7 +1057,7 @@ private void TryUpdateSyncPivot() if (bestPersisted < newPivotHeader.Number) { - if (Logger.IsTrace) Logger.Trace("Best persisted is lower than sync pivot. Using best persisted stata as pivot."); + if (Logger.IsTrace) Logger.Trace("Best persisted is lower than sync pivot. Using best persisted state as pivot."); newPivotHeader = FindHeader(bestPersisted.Value, BlockTreeLookupOptions.RequireCanonical); } if (newPivotHeader is null) return; diff --git a/src/Nethermind/Nethermind.Blockchain/Metrics.cs b/src/Nethermind/Nethermind.Blockchain/Metrics.cs index 91864c136fb..648eac7402c 100644 --- a/src/Nethermind/Nethermind.Blockchain/Metrics.cs +++ b/src/Nethermind/Nethermind.Blockchain/Metrics.cs @@ -104,6 +104,6 @@ public static class Metrics [DetailedMetric] [ExponentialPowerHistogramMetric(Start = 100, Factor = 1.25, Count = 50)] - [Description("Histogram of block prorcessing time")] + [Description("Histogram of block processing time")] public static IMetricObserver BlockProcessingTimeMicros { get; set; } = new NoopMetricObserver(); } diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs index 5f2cbd74005..8658cb93301 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs @@ -76,7 +76,7 @@ private void BlockTreeOnBlockAddedToMain(object? sender, BlockReplacementEventAr EnsureCanonical(e.Block); NewCanonicalReceipts?.Invoke(this, e); - // Dont block main loop + // Don't block the main loop Task.Run(() => { Block newMain = e.Block; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaPlugin.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaPlugin.cs index 58b878a4478..08f737898b7 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaPlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaPlugin.cs @@ -135,7 +135,7 @@ protected override void Load(ContainerBuilder builder) } /// - /// Some validation component that is active in rpc and validation but not in block produccer. + /// Some validation component that is active in RPC and validation but not in block producer. /// /// /// diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Rewards/AuRaRewardCalculator.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Rewards/AuRaRewardCalculator.cs index 83dc02b25b2..6925261f4fa 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Rewards/AuRaRewardCalculator.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Rewards/AuRaRewardCalculator.cs @@ -68,7 +68,7 @@ public BlockReward[] CalculateRewards(Block block) private static BlockReward[] CalculateRewardsWithContract(Block block, IRewardContract contract) { - (Address[] beneficieries, ushort[] kinds) GetBeneficiaries() + (Address[] beneficiaries, ushort[] kinds) GetBeneficiaries() { var length = block.Uncles.Length + 1; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityBase.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityBase.cs index 84cda756fc6..058a25af08d 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityBase.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityBase.cs @@ -58,8 +58,8 @@ public int Compare(Transaction x, Transaction y) // we already have nonce ordered by previous code, we don't deal with it here // first order by whitelisted - int whitelistedComparision = IsWhiteListed(y).CompareTo(IsWhiteListed(x)); - if (whitelistedComparision != 0) return whitelistedComparision; + int whitelistedComparison = IsWhiteListed(y).CompareTo(IsWhiteListed(x)); + if (whitelistedComparison != 0) return whitelistedComparison; // then order by priority descending return GetPriority(y).CompareTo(GetPriority(x)); diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/RandomContractTxSource.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/RandomContractTxSource.cs index af820085092..c4dc44efa37 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/RandomContractTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/RandomContractTxSource.cs @@ -38,7 +38,7 @@ public RandomContractTxSource( IList contracts, IEciesCipher eciesCipher, ISigner signer, - IProtectedPrivateKey previousCryptoKey, // this is for backwards-compability when upgrading validator node + IProtectedPrivateKey previousCryptoKey, // this is for backwards-compatibility when upgrading validator node ICryptoRandom cryptoRandom, ILogManager logManager) { diff --git a/src/Nethermind/Nethermind.Consensus.Test/BlockExtenstionsTests.cs b/src/Nethermind/Nethermind.Consensus.Test/BlockExtenstionsTests.cs index 5c0cc4f82b4..a37dbe23e03 100644 --- a/src/Nethermind/Nethermind.Consensus.Test/BlockExtenstionsTests.cs +++ b/src/Nethermind/Nethermind.Consensus.Test/BlockExtenstionsTests.cs @@ -10,7 +10,7 @@ namespace Nethermind.Consensus.Test { - public class BlockExtenstionsTests + public class BlockExtensionsTests { [Test] public void Is_by_nethermind_node() diff --git a/src/Nethermind/Nethermind.Consensus.Test/TargetAdjustedGasLimitCalculatorTests.cs b/src/Nethermind/Nethermind.Consensus.Test/TargetAdjustedGasLimitCalculatorTests.cs index 882e58a7a4d..4761d0e9ee8 100644 --- a/src/Nethermind/Nethermind.Consensus.Test/TargetAdjustedGasLimitCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Consensus.Test/TargetAdjustedGasLimitCalculatorTests.cs @@ -49,7 +49,7 @@ public void Is_calculating_correct_gasLimit(long currentGasLimit, long targetGas } [Test] - public void Doesnt_go_below_minimum() + public void DoesNot_go_below_minimum() { int londonBlock = 5; long gasLimit = 5000; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs index 763baa9855c..a2742e38bfe 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs @@ -59,10 +59,10 @@ public Block[] Process(BlockHeader? baseBlock, IReadOnlyList suggestedBlo { if (baseBlock is null && suggestedBlock.IsGenesis) { - // Super special ultra mega - I dont wanna deal with this right now - special case where genesis is handled - // specially from outside where the state are added from `GenesisLoader` but not part of the block processor - // but it still pass through the blocktree suggest to blockchain processor event chain - // Meaning dont set state when handling genesis. + // Super special ultra mega – I don't want to deal with this right now – special case where genesis is handled + // externally, where the state is added via `GenesisLoader` but not processed by the block processor + // even though it still passes through the block tree suggest to blockchain processor event chain. + // Meaning don't set state when handling genesis. } else { diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs index 3a1bb9d7be6..83833ef5631 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs @@ -174,7 +174,7 @@ public IEnumerable TraceBadBlockToFile(Hash256 blockHash, GethTraceOptio // Previously, when the processing options is not `TraceTransaction`, the base block is the parent of the block // which is set by the `BranchProcessor`, which mean the state override probably does not take affect. - // However, when it is `TraceTransactioon`, it apply `ForceSameBlock` to `BlockchainProcessor` which will send the same + // However, when it is `TraceTransaction`, it applies `ForceSameBlock` to `BlockchainProcessor`, which will send the same // block as the baseBlock, which is important as the stateroot of the baseblock is modified in `BuildAndOverride`. // // Wild stuff! diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 092da63491e..8c427246dd4 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -51,7 +51,7 @@ namespace Nethermind.Core.Test.Blockchain; public class TestBlockchain : IDisposable { public const int DefaultTimeout = 10000; - protected long TestTimout { get; init; } = DefaultTimeout; + protected long TestTimeout { get; init; } = DefaultTimeout; public IStateReader StateReader => _fromContainer.StateReader; public IEthereumEcdsa EthereumEcdsa => _fromContainer.EthereumEcdsa; public INonceManager NonceManager => _fromContainer.NonceManager; @@ -391,7 +391,7 @@ public Block Build() protected virtual AutoCancelTokenSource CreateCancellationSource() { - return AutoCancelTokenSource.ThatCancelAfter(Debugger.IsAttached ? TimeSpan.FromMilliseconds(-1) : TimeSpan.FromMilliseconds(TestTimout)); + return AutoCancelTokenSource.ThatCancelAfter(Debugger.IsAttached ? TimeSpan.FromMilliseconds(-1) : TimeSpan.FromMilliseconds(TestTimeout)); } protected virtual async Task AddBlocksOnStart() diff --git a/src/Nethermind/Nethermind.Core.Test/BloomTests.cs b/src/Nethermind/Nethermind.Core.Test/BloomTests.cs index 231b6353f7b..18b11fbfa93 100644 --- a/src/Nethermind/Nethermind.Core.Test/BloomTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/BloomTests.cs @@ -38,7 +38,7 @@ public void matches_previously_added_item(int count, int topicMax) [TestCase(10, 1)] [TestCase(10, 10)] [TestCase(100, 1)] - public void doesnt_match_not_added_item(int count, int topicMax) + public void does_not_match_not_added_item(int count, int topicMax) { MatchingTest(() => GetLogEntries(count, topicMax), addedEntries => GetLogEntries(count, topicMax, @@ -46,7 +46,7 @@ public void doesnt_match_not_added_item(int count, int topicMax) } [Test] - public void empty_doesnt_match_any_item() + public void empty_does_not_match_any_item() { MatchingTest(Array.Empty, static addedEntries => GetLogEntries(100, 10), false); } diff --git a/src/Nethermind/Nethermind.Core.Test/BytesTests.cs b/src/Nethermind/Nethermind.Core.Test/BytesTests.cs index b4ddca6e783..f3371d834c1 100644 --- a/src/Nethermind/Nethermind.Core.Test/BytesTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/BytesTests.cs @@ -463,7 +463,7 @@ public void Xor(byte[] first, byte[] second, byte[] expected) } [Test] - public void NullableComparision() + public void NullableComparison() { Bytes.NullableEqualityComparer.Equals(null, null).Should().BeTrue(); } diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/CompactReceiptStorageDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/CompactReceiptStorageDecoderTests.cs index 6c63361f2b8..3b12e39b849 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/CompactReceiptStorageDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/CompactReceiptStorageDecoderTests.cs @@ -254,7 +254,7 @@ private void AssertStorageReceipt(TxReceipt txReceipt, TxReceipt? deserialized) Assert.That(deserialized?.StatusCode, Is.EqualTo(txReceipt.StatusCode), "status"); } - private void AssertStorageLegaxyReceipt(TxReceipt txReceipt, TxReceipt deserialized) + private void AssertStorageLegacyReceipt(TxReceipt txReceipt, TxReceipt deserialized) { Assert.That(deserialized.TxType, Is.EqualTo(txReceipt.TxType), "tx type"); Assert.That(deserialized.BlockHash, Is.EqualTo(txReceipt.BlockHash), "block hash"); diff --git a/src/Nethermind/Nethermind.Core.Test/Modules/LocalChannelFactory.cs b/src/Nethermind/Nethermind.Core.Test/Modules/LocalChannelFactory.cs index b25817faa58..f931caedcc0 100644 --- a/src/Nethermind/Nethermind.Core.Test/Modules/LocalChannelFactory.cs +++ b/src/Nethermind/Nethermind.Core.Test/Modules/LocalChannelFactory.cs @@ -90,7 +90,7 @@ protected override void DoBind(EndPoint localAddress) } } - // Needed because the default local address did not compare the id and because it need to be convertiable to + // Needed because the default local address did not compare the ID and because it needs to be convertible to // IPEndpoint private class NethermindLocalAddress(string id, IPEndPoint ipEndPoint) : LocalAddress(id), IIPEndpointSource { diff --git a/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs b/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs index 06098ae038c..ada4a68da99 100644 --- a/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs +++ b/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs @@ -20,7 +20,7 @@ protected override void Load(ContainerBuilder builder) { builder .AddSingleton() - // NOTE: The ordering of block preprocessor is not guarenteed + // NOTE: The ordering of block preprocessors is not guaranteed .AddComposite() .AddSingleton() .AddSingleton() diff --git a/src/Nethermind/Nethermind.Core.Test/Modules/TestEnvironmentModule.cs b/src/Nethermind/Nethermind.Core.Test/Modules/TestEnvironmentModule.cs index b9cd9fca88a..12d5c54a532 100644 --- a/src/Nethermind/Nethermind.Core.Test/Modules/TestEnvironmentModule.cs +++ b/src/Nethermind/Nethermind.Core.Test/Modules/TestEnvironmentModule.cs @@ -42,7 +42,7 @@ protected override void Load(ContainerBuilder builder) builder .AddSingleton(new TestLogManager(LogLevel.Error)) // Limbologs actually have IsTrace set to true, so actually slow. .AddSingleton((_) => new MemDbFactory()) - // These two dont use db provider + // These two don't use the DB provider .AddKeyedSingleton(DbNames.PeersDb, (_) => new MemDb()) .AddKeyedSingleton(DbNames.DiscoveryNodes, (_) => new MemDb()) .AddSingleton(networkConfig => new LocalChannelFactory(networkGroup ?? nameof(TestEnvironmentModule), networkConfig)) diff --git a/src/Nethermind/Nethermind.Core.Test/TestRawTrieStore.cs b/src/Nethermind/Nethermind.Core.Test/TestRawTrieStore.cs index a31eb627a2d..67e44e3e28f 100644 --- a/src/Nethermind/Nethermind.Core.Test/TestRawTrieStore.cs +++ b/src/Nethermind/Nethermind.Core.Test/TestRawTrieStore.cs @@ -44,7 +44,7 @@ public event EventHandler? ReorgBoundaryReached remove => throw new Exception("Unsupported operation"); } - public IReadOnlyKeyValueStore TrieNodeRlpStore => throw new Exception("Unsupported operatioon"); + public IReadOnlyKeyValueStore TrieNodeRlpStore => throw new Exception("Unsupported operation"); private Lock _scopeLock = new Lock(); private Lock _pruneLock = new Lock(); diff --git a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs index 9f80fe93011..512dea16d9b 100644 --- a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs +++ b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs @@ -371,7 +371,7 @@ public static ContainerBuilder Intercept(this ContainerBuilder builder, Actio } /// - /// A convenient way of creating a service whose member can be configured indipendent of other instance of the same + /// A convenient way of creating a service whose members can be configured independent of other instances of the same /// type (assuming the type is of lifetime scope). This is useful for same type with multiple configuration /// or a graph of multiple same type. The T is expected to be of a main container of sort that contains the /// main service of interest. diff --git a/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs b/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs index e6a5f23545b..8e395ecb720 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs @@ -722,7 +722,7 @@ public static void OutputBytesToByteHex(this ReadOnlySpan bytes, Span(ref output) = (byte)(val >> 8); @@ -779,7 +779,7 @@ public static void OutputBytesToCharHex(ref byte input, int length, ref char cha { skip++; // Odd number of hex chars, handle the first - // seperately so loop can work in pairs + // separately so loop can work in pairs uint val = Unsafe.Add(ref Lookup32[0], input); charsRef = (char)(val >> 16); @@ -1135,7 +1135,7 @@ public static void FromHexString(ReadOnlySpan hexString, Span result if (actualLength != result.Length) { - throw new ArgumentException($"Incorrect result lenght, expected {actualLength}", nameof(result)); + throw new ArgumentException($"Incorrect result length, expected {actualLength}", nameof(result)); } FromHexString(chars, result, oddMod); diff --git a/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs index 14ac04fe0fb..0c9c08b282e 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs @@ -132,7 +132,7 @@ private static string ToHexStringWithEip55Checksum(ReadOnlySpan bytes, boo if (odd) { // Odd number of hex chars, handle the first - // seperately so loop can work in pairs + // separately so loop can work in pairs uint val = lookup32[bytes[0]]; char char2 = (char)(val >> 16); chars[0] = char.IsLetter(char2) && hashHex[1] > '7' diff --git a/src/Nethermind/Nethermind.Core/Extensions/SpecProviderExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/SpecProviderExtensions.cs index b5205d18699..d1e0188dd5d 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/SpecProviderExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/SpecProviderExtensions.cs @@ -9,8 +9,8 @@ namespace Nethermind.Core.Extensions public static class SpecProviderExtensions { /// - /// this method is here only for getting spec related to receipts. - /// Reason of adding is that at sometime we dont know the Timestamp. + /// This method only retrieves the spec related to receipts. + /// Reason for adding it is that sometimes we don't know the timestamp. /// /// /// @@ -21,8 +21,8 @@ public static IReceiptSpec GetReceiptSpec(this ISpecProvider specProvider, long } /// - /// this method is here only for getting spec for 1559. - /// Reason of adding is that at sometime we dont know the Timestamp. + /// This method only retrieves the spec for 1559. + /// Reason for adding it is that sometimes we don't know the timestamp. /// /// /// diff --git a/src/Nethermind/Nethermind.Core/SlotTime.cs b/src/Nethermind/Nethermind.Core/SlotTime.cs index 147710f2854..c0d1e48f7eb 100644 --- a/src/Nethermind/Nethermind.Core/SlotTime.cs +++ b/src/Nethermind/Nethermind.Core/SlotTime.cs @@ -7,7 +7,7 @@ namespace Nethermind.Core; public class SlotTime(ulong genesisTimestampMs, ITimestamper timestamper, TimeSpan slotLength, TimeSpan blockUpToDateCutoff) { - public class SlotCalulationException(string message, Exception? innerException = null) : Exception(message, innerException); + public class SlotCalculationException(string message, Exception? innerException = null) : Exception(message, innerException); public readonly ulong GenesisTimestampMs = genesisTimestampMs; @@ -25,7 +25,7 @@ public ulong GetSlot(ulong slotTimestampMs) long slotTimeSinceGenesis = (long)slotTimestampMs - (long)GenesisTimestampMs; if (slotTimeSinceGenesis < 0) { - throw new SlotCalulationException($"Slot timestamp {slotTimestampMs}ms was before than genesis timestamp {GenesisTimestampMs}ms."); + throw new SlotCalculationException($"Slot timestamp {slotTimestampMs}ms was before than genesis timestamp {GenesisTimestampMs}ms."); } return (ulong)slotTimeSinceGenesis / (ulong)slotLength.TotalMilliseconds; diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs index b2b506b1d47..f0efb6213da 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs @@ -32,7 +32,7 @@ public class DbConfig : IDbConfig "memtable_whole_key_filtering=true;" + "memtable_prefix_bloom_size_ratio=0.02;" + - // Rocksdb turn this on by default a few release ago. But we dont want it yet, not sure the impact on read is + // Rocksdb turned this on by default a few releases ago, but we don't want it yet; the impact on reads is unclear // significant or not. "level_compaction_dynamic_level_bytes=false;" + @@ -248,7 +248,7 @@ public class DbConfig : IDbConfig "max_bytes_for_level_multiplier=10;" + "max_bytes_for_level_base=350000000;" + - // Change back file size multiplier as we dont want ridiculous file size, making compaction uneven, + // Change back file size multiplier as we don't want ridiculous file sizes making compaction uneven, // but set high base size. This mean a lot of file, but you are using archive mode, so this should be expected. "target_file_size_multiplier=1;" + "target_file_size_base=256000000;" + diff --git a/src/Nethermind/Nethermind.Db.Rocks/Statistics/DbMetricsUpdater.cs b/src/Nethermind/Nethermind.Db.Rocks/Statistics/DbMetricsUpdater.cs index db5ffcb1600..e541f05e099 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Statistics/DbMetricsUpdater.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Statistics/DbMetricsUpdater.cs @@ -89,7 +89,7 @@ public void ProcessCompactionStats(string compactionStatsString) if (!string.IsNullOrEmpty(compactionStatsString)) { ExtractStatsPerLevel(compactionStatsString); - ExctractIntervalCompaction(compactionStatsString); + ExtractIntervalCompaction(compactionStatsString); } else { @@ -137,7 +137,7 @@ private void ExtractStatsPerLevel(string compactionStatsDump) /// Example line: /// Interval compaction: 0.00 GB write, 0.00 MB/s write, 0.00 GB read, 0.00 MB/s read, 0.0 seconds /// - private void ExctractIntervalCompaction(string compactionStatsDump) + private void ExtractIntervalCompaction(string compactionStatsDump) { if (!string.IsNullOrEmpty(compactionStatsDump)) { @@ -154,7 +154,7 @@ private void ExctractIntervalCompaction(string compactionStatsDump) } else { - logger.Warn($"Cannot find 'Interval compaction' stats for {dbName} database in the compation stats dump:{Environment.NewLine}{compactionStatsDump}"); + logger.Warn($"Cannot find 'Interval compaction' stats for {dbName} database in the compaction stats dump:{Environment.NewLine}{compactionStatsDump}"); } } } diff --git a/src/Nethermind/Nethermind.Db.Test/FullPruning/FullPruningDbTests.cs b/src/Nethermind/Nethermind.Db.Test/FullPruning/FullPruningDbTests.cs index 7656307b45a..77cd44d8df1 100644 --- a/src/Nethermind/Nethermind.Db.Test/FullPruning/FullPruningDbTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/FullPruning/FullPruningDbTests.cs @@ -81,7 +81,7 @@ public void during_pruning_duplicate_on_read() } [Test] - public void during_pruning_dont_duplicate_read_with_skip_duplicate_read() + public void during_pruning_do_not_duplicate_read_with_skip_duplicate_read() { TestContext test = new(); byte[] key = { 1, 2 }; diff --git a/src/Nethermind/Nethermind.Db/IDbFactory.cs b/src/Nethermind/Nethermind.Db/IDbFactory.cs index 3a45f50e476..2ce63caca62 100644 --- a/src/Nethermind/Nethermind.Db/IDbFactory.cs +++ b/src/Nethermind/Nethermind.Db/IDbFactory.cs @@ -13,21 +13,21 @@ public interface IDbFactory /// /// Creates a standard Db. /// - /// Setting to use for DB creation. + /// Settings to use for DB creation. /// Standard DB. IDb CreateDb(DbSettings dbSettings); /// /// Creates a column Db. /// - /// Setting to use for DB creation. + /// Settings to use for DB creation. /// Column DB. IColumnsDb CreateColumnsDb(DbSettings dbSettings) where T : struct, Enum; /// /// Gets the file system path for the DB. /// - /// Setting to use for DB creation. + /// Settings to use for DB creation. /// File system path for the DB. public string GetFullDbPath(DbSettings dbSettings) => dbSettings.DbPath; } diff --git a/src/Nethermind/Nethermind.Db/IPruningConfig.cs b/src/Nethermind/Nethermind.Db/IPruningConfig.cs index b700e2e2066..476042605a3 100644 --- a/src/Nethermind/Nethermind.Db/IPruningConfig.cs +++ b/src/Nethermind/Nethermind.Db/IPruningConfig.cs @@ -92,7 +92,7 @@ The max number of parallel tasks that can be used by full pruning. [ConfigItem(Description = "Minimum persisted cache prune target", DefaultValue = "50000000")] long PrunePersistedNodeMinimumTarget { get; set; } - [ConfigItem(Description = "Maximimum number of block worth of unpersisted state in memory. Default is 297, which is number of mainnet block per hour.", DefaultValue = "297")] + [ConfigItem(Description = "Maximum number of blocks worth of unpersisted state in memory. Default is 297, which is the number of mainnet blocks per hour.", DefaultValue = "297")] long MaxUnpersistedBlockCount { get; set; } [ConfigItem(Description = "Minimum number of block worth of unpersisted state in memory. Prevent memory pruning too often due to insufficient dirty cache memory.", DefaultValue = "8")] diff --git a/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs b/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs index 979ff10526d..d69a532c873 100644 --- a/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs +++ b/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs @@ -240,7 +240,7 @@ private void LoadData() bytes = rentedBuffer.AsSpan(0, read + bytes.Length); while (true) { - // Store the original span incase need to undo the key slicing if end of line not found + // Store the original span in case we need to undo the key slicing when the end of line is not found Span iterationSpan = bytes; int commaIndex = bytes.IndexOf((byte)','); Span key = default; diff --git a/src/Nethermind/Nethermind.Era1/AdminEraService.cs b/src/Nethermind/Nethermind.Era1/AdminEraService.cs index 16eb9cc7144..d8e89290ae9 100644 --- a/src/Nethermind/Nethermind.Era1/AdminEraService.cs +++ b/src/Nethermind/Nethermind.Era1/AdminEraService.cs @@ -66,7 +66,7 @@ public string ImportHistory(string source, long from, long to, string? accumulat private async Task StartExportTask(string destination, long from, long to) { - // Creating the task is outside the try block so that argument exception can be cought + // Creating the task is outside the try block so that argument exceptions can be caught Task task = _eraExporter.Export( destination, from, diff --git a/src/Nethermind/Nethermind.Era1/EraReader.cs b/src/Nethermind/Nethermind.Era1/EraReader.cs index cb6d483355a..740d2167c6c 100644 --- a/src/Nethermind/Nethermind.Era1/EraReader.cs +++ b/src/Nethermind/Nethermind.Era1/EraReader.cs @@ -88,7 +88,7 @@ public async Task VerifyContent(ISpecProvider specProvider, IBlock if (!blockValidator.ValidateBodyAgainstHeader(err.Block.Header, err.Block.Body, out string? error)) { - throw new EraVerificationException($"Mismatched block body againts header: {error}. Block number {blockNumber}."); + throw new EraVerificationException($"Mismatched block body against header: {error}. Block number {blockNumber}."); } if (!blockValidator.ValidateOrphanedBlock(err.Block, out error)) @@ -178,8 +178,8 @@ private async Task ReadBlockAndReceipts(long blockNumber, bool position, static (buffer) => new UInt256(buffer.Span, isBigEndian: false), EntryTypes.TotalDifficulty, - out UInt256 currentTotalDiffulty); - header.TotalDifficulty = currentTotalDiffulty; + out UInt256 currentTotalDifficulty); + header.TotalDifficulty = currentTotalDifficulty; Block block = new Block(header, body); return new EntryReadResult(block, receipts); diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs index 666cc07d6bb..bf05bb4b396 100644 --- a/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs @@ -74,10 +74,10 @@ private Result RunInternal(ReadOnlySpan inputDataSpan) byte[] result = new byte[32]; KeccakHash.ComputeHashBytesToSpan(publicKey.Slice(1, 64), result); - ref byte refResut = ref MemoryMarshal.GetArrayDataReference(result); + ref byte refResult = ref MemoryMarshal.GetArrayDataReference(result); // Clear first 12 bytes, as address is last 20 bytes of the hash - Unsafe.InitBlockUnaligned(ref refResut, 0, 12); + Unsafe.InitBlockUnaligned(ref refResult, 0, 12); return result; } } diff --git a/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs b/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs index 0af189691f4..3a50b711b49 100644 --- a/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs @@ -24,7 +24,7 @@ public class TestCase public static MethodInfo GetFluentOpcodeFunction(Instruction opcode) { - static bool HasDigit(Instruction opcode, Instruction[] treatLikeSuffexedOpcode, Instruction[] treatLikeNonSuffexedOpcode, out int prefixLen, out string opcodeAsString) + static bool HasDigit(Instruction opcode, Instruction[] treatLikeSuffixedOpcode, Instruction[] treatLikeNonSuffixedOpcode, out int prefixLen, out string opcodeAsString) { // opcode with multiple indexes at the end like PUSH or DUP or SWAP are represented as one function // with the char 'x' instead of the number with one byte argument to diff i.g : PUSH32 => PUSHx(32, ...) @@ -32,13 +32,13 @@ static bool HasDigit(Instruction opcode, Instruction[] treatLikeSuffexedOpcode, prefixLen = opcodeAsString.Length; // STORE8 is excluded from filter and always returns false cause it is one of it own and has a function mapped directly to it - if (treatLikeSuffexedOpcode.Contains(opcode)) + if (treatLikeSuffixedOpcode.Contains(opcode)) { return false; } // CREATE is included from filter and always return true it is mapped to CREATE(byte) - if (treatLikeNonSuffexedOpcode.Contains(opcode)) + if (treatLikeNonSuffixedOpcode.Contains(opcode)) { return true; } diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs index 4e3b3223c7b..b02611c9107 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs @@ -49,13 +49,13 @@ public void Test_EIP_3860_GasCost_Create(string createCode, bool eip3860Enabled, [TestCase("60006000F5")] public void Test_EIP_3860_InitCode_Create_Exceeds_Limit(string createCode) { - string dataLenghtHex = (Spec.MaxInitCodeSize + 1).ToString("X"); - Instruction dataPush = Instruction.PUSH1 + (byte)(dataLenghtHex.Length / 2 - 1); + string dataLengthHex = (Spec.MaxInitCodeSize + 1).ToString("X"); + Instruction dataPush = Instruction.PUSH1 + (byte)(dataLengthHex.Length / 2 - 1); bool isCreate2 = createCode[^2..] == Instruction.CREATE2.ToString("X"); byte[] evmCode = isCreate2 - ? Prepare.EvmCode.PushSingle(0).FromCode(dataPush.ToString("X") + dataLenghtHex + createCode).Done - : Prepare.EvmCode.FromCode(dataPush.ToString("X") + dataLenghtHex + createCode).Done; + ? Prepare.EvmCode.PushSingle(0).FromCode(dataPush.ToString("X") + dataLengthHex + createCode).Done + : Prepare.EvmCode.FromCode(dataPush.ToString("X") + dataLengthHex + createCode).Done; TestState.CreateAccount(TestItem.AddressC, 1.Ether()); TestState.InsertCode(TestItem.AddressC, evmCode, Spec); diff --git a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs b/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs index f19ce925c27..f46d0d83437 100644 --- a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs @@ -194,7 +194,7 @@ public void Commit_adds_refunds() } [Test] - public void Restore_doesnt_add_refunds() + public void Restore_does_not_add_refunds() { EvmState parentEvmState = CreateEvmState(); using (EvmState evmState = CreateEvmState(parentEvmState)) diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs index 7be709f27d2..59fc7149053 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs @@ -75,7 +75,7 @@ public static IEnumerable OptimizedAddressCases } [TestCaseSource(nameof(OptimizedAddressCases))] - public void ReportAccess_AddressIsSetToOptmizedWithNoStorageCells_OnlyAddressesNotOptimizedIsInTheAccesslist(IEnumerable
optimized, IEnumerable
expected) + public void ReportAccess_AddressIsSetToOptimizedWithNoStorageCells_OnlyAddressesNotOptimizedIsInTheAccessList(IEnumerable
optimized, IEnumerable
expected) { JournalSet
accessedAddresses = [TestItem.AddressA, TestItem.AddressB]; JournalSet accessedStorageCells = []; @@ -87,7 +87,7 @@ public void ReportAccess_AddressIsSetToOptmizedWithNoStorageCells_OnlyAddressesN } [Test] - public void ReportAccess_AddressAIsSetToOptmizedAndHasStorageCell_AddressAAndBIsInTheAccesslist() + public void ReportAccess_AddressAIsSetToOptimizedAndHasStorageCell_AddressAAndBIsInTheAccessList() { JournalSet
accessedAddresses = [TestItem.AddressA, TestItem.AddressB]; JournalSet accessedStorageCells = [new StorageCell(TestItem.AddressA, 0)]; @@ -99,7 +99,7 @@ public void ReportAccess_AddressAIsSetToOptmizedAndHasStorageCell_AddressAAndBIs } [Test] - public void ReportAccess_AddressAIsSetToOptmizedAndHasStorageCell_AccesslistHasCorrectStorageCell() + public void ReportAccess_AddressAIsSetToOptimizedAndHasStorageCell_AccessListHasCorrectStorageCell() { JournalSet
accessedAddresses = [TestItem.AddressA, TestItem.AddressB]; JournalSet accessedStorageCells = [new StorageCell(TestItem.AddressA, 1)]; diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs index e53fd52c78a..65f4205c798 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs @@ -125,9 +125,9 @@ public void Debugger_Halts_Execution_On_Breakpoint_If_Condition_Is_True(string b } [TestCase("0x5b5b5b5b5b5b5b5b5b5b00")] - public void Debugger_Halts_Execution_On_Eeach_Iteration_using_StepByStepMode(string bytecodeHex) + public void Debugger_Halts_Execution_On_Each_Iteration_using_StepByStepMode(string bytecodeHex) { - // this bytecode is just a bunch of NOP/JUMPDEST, the idea is it will take as much bytes in the bytecode as steps to go throught it + // this bytecode is just a bunch of NOP/JUMPDEST; the idea is it will take as many bytes in the bytecode as steps to go through it byte[] bytecode = Bytes.FromHexString(bytecodeHex); using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) @@ -161,7 +161,7 @@ public void Debugger_Halts_Execution_On_Eeach_Iteration_using_StepByStepMode(str [TestCase("0x5b5b5b5b5b5b5b5b5b5b00")] public void Debugger_Skips_Single_Step_Breakpoints_When_MoveNext_Uses_Override(string bytecodeHex) { - // this bytecode is just a bunch of NOP/JUMPDEST, the idea is it will take as much bytes in the bytecode as steps to go throught it + // this bytecode is just a bunch of NOP/JUMPDEST; the idea is it will take as many bytes in the bytecode as steps to go through it byte[] bytecode = Bytes.FromHexString(bytecodeHex); using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) @@ -193,7 +193,7 @@ public void Debugger_Skips_Single_Step_Breakpoints_When_MoveNext_Uses_Override(s [TestCase("0x5b5b5b5b5b5b5b5b5b5b00")] public void Debugger_Switches_To_Single_Steps_After_First_Breakpoint(string bytecodeHex) { - // this bytecode is just a bunch of NOP/JUMPDEST, the idea is it will take as much bytes in the bytecode as steps to go throught it + // this bytecode is just a bunch of NOP/JUMPDEST; the idea is it will take as many bytes in the bytecode as steps to go through it byte[] bytecode = Bytes.FromHexString(bytecodeHex); (int depth, int pc) BREAKPOINT = (0, 5); @@ -435,7 +435,7 @@ public void Debugger_Halts_Execution_When_Global_Condition_Is_Met(string bytecod const int DATA_STACK_HEIGHT = 10; using DebugTracer tracer = new DebugTracer(GethLikeTxTracer); - tracer.SetCondtion(state => state.DataStackHead == DATA_STACK_HEIGHT); + tracer.SetCondition(state => state.DataStackHead == DATA_STACK_HEIGHT); Thread vmThread = new Thread(() => Execute(tracer, bytecode)); vmThread.Start(); @@ -455,7 +455,7 @@ public void Debugger_Halts_Execution_When_Global_Condition_Is_Met(string bytecod } [TestCase("0x5b601760005600")] - public void Debugger_Wont_Halt_If_Breakpoint_Is_Unreacheable(string bytecodeHex) + public void Debugger_Wont_Halt_If_Breakpoint_Is_Unreachable(string bytecodeHex) { byte[] bytecode = Bytes.FromHexString(bytecodeHex); diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxTraceCollectionConverterTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxTraceCollectionConverterTests.cs index b7d0959b0cf..289ca3592cc 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxTraceCollectionConverterTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxTraceCollectionConverterTests.cs @@ -32,7 +32,7 @@ public void Write_empty() Assert.That(result, Is.EqualTo("[]")); } - [TestCaseSource(nameof(TracesAndJsonsSource))] + [TestCaseSource(nameof(TraceAndJsonSource))] public void Write_with_traces_with_tx_hash(GethLikeTxTrace trace, string json) { var expected = $"""[{json}]"""; @@ -65,7 +65,7 @@ public void Read_empty() } - [TestCaseSource(nameof(TracesAndJsonsSource))] + [TestCaseSource(nameof(TraceAndJsonSource))] public void Read_with_traces(GethLikeTxTrace expectedTrace, string json) { var result = _serializer.Deserialize($"""[{json}]"""); @@ -79,7 +79,7 @@ public void Read_with_traces(GethLikeTxTrace expectedTrace, string json) }); } - private static IEnumerable TracesAndJsonsSource() + private static IEnumerable TraceAndJsonSource() { yield return [ new GethLikeTxTrace { Gas = 1, ReturnValue = [0x01], TxHash = null }, diff --git a/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs index e2d791ec8c9..c95c4576e8a 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs @@ -79,7 +79,7 @@ public void UnsetBreakPoint(int depth, int programCounter) } } - public void SetCondtion(Func? condition = null) + public void SetCondition(Func? condition = null) { if (CurrentPhase is DebugPhase.Blocked or DebugPhase.Starting) _globalBreakCondition = condition; } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs b/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs index 107c7b4f2f6..46318f1ac3c 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs @@ -22,28 +22,28 @@ public ReceiptsJsonRpcDataSource(Uri uri, IJsonSerializer serializer) : base(uri public Hash256 Parameter { get; set; } = null!; - public override async Task GetJsonData() => GetJson(await GetJsonDatas()); + public override async Task GetJsonData() => GetJson(await GetJsonPayloads()); - private string GetJson(IEnumerable jsons) => $"[{string.Join(',', jsons)}]"; + private string GetJson(IEnumerable jsonItems) => $"[{string.Join(',', jsonItems)}]"; - private async Task> GetJsonDatas() + private async Task> GetJsonPayloads() { JsonRpcRequest request = CreateRequest("eth_getBlockByHash", Parameter.ToString(), false); string blockJson = await SendRequest(request); BlockForRpcTxHashes block = _serializer.Deserialize>(blockJson).Result; - List transactionsJsons = new(block.Transactions!.Length); + List transactionJsonPayloads = new(block.Transactions!.Length); foreach (string tx in block.Transactions) { - transactionsJsons.Add(await SendRequest(CreateRequest("eth_getTransactionReceipt", tx))); + transactionJsonPayloads.Add(await SendRequest(CreateRequest("eth_getTransactionReceipt", tx))); } - return transactionsJsons; + return transactionJsonPayloads; } public override async Task<(IEnumerable, string)> GetData() { - IEnumerable receiptJsons = (await GetJsonDatas()).ToArray(); - return (receiptJsons.Select(j => _serializer.Deserialize>(j).Result), GetJson(receiptJsons)); + IEnumerable receiptJsonPayloads = (await GetJsonPayloads()).ToArray(); + return (receiptJsonPayloads.Select(j => _serializer.Deserialize>(j).Result), GetJson(receiptJsonPayloads)); } private class BlockForRpcTxHashes : BlockForRpc diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs index e5adef5fd85..b4d3b60fd4c 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs @@ -101,7 +101,7 @@ public async Task Debug_traceCall_runs_on_top_of_specified_block() "00000000000000000000000000000000000000000000003635c9adc5de9f09e5" )] [TestCase( - "Executes precompile using overriden address", + "Executes precompile using overridden address", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""", "000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099" @@ -126,12 +126,12 @@ public async Task Debug_traceCall_with_state_override(string name, string transa } [TestCase( - "When balance is overriden", + "When balance is overridden", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x100"}""", """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""" )] [TestCase( - "When address code is overriden", + "When address code is overridden", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" )] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs index a24af91894b..e44e58ce24b 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs @@ -318,7 +318,7 @@ public async Task should_estimate_transaction_with_deployed_code_when_eip3607_en """{"jsonrpc":"2.0","result":"0xabdd","id":67}""" // Store uint256 (cold access) + few other light instructions + intrinsic transaction cost )] [TestCase( - "Executes precompile using overriden address", + "Executes precompile using overridden address", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""", """{"jsonrpc":"2.0","result":"0x6440","id":67}""" // EcRecover call + intrinsic transaction cost @@ -337,12 +337,12 @@ public async Task Estimate_gas_with_state_override(string name, string transacti } [TestCase( - "When balance and nonce is overriden", + "When balance and nonce is overridden", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","value":"0x123"}""", """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x123", "nonce": "0x123"}}""" )] [TestCase( - "When address code is overriden", + "When address code is overridden", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0x60fe47b1112233445566778899001122334455667788990011223344556677889900112233445566778899001122"}""", """{"0xc200000000000000000000000000000000000000":{"code":"0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632a1afcd914603457806360fe47b114604d575b5f80fd5b603b5f5481565b60405190815260200160405180910390f35b605c6058366004605e565b5f55565b005b5f60208284031215606d575f80fd5b503591905056fea2646970667358221220fd4e5f3894be8e57fc7460afebb5c90d96c3486d79bf47b00c2ed666ab2f82b364736f6c634300081a0033"}}""" )] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index 7e509b1f037..0934acc45df 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -395,7 +395,7 @@ public async Task Eth_call_with_revert() """{"jsonrpc":"2.0","result":"0x00000000000000000000000000000000000000000000003635c9adc5de9f09e5","id":67}""" )] [TestCase( - "Executes precompile using overriden address", + "Executes precompile using overridden address", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""", """{"jsonrpc":"2.0","result":"0x000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099","id":67}""" @@ -413,12 +413,12 @@ public async Task Eth_call_with_state_override(string name, string transactionJs } [TestCase( - "When balance and nonce is overriden", + "When balance and nonce is overridden", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x1"}""", """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x123", "nonce": "0x123"}}""" )] [TestCase( - "When address code is overriden", + "When address code is overridden", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" )] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs index 921baa41f7c..a00b1905ef4 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs @@ -67,8 +67,8 @@ public class TestRpcBlockchain : TestBlockchain public IFeeHistoryOracle? FeeHistoryOracle { get; private set; } public static Builder ForTest(string sealEngineType, long? testTimeout = null) => ForTest(sealEngineType, testTimeout); - public static Builder ForTest(string sealEngineType, long? testTimout = null) where T : TestRpcBlockchain, new() => - new(new T { SealEngineType = sealEngineType, TestTimout = testTimout ?? DefaultTimeout }); + public static Builder ForTest(string sealEngineType, long? testTimeout = null) where T : TestRpcBlockchain, new() => + new(new T { SealEngineType = sealEngineType, TestTimeout = testTimeout ?? DefaultTimeout }); public static Builder ForTest(T blockchain) where T : TestRpcBlockchain => new(blockchain); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index 41e56ab82bd..479098fe41c 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -960,7 +960,7 @@ public async Task Trace_replayBlockTransactions_stateDiff() """{"jsonrpc":"2.0","result":{"output":null,"stateDiff":{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":{"\u002B":"0x0"},"code":"=","nonce":{"\u002B":"0x1"},"storage":{}},"0xc200000000000000000000000000000000000000":{"balance":"=","code":"=","nonce":"=","storage":{"0x0000000000000000000000000000000000000000000000000000000000000000":{"*":{"from":"0x0000000000000000000000000000000000000000000000000000000000123456","to":"0x1122334455667788990011223344556677889900112233445566778899001122"}}}}},"trace":[],"vmTrace":null},"id":67}""" )] [TestCase( - "Executes precompile using overriden address", + "Executes precompile using overridden address", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0x0000000000000000000000000000000000123456","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055","gas":"0xf4240"}""", "trace", """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0x0000000000000000000000000000000000123456", "code": "0x"}}""", diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs index 65cdf2cd9bf..988d0938a82 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs @@ -188,9 +188,9 @@ public IReadOnlyCollection GetBlockTrace(Block block, Cancellat public object GetConfigValue(string category, string name) => _configProvider.GetRawValue(category, name); - public SyncReportSymmary GetCurrentSyncStage() + public SyncReportSummary GetCurrentSyncStage() { - return new SyncReportSymmary + return new SyncReportSummary { CurrentStage = _syncModeSelector.Current.ToString() }; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs index 4a2a173485a..d4545358cfa 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs @@ -415,9 +415,9 @@ public ResultWrapper debug_getRawHeader(BlockParameter blockParameter) return ResultWrapper.Success(rlp.Bytes); } - public Task> debug_getSyncStage() + public Task> debug_getSyncStage() { - return ResultWrapper.Success(debugBridge.GetCurrentSyncStage()); + return ResultWrapper.Success(debugBridge.GetCurrentSyncStage()); } public ResultWrapper> debug_standardTraceBlockToFile(Hash256 blockHash, GethTraceOptions options = null) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs index f74639c01ba..331859fa10c 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs @@ -33,7 +33,7 @@ public interface IDebugBridge void UpdateHeadBlock(Hash256 blockHash); Task MigrateReceipts(long from, long to); void InsertReceipts(BlockParameter blockParameter, TxReceipt[] receipts); - SyncReportSymmary GetCurrentSyncStage(); + SyncReportSummary GetCurrentSyncStage(); bool HaveNotSyncedHeadersYet(); IEnumerable TraceBlockToFile(Hash256 blockHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); IEnumerable TraceBadBlockToFile(Hash256 blockHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs index aa9421b5908..d5f2d5f3939 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs @@ -104,7 +104,7 @@ public interface IDebugRpcModule : IRpcModule ResultWrapper debug_getRawTransaction(Hash256 transactionHash); [JsonRpcMethod(Description = "Retrives Nethermind Sync Stage, With extra Metadata")] - Task> debug_getSyncStage(); + Task> debug_getSyncStage(); [JsonRpcMethod(Description = "Writes to a file the full stack trace of all invoked opcodes of the transaction specified (or all transactions if not specified) that was included in the block specified. The parent of the block must be present or it will fail.", IsImplemented = true, IsSharable = false)] diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs index 3e1ab8a41d6..f731ae4786e 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs @@ -42,7 +42,7 @@ private abstract class TxExecutor(IBlockchainBridge blockchainBridge, I return ZeroMaxFeePerGasError; if (eip1559Transaction.MaxFeePerGas < eip1559Transaction.MaxPriorityFeePerGas) - return MaxFeePerGasSmallerThenMaxPriorityFeePerGasError( + return MaxFeePerGasSmallerThanMaxPriorityFeePerGasError( eip1559Transaction.MaxFeePerGas, eip1559Transaction.MaxPriorityFeePerGas); } @@ -138,7 +138,7 @@ protected ResultWrapper CreateResultWrapper(bool inputError, string? er private const string MissingToInBlobTxError = "missing \"to\" in blob transaction"; private const string ZeroMaxFeePerBlobGasError = "maxFeePerBlobGas, if specified, must be non-zero"; private const string ZeroMaxFeePerGasError = "maxFeePerGas must be non-zero"; - private static string MaxFeePerGasSmallerThenMaxPriorityFeePerGasError( + private static string MaxFeePerGasSmallerThanMaxPriorityFeePerGasError( UInt256? maxFeePerGas, UInt256? maxPriorityFeePerGas) => $"maxFeePerGas ({maxFeePerGas}) < maxPriorityFeePerGas ({maxPriorityFeePerGas})"; diff --git a/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs b/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs index 4497f7cf048..150e27b716b 100644 --- a/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs +++ b/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs @@ -101,7 +101,7 @@ private static void SetupLogRules(string logRules) IEnumerable loggingRules = ParseRules(logRules, targets); foreach (LoggingRule loggingRule in loggingRules) { - RemoveOverridenRules(configurationLoggingRules, loggingRule); + RemoveOverriddenRules(configurationLoggingRules, loggingRule); configurationLoggingRules.Add(loggingRule); } } @@ -111,7 +111,7 @@ private static void SetupLogRules(string logRules) private static Target[] GetTargets(IList configurationLoggingRules) => configurationLoggingRules.SelectMany(static r => r.Targets).Distinct().ToArray(); - private static void RemoveOverridenRules(IList configurationLoggingRules, LoggingRule loggingRule) + private static void RemoveOverriddenRules(IList configurationLoggingRules, LoggingRule loggingRule) { string reqexPattern = $"^{loggingRule.LoggerNamePattern.Replace(".", "\\.").Replace("*", ".*")}$"; for (int j = 0; j < configurationLoggingRules.Count;) diff --git a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs index 5a281b2097d..bb9b788da75 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs @@ -139,7 +139,7 @@ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder, .AddDecorator((ctx, api) => { // Yes getting from `TestBlockchain` itself, since steps are not run - // and some of these are not from DI. you know... chicken and egg, but dont forgot about rooster. + // and some of these are not from DI. you know... chicken and egg, but don't forget about the rooster. api.TxPool = TxPool; api.TransactionComparerProvider = TransactionComparerProvider; api.FinalizationManager = Substitute.For(); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.PayloadProduction.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.PayloadProduction.cs index ac451d5cab7..8e91862ee53 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.PayloadProduction.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.PayloadProduction.cs @@ -483,7 +483,7 @@ public async Task TestTwoTransaction_SameContract_WithBlockImprovement() [Test] [Retry(3)] - public async Task getPayloadV1_doesnt_wait_for_improvement_when_block_is_not_empty() + public async Task getPayloadV1_does_not_wait_for_improvement_when_block_is_not_empty() { TimeSpan delay = TimeSpan.FromMilliseconds(10); TimeSpan timePerSlot = 50 * delay; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.RelayBuilder.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.RelayBuilder.cs index 7291adf8344..241e3ab6f9c 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.RelayBuilder.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.RelayBuilder.cs @@ -107,7 +107,7 @@ public virtual async Task forkchoiceUpdatedV1_should_communicate_with_boost_rela .WithContent("{\"timestamp\":\"0x3e8\",\"prevRandao\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"suggestedFeeRecipient\":\"0x0000000000000000000000000000000000000000\"}") .Respond("application/json", "{\"timestamp\":\"0x3e9\",\"prevRandao\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"suggestedFeeRecipient\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\"}"); - //TODO: think about extracting an essely serialisable class, test its serializatoin sepratly, refactor with it similar methods like the one above + // TODO: extract an easily serializable class, test its serialization separately, and refactor similar methods like the one above var expected_parentHash = parentHash; var expected_feeRecipient = "0xb7705ae4c6f81b66cdb323c65f4e8133690fc099"; var expected_stateRoot = "0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f"; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs index 0d04a8ac427..e3fff19a3d5 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs @@ -91,7 +91,7 @@ public async Task forkChoiceUpdatedV1_unknown_block_initiates_syncing() } [Test] - public async Task forkChoiceUpdatedV1_unknown_block_without_newpayload_initiates_syncing() + public async Task forkChoiceUpdatedV1_unknown_block_without_newPayload_initiates_syncing() { using MergeTestBlockchain chain = await CreateBlockchain(); IEngineRpcModule rpc = chain.EngineRpcModule; @@ -137,7 +137,7 @@ public async Task forkChoiceUpdatedV1_unknown_block_without_newpayload_initiates } [Test] - public async Task forkChoiceUpdatedV1_unknown_block_without_newpayload_and_peer_timeout__it_does_not_initiates_syncing() + public async Task forkChoiceUpdatedV1_unknown_block_without_newPayload_and_peer_timeout__it_does_not_initiate_syncing() { using MergeTestBlockchain chain = await CreateBlockchain(); IEngineRpcModule rpc = chain.EngineRpcModule; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs index fd73ea05442..bc10ea8e5b6 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs @@ -441,14 +441,14 @@ public async Task executePayloadV1_rejects_block_with_invalid_receiptsRoot() } [Test] - public async Task executePayloadV1_result_is_fail_when_blockchainprocessor_report_exception() + public async Task executePayloadV1_result_is_fail_when_blockchain_processor_reports_exception() { using MergeTestBlockchain chain = await CreateBaseBlockchain() .Build(new TestSingleReleaseSpecProvider(London.Instance)); IEngineRpcModule rpc = chain.EngineRpcModule; ((TestBranchProcessorInterceptor)chain.BranchProcessor).ExceptionToThrow = - new Exception("unxpected exception"); + new Exception("unexpected exception"); ExecutionPayload executionPayload = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV1(executionPayload); @@ -729,7 +729,7 @@ public async Task Invalid_block_on_processing_wont_be_accepted_if_sent_twice_in_ chain.ReadOnlyState.GetBalance(TestItem.AddressA).Should().BeGreaterThan(UInt256.One); // block is an invalid block, but it is impossible to detect until we process it. - // it is invalid because after you processs its transactions, the root of the state trie + // it is invalid because after you process its transactions, the root of the state trie // doesn't match the state root in the block Block? block = Build.A.Block .WithNumber(head.Number + 1) diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/StartingSyncPivotUpdaterTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/StartingSyncPivotUpdaterTests.cs index f9e6227d24b..969bc1bb607 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/StartingSyncPivotUpdaterTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/StartingSyncPivotUpdaterTests.cs @@ -49,7 +49,7 @@ public void Setup() ISyncPeer? fakePeer = Substitute.For(); fakePeer.GetHeadBlockHeader(default, default).ReturnsForAnyArgs(x => _externalPeerBlockTree!.Head!.Header); - // for unsafe pivot updator + // for unsafe pivot updater Hash256 pivotHash = _externalPeerBlockTree!.FindLevel(35)!.BlockInfos[0].BlockHash; fakePeer.GetBlockHeaders(35, 1, 0, default).ReturnsForAnyArgs(x => _externalPeerBlockTree!.FindHeaders(pivotHash, 1, 0, default)); @@ -102,7 +102,7 @@ public void TrySetFreshPivot_saves_FinalizedHash_in_db() } [Test] - public void TrySetFreshPivot_for_unsafe_updator_saves_pivot_64_blocks_behind_HeadBlockHash_in_db() + public void TrySetFreshPivot_for_unsafe_updater_saves_pivot_64_blocks_behind_HeadBlockHash_in_db() { _ = new UnsafeStartingSyncPivotUpdater( _blockTree!, diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/IExecutionPayloadParams.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/IExecutionPayloadParams.cs index c15857d0000..1932720394e 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/IExecutionPayloadParams.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/IExecutionPayloadParams.cs @@ -20,7 +20,7 @@ public enum ValidationResult : byte { Success, Fail, Invalid }; public class ExecutionPayloadParams(byte[][]? executionRequests = null) { /// - /// Gets or sets as defined in + /// Gets or sets as defined in /// EIP-7685. /// public byte[][]? ExecutionRequests { get; set; } = executionRequests; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs index 38856536a0b..59989242ae3 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs @@ -52,7 +52,7 @@ protected async Task> ForkchoiceUpdated } finally { - Metrics.ForkchoiceUpdedExecutionTime = (long)Stopwatch.GetElapsedTime(startTime).TotalMilliseconds; + Metrics.ForkchoiceUpdatedExecutionTime = (long)Stopwatch.GetElapsedTime(startTime).TotalMilliseconds; _locker.Release(); } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Prague.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Prague.cs index 126011ca6b8..c72cccbb3ab 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Prague.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Prague.cs @@ -15,7 +15,7 @@ public partial class EngineRpcModule : IEngineRpcModule readonly IAsyncHandler _getPayloadHandlerV4; /// - /// Method parameter list is extended with parameter. + /// Method parameter list is extended with parameter. /// EIP-7685. /// public Task> engine_newPayloadV4(ExecutionPayloadV3 executionPayload, byte[]?[] blobVersionedHashes, Hash256? parentBeaconBlockRoot, byte[][]? executionRequests) diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs index d9143e6d2d8..6230f7ef444 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs @@ -364,7 +364,7 @@ ValidationResult TryCacheResult(ValidationResult result, string? errorMessage) // been suggested. there are three possibilities, either the block hasn't been processed yet, // the block was processed and returned invalid but this wasn't saved anywhere or the block was // processed and marked as valid. - // if marked as processed by the blocktree then return VALID, otherwise null so that it's process a few lines below + // if marked as processed by the block tree then return VALID, otherwise null so that it's processed a few lines below AddBlockResult.AlreadyKnown => _blockTree.WasProcessed(block.Number, block.Hash!) ? ValidationResult.Valid : null, _ => null }; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Metrics.cs b/src/Nethermind/Nethermind.Merge.Plugin/Metrics.cs index 752459cfcd3..809c2c29137 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Metrics.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Metrics.cs @@ -14,8 +14,8 @@ public static class Metrics public static long NewPayloadExecutionTime { get; set; } [GaugeMetric] - [Description("ForkchoiceUpded request execution time")] - public static long ForkchoiceUpdedExecutionTime { get; set; } + [Description("ForkchoiceUpdated request execution time")] + public static long ForkchoiceUpdatedExecutionTime { get; set; } [CounterMetric] [Description("Number of GetPayload Requests")] diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsRequestingTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsRequestingTests.cs index 6bbf7ace5c0..65667733805 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsRequestingTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsRequestingTests.cs @@ -150,7 +150,7 @@ public void TearDown() } [Test] - public async Task Should_request_from_others_after_timout() + public async Task Should_request_from_others_after_timeout() { await Task.Delay(Timeout); @@ -170,7 +170,7 @@ public async Task Should_not_request_from_others_if_received() [Test] - public async Task Should_not_request_from_others_if_received_immidietly() + public async Task Should_not_request_from_others_if_received_immediately() { HandleZeroMessage(_handler, new Network.P2P.Subprotocols.Eth.V66.Messages.PooledTransactionsMessage(1111, new PooledTransactionsMessage(_txs)), Eth65MessageCode.PooledTransactions); await Task.Delay(Timeout); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs index 657350833df..12d64964220 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs @@ -127,7 +127,7 @@ public void Can_handle_NewPooledTransactions_message([Values(0, 1, 2, 100)] int [TestCase(true)] [TestCase(false)] - public void Should_throw_when_sizes_doesnt_match(bool removeSize) + public void Should_throw_when_sizes_do_not_match(bool removeSize) { GenerateLists(4, out ArrayPoolList types, out ArrayPoolList sizes, out ArrayPoolList hashes); diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandler.cs index 2dc39f7e537..56777942fd9 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandler.cs @@ -112,7 +112,7 @@ public override Task> GetNodeData(IReadOnlyList> SendRequest(GetNodeDataMessag { if (Logger.IsTrace) { - Logger.Trace("Sending node fata request:"); + Logger.Trace("Sending node data request:"); Logger.Trace($"Keys count: {message.Hashes.Count}"); } @@ -149,7 +149,7 @@ protected virtual Task> SendRequest(GetNodeDataMessag { if (Logger.IsTrace) { - Logger.Trace("Sending node fata request:"); + Logger.Trace("Sending receipts request:"); Logger.Trace($"Hashes count: {message.Hashes.Count}"); } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandler.cs index 99ea83e9892..dc0adcb8bab 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandler.cs @@ -221,7 +221,7 @@ protected override async Task> SendRequest(V63.Messag { if (Logger.IsTrace) { - Logger.Trace("Sending node fata request:"); + Logger.Trace("Sending node data request:"); Logger.Trace($"Keys count: {message.Hashes.Count}"); } @@ -239,7 +239,7 @@ protected override async Task> SendRequest(V63.Messag { if (Logger.IsTrace) { - Logger.Trace("Sending node fata request:"); + Logger.Trace("Sending receipts request:"); Logger.Trace($"Hashes count: {message.Hashes.Count}"); } diff --git a/src/Nethermind/Nethermind.Runner/wwwroot/index.html b/src/Nethermind/Nethermind.Runner/wwwroot/index.html index c9e34b49e66..7f826e8faca 100644 --- a/src/Nethermind/Nethermind.Runner/wwwroot/index.html +++ b/src/Nethermind/Nethermind.Runner/wwwroot/index.html @@ -90,8 +90,8 @@
Max: MB
-
-
Lastest Block
+
+
Latest Block
Not Synced
Gas Target
diff --git a/src/Nethermind/Nethermind.Runner/wwwroot/js/bundle.js b/src/Nethermind/Nethermind.Runner/wwwroot/js/bundle.js index 05cbff79ae1..2bcc888ebfe 100644 --- a/src/Nethermind/Nethermind.Runner/wwwroot/js/bundle.js +++ b/src/Nethermind/Nethermind.Runner/wwwroot/js/bundle.js @@ -1,6 +1,6 @@ (()=>{var Ct=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var ai=Ct((KS,mh)=>{mh.exports={Aacute:"\xC1",aacute:"\xE1",Abreve:"\u0102",abreve:"\u0103",ac:"\u223E",acd:"\u223F",acE:"\u223E\u0333",Acirc:"\xC2",acirc:"\xE2",acute:"\xB4",Acy:"\u0410",acy:"\u0430",AElig:"\xC6",aelig:"\xE6",af:"\u2061",Afr:"\u{1D504}",afr:"\u{1D51E}",Agrave:"\xC0",agrave:"\xE0",alefsym:"\u2135",aleph:"\u2135",Alpha:"\u0391",alpha:"\u03B1",Amacr:"\u0100",amacr:"\u0101",amalg:"\u2A3F",amp:"&",AMP:"&",andand:"\u2A55",And:"\u2A53",and:"\u2227",andd:"\u2A5C",andslope:"\u2A58",andv:"\u2A5A",ang:"\u2220",ange:"\u29A4",angle:"\u2220",angmsdaa:"\u29A8",angmsdab:"\u29A9",angmsdac:"\u29AA",angmsdad:"\u29AB",angmsdae:"\u29AC",angmsdaf:"\u29AD",angmsdag:"\u29AE",angmsdah:"\u29AF",angmsd:"\u2221",angrt:"\u221F",angrtvb:"\u22BE",angrtvbd:"\u299D",angsph:"\u2222",angst:"\xC5",angzarr:"\u237C",Aogon:"\u0104",aogon:"\u0105",Aopf:"\u{1D538}",aopf:"\u{1D552}",apacir:"\u2A6F",ap:"\u2248",apE:"\u2A70",ape:"\u224A",apid:"\u224B",apos:"'",ApplyFunction:"\u2061",approx:"\u2248",approxeq:"\u224A",Aring:"\xC5",aring:"\xE5",Ascr:"\u{1D49C}",ascr:"\u{1D4B6}",Assign:"\u2254",ast:"*",asymp:"\u2248",asympeq:"\u224D",Atilde:"\xC3",atilde:"\xE3",Auml:"\xC4",auml:"\xE4",awconint:"\u2233",awint:"\u2A11",backcong:"\u224C",backepsilon:"\u03F6",backprime:"\u2035",backsim:"\u223D",backsimeq:"\u22CD",Backslash:"\u2216",Barv:"\u2AE7",barvee:"\u22BD",barwed:"\u2305",Barwed:"\u2306",barwedge:"\u2305",bbrk:"\u23B5",bbrktbrk:"\u23B6",bcong:"\u224C",Bcy:"\u0411",bcy:"\u0431",bdquo:"\u201E",becaus:"\u2235",because:"\u2235",Because:"\u2235",bemptyv:"\u29B0",bepsi:"\u03F6",bernou:"\u212C",Bernoullis:"\u212C",Beta:"\u0392",beta:"\u03B2",beth:"\u2136",between:"\u226C",Bfr:"\u{1D505}",bfr:"\u{1D51F}",bigcap:"\u22C2",bigcirc:"\u25EF",bigcup:"\u22C3",bigodot:"\u2A00",bigoplus:"\u2A01",bigotimes:"\u2A02",bigsqcup:"\u2A06",bigstar:"\u2605",bigtriangledown:"\u25BD",bigtriangleup:"\u25B3",biguplus:"\u2A04",bigvee:"\u22C1",bigwedge:"\u22C0",bkarow:"\u290D",blacklozenge:"\u29EB",blacksquare:"\u25AA",blacktriangle:"\u25B4",blacktriangledown:"\u25BE",blacktriangleleft:"\u25C2",blacktriangleright:"\u25B8",blank:"\u2423",blk12:"\u2592",blk14:"\u2591",blk34:"\u2593",block:"\u2588",bne:"=\u20E5",bnequiv:"\u2261\u20E5",bNot:"\u2AED",bnot:"\u2310",Bopf:"\u{1D539}",bopf:"\u{1D553}",bot:"\u22A5",bottom:"\u22A5",bowtie:"\u22C8",boxbox:"\u29C9",boxdl:"\u2510",boxdL:"\u2555",boxDl:"\u2556",boxDL:"\u2557",boxdr:"\u250C",boxdR:"\u2552",boxDr:"\u2553",boxDR:"\u2554",boxh:"\u2500",boxH:"\u2550",boxhd:"\u252C",boxHd:"\u2564",boxhD:"\u2565",boxHD:"\u2566",boxhu:"\u2534",boxHu:"\u2567",boxhU:"\u2568",boxHU:"\u2569",boxminus:"\u229F",boxplus:"\u229E",boxtimes:"\u22A0",boxul:"\u2518",boxuL:"\u255B",boxUl:"\u255C",boxUL:"\u255D",boxur:"\u2514",boxuR:"\u2558",boxUr:"\u2559",boxUR:"\u255A",boxv:"\u2502",boxV:"\u2551",boxvh:"\u253C",boxvH:"\u256A",boxVh:"\u256B",boxVH:"\u256C",boxvl:"\u2524",boxvL:"\u2561",boxVl:"\u2562",boxVL:"\u2563",boxvr:"\u251C",boxvR:"\u255E",boxVr:"\u255F",boxVR:"\u2560",bprime:"\u2035",breve:"\u02D8",Breve:"\u02D8",brvbar:"\xA6",bscr:"\u{1D4B7}",Bscr:"\u212C",bsemi:"\u204F",bsim:"\u223D",bsime:"\u22CD",bsolb:"\u29C5",bsol:"\\",bsolhsub:"\u27C8",bull:"\u2022",bullet:"\u2022",bump:"\u224E",bumpE:"\u2AAE",bumpe:"\u224F",Bumpeq:"\u224E",bumpeq:"\u224F",Cacute:"\u0106",cacute:"\u0107",capand:"\u2A44",capbrcup:"\u2A49",capcap:"\u2A4B",cap:"\u2229",Cap:"\u22D2",capcup:"\u2A47",capdot:"\u2A40",CapitalDifferentialD:"\u2145",caps:"\u2229\uFE00",caret:"\u2041",caron:"\u02C7",Cayleys:"\u212D",ccaps:"\u2A4D",Ccaron:"\u010C",ccaron:"\u010D",Ccedil:"\xC7",ccedil:"\xE7",Ccirc:"\u0108",ccirc:"\u0109",Cconint:"\u2230",ccups:"\u2A4C",ccupssm:"\u2A50",Cdot:"\u010A",cdot:"\u010B",cedil:"\xB8",Cedilla:"\xB8",cemptyv:"\u29B2",cent:"\xA2",centerdot:"\xB7",CenterDot:"\xB7",cfr:"\u{1D520}",Cfr:"\u212D",CHcy:"\u0427",chcy:"\u0447",check:"\u2713",checkmark:"\u2713",Chi:"\u03A7",chi:"\u03C7",circ:"\u02C6",circeq:"\u2257",circlearrowleft:"\u21BA",circlearrowright:"\u21BB",circledast:"\u229B",circledcirc:"\u229A",circleddash:"\u229D",CircleDot:"\u2299",circledR:"\xAE",circledS:"\u24C8",CircleMinus:"\u2296",CirclePlus:"\u2295",CircleTimes:"\u2297",cir:"\u25CB",cirE:"\u29C3",cire:"\u2257",cirfnint:"\u2A10",cirmid:"\u2AEF",cirscir:"\u29C2",ClockwiseContourIntegral:"\u2232",CloseCurlyDoubleQuote:"\u201D",CloseCurlyQuote:"\u2019",clubs:"\u2663",clubsuit:"\u2663",colon:":",Colon:"\u2237",Colone:"\u2A74",colone:"\u2254",coloneq:"\u2254",comma:",",commat:"@",comp:"\u2201",compfn:"\u2218",complement:"\u2201",complexes:"\u2102",cong:"\u2245",congdot:"\u2A6D",Congruent:"\u2261",conint:"\u222E",Conint:"\u222F",ContourIntegral:"\u222E",copf:"\u{1D554}",Copf:"\u2102",coprod:"\u2210",Coproduct:"\u2210",copy:"\xA9",COPY:"\xA9",copysr:"\u2117",CounterClockwiseContourIntegral:"\u2233",crarr:"\u21B5",cross:"\u2717",Cross:"\u2A2F",Cscr:"\u{1D49E}",cscr:"\u{1D4B8}",csub:"\u2ACF",csube:"\u2AD1",csup:"\u2AD0",csupe:"\u2AD2",ctdot:"\u22EF",cudarrl:"\u2938",cudarrr:"\u2935",cuepr:"\u22DE",cuesc:"\u22DF",cularr:"\u21B6",cularrp:"\u293D",cupbrcap:"\u2A48",cupcap:"\u2A46",CupCap:"\u224D",cup:"\u222A",Cup:"\u22D3",cupcup:"\u2A4A",cupdot:"\u228D",cupor:"\u2A45",cups:"\u222A\uFE00",curarr:"\u21B7",curarrm:"\u293C",curlyeqprec:"\u22DE",curlyeqsucc:"\u22DF",curlyvee:"\u22CE",curlywedge:"\u22CF",curren:"\xA4",curvearrowleft:"\u21B6",curvearrowright:"\u21B7",cuvee:"\u22CE",cuwed:"\u22CF",cwconint:"\u2232",cwint:"\u2231",cylcty:"\u232D",dagger:"\u2020",Dagger:"\u2021",daleth:"\u2138",darr:"\u2193",Darr:"\u21A1",dArr:"\u21D3",dash:"\u2010",Dashv:"\u2AE4",dashv:"\u22A3",dbkarow:"\u290F",dblac:"\u02DD",Dcaron:"\u010E",dcaron:"\u010F",Dcy:"\u0414",dcy:"\u0434",ddagger:"\u2021",ddarr:"\u21CA",DD:"\u2145",dd:"\u2146",DDotrahd:"\u2911",ddotseq:"\u2A77",deg:"\xB0",Del:"\u2207",Delta:"\u0394",delta:"\u03B4",demptyv:"\u29B1",dfisht:"\u297F",Dfr:"\u{1D507}",dfr:"\u{1D521}",dHar:"\u2965",dharl:"\u21C3",dharr:"\u21C2",DiacriticalAcute:"\xB4",DiacriticalDot:"\u02D9",DiacriticalDoubleAcute:"\u02DD",DiacriticalGrave:"`",DiacriticalTilde:"\u02DC",diam:"\u22C4",diamond:"\u22C4",Diamond:"\u22C4",diamondsuit:"\u2666",diams:"\u2666",die:"\xA8",DifferentialD:"\u2146",digamma:"\u03DD",disin:"\u22F2",div:"\xF7",divide:"\xF7",divideontimes:"\u22C7",divonx:"\u22C7",DJcy:"\u0402",djcy:"\u0452",dlcorn:"\u231E",dlcrop:"\u230D",dollar:"$",Dopf:"\u{1D53B}",dopf:"\u{1D555}",Dot:"\xA8",dot:"\u02D9",DotDot:"\u20DC",doteq:"\u2250",doteqdot:"\u2251",DotEqual:"\u2250",dotminus:"\u2238",dotplus:"\u2214",dotsquare:"\u22A1",doublebarwedge:"\u2306",DoubleContourIntegral:"\u222F",DoubleDot:"\xA8",DoubleDownArrow:"\u21D3",DoubleLeftArrow:"\u21D0",DoubleLeftRightArrow:"\u21D4",DoubleLeftTee:"\u2AE4",DoubleLongLeftArrow:"\u27F8",DoubleLongLeftRightArrow:"\u27FA",DoubleLongRightArrow:"\u27F9",DoubleRightArrow:"\u21D2",DoubleRightTee:"\u22A8",DoubleUpArrow:"\u21D1",DoubleUpDownArrow:"\u21D5",DoubleVerticalBar:"\u2225",DownArrowBar:"\u2913",downarrow:"\u2193",DownArrow:"\u2193",Downarrow:"\u21D3",DownArrowUpArrow:"\u21F5",DownBreve:"\u0311",downdownarrows:"\u21CA",downharpoonleft:"\u21C3",downharpoonright:"\u21C2",DownLeftRightVector:"\u2950",DownLeftTeeVector:"\u295E",DownLeftVectorBar:"\u2956",DownLeftVector:"\u21BD",DownRightTeeVector:"\u295F",DownRightVectorBar:"\u2957",DownRightVector:"\u21C1",DownTeeArrow:"\u21A7",DownTee:"\u22A4",drbkarow:"\u2910",drcorn:"\u231F",drcrop:"\u230C",Dscr:"\u{1D49F}",dscr:"\u{1D4B9}",DScy:"\u0405",dscy:"\u0455",dsol:"\u29F6",Dstrok:"\u0110",dstrok:"\u0111",dtdot:"\u22F1",dtri:"\u25BF",dtrif:"\u25BE",duarr:"\u21F5",duhar:"\u296F",dwangle:"\u29A6",DZcy:"\u040F",dzcy:"\u045F",dzigrarr:"\u27FF",Eacute:"\xC9",eacute:"\xE9",easter:"\u2A6E",Ecaron:"\u011A",ecaron:"\u011B",Ecirc:"\xCA",ecirc:"\xEA",ecir:"\u2256",ecolon:"\u2255",Ecy:"\u042D",ecy:"\u044D",eDDot:"\u2A77",Edot:"\u0116",edot:"\u0117",eDot:"\u2251",ee:"\u2147",efDot:"\u2252",Efr:"\u{1D508}",efr:"\u{1D522}",eg:"\u2A9A",Egrave:"\xC8",egrave:"\xE8",egs:"\u2A96",egsdot:"\u2A98",el:"\u2A99",Element:"\u2208",elinters:"\u23E7",ell:"\u2113",els:"\u2A95",elsdot:"\u2A97",Emacr:"\u0112",emacr:"\u0113",empty:"\u2205",emptyset:"\u2205",EmptySmallSquare:"\u25FB",emptyv:"\u2205",EmptyVerySmallSquare:"\u25AB",emsp13:"\u2004",emsp14:"\u2005",emsp:"\u2003",ENG:"\u014A",eng:"\u014B",ensp:"\u2002",Eogon:"\u0118",eogon:"\u0119",Eopf:"\u{1D53C}",eopf:"\u{1D556}",epar:"\u22D5",eparsl:"\u29E3",eplus:"\u2A71",epsi:"\u03B5",Epsilon:"\u0395",epsilon:"\u03B5",epsiv:"\u03F5",eqcirc:"\u2256",eqcolon:"\u2255",eqsim:"\u2242",eqslantgtr:"\u2A96",eqslantless:"\u2A95",Equal:"\u2A75",equals:"=",EqualTilde:"\u2242",equest:"\u225F",Equilibrium:"\u21CC",equiv:"\u2261",equivDD:"\u2A78",eqvparsl:"\u29E5",erarr:"\u2971",erDot:"\u2253",escr:"\u212F",Escr:"\u2130",esdot:"\u2250",Esim:"\u2A73",esim:"\u2242",Eta:"\u0397",eta:"\u03B7",ETH:"\xD0",eth:"\xF0",Euml:"\xCB",euml:"\xEB",euro:"\u20AC",excl:"!",exist:"\u2203",Exists:"\u2203",expectation:"\u2130",exponentiale:"\u2147",ExponentialE:"\u2147",fallingdotseq:"\u2252",Fcy:"\u0424",fcy:"\u0444",female:"\u2640",ffilig:"\uFB03",fflig:"\uFB00",ffllig:"\uFB04",Ffr:"\u{1D509}",ffr:"\u{1D523}",filig:"\uFB01",FilledSmallSquare:"\u25FC",FilledVerySmallSquare:"\u25AA",fjlig:"fj",flat:"\u266D",fllig:"\uFB02",fltns:"\u25B1",fnof:"\u0192",Fopf:"\u{1D53D}",fopf:"\u{1D557}",forall:"\u2200",ForAll:"\u2200",fork:"\u22D4",forkv:"\u2AD9",Fouriertrf:"\u2131",fpartint:"\u2A0D",frac12:"\xBD",frac13:"\u2153",frac14:"\xBC",frac15:"\u2155",frac16:"\u2159",frac18:"\u215B",frac23:"\u2154",frac25:"\u2156",frac34:"\xBE",frac35:"\u2157",frac38:"\u215C",frac45:"\u2158",frac56:"\u215A",frac58:"\u215D",frac78:"\u215E",frasl:"\u2044",frown:"\u2322",fscr:"\u{1D4BB}",Fscr:"\u2131",gacute:"\u01F5",Gamma:"\u0393",gamma:"\u03B3",Gammad:"\u03DC",gammad:"\u03DD",gap:"\u2A86",Gbreve:"\u011E",gbreve:"\u011F",Gcedil:"\u0122",Gcirc:"\u011C",gcirc:"\u011D",Gcy:"\u0413",gcy:"\u0433",Gdot:"\u0120",gdot:"\u0121",ge:"\u2265",gE:"\u2267",gEl:"\u2A8C",gel:"\u22DB",geq:"\u2265",geqq:"\u2267",geqslant:"\u2A7E",gescc:"\u2AA9",ges:"\u2A7E",gesdot:"\u2A80",gesdoto:"\u2A82",gesdotol:"\u2A84",gesl:"\u22DB\uFE00",gesles:"\u2A94",Gfr:"\u{1D50A}",gfr:"\u{1D524}",gg:"\u226B",Gg:"\u22D9",ggg:"\u22D9",gimel:"\u2137",GJcy:"\u0403",gjcy:"\u0453",gla:"\u2AA5",gl:"\u2277",glE:"\u2A92",glj:"\u2AA4",gnap:"\u2A8A",gnapprox:"\u2A8A",gne:"\u2A88",gnE:"\u2269",gneq:"\u2A88",gneqq:"\u2269",gnsim:"\u22E7",Gopf:"\u{1D53E}",gopf:"\u{1D558}",grave:"`",GreaterEqual:"\u2265",GreaterEqualLess:"\u22DB",GreaterFullEqual:"\u2267",GreaterGreater:"\u2AA2",GreaterLess:"\u2277",GreaterSlantEqual:"\u2A7E",GreaterTilde:"\u2273",Gscr:"\u{1D4A2}",gscr:"\u210A",gsim:"\u2273",gsime:"\u2A8E",gsiml:"\u2A90",gtcc:"\u2AA7",gtcir:"\u2A7A",gt:">",GT:">",Gt:"\u226B",gtdot:"\u22D7",gtlPar:"\u2995",gtquest:"\u2A7C",gtrapprox:"\u2A86",gtrarr:"\u2978",gtrdot:"\u22D7",gtreqless:"\u22DB",gtreqqless:"\u2A8C",gtrless:"\u2277",gtrsim:"\u2273",gvertneqq:"\u2269\uFE00",gvnE:"\u2269\uFE00",Hacek:"\u02C7",hairsp:"\u200A",half:"\xBD",hamilt:"\u210B",HARDcy:"\u042A",hardcy:"\u044A",harrcir:"\u2948",harr:"\u2194",hArr:"\u21D4",harrw:"\u21AD",Hat:"^",hbar:"\u210F",Hcirc:"\u0124",hcirc:"\u0125",hearts:"\u2665",heartsuit:"\u2665",hellip:"\u2026",hercon:"\u22B9",hfr:"\u{1D525}",Hfr:"\u210C",HilbertSpace:"\u210B",hksearow:"\u2925",hkswarow:"\u2926",hoarr:"\u21FF",homtht:"\u223B",hookleftarrow:"\u21A9",hookrightarrow:"\u21AA",hopf:"\u{1D559}",Hopf:"\u210D",horbar:"\u2015",HorizontalLine:"\u2500",hscr:"\u{1D4BD}",Hscr:"\u210B",hslash:"\u210F",Hstrok:"\u0126",hstrok:"\u0127",HumpDownHump:"\u224E",HumpEqual:"\u224F",hybull:"\u2043",hyphen:"\u2010",Iacute:"\xCD",iacute:"\xED",ic:"\u2063",Icirc:"\xCE",icirc:"\xEE",Icy:"\u0418",icy:"\u0438",Idot:"\u0130",IEcy:"\u0415",iecy:"\u0435",iexcl:"\xA1",iff:"\u21D4",ifr:"\u{1D526}",Ifr:"\u2111",Igrave:"\xCC",igrave:"\xEC",ii:"\u2148",iiiint:"\u2A0C",iiint:"\u222D",iinfin:"\u29DC",iiota:"\u2129",IJlig:"\u0132",ijlig:"\u0133",Imacr:"\u012A",imacr:"\u012B",image:"\u2111",ImaginaryI:"\u2148",imagline:"\u2110",imagpart:"\u2111",imath:"\u0131",Im:"\u2111",imof:"\u22B7",imped:"\u01B5",Implies:"\u21D2",incare:"\u2105",in:"\u2208",infin:"\u221E",infintie:"\u29DD",inodot:"\u0131",intcal:"\u22BA",int:"\u222B",Int:"\u222C",integers:"\u2124",Integral:"\u222B",intercal:"\u22BA",Intersection:"\u22C2",intlarhk:"\u2A17",intprod:"\u2A3C",InvisibleComma:"\u2063",InvisibleTimes:"\u2062",IOcy:"\u0401",iocy:"\u0451",Iogon:"\u012E",iogon:"\u012F",Iopf:"\u{1D540}",iopf:"\u{1D55A}",Iota:"\u0399",iota:"\u03B9",iprod:"\u2A3C",iquest:"\xBF",iscr:"\u{1D4BE}",Iscr:"\u2110",isin:"\u2208",isindot:"\u22F5",isinE:"\u22F9",isins:"\u22F4",isinsv:"\u22F3",isinv:"\u2208",it:"\u2062",Itilde:"\u0128",itilde:"\u0129",Iukcy:"\u0406",iukcy:"\u0456",Iuml:"\xCF",iuml:"\xEF",Jcirc:"\u0134",jcirc:"\u0135",Jcy:"\u0419",jcy:"\u0439",Jfr:"\u{1D50D}",jfr:"\u{1D527}",jmath:"\u0237",Jopf:"\u{1D541}",jopf:"\u{1D55B}",Jscr:"\u{1D4A5}",jscr:"\u{1D4BF}",Jsercy:"\u0408",jsercy:"\u0458",Jukcy:"\u0404",jukcy:"\u0454",Kappa:"\u039A",kappa:"\u03BA",kappav:"\u03F0",Kcedil:"\u0136",kcedil:"\u0137",Kcy:"\u041A",kcy:"\u043A",Kfr:"\u{1D50E}",kfr:"\u{1D528}",kgreen:"\u0138",KHcy:"\u0425",khcy:"\u0445",KJcy:"\u040C",kjcy:"\u045C",Kopf:"\u{1D542}",kopf:"\u{1D55C}",Kscr:"\u{1D4A6}",kscr:"\u{1D4C0}",lAarr:"\u21DA",Lacute:"\u0139",lacute:"\u013A",laemptyv:"\u29B4",lagran:"\u2112",Lambda:"\u039B",lambda:"\u03BB",lang:"\u27E8",Lang:"\u27EA",langd:"\u2991",langle:"\u27E8",lap:"\u2A85",Laplacetrf:"\u2112",laquo:"\xAB",larrb:"\u21E4",larrbfs:"\u291F",larr:"\u2190",Larr:"\u219E",lArr:"\u21D0",larrfs:"\u291D",larrhk:"\u21A9",larrlp:"\u21AB",larrpl:"\u2939",larrsim:"\u2973",larrtl:"\u21A2",latail:"\u2919",lAtail:"\u291B",lat:"\u2AAB",late:"\u2AAD",lates:"\u2AAD\uFE00",lbarr:"\u290C",lBarr:"\u290E",lbbrk:"\u2772",lbrace:"{",lbrack:"[",lbrke:"\u298B",lbrksld:"\u298F",lbrkslu:"\u298D",Lcaron:"\u013D",lcaron:"\u013E",Lcedil:"\u013B",lcedil:"\u013C",lceil:"\u2308",lcub:"{",Lcy:"\u041B",lcy:"\u043B",ldca:"\u2936",ldquo:"\u201C",ldquor:"\u201E",ldrdhar:"\u2967",ldrushar:"\u294B",ldsh:"\u21B2",le:"\u2264",lE:"\u2266",LeftAngleBracket:"\u27E8",LeftArrowBar:"\u21E4",leftarrow:"\u2190",LeftArrow:"\u2190",Leftarrow:"\u21D0",LeftArrowRightArrow:"\u21C6",leftarrowtail:"\u21A2",LeftCeiling:"\u2308",LeftDoubleBracket:"\u27E6",LeftDownTeeVector:"\u2961",LeftDownVectorBar:"\u2959",LeftDownVector:"\u21C3",LeftFloor:"\u230A",leftharpoondown:"\u21BD",leftharpoonup:"\u21BC",leftleftarrows:"\u21C7",leftrightarrow:"\u2194",LeftRightArrow:"\u2194",Leftrightarrow:"\u21D4",leftrightarrows:"\u21C6",leftrightharpoons:"\u21CB",leftrightsquigarrow:"\u21AD",LeftRightVector:"\u294E",LeftTeeArrow:"\u21A4",LeftTee:"\u22A3",LeftTeeVector:"\u295A",leftthreetimes:"\u22CB",LeftTriangleBar:"\u29CF",LeftTriangle:"\u22B2",LeftTriangleEqual:"\u22B4",LeftUpDownVector:"\u2951",LeftUpTeeVector:"\u2960",LeftUpVectorBar:"\u2958",LeftUpVector:"\u21BF",LeftVectorBar:"\u2952",LeftVector:"\u21BC",lEg:"\u2A8B",leg:"\u22DA",leq:"\u2264",leqq:"\u2266",leqslant:"\u2A7D",lescc:"\u2AA8",les:"\u2A7D",lesdot:"\u2A7F",lesdoto:"\u2A81",lesdotor:"\u2A83",lesg:"\u22DA\uFE00",lesges:"\u2A93",lessapprox:"\u2A85",lessdot:"\u22D6",lesseqgtr:"\u22DA",lesseqqgtr:"\u2A8B",LessEqualGreater:"\u22DA",LessFullEqual:"\u2266",LessGreater:"\u2276",lessgtr:"\u2276",LessLess:"\u2AA1",lesssim:"\u2272",LessSlantEqual:"\u2A7D",LessTilde:"\u2272",lfisht:"\u297C",lfloor:"\u230A",Lfr:"\u{1D50F}",lfr:"\u{1D529}",lg:"\u2276",lgE:"\u2A91",lHar:"\u2962",lhard:"\u21BD",lharu:"\u21BC",lharul:"\u296A",lhblk:"\u2584",LJcy:"\u0409",ljcy:"\u0459",llarr:"\u21C7",ll:"\u226A",Ll:"\u22D8",llcorner:"\u231E",Lleftarrow:"\u21DA",llhard:"\u296B",lltri:"\u25FA",Lmidot:"\u013F",lmidot:"\u0140",lmoustache:"\u23B0",lmoust:"\u23B0",lnap:"\u2A89",lnapprox:"\u2A89",lne:"\u2A87",lnE:"\u2268",lneq:"\u2A87",lneqq:"\u2268",lnsim:"\u22E6",loang:"\u27EC",loarr:"\u21FD",lobrk:"\u27E6",longleftarrow:"\u27F5",LongLeftArrow:"\u27F5",Longleftarrow:"\u27F8",longleftrightarrow:"\u27F7",LongLeftRightArrow:"\u27F7",Longleftrightarrow:"\u27FA",longmapsto:"\u27FC",longrightarrow:"\u27F6",LongRightArrow:"\u27F6",Longrightarrow:"\u27F9",looparrowleft:"\u21AB",looparrowright:"\u21AC",lopar:"\u2985",Lopf:"\u{1D543}",lopf:"\u{1D55D}",loplus:"\u2A2D",lotimes:"\u2A34",lowast:"\u2217",lowbar:"_",LowerLeftArrow:"\u2199",LowerRightArrow:"\u2198",loz:"\u25CA",lozenge:"\u25CA",lozf:"\u29EB",lpar:"(",lparlt:"\u2993",lrarr:"\u21C6",lrcorner:"\u231F",lrhar:"\u21CB",lrhard:"\u296D",lrm:"\u200E",lrtri:"\u22BF",lsaquo:"\u2039",lscr:"\u{1D4C1}",Lscr:"\u2112",lsh:"\u21B0",Lsh:"\u21B0",lsim:"\u2272",lsime:"\u2A8D",lsimg:"\u2A8F",lsqb:"[",lsquo:"\u2018",lsquor:"\u201A",Lstrok:"\u0141",lstrok:"\u0142",ltcc:"\u2AA6",ltcir:"\u2A79",lt:"<",LT:"<",Lt:"\u226A",ltdot:"\u22D6",lthree:"\u22CB",ltimes:"\u22C9",ltlarr:"\u2976",ltquest:"\u2A7B",ltri:"\u25C3",ltrie:"\u22B4",ltrif:"\u25C2",ltrPar:"\u2996",lurdshar:"\u294A",luruhar:"\u2966",lvertneqq:"\u2268\uFE00",lvnE:"\u2268\uFE00",macr:"\xAF",male:"\u2642",malt:"\u2720",maltese:"\u2720",Map:"\u2905",map:"\u21A6",mapsto:"\u21A6",mapstodown:"\u21A7",mapstoleft:"\u21A4",mapstoup:"\u21A5",marker:"\u25AE",mcomma:"\u2A29",Mcy:"\u041C",mcy:"\u043C",mdash:"\u2014",mDDot:"\u223A",measuredangle:"\u2221",MediumSpace:"\u205F",Mellintrf:"\u2133",Mfr:"\u{1D510}",mfr:"\u{1D52A}",mho:"\u2127",micro:"\xB5",midast:"*",midcir:"\u2AF0",mid:"\u2223",middot:"\xB7",minusb:"\u229F",minus:"\u2212",minusd:"\u2238",minusdu:"\u2A2A",MinusPlus:"\u2213",mlcp:"\u2ADB",mldr:"\u2026",mnplus:"\u2213",models:"\u22A7",Mopf:"\u{1D544}",mopf:"\u{1D55E}",mp:"\u2213",mscr:"\u{1D4C2}",Mscr:"\u2133",mstpos:"\u223E",Mu:"\u039C",mu:"\u03BC",multimap:"\u22B8",mumap:"\u22B8",nabla:"\u2207",Nacute:"\u0143",nacute:"\u0144",nang:"\u2220\u20D2",nap:"\u2249",napE:"\u2A70\u0338",napid:"\u224B\u0338",napos:"\u0149",napprox:"\u2249",natural:"\u266E",naturals:"\u2115",natur:"\u266E",nbsp:"\xA0",nbump:"\u224E\u0338",nbumpe:"\u224F\u0338",ncap:"\u2A43",Ncaron:"\u0147",ncaron:"\u0148",Ncedil:"\u0145",ncedil:"\u0146",ncong:"\u2247",ncongdot:"\u2A6D\u0338",ncup:"\u2A42",Ncy:"\u041D",ncy:"\u043D",ndash:"\u2013",nearhk:"\u2924",nearr:"\u2197",neArr:"\u21D7",nearrow:"\u2197",ne:"\u2260",nedot:"\u2250\u0338",NegativeMediumSpace:"\u200B",NegativeThickSpace:"\u200B",NegativeThinSpace:"\u200B",NegativeVeryThinSpace:"\u200B",nequiv:"\u2262",nesear:"\u2928",nesim:"\u2242\u0338",NestedGreaterGreater:"\u226B",NestedLessLess:"\u226A",NewLine:` `,nexist:"\u2204",nexists:"\u2204",Nfr:"\u{1D511}",nfr:"\u{1D52B}",ngE:"\u2267\u0338",nge:"\u2271",ngeq:"\u2271",ngeqq:"\u2267\u0338",ngeqslant:"\u2A7E\u0338",nges:"\u2A7E\u0338",nGg:"\u22D9\u0338",ngsim:"\u2275",nGt:"\u226B\u20D2",ngt:"\u226F",ngtr:"\u226F",nGtv:"\u226B\u0338",nharr:"\u21AE",nhArr:"\u21CE",nhpar:"\u2AF2",ni:"\u220B",nis:"\u22FC",nisd:"\u22FA",niv:"\u220B",NJcy:"\u040A",njcy:"\u045A",nlarr:"\u219A",nlArr:"\u21CD",nldr:"\u2025",nlE:"\u2266\u0338",nle:"\u2270",nleftarrow:"\u219A",nLeftarrow:"\u21CD",nleftrightarrow:"\u21AE",nLeftrightarrow:"\u21CE",nleq:"\u2270",nleqq:"\u2266\u0338",nleqslant:"\u2A7D\u0338",nles:"\u2A7D\u0338",nless:"\u226E",nLl:"\u22D8\u0338",nlsim:"\u2274",nLt:"\u226A\u20D2",nlt:"\u226E",nltri:"\u22EA",nltrie:"\u22EC",nLtv:"\u226A\u0338",nmid:"\u2224",NoBreak:"\u2060",NonBreakingSpace:"\xA0",nopf:"\u{1D55F}",Nopf:"\u2115",Not:"\u2AEC",not:"\xAC",NotCongruent:"\u2262",NotCupCap:"\u226D",NotDoubleVerticalBar:"\u2226",NotElement:"\u2209",NotEqual:"\u2260",NotEqualTilde:"\u2242\u0338",NotExists:"\u2204",NotGreater:"\u226F",NotGreaterEqual:"\u2271",NotGreaterFullEqual:"\u2267\u0338",NotGreaterGreater:"\u226B\u0338",NotGreaterLess:"\u2279",NotGreaterSlantEqual:"\u2A7E\u0338",NotGreaterTilde:"\u2275",NotHumpDownHump:"\u224E\u0338",NotHumpEqual:"\u224F\u0338",notin:"\u2209",notindot:"\u22F5\u0338",notinE:"\u22F9\u0338",notinva:"\u2209",notinvb:"\u22F7",notinvc:"\u22F6",NotLeftTriangleBar:"\u29CF\u0338",NotLeftTriangle:"\u22EA",NotLeftTriangleEqual:"\u22EC",NotLess:"\u226E",NotLessEqual:"\u2270",NotLessGreater:"\u2278",NotLessLess:"\u226A\u0338",NotLessSlantEqual:"\u2A7D\u0338",NotLessTilde:"\u2274",NotNestedGreaterGreater:"\u2AA2\u0338",NotNestedLessLess:"\u2AA1\u0338",notni:"\u220C",notniva:"\u220C",notnivb:"\u22FE",notnivc:"\u22FD",NotPrecedes:"\u2280",NotPrecedesEqual:"\u2AAF\u0338",NotPrecedesSlantEqual:"\u22E0",NotReverseElement:"\u220C",NotRightTriangleBar:"\u29D0\u0338",NotRightTriangle:"\u22EB",NotRightTriangleEqual:"\u22ED",NotSquareSubset:"\u228F\u0338",NotSquareSubsetEqual:"\u22E2",NotSquareSuperset:"\u2290\u0338",NotSquareSupersetEqual:"\u22E3",NotSubset:"\u2282\u20D2",NotSubsetEqual:"\u2288",NotSucceeds:"\u2281",NotSucceedsEqual:"\u2AB0\u0338",NotSucceedsSlantEqual:"\u22E1",NotSucceedsTilde:"\u227F\u0338",NotSuperset:"\u2283\u20D2",NotSupersetEqual:"\u2289",NotTilde:"\u2241",NotTildeEqual:"\u2244",NotTildeFullEqual:"\u2247",NotTildeTilde:"\u2249",NotVerticalBar:"\u2224",nparallel:"\u2226",npar:"\u2226",nparsl:"\u2AFD\u20E5",npart:"\u2202\u0338",npolint:"\u2A14",npr:"\u2280",nprcue:"\u22E0",nprec:"\u2280",npreceq:"\u2AAF\u0338",npre:"\u2AAF\u0338",nrarrc:"\u2933\u0338",nrarr:"\u219B",nrArr:"\u21CF",nrarrw:"\u219D\u0338",nrightarrow:"\u219B",nRightarrow:"\u21CF",nrtri:"\u22EB",nrtrie:"\u22ED",nsc:"\u2281",nsccue:"\u22E1",nsce:"\u2AB0\u0338",Nscr:"\u{1D4A9}",nscr:"\u{1D4C3}",nshortmid:"\u2224",nshortparallel:"\u2226",nsim:"\u2241",nsime:"\u2244",nsimeq:"\u2244",nsmid:"\u2224",nspar:"\u2226",nsqsube:"\u22E2",nsqsupe:"\u22E3",nsub:"\u2284",nsubE:"\u2AC5\u0338",nsube:"\u2288",nsubset:"\u2282\u20D2",nsubseteq:"\u2288",nsubseteqq:"\u2AC5\u0338",nsucc:"\u2281",nsucceq:"\u2AB0\u0338",nsup:"\u2285",nsupE:"\u2AC6\u0338",nsupe:"\u2289",nsupset:"\u2283\u20D2",nsupseteq:"\u2289",nsupseteqq:"\u2AC6\u0338",ntgl:"\u2279",Ntilde:"\xD1",ntilde:"\xF1",ntlg:"\u2278",ntriangleleft:"\u22EA",ntrianglelefteq:"\u22EC",ntriangleright:"\u22EB",ntrianglerighteq:"\u22ED",Nu:"\u039D",nu:"\u03BD",num:"#",numero:"\u2116",numsp:"\u2007",nvap:"\u224D\u20D2",nvdash:"\u22AC",nvDash:"\u22AD",nVdash:"\u22AE",nVDash:"\u22AF",nvge:"\u2265\u20D2",nvgt:">\u20D2",nvHarr:"\u2904",nvinfin:"\u29DE",nvlArr:"\u2902",nvle:"\u2264\u20D2",nvlt:"<\u20D2",nvltrie:"\u22B4\u20D2",nvrArr:"\u2903",nvrtrie:"\u22B5\u20D2",nvsim:"\u223C\u20D2",nwarhk:"\u2923",nwarr:"\u2196",nwArr:"\u21D6",nwarrow:"\u2196",nwnear:"\u2927",Oacute:"\xD3",oacute:"\xF3",oast:"\u229B",Ocirc:"\xD4",ocirc:"\xF4",ocir:"\u229A",Ocy:"\u041E",ocy:"\u043E",odash:"\u229D",Odblac:"\u0150",odblac:"\u0151",odiv:"\u2A38",odot:"\u2299",odsold:"\u29BC",OElig:"\u0152",oelig:"\u0153",ofcir:"\u29BF",Ofr:"\u{1D512}",ofr:"\u{1D52C}",ogon:"\u02DB",Ograve:"\xD2",ograve:"\xF2",ogt:"\u29C1",ohbar:"\u29B5",ohm:"\u03A9",oint:"\u222E",olarr:"\u21BA",olcir:"\u29BE",olcross:"\u29BB",oline:"\u203E",olt:"\u29C0",Omacr:"\u014C",omacr:"\u014D",Omega:"\u03A9",omega:"\u03C9",Omicron:"\u039F",omicron:"\u03BF",omid:"\u29B6",ominus:"\u2296",Oopf:"\u{1D546}",oopf:"\u{1D560}",opar:"\u29B7",OpenCurlyDoubleQuote:"\u201C",OpenCurlyQuote:"\u2018",operp:"\u29B9",oplus:"\u2295",orarr:"\u21BB",Or:"\u2A54",or:"\u2228",ord:"\u2A5D",order:"\u2134",orderof:"\u2134",ordf:"\xAA",ordm:"\xBA",origof:"\u22B6",oror:"\u2A56",orslope:"\u2A57",orv:"\u2A5B",oS:"\u24C8",Oscr:"\u{1D4AA}",oscr:"\u2134",Oslash:"\xD8",oslash:"\xF8",osol:"\u2298",Otilde:"\xD5",otilde:"\xF5",otimesas:"\u2A36",Otimes:"\u2A37",otimes:"\u2297",Ouml:"\xD6",ouml:"\xF6",ovbar:"\u233D",OverBar:"\u203E",OverBrace:"\u23DE",OverBracket:"\u23B4",OverParenthesis:"\u23DC",para:"\xB6",parallel:"\u2225",par:"\u2225",parsim:"\u2AF3",parsl:"\u2AFD",part:"\u2202",PartialD:"\u2202",Pcy:"\u041F",pcy:"\u043F",percnt:"%",period:".",permil:"\u2030",perp:"\u22A5",pertenk:"\u2031",Pfr:"\u{1D513}",pfr:"\u{1D52D}",Phi:"\u03A6",phi:"\u03C6",phiv:"\u03D5",phmmat:"\u2133",phone:"\u260E",Pi:"\u03A0",pi:"\u03C0",pitchfork:"\u22D4",piv:"\u03D6",planck:"\u210F",planckh:"\u210E",plankv:"\u210F",plusacir:"\u2A23",plusb:"\u229E",pluscir:"\u2A22",plus:"+",plusdo:"\u2214",plusdu:"\u2A25",pluse:"\u2A72",PlusMinus:"\xB1",plusmn:"\xB1",plussim:"\u2A26",plustwo:"\u2A27",pm:"\xB1",Poincareplane:"\u210C",pointint:"\u2A15",popf:"\u{1D561}",Popf:"\u2119",pound:"\xA3",prap:"\u2AB7",Pr:"\u2ABB",pr:"\u227A",prcue:"\u227C",precapprox:"\u2AB7",prec:"\u227A",preccurlyeq:"\u227C",Precedes:"\u227A",PrecedesEqual:"\u2AAF",PrecedesSlantEqual:"\u227C",PrecedesTilde:"\u227E",preceq:"\u2AAF",precnapprox:"\u2AB9",precneqq:"\u2AB5",precnsim:"\u22E8",pre:"\u2AAF",prE:"\u2AB3",precsim:"\u227E",prime:"\u2032",Prime:"\u2033",primes:"\u2119",prnap:"\u2AB9",prnE:"\u2AB5",prnsim:"\u22E8",prod:"\u220F",Product:"\u220F",profalar:"\u232E",profline:"\u2312",profsurf:"\u2313",prop:"\u221D",Proportional:"\u221D",Proportion:"\u2237",propto:"\u221D",prsim:"\u227E",prurel:"\u22B0",Pscr:"\u{1D4AB}",pscr:"\u{1D4C5}",Psi:"\u03A8",psi:"\u03C8",puncsp:"\u2008",Qfr:"\u{1D514}",qfr:"\u{1D52E}",qint:"\u2A0C",qopf:"\u{1D562}",Qopf:"\u211A",qprime:"\u2057",Qscr:"\u{1D4AC}",qscr:"\u{1D4C6}",quaternions:"\u210D",quatint:"\u2A16",quest:"?",questeq:"\u225F",quot:'"',QUOT:'"',rAarr:"\u21DB",race:"\u223D\u0331",Racute:"\u0154",racute:"\u0155",radic:"\u221A",raemptyv:"\u29B3",rang:"\u27E9",Rang:"\u27EB",rangd:"\u2992",range:"\u29A5",rangle:"\u27E9",raquo:"\xBB",rarrap:"\u2975",rarrb:"\u21E5",rarrbfs:"\u2920",rarrc:"\u2933",rarr:"\u2192",Rarr:"\u21A0",rArr:"\u21D2",rarrfs:"\u291E",rarrhk:"\u21AA",rarrlp:"\u21AC",rarrpl:"\u2945",rarrsim:"\u2974",Rarrtl:"\u2916",rarrtl:"\u21A3",rarrw:"\u219D",ratail:"\u291A",rAtail:"\u291C",ratio:"\u2236",rationals:"\u211A",rbarr:"\u290D",rBarr:"\u290F",RBarr:"\u2910",rbbrk:"\u2773",rbrace:"}",rbrack:"]",rbrke:"\u298C",rbrksld:"\u298E",rbrkslu:"\u2990",Rcaron:"\u0158",rcaron:"\u0159",Rcedil:"\u0156",rcedil:"\u0157",rceil:"\u2309",rcub:"}",Rcy:"\u0420",rcy:"\u0440",rdca:"\u2937",rdldhar:"\u2969",rdquo:"\u201D",rdquor:"\u201D",rdsh:"\u21B3",real:"\u211C",realine:"\u211B",realpart:"\u211C",reals:"\u211D",Re:"\u211C",rect:"\u25AD",reg:"\xAE",REG:"\xAE",ReverseElement:"\u220B",ReverseEquilibrium:"\u21CB",ReverseUpEquilibrium:"\u296F",rfisht:"\u297D",rfloor:"\u230B",rfr:"\u{1D52F}",Rfr:"\u211C",rHar:"\u2964",rhard:"\u21C1",rharu:"\u21C0",rharul:"\u296C",Rho:"\u03A1",rho:"\u03C1",rhov:"\u03F1",RightAngleBracket:"\u27E9",RightArrowBar:"\u21E5",rightarrow:"\u2192",RightArrow:"\u2192",Rightarrow:"\u21D2",RightArrowLeftArrow:"\u21C4",rightarrowtail:"\u21A3",RightCeiling:"\u2309",RightDoubleBracket:"\u27E7",RightDownTeeVector:"\u295D",RightDownVectorBar:"\u2955",RightDownVector:"\u21C2",RightFloor:"\u230B",rightharpoondown:"\u21C1",rightharpoonup:"\u21C0",rightleftarrows:"\u21C4",rightleftharpoons:"\u21CC",rightrightarrows:"\u21C9",rightsquigarrow:"\u219D",RightTeeArrow:"\u21A6",RightTee:"\u22A2",RightTeeVector:"\u295B",rightthreetimes:"\u22CC",RightTriangleBar:"\u29D0",RightTriangle:"\u22B3",RightTriangleEqual:"\u22B5",RightUpDownVector:"\u294F",RightUpTeeVector:"\u295C",RightUpVectorBar:"\u2954",RightUpVector:"\u21BE",RightVectorBar:"\u2953",RightVector:"\u21C0",ring:"\u02DA",risingdotseq:"\u2253",rlarr:"\u21C4",rlhar:"\u21CC",rlm:"\u200F",rmoustache:"\u23B1",rmoust:"\u23B1",rnmid:"\u2AEE",roang:"\u27ED",roarr:"\u21FE",robrk:"\u27E7",ropar:"\u2986",ropf:"\u{1D563}",Ropf:"\u211D",roplus:"\u2A2E",rotimes:"\u2A35",RoundImplies:"\u2970",rpar:")",rpargt:"\u2994",rppolint:"\u2A12",rrarr:"\u21C9",Rrightarrow:"\u21DB",rsaquo:"\u203A",rscr:"\u{1D4C7}",Rscr:"\u211B",rsh:"\u21B1",Rsh:"\u21B1",rsqb:"]",rsquo:"\u2019",rsquor:"\u2019",rthree:"\u22CC",rtimes:"\u22CA",rtri:"\u25B9",rtrie:"\u22B5",rtrif:"\u25B8",rtriltri:"\u29CE",RuleDelayed:"\u29F4",ruluhar:"\u2968",rx:"\u211E",Sacute:"\u015A",sacute:"\u015B",sbquo:"\u201A",scap:"\u2AB8",Scaron:"\u0160",scaron:"\u0161",Sc:"\u2ABC",sc:"\u227B",sccue:"\u227D",sce:"\u2AB0",scE:"\u2AB4",Scedil:"\u015E",scedil:"\u015F",Scirc:"\u015C",scirc:"\u015D",scnap:"\u2ABA",scnE:"\u2AB6",scnsim:"\u22E9",scpolint:"\u2A13",scsim:"\u227F",Scy:"\u0421",scy:"\u0441",sdotb:"\u22A1",sdot:"\u22C5",sdote:"\u2A66",searhk:"\u2925",searr:"\u2198",seArr:"\u21D8",searrow:"\u2198",sect:"\xA7",semi:";",seswar:"\u2929",setminus:"\u2216",setmn:"\u2216",sext:"\u2736",Sfr:"\u{1D516}",sfr:"\u{1D530}",sfrown:"\u2322",sharp:"\u266F",SHCHcy:"\u0429",shchcy:"\u0449",SHcy:"\u0428",shcy:"\u0448",ShortDownArrow:"\u2193",ShortLeftArrow:"\u2190",shortmid:"\u2223",shortparallel:"\u2225",ShortRightArrow:"\u2192",ShortUpArrow:"\u2191",shy:"\xAD",Sigma:"\u03A3",sigma:"\u03C3",sigmaf:"\u03C2",sigmav:"\u03C2",sim:"\u223C",simdot:"\u2A6A",sime:"\u2243",simeq:"\u2243",simg:"\u2A9E",simgE:"\u2AA0",siml:"\u2A9D",simlE:"\u2A9F",simne:"\u2246",simplus:"\u2A24",simrarr:"\u2972",slarr:"\u2190",SmallCircle:"\u2218",smallsetminus:"\u2216",smashp:"\u2A33",smeparsl:"\u29E4",smid:"\u2223",smile:"\u2323",smt:"\u2AAA",smte:"\u2AAC",smtes:"\u2AAC\uFE00",SOFTcy:"\u042C",softcy:"\u044C",solbar:"\u233F",solb:"\u29C4",sol:"/",Sopf:"\u{1D54A}",sopf:"\u{1D564}",spades:"\u2660",spadesuit:"\u2660",spar:"\u2225",sqcap:"\u2293",sqcaps:"\u2293\uFE00",sqcup:"\u2294",sqcups:"\u2294\uFE00",Sqrt:"\u221A",sqsub:"\u228F",sqsube:"\u2291",sqsubset:"\u228F",sqsubseteq:"\u2291",sqsup:"\u2290",sqsupe:"\u2292",sqsupset:"\u2290",sqsupseteq:"\u2292",square:"\u25A1",Square:"\u25A1",SquareIntersection:"\u2293",SquareSubset:"\u228F",SquareSubsetEqual:"\u2291",SquareSuperset:"\u2290",SquareSupersetEqual:"\u2292",SquareUnion:"\u2294",squarf:"\u25AA",squ:"\u25A1",squf:"\u25AA",srarr:"\u2192",Sscr:"\u{1D4AE}",sscr:"\u{1D4C8}",ssetmn:"\u2216",ssmile:"\u2323",sstarf:"\u22C6",Star:"\u22C6",star:"\u2606",starf:"\u2605",straightepsilon:"\u03F5",straightphi:"\u03D5",strns:"\xAF",sub:"\u2282",Sub:"\u22D0",subdot:"\u2ABD",subE:"\u2AC5",sube:"\u2286",subedot:"\u2AC3",submult:"\u2AC1",subnE:"\u2ACB",subne:"\u228A",subplus:"\u2ABF",subrarr:"\u2979",subset:"\u2282",Subset:"\u22D0",subseteq:"\u2286",subseteqq:"\u2AC5",SubsetEqual:"\u2286",subsetneq:"\u228A",subsetneqq:"\u2ACB",subsim:"\u2AC7",subsub:"\u2AD5",subsup:"\u2AD3",succapprox:"\u2AB8",succ:"\u227B",succcurlyeq:"\u227D",Succeeds:"\u227B",SucceedsEqual:"\u2AB0",SucceedsSlantEqual:"\u227D",SucceedsTilde:"\u227F",succeq:"\u2AB0",succnapprox:"\u2ABA",succneqq:"\u2AB6",succnsim:"\u22E9",succsim:"\u227F",SuchThat:"\u220B",sum:"\u2211",Sum:"\u2211",sung:"\u266A",sup1:"\xB9",sup2:"\xB2",sup3:"\xB3",sup:"\u2283",Sup:"\u22D1",supdot:"\u2ABE",supdsub:"\u2AD8",supE:"\u2AC6",supe:"\u2287",supedot:"\u2AC4",Superset:"\u2283",SupersetEqual:"\u2287",suphsol:"\u27C9",suphsub:"\u2AD7",suplarr:"\u297B",supmult:"\u2AC2",supnE:"\u2ACC",supne:"\u228B",supplus:"\u2AC0",supset:"\u2283",Supset:"\u22D1",supseteq:"\u2287",supseteqq:"\u2AC6",supsetneq:"\u228B",supsetneqq:"\u2ACC",supsim:"\u2AC8",supsub:"\u2AD4",supsup:"\u2AD6",swarhk:"\u2926",swarr:"\u2199",swArr:"\u21D9",swarrow:"\u2199",swnwar:"\u292A",szlig:"\xDF",Tab:" ",target:"\u2316",Tau:"\u03A4",tau:"\u03C4",tbrk:"\u23B4",Tcaron:"\u0164",tcaron:"\u0165",Tcedil:"\u0162",tcedil:"\u0163",Tcy:"\u0422",tcy:"\u0442",tdot:"\u20DB",telrec:"\u2315",Tfr:"\u{1D517}",tfr:"\u{1D531}",there4:"\u2234",therefore:"\u2234",Therefore:"\u2234",Theta:"\u0398",theta:"\u03B8",thetasym:"\u03D1",thetav:"\u03D1",thickapprox:"\u2248",thicksim:"\u223C",ThickSpace:"\u205F\u200A",ThinSpace:"\u2009",thinsp:"\u2009",thkap:"\u2248",thksim:"\u223C",THORN:"\xDE",thorn:"\xFE",tilde:"\u02DC",Tilde:"\u223C",TildeEqual:"\u2243",TildeFullEqual:"\u2245",TildeTilde:"\u2248",timesbar:"\u2A31",timesb:"\u22A0",times:"\xD7",timesd:"\u2A30",tint:"\u222D",toea:"\u2928",topbot:"\u2336",topcir:"\u2AF1",top:"\u22A4",Topf:"\u{1D54B}",topf:"\u{1D565}",topfork:"\u2ADA",tosa:"\u2929",tprime:"\u2034",trade:"\u2122",TRADE:"\u2122",triangle:"\u25B5",triangledown:"\u25BF",triangleleft:"\u25C3",trianglelefteq:"\u22B4",triangleq:"\u225C",triangleright:"\u25B9",trianglerighteq:"\u22B5",tridot:"\u25EC",trie:"\u225C",triminus:"\u2A3A",TripleDot:"\u20DB",triplus:"\u2A39",trisb:"\u29CD",tritime:"\u2A3B",trpezium:"\u23E2",Tscr:"\u{1D4AF}",tscr:"\u{1D4C9}",TScy:"\u0426",tscy:"\u0446",TSHcy:"\u040B",tshcy:"\u045B",Tstrok:"\u0166",tstrok:"\u0167",twixt:"\u226C",twoheadleftarrow:"\u219E",twoheadrightarrow:"\u21A0",Uacute:"\xDA",uacute:"\xFA",uarr:"\u2191",Uarr:"\u219F",uArr:"\u21D1",Uarrocir:"\u2949",Ubrcy:"\u040E",ubrcy:"\u045E",Ubreve:"\u016C",ubreve:"\u016D",Ucirc:"\xDB",ucirc:"\xFB",Ucy:"\u0423",ucy:"\u0443",udarr:"\u21C5",Udblac:"\u0170",udblac:"\u0171",udhar:"\u296E",ufisht:"\u297E",Ufr:"\u{1D518}",ufr:"\u{1D532}",Ugrave:"\xD9",ugrave:"\xF9",uHar:"\u2963",uharl:"\u21BF",uharr:"\u21BE",uhblk:"\u2580",ulcorn:"\u231C",ulcorner:"\u231C",ulcrop:"\u230F",ultri:"\u25F8",Umacr:"\u016A",umacr:"\u016B",uml:"\xA8",UnderBar:"_",UnderBrace:"\u23DF",UnderBracket:"\u23B5",UnderParenthesis:"\u23DD",Union:"\u22C3",UnionPlus:"\u228E",Uogon:"\u0172",uogon:"\u0173",Uopf:"\u{1D54C}",uopf:"\u{1D566}",UpArrowBar:"\u2912",uparrow:"\u2191",UpArrow:"\u2191",Uparrow:"\u21D1",UpArrowDownArrow:"\u21C5",updownarrow:"\u2195",UpDownArrow:"\u2195",Updownarrow:"\u21D5",UpEquilibrium:"\u296E",upharpoonleft:"\u21BF",upharpoonright:"\u21BE",uplus:"\u228E",UpperLeftArrow:"\u2196",UpperRightArrow:"\u2197",upsi:"\u03C5",Upsi:"\u03D2",upsih:"\u03D2",Upsilon:"\u03A5",upsilon:"\u03C5",UpTeeArrow:"\u21A5",UpTee:"\u22A5",upuparrows:"\u21C8",urcorn:"\u231D",urcorner:"\u231D",urcrop:"\u230E",Uring:"\u016E",uring:"\u016F",urtri:"\u25F9",Uscr:"\u{1D4B0}",uscr:"\u{1D4CA}",utdot:"\u22F0",Utilde:"\u0168",utilde:"\u0169",utri:"\u25B5",utrif:"\u25B4",uuarr:"\u21C8",Uuml:"\xDC",uuml:"\xFC",uwangle:"\u29A7",vangrt:"\u299C",varepsilon:"\u03F5",varkappa:"\u03F0",varnothing:"\u2205",varphi:"\u03D5",varpi:"\u03D6",varpropto:"\u221D",varr:"\u2195",vArr:"\u21D5",varrho:"\u03F1",varsigma:"\u03C2",varsubsetneq:"\u228A\uFE00",varsubsetneqq:"\u2ACB\uFE00",varsupsetneq:"\u228B\uFE00",varsupsetneqq:"\u2ACC\uFE00",vartheta:"\u03D1",vartriangleleft:"\u22B2",vartriangleright:"\u22B3",vBar:"\u2AE8",Vbar:"\u2AEB",vBarv:"\u2AE9",Vcy:"\u0412",vcy:"\u0432",vdash:"\u22A2",vDash:"\u22A8",Vdash:"\u22A9",VDash:"\u22AB",Vdashl:"\u2AE6",veebar:"\u22BB",vee:"\u2228",Vee:"\u22C1",veeeq:"\u225A",vellip:"\u22EE",verbar:"|",Verbar:"\u2016",vert:"|",Vert:"\u2016",VerticalBar:"\u2223",VerticalLine:"|",VerticalSeparator:"\u2758",VerticalTilde:"\u2240",VeryThinSpace:"\u200A",Vfr:"\u{1D519}",vfr:"\u{1D533}",vltri:"\u22B2",vnsub:"\u2282\u20D2",vnsup:"\u2283\u20D2",Vopf:"\u{1D54D}",vopf:"\u{1D567}",vprop:"\u221D",vrtri:"\u22B3",Vscr:"\u{1D4B1}",vscr:"\u{1D4CB}",vsubnE:"\u2ACB\uFE00",vsubne:"\u228A\uFE00",vsupnE:"\u2ACC\uFE00",vsupne:"\u228B\uFE00",Vvdash:"\u22AA",vzigzag:"\u299A",Wcirc:"\u0174",wcirc:"\u0175",wedbar:"\u2A5F",wedge:"\u2227",Wedge:"\u22C0",wedgeq:"\u2259",weierp:"\u2118",Wfr:"\u{1D51A}",wfr:"\u{1D534}",Wopf:"\u{1D54E}",wopf:"\u{1D568}",wp:"\u2118",wr:"\u2240",wreath:"\u2240",Wscr:"\u{1D4B2}",wscr:"\u{1D4CC}",xcap:"\u22C2",xcirc:"\u25EF",xcup:"\u22C3",xdtri:"\u25BD",Xfr:"\u{1D51B}",xfr:"\u{1D535}",xharr:"\u27F7",xhArr:"\u27FA",Xi:"\u039E",xi:"\u03BE",xlarr:"\u27F5",xlArr:"\u27F8",xmap:"\u27FC",xnis:"\u22FB",xodot:"\u2A00",Xopf:"\u{1D54F}",xopf:"\u{1D569}",xoplus:"\u2A01",xotime:"\u2A02",xrarr:"\u27F6",xrArr:"\u27F9",Xscr:"\u{1D4B3}",xscr:"\u{1D4CD}",xsqcup:"\u2A06",xuplus:"\u2A04",xutri:"\u25B3",xvee:"\u22C1",xwedge:"\u22C0",Yacute:"\xDD",yacute:"\xFD",YAcy:"\u042F",yacy:"\u044F",Ycirc:"\u0176",ycirc:"\u0177",Ycy:"\u042B",ycy:"\u044B",yen:"\xA5",Yfr:"\u{1D51C}",yfr:"\u{1D536}",YIcy:"\u0407",yicy:"\u0457",Yopf:"\u{1D550}",yopf:"\u{1D56A}",Yscr:"\u{1D4B4}",yscr:"\u{1D4CE}",YUcy:"\u042E",yucy:"\u044E",yuml:"\xFF",Yuml:"\u0178",Zacute:"\u0179",zacute:"\u017A",Zcaron:"\u017D",zcaron:"\u017E",Zcy:"\u0417",zcy:"\u0437",Zdot:"\u017B",zdot:"\u017C",zeetrf:"\u2128",ZeroWidthSpace:"\u200B",Zeta:"\u0396",zeta:"\u03B6",zfr:"\u{1D537}",Zfr:"\u2128",ZHcy:"\u0416",zhcy:"\u0436",zigrarr:"\u21DD",zopf:"\u{1D56B}",Zopf:"\u2124",Zscr:"\u{1D4B5}",zscr:"\u{1D4CF}",zwj:"\u200D",zwnj:"\u200C"}});var Sl=Ct((t2,dh)=>{dh.exports={Aacute:"\xC1",aacute:"\xE1",Acirc:"\xC2",acirc:"\xE2",acute:"\xB4",AElig:"\xC6",aelig:"\xE6",Agrave:"\xC0",agrave:"\xE0",amp:"&",AMP:"&",Aring:"\xC5",aring:"\xE5",Atilde:"\xC3",atilde:"\xE3",Auml:"\xC4",auml:"\xE4",brvbar:"\xA6",Ccedil:"\xC7",ccedil:"\xE7",cedil:"\xB8",cent:"\xA2",copy:"\xA9",COPY:"\xA9",curren:"\xA4",deg:"\xB0",divide:"\xF7",Eacute:"\xC9",eacute:"\xE9",Ecirc:"\xCA",ecirc:"\xEA",Egrave:"\xC8",egrave:"\xE8",ETH:"\xD0",eth:"\xF0",Euml:"\xCB",euml:"\xEB",frac12:"\xBD",frac14:"\xBC",frac34:"\xBE",gt:">",GT:">",Iacute:"\xCD",iacute:"\xED",Icirc:"\xCE",icirc:"\xEE",iexcl:"\xA1",Igrave:"\xCC",igrave:"\xEC",iquest:"\xBF",Iuml:"\xCF",iuml:"\xEF",laquo:"\xAB",lt:"<",LT:"<",macr:"\xAF",micro:"\xB5",middot:"\xB7",nbsp:"\xA0",not:"\xAC",Ntilde:"\xD1",ntilde:"\xF1",Oacute:"\xD3",oacute:"\xF3",Ocirc:"\xD4",ocirc:"\xF4",Ograve:"\xD2",ograve:"\xF2",ordf:"\xAA",ordm:"\xBA",Oslash:"\xD8",oslash:"\xF8",Otilde:"\xD5",otilde:"\xF5",Ouml:"\xD6",ouml:"\xF6",para:"\xB6",plusmn:"\xB1",pound:"\xA3",quot:'"',QUOT:'"',raquo:"\xBB",reg:"\xAE",REG:"\xAE",sect:"\xA7",shy:"\xAD",sup1:"\xB9",sup2:"\xB2",sup3:"\xB3",szlig:"\xDF",THORN:"\xDE",thorn:"\xFE",times:"\xD7",Uacute:"\xDA",uacute:"\xFA",Ucirc:"\xDB",ucirc:"\xFB",Ugrave:"\xD9",ugrave:"\xF9",uml:"\xA8",Uuml:"\xDC",uuml:"\xFC",Yacute:"\xDD",yacute:"\xFD",yen:"\xA5",yuml:"\xFF"}});var si=Ct((e2,hh)=>{hh.exports={amp:"&",apos:"'",gt:">",lt:"<",quot:'"'}});var Ll=Ct((r2,gh)=>{gh.exports={"0":65533,"128":8364,"130":8218,"131":402,"132":8222,"133":8230,"134":8224,"135":8225,"136":710,"137":8240,"138":352,"139":8249,"140":338,"142":381,"145":8216,"146":8217,"147":8220,"148":8221,"149":8226,"150":8211,"151":8212,"152":732,"153":8482,"154":353,"155":8250,"156":339,"158":382,"159":376}});var Al=Ct(Ir=>{"use strict";var xh=Ir&&Ir.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Ir,"__esModule",{value:!0});var El=xh(Ll()),yh=String.fromCodePoint||function(t){var e="";return t>65535&&(t-=65536,e+=String.fromCharCode(t>>>10&1023|55296),t=56320|t&1023),e+=String.fromCharCode(t),e};function vh(t){return t>=55296&&t<=57343||t>1114111?"\uFFFD":(t in El.default&&(t=El.default[t]),yh(t))}Ir.default=vh});var li=Ct(At=>{"use strict";var In=At&&At.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(At,"__esModule",{value:!0});At.decodeHTML=At.decodeHTMLStrict=At.decodeXML=void 0;var ui=In(ai()),bh=In(Sl()),wh=In(si()),Dl=In(Al()),kh=/&(?:[a-zA-Z0-9]+|#[xX][\da-fA-F]+|#\d+);/g;At.decodeXML=ql(wh.default);At.decodeHTMLStrict=ql(ui.default);function ql(t){var e=Il(t);return function(r){return String(r).replace(kh,e)}}var Cl=function(t,e){return t{"use strict";var Nl=ut&&ut.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(ut,"__esModule",{value:!0});ut.escapeUTF8=ut.escape=ut.encodeNonAsciiHTML=ut.encodeHTML=ut.encodeXML=void 0;var _h=Nl(si()),Bl=Hl(_h.default),Rl=Fl(Bl);ut.encodeXML=$l(Bl);var Th=Nl(ai()),ci=Hl(Th.default),Mh=Fl(ci);ut.encodeHTML=Lh(ci,Mh);ut.encodeNonAsciiHTML=$l(ci);function Hl(t){return Object.keys(t).sort().reduce(function(e,r){return e[t[r]]="&"+r+";",e},{})}function Fl(t){for(var e=[],r=[],n=0,o=Object.keys(t);n1?Sh(t):t.charCodeAt(0)).toString(16).toUpperCase()+";"}function Lh(t,e){return function(r){return r.replace(e,function(n){return t[n]}).replace(Ol,Nn)}}var Pl=new RegExp(Rl.source+"|"+Ol.source,"g");function Eh(t){return t.replace(Pl,Nn)}ut.escape=Eh;function Ah(t){return t.replace(Rl,Nn)}ut.escapeUTF8=Ah;function $l(t){return function(e){return e.replace(Pl,function(r){return t[r]||Nn(r)})}}});var Gl=Ct(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.decodeXMLStrict=O.decodeHTML5Strict=O.decodeHTML4Strict=O.decodeHTML5=O.decodeHTML4=O.decodeHTMLStrict=O.decodeHTML=O.decodeXML=O.encodeHTML5=O.encodeHTML4=O.escapeUTF8=O.escape=O.encodeNonAsciiHTML=O.encodeHTML=O.encodeXML=O.encode=O.decodeStrict=O.decode=void 0;var Bn=li(),Ul=fi();function Dh(t,e){return(!e||e<=0?Bn.decodeXML:Bn.decodeHTML)(t)}O.decode=Dh;function Ch(t,e){return(!e||e<=0?Bn.decodeXML:Bn.decodeHTMLStrict)(t)}O.decodeStrict=Ch;function qh(t,e){return(!e||e<=0?Ul.encodeXML:Ul.encodeHTML)(t)}O.encode=qh;var _e=fi();Object.defineProperty(O,"encodeXML",{enumerable:!0,get:function(){return _e.encodeXML}});Object.defineProperty(O,"encodeHTML",{enumerable:!0,get:function(){return _e.encodeHTML}});Object.defineProperty(O,"encodeNonAsciiHTML",{enumerable:!0,get:function(){return _e.encodeNonAsciiHTML}});Object.defineProperty(O,"escape",{enumerable:!0,get:function(){return _e.escape}});Object.defineProperty(O,"escapeUTF8",{enumerable:!0,get:function(){return _e.escapeUTF8}});Object.defineProperty(O,"encodeHTML4",{enumerable:!0,get:function(){return _e.encodeHTML}});Object.defineProperty(O,"encodeHTML5",{enumerable:!0,get:function(){return _e.encodeHTML}});var jt=li();Object.defineProperty(O,"decodeXML",{enumerable:!0,get:function(){return jt.decodeXML}});Object.defineProperty(O,"decodeHTML",{enumerable:!0,get:function(){return jt.decodeHTML}});Object.defineProperty(O,"decodeHTMLStrict",{enumerable:!0,get:function(){return jt.decodeHTMLStrict}});Object.defineProperty(O,"decodeHTML4",{enumerable:!0,get:function(){return jt.decodeHTML}});Object.defineProperty(O,"decodeHTML5",{enumerable:!0,get:function(){return jt.decodeHTML}});Object.defineProperty(O,"decodeHTML4Strict",{enumerable:!0,get:function(){return jt.decodeHTMLStrict}});Object.defineProperty(O,"decodeHTML5Strict",{enumerable:!0,get:function(){return jt.decodeHTMLStrict}});Object.defineProperty(O,"decodeXMLStrict",{enumerable:!0,get:function(){return jt.decodeXML}})});var tc=Ct((s2,Kl)=>{"use strict";function Ih(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function Vl(t,e){for(var r=0;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(c){throw c},f:o}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var i=!0,a=!1,s;return{s:function(){r=r.call(t)},n:function(){var c=r.next();return i=c.done,c},e:function(c){a=!0,s=c},f:function(){try{!i&&r.return!=null&&r.return()}finally{if(a)throw s}}}}function Bh(t,e){if(t){if(typeof t=="string")return zl(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if(r==="Object"&&t.constructor&&(r=t.constructor.name),r==="Map"||r==="Set")return Array.from(t);if(r==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return zl(t,e)}}function zl(t,e){(e==null||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r0?t*40+55:0,a=e>0?e*40+55:0,s=r>0?r*40+55:0;n[o]=Oh([i,a,s])}function Jl(t){for(var e=t.toString(16);e.length<2;)e="0"+e;return e}function Oh(t){var e=[],r=Zl(t),n;try{for(r.s();!(n=r.n()).done;){var o=n.value;e.push(Jl(o))}}catch(i){r.e(i)}finally{r.f()}return"#"+e.join("")}function Wl(t,e,r,n){var o;return e==="text"?o=Gh(r,n):e==="display"?o=$h(t,r,n):e==="xterm256Foreground"?o=Fn(t,n.colors[r]):e==="xterm256Background"?o=On(t,n.colors[r]):e==="rgb"&&(o=Ph(t,r)),o}function Ph(t,e){e=e.substring(2).slice(0,-1);var r=+e.substr(0,2),n=e.substring(5).split(";"),o=n.map(function(i){return("0"+Number(i).toString(16)).substr(-2)}).join("");return Hn(t,(r===38?"color:#":"background-color:#")+o)}function $h(t,e,r){e=parseInt(e,10);var n={"-1":function(){return"
"},0:function(){return t.length&&Ql(t)},1:function(){return Zt(t,"b")},3:function(){return Zt(t,"i")},4:function(){return Zt(t,"u")},8:function(){return Hn(t,"display:none")},9:function(){return Zt(t,"strike")},22:function(){return Hn(t,"font-weight:normal;text-decoration:none;font-style:normal")},23:function(){return jl(t,"i")},24:function(){return jl(t,"u")},39:function(){return Fn(t,r.fg)},49:function(){return On(t,r.bg)},53:function(){return Hn(t,"text-decoration:overline")}},o;return n[e]?o=n[e]():4"}).join("")}function Rn(t,e){for(var r=[],n=t;n<=e;n++)r.push(n);return r}function Uh(t){return function(e){return(t===null||e.category!==t)&&t!=="all"}}function Xl(t){t=parseInt(t,10);var e=null;return t===0?e="all":t===1?e="bold":2")}function Hn(t,e){return Zt(t,"span",e)}function Fn(t,e){return Zt(t,"span","color:"+e)}function On(t,e){return Zt(t,"span","background-color:"+e)}function jl(t,e){var r;if(t.slice(-1)[0]===e&&(r=t.pop()),r)return""}function Vh(t,e,r){var n=!1,o=3;function i(){return""}function a(L,b){return r("xterm256Foreground",b),""}function s(L,b){return r("xterm256Background",b),""}function u(L){return e.newline?r("display",-1):r("text",L),""}function c(L,b){n=!0,b.trim().length===0&&(b="0"),b=b.trimRight(";").split(";");var N=Zl(b),H;try{for(N.s();!(H=N.n()).done;){var P=H.value;r("display",P)}}catch(I){N.e(I)}finally{N.f()}return""}function l(L){return r("text",L),""}function p(L){return r("rgb",L),""}var f=[{pattern:/^\x08+/,sub:i},{pattern:/^\x1b\[[012]?K/,sub:i},{pattern:/^\x1b\[\(B/,sub:i},{pattern:/^\x1b\[[34]8;2;\d+;\d+;\d+m/,sub:p},{pattern:/^\x1b\[38;5;(\d+)m/,sub:a},{pattern:/^\x1b\[48;5;(\d+)m/,sub:s},{pattern:/^\n/,sub:u},{pattern:/^\r+\n/,sub:u},{pattern:/^\r/,sub:u},{pattern:/^\x1b\[((?:\d{1,3};?)+|)m/,sub:c},{pattern:/^\x1b\[\d?J/,sub:i},{pattern:/^\x1b\[\d{0,3};\d{0,3}f/,sub:i},{pattern:/^\x1b\[?[\d;]{0,3}/,sub:i},{pattern:/^(([^\x1b\x08\r\n])+)/,sub:l}];function m(L,b){b>o&&n||(n=!1,t=t.replace(L.pattern,L.sub))}var d=[],y=t,k=y.length;t:for(;k>0;){for(var _=0,q=0,A=f.length;qe?1:t>=e?0:NaN}function Gn(t,e){return t==null||e==null?NaN:et?1:e>=t?0:NaN}function Kt(t){let e,r,n;t.length!==2?(e=ft,r=(s,u)=>ft(t(s),u),n=(s,u)=>t(s)-u):(e=t===ft||t===Gn?t:yc,r=t,n=t);function o(s,u,c=0,l=s.length){if(c>>1;r(s[p],u)<0?c=p+1:l=p}while(c>>1;r(s[p],u)<=0?c=p+1:l=p}while(cc&&n(s[p-1],u)>-n(s[p],u)?p-1:p}return{left:o,center:a,right:i}}function yc(){return 0}function Nr(t){return t===null?NaN:+t}function*Si(t,e){if(e===void 0)for(let r of t)r!=null&&(r=+r)>=r&&(yield r);else{let r=-1;for(let n of t)(n=e(n,++r,t))!=null&&(n=+n)>=n&&(yield n)}}var Li=Kt(ft),Ei=Li.right,vc=Li.left,bc=Kt(Nr).center,Vn=Ei;function Me(t,e){let r,n;if(e===void 0)for(let o of t)o!=null&&(r===void 0?o>=o&&(r=n=o):(r>o&&(r=o),n=i&&(r=n=i):(r>i&&(r=i),n{let n=t(e,r);return n||n===0?n:(t(r,r)===0)-(t(e,e)===0)}}function zn(t,e){return(t==null||!(t>=t))-(e==null||!(e>=e))||(te?1:0)}var Tc=Math.sqrt(50),Mc=Math.sqrt(10),Sc=Math.sqrt(2);function Br(t,e,r){let n=(e-t)/Math.max(0,r),o=Math.floor(Math.log10(n)),i=n/Math.pow(10,o),a=i>=Tc?10:i>=Mc?5:i>=Sc?2:1,s,u,c;return o<0?(c=Math.pow(10,-o)/a,s=Math.round(t*c),u=Math.round(e*c),s/ce&&--u,c=-c):(c=Math.pow(10,o)*a,s=Math.round(t/c),u=Math.round(e/c),s*ce&&--u),u0))return[];if(t===e)return[t];let n=e=o))return[];let s=i-o+1,u=new Array(s);if(n)if(a<0)for(let c=0;c=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r=o)&&(r=o)}return r}function Rr(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r>n||r===void 0&&n>=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r>o||r===void 0&&o>=o)&&(r=o)}return r}function Hr(t,e,r=0,n=1/0,o){if(e=Math.floor(e),r=Math.floor(Math.max(0,r)),n=Math.floor(Math.min(t.length-1,n)),!(r<=e&&e<=n))return t;for(o=o===void 0?zn:Di(o);n>r;){if(n-r>600){let u=n-r+1,c=e-r+1,l=Math.log(u),p=.5*Math.exp(2*l/3),f=.5*Math.sqrt(l*p*(u-p)/u)*(c-u/2<0?-1:1),m=Math.max(r,Math.floor(e-c*p/u+f)),d=Math.min(n,Math.floor(e+(u-c)*p/u+f));Hr(t,e,m,d,o)}let i=t[e],a=r,s=n;for(Ke(t,r,e),o(t[n],i)>0&&Ke(t,r,n);a0;)--s}o(t[r],i)===0?Ke(t,r,s):(++s,Ke(t,s,n)),s<=e&&(r=s+1),e<=s&&(n=s-1)}return t}function Ke(t,e,r){let n=t[e];t[e]=t[r],t[r]=n}function Ee(t,e,r){if(t=Float64Array.from(Si(t,r)),!(!(n=t.length)||isNaN(e=+e))){if(e<=0||n<2)return Rr(t);if(e>=1)return ee(t);var n,o=(n-1)*e,i=Math.floor(o),a=ee(Hr(t,i).subarray(0,i+1)),s=Rr(t.subarray(i+1));return a+(s-a)*(o-i)}}function Ae(t,e,r){t=+t,e=+e,r=(o=arguments.length)<2?(e=t,t=0,1):o<3?1:+r;for(var n=-1,o=Math.max(0,Math.ceil((e-t)/r))|0,i=new Array(o);++n+t(e)}function Dc(t,e){return e=Math.max(0,t.bandwidth()-e*2)/2,t.round()&&(e=Math.round(e)),r=>+t(r)+e}function Cc(){return!this.__axis}function Ii(t,e){var r=[],n=null,o=null,i=6,a=6,s=3,u=typeof window<"u"&&window.devicePixelRatio>1?0:.5,c=t===Yn||t===tr?-1:1,l=t===tr||t===Wn?"x":"y",p=t===Yn||t===Xn?Lc:Ec;function f(m){var d=n??(e.ticks?e.ticks.apply(e,r):e.domain()),y=o??(e.tickFormat?e.tickFormat.apply(e,r):Ci),k=Math.max(i,0)+s,_=e.range(),q=+_[0]+u,A=+_[_.length-1]+u,D=(e.bandwidth?Dc:Ac)(e.copy(),u),L=m.selection?m.selection():m,b=L.selectAll(".domain").data([null]),N=L.selectAll(".tick").data(d,e).order(),H=N.exit(),P=N.enter().append("g").attr("class","tick"),I=N.select("line"),h=N.select("text");b=b.merge(b.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),N=N.merge(P),I=I.merge(P.append("line").attr("stroke","currentColor").attr(l+"2",c*i)),h=h.merge(P.append("text").attr("fill","currentColor").attr(l,c*k).attr("dy",t===Yn?"0em":t===Xn?"0.71em":"0.32em")),m!==L&&(b=b.transition(m),N=N.transition(m),I=I.transition(m),h=h.transition(m),H=H.transition(m).attr("opacity",qi).attr("transform",function(T){return isFinite(T=D(T))?p(T+u):this.getAttribute("transform")}),P.attr("opacity",qi).attr("transform",function(T){var E=this.parentNode.__axis;return p((E&&isFinite(E=E(T))?E:D(T))+u)})),H.remove(),b.attr("d",t===tr||t===Wn?a?"M"+c*a+","+q+"H"+u+"V"+A+"H"+c*a:"M"+u+","+q+"V"+A:a?"M"+q+","+c*a+"V"+u+"H"+A+"V"+c*a:"M"+q+","+u+"H"+A),N.attr("opacity",1).attr("transform",function(T){return p(D(T)+u)}),I.attr(l+"2",c*i),h.attr(l,c*k).text(y),L.filter(Cc).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===Wn?"start":t===tr?"end":"middle"),L.each(function(){this.__axis=D})}return f.scale=function(m){return arguments.length?(e=m,f):e},f.ticks=function(){return r=Array.from(arguments),f},f.tickArguments=function(m){return arguments.length?(r=m==null?[]:Array.from(m),f):r.slice()},f.tickValues=function(m){return arguments.length?(n=m==null?null:Array.from(m),f):n&&n.slice()},f.tickFormat=function(m){return arguments.length?(o=m,f):o},f.tickSize=function(m){return arguments.length?(i=a=+m,f):i},f.tickSizeInner=function(m){return arguments.length?(i=+m,f):i},f.tickSizeOuter=function(m){return arguments.length?(a=+m,f):a},f.tickPadding=function(m){return arguments.length?(s=+m,f):s},f.offset=function(m){return arguments.length?(u=+m,f):u},f}function Fr(t){return Ii(Xn,t)}function Or(t){return Ii(tr,t)}var qc={value:()=>{}};function Bi(){for(var t=0,e=arguments.length,r={},n;t=0&&(n=r.slice(o+1),r=r.slice(0,o)),r&&!e.hasOwnProperty(r))throw new Error("unknown type: "+r);return{type:r,name:n}})}Pr.prototype=Bi.prototype={constructor:Pr,on:function(t,e){var r=this._,n=Ic(t+"",r),o,i=-1,a=n.length;if(arguments.length<2){for(;++i0)for(var r=new Array(o),n=0,o,i;n=0&&(e=t.slice(0,r))!=="xmlns"&&(t=t.slice(r+1)),Zn.hasOwnProperty(e)?{space:Zn[e],local:t}:t}function Bc(t){return function(){var e=this.ownerDocument,r=this.namespaceURI;return r===$r&&e.documentElement.namespaceURI===$r?e.createElement(t):e.createElementNS(r,t)}}function Rc(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Ur(t){var e=qt(t);return(e.local?Rc:Bc)(e)}function Hc(){}function re(t){return t==null?Hc:function(){return this.querySelector(t)}}function Ri(t){typeof t!="function"&&(t=re(t));for(var e=this._groups,r=e.length,n=new Array(r),o=0;o=A&&(A=q+1);!(L=k[A])&&++A=0;)(a=n[o])&&(i&&a.compareDocumentPosition(i)^4&&i.parentNode.insertBefore(a,i),i=a);return this}function Xi(t){t||(t=Zc);function e(p,f){return p&&f?t(p.__data__,f.__data__):!p-!f}for(var r=this._groups,n=r.length,o=new Array(n),i=0;ie?1:t>=e?0:NaN}function ji(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function Zi(){return Array.from(this)}function Ji(){for(var t=this._groups,e=0,r=t.length;e1?this.each((e==null?nf:typeof e=="function"?af:of)(t,e,r??"")):Ft(this.node(),t)}function Ft(t,e){return t.style.getPropertyValue(e)||zr(t).getComputedStyle(t,null).getPropertyValue(e)}function sf(t){return function(){delete this[t]}}function uf(t,e){return function(){this[t]=e}}function lf(t,e){return function(){var r=e.apply(this,arguments);r==null?delete this[t]:this[t]=r}}function na(t,e){return arguments.length>1?this.each((e==null?sf:typeof e=="function"?lf:uf)(t,e)):this.node()[t]}function oa(t){return t.trim().split(/^|\s+/)}function Qn(t){return t.classList||new ia(t)}function ia(t){this._node=t,this._names=oa(t.getAttribute("class")||"")}ia.prototype={add:function(t){var e=this._names.indexOf(t);e<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var e=this._names.indexOf(t);e>=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function aa(t,e){for(var r=Qn(t),n=-1,o=e.length;++n=0&&(r=e.slice(n+1),e=e.slice(0,n)),{type:e,name:r}})}function Lf(t){return function(){var e=this.__on;if(e){for(var r=0,n=-1,o=e.length,i;r>8&15|e>>4&240,e>>4&15|e&240,(e&15)<<4|e&15,1):r===8?Yr(e>>24&255,e>>16&255,e>>8&255,(e&255)/255):r===4?Yr(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|e&240,((e&15)<<4|e&15)/255):null):(e=If.exec(t))?new et(e[1],e[2],e[3],1):(e=Nf.exec(t))?new et(e[1]*255/100,e[2]*255/100,e[3]*255/100,1):(e=Bf.exec(t))?Yr(e[1],e[2],e[3],e[4]):(e=Rf.exec(t))?Yr(e[1]*255/100,e[2]*255/100,e[3]*255/100,e[4]):(e=Hf.exec(t))?Aa(e[1],e[2]/100,e[3]/100,1):(e=Ff.exec(t))?Aa(e[1],e[2]/100,e[3]/100,e[4]):_a.hasOwnProperty(t)?Sa(_a[t]):t==="transparent"?new et(NaN,NaN,NaN,0):null}function Sa(t){return new et(t>>16&255,t>>8&255,t&255,1)}function Yr(t,e,r,n){return n<=0&&(t=e=r=NaN),new et(t,e,r,n)}function eo(t){return t instanceof ae||(t=yt(t)),t?(t=t.rgb(),new et(t.r,t.g,t.b,t.opacity)):new et}function qe(t,e,r,n){return arguments.length===1?eo(t):new et(t,e,r,n??1)}function et(t,e,r,n){this.r=+t,this.g=+e,this.b=+r,this.opacity=+n}De(et,qe,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new et(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new et(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new et(oe(this.r),oe(this.g),oe(this.b),Xr(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:La,formatHex:La,formatHex8:$f,formatRgb:Ea,toString:Ea}));function La(){return`#${ne(this.r)}${ne(this.g)}${ne(this.b)}`}function $f(){return`#${ne(this.r)}${ne(this.g)}${ne(this.b)}${ne((isNaN(this.opacity)?1:this.opacity)*255)}`}function Ea(){let t=Xr(this.opacity);return`${t===1?"rgb(":"rgba("}${oe(this.r)}, ${oe(this.g)}, ${oe(this.b)}${t===1?")":`, ${t})`}`}function Xr(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function oe(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function ne(t){return t=oe(t),(t<16?"0":"")+t.toString(16)}function Aa(t,e,r,n){return n<=0?t=e=r=NaN:r<=0||r>=1?t=e=NaN:e<=0&&(t=NaN),new xt(t,e,r,n)}function Ca(t){if(t instanceof xt)return new xt(t.h,t.s,t.l,t.opacity);if(t instanceof ae||(t=yt(t)),!t)return new xt;if(t instanceof xt)return t;t=t.rgb();var e=t.r/255,r=t.g/255,n=t.b/255,o=Math.min(e,r,n),i=Math.max(e,r,n),a=NaN,s=i-o,u=(i+o)/2;return s?(e===i?a=(r-n)/s+(r0&&u<1?0:a,new xt(a,s,u,t.opacity)}function qa(t,e,r,n){return arguments.length===1?Ca(t):new xt(t,e,r,n??1)}function xt(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}De(xt,qa,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new xt(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new xt(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,e=isNaN(t)||isNaN(this.s)?0:this.s,r=this.l,n=r+(r<.5?r:1-r)*e,o=2*r-n;return new et(to(t>=240?t-240:t+120,o,n),to(t,o,n),to(t<120?t+240:t-120,o,n),this.opacity)},clamp(){return new xt(Da(this.h),Wr(this.s),Wr(this.l),Xr(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){let t=Xr(this.opacity);return`${t===1?"hsl(":"hsla("}${Da(this.h)}, ${Wr(this.s)*100}%, ${Wr(this.l)*100}%${t===1?")":`, ${t})`}`}}));function Da(t){return t=(t||0)%360,t<0?t+360:t}function Wr(t){return Math.max(0,Math.min(1,t||0))}function to(t,e,r){return(t<60?e+(r-e)*t/60:t<180?r:t<240?e+(r-e)*(240-t)/60:e)*255}var Ia=Math.PI/180,Na=180/Math.PI;var Fa=-.14861,ro=1.78277,no=-.29227,jr=-.90649,ar=1.97294,Ba=ar*jr,Ra=ar*ro,Ha=ro*no-jr*Fa;function Uf(t){if(t instanceof se)return new se(t.h,t.s,t.l,t.opacity);t instanceof et||(t=eo(t));var e=t.r/255,r=t.g/255,n=t.b/255,o=(Ha*n+Ba*e-Ra*r)/(Ha+Ba-Ra),i=n-o,a=(ar*(r-o)-no*i)/jr,s=Math.sqrt(a*a+i*i)/(ar*o*(1-o)),u=s?Math.atan2(a,i)*Na-120:NaN;return new se(u<0?u+360:u,s,o,t.opacity)}function mt(t,e,r,n){return arguments.length===1?Uf(t):new se(t,e,r,n??1)}function se(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}De(se,mt,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new se(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new se(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=isNaN(this.h)?0:(this.h+120)*Ia,e=+this.l,r=isNaN(this.s)?0:this.s*e*(1-e),n=Math.cos(t),o=Math.sin(t);return new et(255*(e+r*(Fa*n+ro*o)),255*(e+r*(no*n+jr*o)),255*(e+r*(ar*n)),this.opacity)}}));function oo(t,e,r,n,o){var i=t*t,a=i*t;return((1-3*t+3*i-a)*e+(4-6*i+3*a)*r+(1+3*t+3*i-3*a)*n+a*o)/6}function Oa(t){var e=t.length-1;return function(r){var n=r<=0?r=0:r>=1?(r=1,e-1):Math.floor(r*e),o=t[n],i=t[n+1],a=n>0?t[n-1]:2*o-i,s=n()=>t;function $a(t,e){return function(r){return t+r*e}}function Gf(t,e,r){return t=Math.pow(t,r),e=Math.pow(e,r)-t,r=1/r,function(n){return Math.pow(t+n*e,r)}}function Ua(t,e){var r=e-t;return r?$a(t,r>180||r<-180?r-360*Math.round(r/360):r):Ie(isNaN(t)?e:t)}function Ga(t){return(t=+t)==1?Nt:function(e,r){return r-e?Gf(e,r,t):Ie(isNaN(e)?r:e)}}function Nt(t,e){var r=e-t;return r?$a(t,r):Ie(isNaN(t)?e:t)}var ue=function t(e){var r=Ga(e);function n(o,i){var a=r((o=qe(o)).r,(i=qe(i)).r),s=r(o.g,i.g),u=r(o.b,i.b),c=Nt(o.opacity,i.opacity);return function(l){return o.r=a(l),o.g=s(l),o.b=u(l),o.opacity=c(l),o+""}}return n.gamma=t,n}(1);function Va(t){return function(e){var r=e.length,n=new Array(r),o=new Array(r),i=new Array(r),a,s;for(a=0;ar&&(i=e.slice(r,i),s[a]?s[a]+=i:s[++a]=i),(n=n[0])===(o=o[0])?s[a]?s[a]+=o:s[++a]=o:(s[++a]=null,u.push({i:a,x:Z(n,o)})),r=io.lastIndex;return r180?l+=360:l-c>180&&(c+=360),f.push({i:p.push(o(p)+"rotate(",null,n)-2,x:Z(c,l)})):l&&p.push(o(p)+"rotate("+l+n)}function s(c,l,p,f){c!==l?f.push({i:p.push(o(p)+"skewX(",null,n)-2,x:Z(c,l)}):l&&p.push(o(p)+"skewX("+l+n)}function u(c,l,p,f,m,d){if(c!==p||l!==f){var y=m.push(o(m)+"scale(",null,",",null,")");d.push({i:y-4,x:Z(c,p)},{i:y-2,x:Z(l,f)})}else(p!==1||f!==1)&&m.push(o(m)+"scale("+p+","+f+")")}return function(c,l){var p=[],f=[];return c=t(c),l=t(l),i(c.translateX,c.translateY,l.translateX,l.translateY,p,f),a(c.rotate,l.rotate,p,f),s(c.skewX,l.skewX,p,f),u(c.scaleX,c.scaleY,l.scaleX,l.scaleY,p,f),c=l=null,function(m){for(var d=-1,y=f.length,k;++d=0&&t._call.call(void 0,e),t=t._next;--Ne}function es(){le=(tn=pr.now())+en,Ne=cr=0;try{os()}finally{Ne=0,Jf(),le=0}}function Zf(){var t=pr.now(),e=t-tn;e>rs&&(en-=e,tn=t)}function Jf(){for(var t,e=Kr,r,n=1/0;e;)e._call?(n>e._time&&(n=e._time),t=e,e=e._next):(r=e._next,e._next=null,e=t?t._next=r:Kr=r);fr=t,co(n)}function co(t){if(!Ne){cr&&(cr=clearTimeout(cr));var e=t-le;e>24?(t<1/0&&(cr=setTimeout(es,t-pr.now()-en)),lr&&(lr=clearInterval(lr))):(lr||(tn=pr.now(),lr=setInterval(Zf,rs)),Ne=1,ns(es))}}function nn(t,e,r){var n=new mr;return e=e==null?0:+e,n.restart(o=>{n.stop(),t(o+e)},e,r),n}var Qf=jn("start","end","cancel","interrupt"),Kf=[],ss=0,is=1,an=2,on=3,as=4,sn=5,hr=6;function Pt(t,e,r,n,o,i){var a=t.__transition;if(!a)t.__transition={};else if(r in a)return;tp(t,r,{name:e,index:n,group:o,on:Qf,tween:Kf,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:ss})}function gr(t,e){var r=J(t,e);if(r.state>ss)throw new Error("too late; already scheduled");return r}function rt(t,e){var r=J(t,e);if(r.state>on)throw new Error("too late; already running");return r}function J(t,e){var r=t.__transition;if(!r||!(r=r[e]))throw new Error("transition not found");return r}function tp(t,e,r){var n=t.__transition,o;n[e]=r,r.timer=rn(i,0,r.time);function i(c){r.state=is,r.timer.restart(a,r.delay,r.time),r.delay<=c&&a(c-r.delay)}function a(c){var l,p,f,m;if(r.state!==is)return u();for(l in n)if(m=n[l],m.name===r.name){if(m.state===on)return nn(a);m.state===as?(m.state=hr,m.timer.stop(),m.on.call("interrupt",t,t.__data__,m.index,m.group),delete n[l]):+lan&&n.state=0&&(e=e.slice(0,r)),!e||e==="start"})}function bp(t,e,r){var n,o,i=vp(e)?gr:rt;return function(){var a=i(this,t),s=a.on;s!==n&&(o=(n=s).copy()).on(e,r),a.on=o}}function ys(t,e){var r=this._id;return arguments.length<2?J(this.node(),r).on.on(t):this.each(bp(r,t,e))}function wp(t){return function(){var e=this.parentNode;for(var r in this.__transition)if(+r!==t)return;e&&e.removeChild(this)}}function vs(){return this.on("end.remove",wp(this._id))}function bs(t){var e=this._name,r=this._id;typeof t!="function"&&(t=re(t));for(var n=this._groups,o=n.length,i=new Array(o),a=0;a=0))throw new Error(`invalid digits: ${t}`);if(e>15)return qs;let r=10**e;return function(n){this._+=n[0];for(let o=1,i=n.length;oce)if(!(Math.abs(p*u-c*l)>ce)||!i)this._append`L${this._x1=e},${this._y1=r}`;else{let m=n-a,d=o-s,y=u*u+c*c,k=m*m+d*d,_=Math.sqrt(y),q=Math.sqrt(f),A=i*Math.tan((po-Math.acos((y+f-k)/(2*_*q)))/2),D=A/q,L=A/_;Math.abs(D-1)>ce&&this._append`L${e+D*l},${r+D*p}`,this._append`A${i},${i},0,0,${+(p*m>l*d)},${this._x1=e+L*u},${this._y1=r+L*c}`}}arc(e,r,n,o,i,a){if(e=+e,r=+r,n=+n,a=!!a,n<0)throw new Error(`negative radius: ${n}`);let s=n*Math.cos(o),u=n*Math.sin(o),c=e+s,l=r+u,p=1^a,f=a?o-i:i-o;this._x1===null?this._append`M${c},${l}`:(Math.abs(this._x1-c)>ce||Math.abs(this._y1-l)>ce)&&this._append`L${c},${l}`,n&&(f<0&&(f=f%mo+mo),f>Hp?this._append`A${n},${n},0,1,${p},${e-s},${r-u}A${n},${n},0,1,${p},${this._x1=c},${this._y1=l}`:f>ce&&this._append`A${n},${n},0,${+(f>=po)},${p},${this._x1=e+n*Math.cos(i)},${this._y1=r+n*Math.sin(i)}`)}rect(e,r,n,o){this._append`M${this._x0=this._x1=+e},${this._y0=this._y1=+r}h${n=+n}v${+o}h${-n}Z`}toString(){return this._}};function Is(){return new fe}Is.prototype=fe.prototype;function Ns(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)}function pe(t,e){if((r=(t=e?t.toExponential(e-1):t.toExponential()).indexOf("e"))<0)return null;var r,n=t.slice(0,r);return[n.length>1?n[0]+n.slice(2):n,+t.slice(r+1)]}function Mt(t){return t=pe(Math.abs(t)),t?t[1]:NaN}function Bs(t,e){return function(r,n){for(var o=r.length,i=[],a=0,s=t[0],u=0;o>0&&s>0&&(u+s+1>n&&(s=Math.max(1,n-u)),i.push(r.substring(o-=s,o+s)),!((u+=s+1)>n));)s=t[a=(a+1)%t.length];return i.reverse().join(e)}}function Rs(t){return function(e){return e.replace(/[0-9]/g,function(r){return t[+r]})}}var Op=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function St(t){if(!(e=Op.exec(t)))throw new Error("invalid format: "+t);var e;return new pn({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}St.prototype=pn.prototype;function pn(t){this.fill=t.fill===void 0?" ":t.fill+"",this.align=t.align===void 0?">":t.align+"",this.sign=t.sign===void 0?"-":t.sign+"",this.symbol=t.symbol===void 0?"":t.symbol+"",this.zero=!!t.zero,this.width=t.width===void 0?void 0:+t.width,this.comma=!!t.comma,this.precision=t.precision===void 0?void 0:+t.precision,this.trim=!!t.trim,this.type=t.type===void 0?"":t.type+""}pn.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function Hs(t){t:for(var e=t.length,r=1,n=-1,o;r0&&(n=0);break}return n>0?t.slice(0,n)+t.slice(o+1):t}var ho;function Fs(t,e){var r=pe(t,e);if(!r)return t+"";var n=r[0],o=r[1],i=o-(ho=Math.max(-8,Math.min(8,Math.floor(o/3)))*3)+1,a=n.length;return i===a?n:i>a?n+new Array(i-a+1).join("0"):i>0?n.slice(0,i)+"."+n.slice(i):"0."+new Array(1-i).join("0")+pe(t,Math.max(0,e+i-1))[0]}function go(t,e){var r=pe(t,e);if(!r)return t+"";var n=r[0],o=r[1];return o<0?"0."+new Array(-o).join("0")+n:n.length>o+1?n.slice(0,o+1)+"."+n.slice(o+1):n+new Array(o-n.length+2).join("0")}var xo={"%":(t,e)=>(t*100).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:Ns,e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>go(t*100,e),r:go,s:Fs,X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function yo(t){return t}var Os=Array.prototype.map,Ps=["y","z","a","f","p","n","\xB5","m","","k","M","G","T","P","E","Z","Y"];function $s(t){var e=t.grouping===void 0||t.thousands===void 0?yo:Bs(Os.call(t.grouping,Number),t.thousands+""),r=t.currency===void 0?"":t.currency[0]+"",n=t.currency===void 0?"":t.currency[1]+"",o=t.decimal===void 0?".":t.decimal+"",i=t.numerals===void 0?yo:Rs(Os.call(t.numerals,String)),a=t.percent===void 0?"%":t.percent+"",s=t.minus===void 0?"\u2212":t.minus+"",u=t.nan===void 0?"NaN":t.nan+"";function c(p){p=St(p);var f=p.fill,m=p.align,d=p.sign,y=p.symbol,k=p.zero,_=p.width,q=p.comma,A=p.precision,D=p.trim,L=p.type;L==="n"?(q=!0,L="g"):xo[L]||(A===void 0&&(A=12),D=!0,L="g"),(k||f==="0"&&m==="=")&&(k=!0,f="0",m="=");var b=y==="$"?r:y==="#"&&/[boxX]/.test(L)?"0"+L.toLowerCase():"",N=y==="$"?n:/[%p]/.test(L)?a:"",H=xo[L],P=/[defgprs%]/.test(L);A=A===void 0?6:/[gprs]/.test(L)?Math.max(1,Math.min(21,A)):Math.max(0,Math.min(20,A));function I(h){var T=b,E=N,R,g,x;if(L==="c")E=H(h)+E,h="";else{h=+h;var M=h<0||1/h<0;if(h=isNaN(h)?u:H(Math.abs(h),A),D&&(h=Hs(h)),M&&+h==0&&d!=="+"&&(M=!1),T=(M?d==="("?d:s:d==="-"||d==="("?"":d)+T,E=(L==="s"?Ps[8+ho/3]:"")+E+(M&&d==="("?")":""),P){for(R=-1,g=h.length;++Rx||x>57){E=(x===46?o+h.slice(R+1):h.slice(R))+E,h=h.slice(0,R);break}}}q&&!k&&(h=e(h,1/0));var S=T.length+h.length+E.length,v=S<_?new Array(_-S+1).join(f):"";switch(q&&k&&(h=e(v+h,v.length?_-E.length:1/0),v=""),m){case"<":h=T+h+E+v;break;case"=":h=T+v+h+E;break;case"^":h=v.slice(0,S=v.length>>1)+T+h+E+v.slice(S);break;default:h=v+T+h+E;break}return i(h)}return I.toString=function(){return p+""},I}function l(p,f){var m=c((p=St(p),p.type="f",p)),d=Math.max(-8,Math.min(8,Math.floor(Mt(f)/3)))*3,y=Math.pow(10,-d),k=Ps[8+d/3];return function(_){return m(y*_)+k}}return{format:c,formatPrefix:l}}var mn,bt,dn;vo({thousands:",",grouping:[3],currency:["$",""]});function vo(t){return mn=$s(t),bt=mn.format,dn=mn.formatPrefix,mn}function bo(t){return Math.max(0,-Mt(Math.abs(t)))}function wo(t,e){return Math.max(0,Math.max(-8,Math.min(8,Math.floor(Mt(e)/3)))*3-Mt(Math.abs(t)))}function ko(t,e){return t=Math.abs(t),e=Math.abs(e)-t,Math.max(0,Mt(e)-Mt(t))+1}function Pp(t){var e=0,r=t.children,n=r&&r.length;if(!n)e=1;else for(;--n>=0;)e+=r[n].value;t.value=e}function Us(){return this.eachAfter(Pp)}function Gs(t,e){let r=-1;for(let n of this)t.call(e,n,++r,this);return this}function Vs(t,e){for(var r=this,n=[r],o,i,a=-1;r=n.pop();)if(t.call(e,r,++a,this),o=r.children)for(i=o.length-1;i>=0;--i)n.push(o[i]);return this}function zs(t,e){for(var r=this,n=[r],o=[],i,a,s,u=-1;r=n.pop();)if(o.push(r),i=r.children)for(a=0,s=i.length;a=0;)r+=n[o].value;e.value=r})}function Xs(t){return this.eachBefore(function(e){e.children&&e.children.sort(t)})}function js(t){for(var e=this,r=$p(e,t),n=[e];e!==r;)e=e.parent,n.push(e);for(var o=n.length;t!==r;)n.splice(o,0,t),t=t.parent;return n}function $p(t,e){if(t===e)return t;var r=t.ancestors(),n=e.ancestors(),o=null;for(t=r.pop(),e=n.pop();t===e;)o=t,t=r.pop(),e=n.pop();return o}function Zs(){for(var t=this,e=[t];t=t.parent;)e.push(t);return e}function Js(){return Array.from(this)}function Qs(){var t=[];return this.eachBefore(function(e){e.children||t.push(e)}),t}function Ks(){var t=this,e=[];return t.each(function(r){r!==t&&e.push({source:r.parent,target:r})}),e}function*tu(){var t=this,e,r=[t],n,o,i;do for(e=r.reverse(),r=[];t=e.pop();)if(yield t,n=t.children)for(o=0,i=n.length;o=0;--s)o.push(i=a[s]=new yr(a[s])),i.parent=n,i.depth=n.depth+1;return r.eachBefore(Yp)}function Up(){return Re(this).eachBefore(zp)}function Gp(t){return t.children}function Vp(t){return Array.isArray(t)?t[1]:null}function zp(t){t.data.value!==void 0&&(t.value=t.data.value),t.data=t.data.data}function Yp(t){var e=0;do t.height=e;while((t=t.parent)&&t.height<++e)}function yr(t){this.data=t,this.depth=this.height=0,this.parent=null}yr.prototype=Re.prototype={constructor:yr,count:Us,each:Gs,eachAfter:zs,eachBefore:Vs,find:Ys,sum:Ws,sort:Xs,path:js,ancestors:Zs,descendants:Js,leaves:Qs,links:Ks,copy:Up,[Symbol.iterator]:tu};function eu(t){if(typeof t!="function")throw new Error;return t}function He(){return 0}function Fe(t){return function(){return t}}function ru(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)}function nu(t,e,r,n,o){for(var i=t.children,a,s=-1,u=i.length,c=t.value&&(n-e)/t.value;++sq&&(q=c),b=k*k*L,A=Math.max(q/b,b/_),A>D){k-=c;break}D=A}a.push(u={value:k,dice:m1?n:1)},r}(Wp);function _o(){var t=vr,e=!1,r=1,n=1,o=[0],i=He,a=He,s=He,u=He,c=He;function l(f){return f.x0=f.y0=0,f.x1=r,f.y1=n,f.eachBefore(p),o=[0],e&&f.eachBefore(ru),f}function p(f){var m=o[f.depth],d=f.x0+m,y=f.y0+m,k=f.x1-m,_=f.y1-m;ke&&(r=t,t=e,e=r),function(n){return Math.max(t,Math.min(e,n))}}function Zp(t,e,r){var n=t[0],o=t[1],i=e[0],a=e[1];return o2?Jp:Zp,u=c=null,p}function p(f){return f==null||isNaN(f=+f)?i:(u||(u=s(t.map(n),e,r)))(n(a(f)))}return p.invert=function(f){return a(o((c||(c=s(e,t.map(n),Z)))(f)))},p.domain=function(f){return arguments.length?(t=Array.from(f,So),l()):t.slice()},p.range=function(f){return arguments.length?(e=Array.from(f),l()):e.slice()},p.rangeRound=function(f){return e=Array.from(f),r=ur,l()},p.clamp=function(f){return arguments.length?(a=f?!0:Ut,l()):a!==Ut},p.interpolate=function(f){return arguments.length?(r=f,l()):r},p.unknown=function(f){return arguments.length?(i=f,p):i},function(f,m){return n=f,o=m,l()}}function wr(){return Qp()(Ut,Ut)}function Eo(t,e,r,n){var o=Le(t,e,r),i;switch(n=St(n??",f"),n.type){case"s":{var a=Math.max(Math.abs(t),Math.abs(e));return n.precision==null&&!isNaN(i=wo(o,a))&&(n.precision=i),dn(n,a)}case"":case"e":case"g":case"p":case"r":{n.precision==null&&!isNaN(i=ko(o,Math.max(Math.abs(t),Math.abs(e))))&&(n.precision=i-(n.type==="e"));break}case"f":case"%":{n.precision==null&&!isNaN(i=bo(o))&&(n.precision=i-(n.type==="%")*2);break}}return bt(n)}function Kp(t){var e=t.domain;return t.ticks=function(r){var n=e();return te(n[0],n[n.length-1],r??10)},t.tickFormat=function(r,n){var o=e();return Eo(o[0],o[o.length-1],r??10,n)},t.nice=function(r){r==null&&(r=10);var n=e(),o=0,i=n.length-1,a=n[o],s=n[i],u,c,l=10;for(s0;){if(c=Qe(a,s,r),c===u)return n[o]=a,n[i]=s,e(n);if(c>0)a=Math.floor(a/c)*c,s=Math.ceil(s/c)*c;else if(c<0)a=Math.ceil(a*c)/c,s=Math.floor(s*c)/c;else break;u=c}return t},t}function de(){var t=wr();return t.copy=function(){return hn(t,de())},$t.apply(t,arguments),Kp(t)}function kr(t,e){t=t.slice();var r=0,n=t.length-1,o=t[r],i=t[n],a;return iMath.pow(t,e)}function om(t){return t===Math.E?Math.log:t===10&&Math.log10||t===2&&Math.log2||(t=Math.log(t),e=>Math.log(e)/t)}function lu(t){return(e,r)=>-t(-e,r)}function cu(t){let e=t(su,uu),r=e.domain,n=10,o,i;function a(){return o=om(n),i=nm(n),r()[0]<0?(o=lu(o),i=lu(i),t(tm,em)):t(su,uu),e}return e.base=function(s){return arguments.length?(n=+s,a()):n},e.domain=function(s){return arguments.length?(r(s),a()):r()},e.ticks=s=>{let u=r(),c=u[0],l=u[u.length-1],p=l0){for(;f<=m;++f)for(d=1;dl)break;_.push(y)}}else for(;f<=m;++f)for(d=n-1;d>=1;--d)if(y=f>0?d/i(-f):d*i(f),!(yl)break;_.push(y)}_.length*2{if(s==null&&(s=10),u==null&&(u=n===10?"s":","),typeof u!="function"&&(!(n%1)&&(u=St(u)).precision==null&&(u.trim=!0),u=bt(u)),s===1/0)return u;let c=Math.max(1,n*s/e.ticks().length);return l=>{let p=l/i(Math.round(o(l)));return p*nr(kr(r(),{floor:s=>i(Math.floor(o(s))),ceil:s=>i(Math.ceil(o(s)))})),e}var Ao=new Date,Do=new Date;function z(t,e,r,n){function o(i){return t(i=arguments.length===0?new Date:new Date(+i)),i}return o.floor=i=>(t(i=new Date(+i)),i),o.ceil=i=>(t(i=new Date(i-1)),e(i,1),t(i),i),o.round=i=>{let a=o(i),s=o.ceil(i);return i-a(e(i=new Date(+i),a==null?1:Math.floor(a)),i),o.range=(i,a,s)=>{let u=[];if(i=o.ceil(i),s=s==null?1:Math.floor(s),!(i0))return u;let c;do u.push(c=new Date(+i)),e(i,s),t(i);while(cz(a=>{if(a>=a)for(;t(a),!i(a);)a.setTime(a-1)},(a,s)=>{if(a>=a)if(s<0)for(;++s<=0;)for(;e(a,-1),!i(a););else for(;--s>=0;)for(;e(a,1),!i(a););}),r&&(o.count=(i,a)=>(Ao.setTime(+i),Do.setTime(+a),t(Ao),t(Do),Math.floor(r(Ao,Do))),o.every=i=>(i=Math.floor(i),!isFinite(i)||!(i>0)?null:i>1?o.filter(n?a=>n(a)%i===0:a=>o.count(0,a)%i===0):o)),o}var _r=z(()=>{},(t,e)=>{t.setTime(+t+e)},(t,e)=>e-t);_r.every=t=>(t=Math.floor(t),!isFinite(t)||!(t>0)?null:t>1?z(e=>{e.setTime(Math.floor(e/t)*t)},(e,r)=>{e.setTime(+e+r*t)},(e,r)=>(r-e)/t):_r);var m_=_r.range;var Lt=z(t=>{t.setTime(t-t.getMilliseconds())},(t,e)=>{t.setTime(+t+e*1e3)},(t,e)=>(e-t)/1e3,t=>t.getUTCSeconds()),fu=Lt.range;var Oe=z(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*1e3)},(t,e)=>{t.setTime(+t+e*6e4)},(t,e)=>(e-t)/6e4,t=>t.getMinutes()),im=Oe.range,gn=z(t=>{t.setUTCSeconds(0,0)},(t,e)=>{t.setTime(+t+e*6e4)},(t,e)=>(e-t)/6e4,t=>t.getUTCMinutes()),am=gn.range;var Pe=z(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*1e3-t.getMinutes()*6e4)},(t,e)=>{t.setTime(+t+e*36e5)},(t,e)=>(e-t)/36e5,t=>t.getHours()),sm=Pe.range,xn=z(t=>{t.setUTCMinutes(0,0,0)},(t,e)=>{t.setTime(+t+e*36e5)},(t,e)=>(e-t)/36e5,t=>t.getUTCHours()),um=xn.range;var Rt=z(t=>t.setHours(0,0,0,0),(t,e)=>t.setDate(t.getDate()+e),(t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*6e4)/864e5,t=>t.getDate()-1),lm=Rt.range,Mr=z(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>t.getUTCDate()-1),cm=Mr.range,yn=z(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>Math.floor(t/864e5)),fm=yn.range;function xe(t){return z(e=>{e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)},(e,r)=>{e.setDate(e.getDate()+r*7)},(e,r)=>(r-e-(r.getTimezoneOffset()-e.getTimezoneOffset())*6e4)/6048e5)}var Ht=xe(0),$e=xe(1),mu=xe(2),du=xe(3),Gt=xe(4),hu=xe(5),gu=xe(6),xu=Ht.range,pm=$e.range,mm=mu.range,dm=du.range,hm=Gt.range,gm=hu.range,xm=gu.range;function ye(t){return z(e=>{e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)},(e,r)=>{e.setUTCDate(e.getUTCDate()+r*7)},(e,r)=>(r-e)/6048e5)}var ve=ye(0),Ue=ye(1),yu=ye(2),vu=ye(3),Vt=ye(4),bu=ye(5),wu=ye(6),ku=ve.range,ym=Ue.range,vm=yu.range,bm=vu.range,wm=Vt.range,km=bu.range,_m=wu.range;var Ge=z(t=>{t.setDate(1),t.setHours(0,0,0,0)},(t,e)=>{t.setMonth(t.getMonth()+e)},(t,e)=>e.getMonth()-t.getMonth()+(e.getFullYear()-t.getFullYear())*12,t=>t.getMonth()),Tm=Ge.range,vn=z(t=>{t.setUTCDate(1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCMonth(t.getUTCMonth()+e)},(t,e)=>e.getUTCMonth()-t.getUTCMonth()+(e.getUTCFullYear()-t.getUTCFullYear())*12,t=>t.getUTCMonth()),Mm=vn.range;var pt=z(t=>{t.setMonth(0,1),t.setHours(0,0,0,0)},(t,e)=>{t.setFullYear(t.getFullYear()+e)},(t,e)=>e.getFullYear()-t.getFullYear(),t=>t.getFullYear());pt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:z(e=>{e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)},(e,r)=>{e.setFullYear(e.getFullYear()+r*t)});var Sm=pt.range,wt=z(t=>{t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCFullYear(t.getUTCFullYear()+e)},(t,e)=>e.getUTCFullYear()-t.getUTCFullYear(),t=>t.getUTCFullYear());wt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:z(e=>{e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)},(e,r)=>{e.setUTCFullYear(e.getUTCFullYear()+r*t)});var Lm=wt.range;function Tu(t,e,r,n,o,i){let a=[[Lt,1,1e3],[Lt,5,5*1e3],[Lt,15,15*1e3],[Lt,30,30*1e3],[i,1,6e4],[i,5,5*6e4],[i,15,15*6e4],[i,30,30*6e4],[o,1,36e5],[o,3,3*36e5],[o,6,6*36e5],[o,12,12*36e5],[n,1,864e5],[n,2,2*864e5],[r,1,6048e5],[e,1,2592e6],[e,3,3*2592e6],[t,1,31536e6]];function s(c,l,p){let f=lk).right(a,f);if(m===a.length)return t.every(Le(c/31536e6,l/31536e6,p));if(m===0)return _r.every(Math.max(Le(c,l,p),1));let[d,y]=a[f/a[m-1][2]53)return null;"w"in w||(w.w=1),"Z"in w?(Y=No(Sr(w.y,0,1)),lt=Y.getUTCDay(),Y=lt>4||lt===0?Ue.ceil(Y):Ue(Y),Y=Mr.offset(Y,(w.V-1)*7),w.y=Y.getUTCFullYear(),w.m=Y.getUTCMonth(),w.d=Y.getUTCDate()+(w.w+6)%7):(Y=Io(Sr(w.y,0,1)),lt=Y.getDay(),Y=lt>4||lt===0?$e.ceil(Y):$e(Y),Y=Rt.offset(Y,(w.V-1)*7),w.y=Y.getFullYear(),w.m=Y.getMonth(),w.d=Y.getDate()+(w.w+6)%7)}else("W"in w||"U"in w)&&("w"in w||(w.w="u"in w?w.u%7:"W"in w?1:0),lt="Z"in w?No(Sr(w.y,0,1)).getUTCDay():Io(Sr(w.y,0,1)).getDay(),w.m=0,w.d="W"in w?(w.w+6)%7+w.W*7-(lt+5)%7:w.w+w.U*7-(lt+6)%7);return"Z"in w?(w.H+=w.Z/100|0,w.M+=w.Z%100,No(w)):Io(w)}}function H(C,F,U,w){for(var st=0,Y=F.length,lt=U.length,ct,Qt;st=lt)return-1;if(ct=F.charCodeAt(st++),ct===37){if(ct=F.charAt(st++),Qt=L[ct in Mu?F.charAt(st++):ct],!Qt||(w=Qt(C,U,w))<0)return-1}else if(ct!=U.charCodeAt(w++))return-1}return w}function P(C,F,U){var w=c.exec(F.slice(U));return w?(C.p=l.get(w[0].toLowerCase()),U+w[0].length):-1}function I(C,F,U){var w=m.exec(F.slice(U));return w?(C.w=d.get(w[0].toLowerCase()),U+w[0].length):-1}function h(C,F,U){var w=p.exec(F.slice(U));return w?(C.w=f.get(w[0].toLowerCase()),U+w[0].length):-1}function T(C,F,U){var w=_.exec(F.slice(U));return w?(C.m=q.get(w[0].toLowerCase()),U+w[0].length):-1}function E(C,F,U){var w=y.exec(F.slice(U));return w?(C.m=k.get(w[0].toLowerCase()),U+w[0].length):-1}function R(C,F,U){return H(C,e,F,U)}function g(C,F,U){return H(C,r,F,U)}function x(C,F,U){return H(C,n,F,U)}function M(C){return a[C.getDay()]}function S(C){return i[C.getDay()]}function v(C){return u[C.getMonth()]}function B(C){return s[C.getMonth()]}function G(C){return o[+(C.getHours()>=12)]}function K(C){return 1+~~(C.getMonth()/3)}function ot(C){return a[C.getUTCDay()]}function ht(C){return i[C.getUTCDay()]}function tt(C){return u[C.getUTCMonth()]}function Dt(C){return s[C.getUTCMonth()]}function gt(C){return o[+(C.getUTCHours()>=12)]}function Je(C){return 1+~~(C.getUTCMonth()/3)}return{format:function(C){var F=b(C+="",A);return F.toString=function(){return C},F},parse:function(C){var F=N(C+="",!1);return F.toString=function(){return C},F},utcFormat:function(C){var F=b(C+="",D);return F.toString=function(){return C},F},utcParse:function(C){var F=N(C+="",!0);return F.toString=function(){return C},F}}}var Mu={"-":"",_:" ",0:"0"},Q=/^\s*\d+/,Cm=/^%/,qm=/[\\^$*+?|[\]().{}]/g;function V(t,e,r){var n=t<0?"-":"",o=(n?-t:t)+"",i=o.length;return n+(i[e.toLowerCase(),r]))}function Nm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.w=+n[0],r+n[0].length):-1}function Bm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.u=+n[0],r+n[0].length):-1}function Rm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.U=+n[0],r+n[0].length):-1}function Hm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.V=+n[0],r+n[0].length):-1}function Fm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.W=+n[0],r+n[0].length):-1}function Su(t,e,r){var n=Q.exec(e.slice(r,r+4));return n?(t.y=+n[0],r+n[0].length):-1}function Lu(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.y=+n[0]+(+n[0]>68?1900:2e3),r+n[0].length):-1}function Om(t,e,r){var n=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(r,r+6));return n?(t.Z=n[1]?0:-(n[2]+(n[3]||"00")),r+n[0].length):-1}function Pm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.q=n[0]*3-3,r+n[0].length):-1}function $m(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.m=n[0]-1,r+n[0].length):-1}function Eu(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.d=+n[0],r+n[0].length):-1}function Um(t,e,r){var n=Q.exec(e.slice(r,r+3));return n?(t.m=0,t.d=+n[0],r+n[0].length):-1}function Au(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.H=+n[0],r+n[0].length):-1}function Gm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.M=+n[0],r+n[0].length):-1}function Vm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.S=+n[0],r+n[0].length):-1}function zm(t,e,r){var n=Q.exec(e.slice(r,r+3));return n?(t.L=+n[0],r+n[0].length):-1}function Ym(t,e,r){var n=Q.exec(e.slice(r,r+6));return n?(t.L=Math.floor(n[0]/1e3),r+n[0].length):-1}function Wm(t,e,r){var n=Cm.exec(e.slice(r,r+1));return n?r+n[0].length:-1}function Xm(t,e,r){var n=Q.exec(e.slice(r));return n?(t.Q=+n[0],r+n[0].length):-1}function jm(t,e,r){var n=Q.exec(e.slice(r));return n?(t.s=+n[0],r+n[0].length):-1}function Du(t,e){return V(t.getDate(),e,2)}function Zm(t,e){return V(t.getHours(),e,2)}function Jm(t,e){return V(t.getHours()%12||12,e,2)}function Qm(t,e){return V(1+Rt.count(pt(t),t),e,3)}function Bu(t,e){return V(t.getMilliseconds(),e,3)}function Km(t,e){return Bu(t,e)+"000"}function td(t,e){return V(t.getMonth()+1,e,2)}function ed(t,e){return V(t.getMinutes(),e,2)}function rd(t,e){return V(t.getSeconds(),e,2)}function nd(t){var e=t.getDay();return e===0?7:e}function od(t,e){return V(Ht.count(pt(t)-1,t),e,2)}function Ru(t){var e=t.getDay();return e>=4||e===0?Gt(t):Gt.ceil(t)}function id(t,e){return t=Ru(t),V(Gt.count(pt(t),t)+(pt(t).getDay()===4),e,2)}function ad(t){return t.getDay()}function sd(t,e){return V($e.count(pt(t)-1,t),e,2)}function ud(t,e){return V(t.getFullYear()%100,e,2)}function ld(t,e){return t=Ru(t),V(t.getFullYear()%100,e,2)}function cd(t,e){return V(t.getFullYear()%1e4,e,4)}function fd(t,e){var r=t.getDay();return t=r>=4||r===0?Gt(t):Gt.ceil(t),V(t.getFullYear()%1e4,e,4)}function pd(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+V(e/60|0,"0",2)+V(e%60,"0",2)}function Cu(t,e){return V(t.getUTCDate(),e,2)}function md(t,e){return V(t.getUTCHours(),e,2)}function dd(t,e){return V(t.getUTCHours()%12||12,e,2)}function hd(t,e){return V(1+Mr.count(wt(t),t),e,3)}function Hu(t,e){return V(t.getUTCMilliseconds(),e,3)}function gd(t,e){return Hu(t,e)+"000"}function xd(t,e){return V(t.getUTCMonth()+1,e,2)}function yd(t,e){return V(t.getUTCMinutes(),e,2)}function vd(t,e){return V(t.getUTCSeconds(),e,2)}function bd(t){var e=t.getUTCDay();return e===0?7:e}function wd(t,e){return V(ve.count(wt(t)-1,t),e,2)}function Fu(t){var e=t.getUTCDay();return e>=4||e===0?Vt(t):Vt.ceil(t)}function kd(t,e){return t=Fu(t),V(Vt.count(wt(t),t)+(wt(t).getUTCDay()===4),e,2)}function _d(t){return t.getUTCDay()}function Td(t,e){return V(Ue.count(wt(t)-1,t),e,2)}function Md(t,e){return V(t.getUTCFullYear()%100,e,2)}function Sd(t,e){return t=Fu(t),V(t.getUTCFullYear()%100,e,2)}function Ld(t,e){return V(t.getUTCFullYear()%1e4,e,4)}function Ed(t,e){var r=t.getUTCDay();return t=r>=4||r===0?Vt(t):Vt.ceil(t),V(t.getUTCFullYear()%1e4,e,4)}function Ad(){return"+0000"}function qu(){return"%"}function Iu(t){return+t}function Nu(t){return Math.floor(+t/1e3)}var Ve,bn,Ou,Pu,$u;Ro({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function Ro(t){return Ve=Bo(t),bn=Ve.format,Ou=Ve.parse,Pu=Ve.utcFormat,$u=Ve.utcParse,Ve}function Dd(t){return new Date(t)}function Cd(t){return t instanceof Date?+t:+new Date(+t)}function Uu(t,e,r,n,o,i,a,s,u,c){var l=wr(),p=l.invert,f=l.domain,m=c(".%L"),d=c(":%S"),y=c("%I:%M"),k=c("%I %p"),_=c("%a %d"),q=c("%b %d"),A=c("%B"),D=c("%Y");function L(b){return(u(b)1?0:t<-1?ze:Math.acos(t)}function Po(t){return t>=1?Ar:t<=-1?-Ar:Math.asin(t)}function Tn(t){let e=3;return t.digits=function(r){if(!arguments.length)return e;if(r==null)e=null;else{let n=Math.floor(r);if(!(n>=0))throw new RangeError(`invalid digits: ${r}`);e=n}return t},()=>new fe(e)}function Bd(t){return t.innerRadius}function Rd(t){return t.outerRadius}function Hd(t){return t.startAngle}function Fd(t){return t.endAngle}function Od(t){return t&&t.padAngle}function Pd(t,e,r,n,o,i,a,s){var u=r-t,c=n-e,l=a-o,p=s-i,f=p*u-l*c;if(!(f*fR*R+g*g&&(H=I,P=h),{cx:H,cy:P,x01:-l,y01:-p,x11:H*(o/L-1),y11:P*(o/L-1)}}function $o(){var t=Bd,e=Rd,r=W(0),n=null,o=Hd,i=Fd,a=Od,s=null,u=Tn(c);function c(){var l,p,f=+t.apply(this,arguments),m=+e.apply(this,arguments),d=o.apply(this,arguments)-Ar,y=i.apply(this,arguments)-Ar,k=Oo(y-d),_=y>d;if(s||(s=l=u()),mat))s.moveTo(0,0);else if(k>Ye-at)s.moveTo(m*zt(d),m*kt(d)),s.arc(0,0,m,d,y,!_),f>at&&(s.moveTo(f*zt(y),f*kt(y)),s.arc(0,0,f,y,d,_));else{var q=d,A=y,D=d,L=y,b=k,N=k,H=a.apply(this,arguments)/2,P=H>at&&(n?+n.apply(this,arguments):be(f*f+m*m)),I=_n(Oo(m-f)/2,+r.apply(this,arguments)),h=I,T=I,E,R;if(P>at){var g=Po(P/f*kt(H)),x=Po(P/m*kt(H));(b-=g*2)>at?(g*=_?1:-1,D+=g,L-=g):(b=0,D=L=(d+y)/2),(N-=x*2)>at?(x*=_?1:-1,q+=x,A-=x):(N=0,q=A=(d+y)/2)}var M=m*zt(q),S=m*kt(q),v=f*zt(L),B=f*kt(L);if(I>at){var G=m*zt(A),K=m*kt(A),ot=f*zt(D),ht=f*kt(D),tt;if(kat?T>at?(E=Mn(ot,ht,M,S,m,T,_),R=Mn(G,K,v,B,m,T,_),s.moveTo(E.cx+E.x01,E.cy+E.y01),Tat)||!(b>at)?s.lineTo(v,B):h>at?(E=Mn(v,B,G,K,f,-h,_),R=Mn(M,S,ot,ht,f,-h,_),s.lineTo(E.cx+E.x01,E.cy+E.y01),ht?1:e>=t?0:NaN}function Ju(t){return t}function Uo(){var t=Ju,e=Zu,r=null,n=W(0),o=W(Ye),i=W(0);function a(s){var u,c=(s=Sn(s)).length,l,p,f=0,m=new Array(c),d=new Array(c),y=+n.apply(this,arguments),k=Math.min(Ye,Math.max(-Ye,o.apply(this,arguments)-y)),_,q=Math.min(Math.abs(k)/c,i.apply(this,arguments)),A=q*(k<0?-1:1),D;for(u=0;u0&&(f+=D);for(e!=null?m.sort(function(L,b){return e(d[L],d[b])}):r!=null&&m.sort(function(L,b){return r(s[L],s[b])}),u=0,p=f?(k-c*A)/f:0;u0?D*p:0)+A,d[l]={data:s[l],index:u,value:D,startAngle:y,endAngle:_,padAngle:q};return d}return a.value=function(s){return arguments.length?(t=typeof s=="function"?s:W(+s),a):t},a.sortValues=function(s){return arguments.length?(e=s,r=null,a):e},a.sort=function(s){return arguments.length?(r=s,e=null,a):r},a.startAngle=function(s){return arguments.length?(n=typeof s=="function"?s:W(+s),a):n},a.endAngle=function(s){return arguments.length?(o=typeof s=="function"?s:W(+s),a):o},a.padAngle=function(s){return arguments.length?(i=typeof s=="function"?s:W(+s),a):i},a}function Qu(t){return t<0?-1:1}function Ku(t,e,r){var n=t._x1-t._x0,o=e-t._x1,i=(t._y1-t._y0)/(n||o<0&&-0),a=(r-t._y1)/(o||n<0&&-0),s=(i*o+a*n)/(n+o);return(Qu(i)+Qu(a))*Math.min(Math.abs(i),Math.abs(a),.5*Math.abs(s))||0}function tl(t,e){var r=t._x1-t._x0;return r?(3*(t._y1-t._y0)/r-e)/2:e}function Go(t,e,r){var n=t._x0,o=t._y0,i=t._x1,a=t._y1,s=(i-n)/3;t._context.bezierCurveTo(n+s,o+s*e,i-s,a-s*r,i,a)}function Ln(t){this._context=t}Ln.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:Go(this,this._t0,tl(this,this._t0));break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){var r=NaN;if(t=+t,e=+e,!(t===this._x1&&e===this._y1)){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,Go(this,tl(this,r=Ku(this,t,e)),r);break;default:Go(this,this._t0,r=Ku(this,t,e));break}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e,this._t0=r}}};function $d(t){this._context=new el(t)}($d.prototype=Object.create(Ln.prototype)).point=function(t,e){Ln.prototype.point.call(this,e,t)};function el(t){this._context=t}el.prototype={moveTo:function(t,e){this._context.moveTo(e,t)},closePath:function(){this._context.closePath()},lineTo:function(t,e){this._context.lineTo(e,t)},bezierCurveTo:function(t,e,r,n,o,i){this._context.bezierCurveTo(e,t,n,r,i,o)}};function En(t){return new Ln(t)}function Yt(t,e,r){this.k=t,this.x=e,this.y=r}Yt.prototype={constructor:Yt,scale:function(t){return t===1?this:new Yt(this.k*t,this.x,this.y)},translate:function(t,e){return t===0&e===0?this:new Yt(this.k,this.x+this.k*t,this.y+this.k*e)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Vo=new Yt(1,0,0);zo.prototype=Yt.prototype;function zo(t){for(;!t.__zoom;)if(!(t=t.parentNode))return Vo;return t.__zoom}var dt=bt(",.0f"),Wt=bt(",.1f");function Wo(t){function e(c){return c.toString().padStart(2,"0")}let r=Math.floor(t/1e3),n=Math.floor(r/60),o=Math.floor(n/60),i=Math.floor(o/24),a=o%24,s=n%60,u=r%60;return i===0&&a===0&&s===0&&u===0?"0s":i>0?`${i}d ${e(a)}h ${e(s)}m ${e(u)}s`:a>0?`${a}h ${e(s)}m ${e(u)}s`:s>0?`${s}m ${e(u)}s`:`${u}s`}var Ud=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function nl(t){let e=new Date(t*1e3),r=String(e.getDate()).padStart(2,"0"),n=Ud[e.getMonth()],o=e.getFullYear(),i=String(e.getHours()).padStart(2,"0"),a=String(e.getMinutes()).padStart(2,"0"),s=String(e.getSeconds()).padStart(2,"0");return`${r} ${n} ${o} ${i}:${a}:${s}`}var Yo=["bytes","kB","MB","GB","TB","PB"];function ol(t){if(!Number.isFinite(t)||t<0)return"0 bytes";let e=0,r=t;for(;r>=1e3&&eGd(a.charCodeAt(0))).length>=o.length/2?`0x${e}`:o}function Gd(t){return t<32||t>=127&&t<160}function Vd(t){if(t.length===0||t.length%2!==0)return new Uint8Array;let e=new Uint8Array(t.length/2);for(let r=0;r=1e14){let o=t/1e18;n=`${rl(o,4)} ${ll}`}else if(t>=1e5){let o=t/1e9;n=`${rl(o,4)} gwei`}else n=`${t} wei`;return n}function An(t){return!t.startsWith("0x")||t.length<14?t:`${t.slice(0,8)}...${t.slice(-6)}`}function Xt(t,e,r=80,n=44,o=60){let i=e[e.length-1],a=i.t-o*1e3;e=e.filter(A=>A.t>=a);let s={top:2,right:2,bottom:2,left:2},u=r-s.left-s.right,c=n-s.top-s.bottom,l=j(t).select("svg");l.empty()&&(l=j(t).append("svg").attr("width",r).attr("height",n),l.append("g").attr("class","line-group").attr("transform",`translate(${s.left},${s.top})`).append("path").attr("class","sparkline-path").attr("fill","none").attr("stroke","#00bff2").attr("stroke-width",1.5),l.append("g").attr("class","y-axis").attr("transform",`translate(${s.left},${s.top})`)),l.attr("width",r).attr("height",n);let f=l.select("g.line-group").select("path.sparkline-path"),m=i.t,d=wn().domain([new Date(a),new Date(m)]).range([0,u]),[y,k]=Me(e,A=>A.v),_=de().domain([y,k]).range([c,0]).nice(),q=We().x(A=>d(new Date(A.t))).y(A=>_(A.v));if(f.datum(e).attr("d",q).attr("transform",null),e.length>1){let A=u/o;f.attr("transform",`translate(${A},0)`),f.transition().duration(300).attr("transform","translate(0,0)")}}function Cr(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r=o)&&(r=o)}return r}function Xe(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r>n||r===void 0&&n>=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r>o||r===void 0&&o>=o)&&(r=o)}return r}function je(t,e){let r=0;if(e===void 0)for(let n of t)(n=+n)&&(r+=n);else{let n=-1;for(let o of t)(o=+e(o,++n,t))&&(r+=o)}return r}function Xd(t){return t.target.depth}function Xo(t,e){return t.sourceLinks.length?t.depth:e-1}function jo(t){return t.targetLinks.length?t.depth:t.sourceLinks.length?Xe(t.sourceLinks,Xd)-1:0}function Ze(t){return function(){return t}}function fl(t,e){return Dn(t.source,e.source)||t.index-e.index}function pl(t,e){return Dn(t.target,e.target)||t.index-e.index}function Dn(t,e){return t.y0-e.y0}function Zo(t){return t.value}function jd(t){return t.index}function Zd(t){return t.nodes}function Jd(t){return t.links}function ml(t,e){let r=t.get(e);if(!r)throw new Error("missing: "+e);return r}function dl({nodes:t}){for(let e of t){let r=e.y0,n=r;for(let o of e.sourceLinks)o.y0=r+o.width/2,r+=o.width;for(let o of e.targetLinks)o.y1=n+o.width/2,n+=o.width}}function Cn(){let t=0,e=0,r=1,n=1,o=24,i=8,a,s=jd,u=Xo,c,l,p=Zd,f=Jd,m=6;function d(){let g={nodes:p.apply(null,arguments),links:f.apply(null,arguments)};return y(g),k(g),_(g),q(g),L(g),dl(g),g}d.update=function(g){return dl(g),g},d.nodeId=function(g){return arguments.length?(s=typeof g=="function"?g:Ze(g),d):s},d.nodeAlign=function(g){return arguments.length?(u=typeof g=="function"?g:Ze(g),d):u},d.nodeSort=function(g){return arguments.length?(c=g,d):c},d.nodeWidth=function(g){return arguments.length?(o=+g,d):o},d.nodePadding=function(g){return arguments.length?(i=a=+g,d):i},d.nodes=function(g){return arguments.length?(p=typeof g=="function"?g:Ze(g),d):p},d.links=function(g){return arguments.length?(f=typeof g=="function"?g:Ze(g),d):f},d.linkSort=function(g){return arguments.length?(l=g,d):l},d.size=function(g){return arguments.length?(t=e=0,r=+g[0],n=+g[1],d):[r-t,n-e]},d.extent=function(g){return arguments.length?(t=+g[0][0],r=+g[1][0],e=+g[0][1],n=+g[1][1],d):[[t,e],[r,n]]},d.iterations=function(g){return arguments.length?(m=+g,d):m};function y({nodes:g,links:x}){for(let[S,v]of g.entries())v.index=S,v.sourceLinks=[],v.targetLinks=[];let M=new Map(g.map((S,v)=>[s(S,v,g),S]));for(let[S,v]of x.entries()){v.index=S;let{source:B,target:G}=v;typeof B!="object"&&(B=v.source=ml(M,B)),typeof G!="object"&&(G=v.target=ml(M,G)),B.sourceLinks.push(v),G.targetLinks.push(v)}if(l!=null)for(let{sourceLinks:S,targetLinks:v}of g)S.sort(l),v.sort(l)}function k({nodes:g}){for(let x of g)x.value=x.fixedValue===void 0?Math.max(je(x.sourceLinks,Zo),je(x.targetLinks,Zo)):x.fixedValue}function _({nodes:g}){let x=g.length,M=new Set(g),S=new Set,v=0;for(;M.size;){for(let B of M){B.depth=v;for(let{target:G}of B.sourceLinks)S.add(G)}if(++v>x)throw new Error("circular link");M=S,S=new Set}}function q({nodes:g}){let x=g.length,M=new Set(g),S=new Set,v=0;for(;M.size;){for(let B of M){B.height=v;for(let{source:G}of B.targetLinks)S.add(G)}if(++v>x)throw new Error("circular link");M=S,S=new Set}}function A({nodes:g}){let x=Cr(g,v=>v.depth)+1,M=(r-t-o)/(x-1),S=new Array(x);for(let v of g){let B=Math.max(0,Math.min(x-1,Math.floor(u.call(null,v,x))));v.layer=B,v.x0=t+B*M,v.x1=v.x0+o,S[B]?S[B].push(v):S[B]=[v]}if(c)for(let v of S)v.sort(c);return S}function D(g){let x=Xe(g,M=>(n-e-(M.length-1)*a)/je(M,Zo));for(let M of g){let S=e;for(let v of M){v.y0=S,v.y1=S+v.value*x,S=v.y1+a;for(let B of v.sourceLinks)B.width=B.value*x}S=(n-S+a)/(M.length+1);for(let v=0;vM.length)-1)),D(x);for(let M=0;M0))continue;let ht=(K/ot-G.y0)*x;G.y0+=ht,G.y1+=ht,h(G)}c===void 0&&B.sort(Dn),H(B,M)}}function N(g,x,M){for(let S=g.length,v=S-2;v>=0;--v){let B=g[v];for(let G of B){let K=0,ot=0;for(let{target:tt,value:Dt}of G.sourceLinks){let gt=Dt*(tt.layer-G.layer);K+=R(G,tt)*gt,ot+=gt}if(!(ot>0))continue;let ht=(K/ot-G.y0)*x;G.y0+=ht,G.y1+=ht,h(G)}c===void 0&&B.sort(Dn),H(B,M)}}function H(g,x){let M=g.length>>1,S=g[M];I(g,S.y0-a,M-1,x),P(g,S.y1+a,M+1,x),I(g,n,g.length-1,x),P(g,e,0,x)}function P(g,x,M,S){for(;M1e-6&&(v.y0+=B,v.y1+=B),x=v.y1+a}}function I(g,x,M,S){for(;M>=0;--M){let v=g[M],B=(v.y1-x)*S;B>1e-6&&(v.y0-=B,v.y1-=B),x=v.y0-a}}function h({sourceLinks:g,targetLinks:x}){if(l===void 0){for(let{source:{sourceLinks:M}}of x)M.sort(pl);for(let{target:{targetLinks:M}}of g)M.sort(fl)}}function T(g){if(l===void 0)for(let{sourceLinks:x,targetLinks:M}of g)x.sort(pl),M.sort(fl)}function E(g,x){let M=g.y0-(g.sourceLinks.length-1)*a/2;for(let{target:S,width:v}of g.sourceLinks){if(S===x)break;M+=v+a}for(let{source:S,width:v}of x.targetLinks){if(S===g)break;M-=v}return M}function R(g,x){let M=x.y0-(x.targetLinks.length-1)*a/2;for(let{source:S,width:v}of x.targetLinks){if(S===g)break;M+=v+a}for(let{target:S,width:v}of g.sourceLinks){if(S===x)break;M-=v}return M}return d}var Jo=Math.PI,Qo=2*Jo,ke=1e-6,Qd=Qo-ke;function Ko(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function hl(){return new Ko}Ko.prototype=hl.prototype={constructor:Ko,moveTo:function(t,e){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)},closePath:function(){this._x1!==null&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,e){this._+="L"+(this._x1=+t)+","+(this._y1=+e)},quadraticCurveTo:function(t,e,r,n){this._+="Q"+ +t+","+ +e+","+(this._x1=+r)+","+(this._y1=+n)},bezierCurveTo:function(t,e,r,n,o,i){this._+="C"+ +t+","+ +e+","+ +r+","+ +n+","+(this._x1=+o)+","+(this._y1=+i)},arcTo:function(t,e,r,n,o){t=+t,e=+e,r=+r,n=+n,o=+o;var i=this._x1,a=this._y1,s=r-t,u=n-e,c=i-t,l=a-e,p=c*c+l*l;if(o<0)throw new Error("negative radius: "+o);if(this._x1===null)this._+="M"+(this._x1=t)+","+(this._y1=e);else if(p>ke)if(!(Math.abs(l*s-u*c)>ke)||!o)this._+="L"+(this._x1=t)+","+(this._y1=e);else{var f=r-i,m=n-a,d=s*s+u*u,y=f*f+m*m,k=Math.sqrt(d),_=Math.sqrt(p),q=o*Math.tan((Jo-Math.acos((d+p-y)/(2*k*_)))/2),A=q/_,D=q/k;Math.abs(A-1)>ke&&(this._+="L"+(t+A*c)+","+(e+A*l)),this._+="A"+o+","+o+",0,0,"+ +(l*f>c*m)+","+(this._x1=t+D*s)+","+(this._y1=e+D*u)}},arc:function(t,e,r,n,o,i){t=+t,e=+e,r=+r,i=!!i;var a=r*Math.cos(n),s=r*Math.sin(n),u=t+a,c=e+s,l=1^i,p=i?n-o:o-n;if(r<0)throw new Error("negative radius: "+r);this._x1===null?this._+="M"+u+","+c:(Math.abs(this._x1-u)>ke||Math.abs(this._y1-c)>ke)&&(this._+="L"+u+","+c),r&&(p<0&&(p=p%Qo+Qo),p>Qd?this._+="A"+r+","+r+",0,1,"+l+","+(t-a)+","+(e-s)+"A"+r+","+r+",0,1,"+l+","+(this._x1=u)+","+(this._y1=c):p>ke&&(this._+="A"+r+","+r+",0,"+ +(p>=Jo)+","+l+","+(this._x1=t+r*Math.cos(o))+","+(this._y1=e+r*Math.sin(o))))},rect:function(t,e,r,n){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +r+"v"+ +n+"h"+-r+"Z"},toString:function(){return this._}};var ti=hl;function ei(t){return function(){return t}}function gl(t){return t[0]}function xl(t){return t[1]}var yl=Array.prototype.slice;function Kd(t){return t.source}function th(t){return t.target}function eh(t){var e=Kd,r=th,n=gl,o=xl,i=null;function a(){var s,u=yl.call(arguments),c=e.apply(this,u),l=r.apply(this,u);if(i||(i=s=ti()),t(i,+n.apply(this,(u[0]=c,u)),+o.apply(this,u),+n.apply(this,(u[0]=l,u)),+o.apply(this,u)),s)return i=null,s+""||null}return a.source=function(s){return arguments.length?(e=s,a):e},a.target=function(s){return arguments.length?(r=s,a):r},a.x=function(s){return arguments.length?(n=typeof s=="function"?s:ei(+s),a):n},a.y=function(s){return arguments.length?(o=typeof s=="function"?s:ei(+s),a):o},a.context=function(s){return arguments.length?(i=s??null,a):i},a}function rh(t,e,r,n,o){t.moveTo(e,r),t.bezierCurveTo(e=(e+n)/2,r,e,o,n,o)}function ri(){return eh(rh)}function nh(t){return[t.source.x1,t.y0]}function oh(t){return[t.target.x0,t.y1]}function ni(){return ri().source(nh).target(oh)}var qn=class{svg;rectG;linkG;nodeG;sankeyGenerator;width=window.innerWidth;height=250;defs;blueColors=["#E1F5FE","#B3E5FC","#81D4FA","#4FC3F7","#29B6F6","#03A9F4","#039BE5","#0288D1","#0277BD","#01579B"];orangeColors=["#FFF5e1","#FFE0B2","#FFCC80","#FFB74D","#FFA726","#FF9800","#FB8C00","#F57C00","#EF6C00","#E65100"];constructor(e){this.svg=j(e).append("svg").attr("width",window.innerWidth).attr("height",this.height).attr("viewBox",[0,0,window.innerWidth,this.height]).style("max-width","100%").style("height","auto"),this.defs=this.svg.append("defs");let r=this.blueColors.slice(5,-1);r=[...r,...r,...r,...r],this.initGradient("blue-flow",r),this.rectG=this.svg.append("g").attr("stroke","#000"),this.linkG=this.svg.append("g").attr("fill","none").style("mix-blend-mode","normal"),this.nodeG=this.svg.append("g"),this.sankeyGenerator=Cn().nodeId(n=>n.name).nodeAlign(jo).nodeWidth(10).nodePadding(30).nodeSort((n,o)=>n.inclusion&&o.inclusion?n.namen.target.inclusion&&o.target.inclusion?n.source.namei/(r.length-1)).attr("stop-color",o=>o),n.append("animate").attr("attributeName","x1").attr("values","0%;200%").attr("dur","12s").attr("repeatCount","indefinite"),n.append("animate").attr("attributeName","x2").attr("values","100%;300%").attr("dur","12s").attr("repeatCount","indefinite")}isRightAligned(e){return!e.inclusion}update(e,r){this.sankeyGenerator.extent([[100,20],[window.innerWidth-100,this.height-25]]);let n=[],o={};this.width=window.innerWidth-56,this.svg.attr("width",this.width).attr("height",this.height).attr("viewBox",[0,0,this.width,this.height]);for(let l of r.links)l.value>0&&(n.push(l),o[l.source]=!0,o[l.target]=!0);let a={nodes:e.filter(l=>o[l.name]).map(l=>({...l})),links:n.map(l=>({...l}))},{nodes:s,links:u}=this.sankeyGenerator(a);this.rectG.selectAll("rect").data(s,l=>l.name).join("rect").attr("x",l=>l.x0).attr("y",l=>l.y0).attr("height",l=>l.y1-l.y0).attr("width",l=>l.x1-l.x0).attr("fill",l=>(l.name==="P2P Network"&&(l.value=r.hashesReceived),l.inclusion?l.name==="Tx Pool"||l.name==="Added To Block"?"#FFA726":"#00BFF2":"#555")),this.linkG.selectAll("path").data(u,l=>l.index).join("path").attr("d",ni()).attr("stroke",l=>l.target.inclusion?"url(#blue-flow)":"#333").attr("stroke-width",l=>Math.max(1,l.width??1));let c=this.nodeG.selectAll("text").data(s,l=>l.name).join(l=>l.append("text").attr("data-last","0"),l=>l,l=>l.remove());c.attr("data-last",function(l){return j(this).attr("data-current")||"0"}).attr("data-current",l=>(l.targetLinks||[]).reduce((f,m)=>f+(m.value||0),0)||l.value||0).attr("x",l=>this.isRightAligned(l)?l.x1+6:l.x0-6).attr("y",l=>(l.y0+l.y1)/2).attr("dy","-0.5em").attr("text-anchor",l=>this.isRightAligned(l)?"start":"end").text(l=>l.name).each(function(){j(this).selectAll("tspan.number").data([0]).join("tspan").attr("class","number").attr("x",()=>{let l=j(this).datum();return l&&l.inclusion?l.x1+6:l.x0-6}).attr("dy","1em")}),c.selectAll("tspan.number").transition().duration(500).tween("text",function(){let l=j(this),p=j(this.parentNode),f=p.empty()?0:parseFloat(p.attr("data-last")||"0"),m=p.empty()?0:parseFloat(p.attr("data-current")||"0"),d=Z(f,m);return function(y){l.text(bt(",.0f")(d(y)))}})}};function vl(t,e,r,n,o,i,a,s){let u=window.innerWidth-56,l={name:"root",children:[...n.map(h=>({name:o(h),item:h,size:a(h)}))]},p=Re(l).sum(h=>h.children?0:a(h.data?h.data.item:h.item)).sort(h=>h.children?0:i(h.data?h.data.item:h.item)),f=p.value??0,m=f>0?f/r:0,d=Math.min(u,u*m);_o().size([d,e-1]).round(!0).tile(vr.ratio(1)).paddingOuter(.5).paddingInner(2)(p);let[y,k]=Me(n,s),_=y&&y>0?y:1e-6,q=k||1,A=kn(Fo).domain([_,q]);function D(h){let T=s(h),E=T>0?T:1e-6;return A(E)}let L=j(t).select("svg");if(L.empty()){L=j(t).append("svg").attr("width",u).attr("height",e).attr("viewBox",[0,0,u,e]);let h=L.append("defs"),T=h.append("pattern").attr("id","unusedStripes").attr("patternUnits","userSpaceOnUse").attr("width",8).attr("height",8);T.append("rect").attr("class","pattern-bg").attr("width",8).attr("height",8).attr("fill","#444"),T.append("path").attr("d","M0,0 l8,8").attr("stroke","#000").attr("stroke-width",1),L.append("rect").attr("class","unused").attr("fill","url(#unusedStripes)").attr("opacity",1).attr("width",u).attr("height",e).attr("stroke","#fff").attr("stroke-width",1),h.append("marker").attr("id","arrowStart").attr("markerWidth",10).attr("markerHeight",10).attr("refX",5).attr("refY",5).attr("orient","auto").attr("markerUnits","strokeWidth").append("path").attr("d","M10,0 L0,5 L10,10").attr("fill","#ccc"),h.append("marker").attr("id","arrowEnd").attr("markerWidth",10).attr("markerHeight",10).attr("refX",5).attr("refY",5).attr("orient","auto").attr("markerUnits","strokeWidth").append("path").attr("d","M0,0 L10,5 L0,10").attr("fill","#ccc")}L.attr("width",u).attr("height",e).attr("viewBox",[0,0,u,e]),L.selectAll("rect.unused").attr("width",u);let b=p.leaves();L.selectAll("g.node").data(b,h=>h.data.name).join(h=>{let T=h.append("g").attr("class","node").attr("data-hash",E=>E.data.name).attr("transform",E=>`translate(${E.x0},${E.y0})`).attr("opacity",0);return T.append("rect").attr("stroke","#000").attr("stroke-width",.5).attr("width",0).attr("height",0).attr("fill",E=>D(E.data.item)),T.transition().duration(600).attr("opacity",1),T.select("rect").transition().duration(600).attr("width",E=>E.x1-E.x0).attr("height",E=>E.y1-E.y0),T},h=>(h.transition().duration(600).attr("transform",T=>`translate(${T.x0},${T.y0})`).attr("opacity",1),h.select("rect").transition().duration(600).attr("width",T=>T.x1-T.x0).attr("height",T=>T.y1-T.y0).attr("fill",T=>D(T.data.item)),h),h=>{h.transition().duration(600).attr("opacity",0).remove()});let H=(r-f)/r,I=H>=.1?[{key:"unused-label",x:d,w:u-d,ratio:H}]:[];L.selectAll("line.unused-arrow").data(I,h=>h.key).join(h=>h.append("line").attr("class","unused-arrow").attr("x1",T=>T.x+10).attr("x2",T=>T.x+T.w-10).attr("y1",145).attr("y2",145).attr("stroke","#ccc").attr("stroke-width",2).attr("marker-start","url(#arrowStart)").attr("marker-end","url(#arrowEnd)").attr("opacity",0).call(T=>T.transition().duration(600).attr("opacity",1)),h=>h.transition().duration(600).attr("x1",T=>T.x+10).attr("x2",T=>T.x+T.w-10),h=>h.transition().duration(600).attr("opacity",0).remove()),L.selectAll("text.unused-label").data(I,h=>h.key).join(h=>h.append("text").attr("class","unused-label").attr("x",T=>T.x+T.w/2).attr("y",135).attr("fill","#ccc").attr("font-size",14).attr("text-anchor","middle").attr("opacity",0).text(T=>`${(T.ratio*100).toFixed(1)}% available`).call(T=>T.transition().duration(600).attr("opacity",1)),h=>h.transition().duration(600).attr("x",T=>T.x+T.w/2).text(T=>`${(T.ratio*100).toFixed(1)}% available`),h=>h.transition().duration(600).attr("opacity",0).remove())}function bl(t,e,r=36){let n={top:4,right:4,bottom:20,left:20},o=t.getBoundingClientRect().width,i=100,a=j(t).append("svg").style("display","block").style("background","black").attr("width",o).attr("height",i),s=a.append("g").attr("transform",`translate(${n.left},${n.top})`);function u(){return o-n.left-n.right}let c=i-n.top-n.bottom,l=[],p,f=br().domain(Ae(r)).range([0,u()]).paddingInner(.3).paddingOuter(.1),m=de().range([c,0]);function d(){return xr().duration(750)}function y(A){if(!A.length)return{min:0,q1:0,median:0,q3:0,max:0,whiskerLow:0,whiskerHigh:0};let D=A.slice().sort(ft),L=D[0],b=D[D.length-1],N=Ee(D,.25),H=Ee(D,.5),P=Ee(D,.75),I=P-N,h=Math.max(L,N-1.5*I),T=Math.min(b,P+1.5*I);return{min:L,q1:N,median:H,q3:P,max:b,whiskerLow:h,whiskerHigh:T}}function k(A,D){let L=A.map(e).filter(x=>Number.isFinite(x)&&x>=0),b=y(L);if(l.length{x.xIndex-=1});l.length&&l[0].xIndex<0;){let x=l.shift();x&&(p=x.stats.median)}l.push({xIndex:r-1,blockNumber:D,stats:b,values:L})}let N=ee(l,x=>x.stats.whiskerHigh)||1;m.domain([0,N]);let H=s.selectAll(".box-group").data(l,x=>x.xIndex);H.exit().transition(d()).attr("transform",x=>`translate(${f(x.xIndex)||0},${c}) scale(0.001,0.001)`).remove();let P=H.enter().append("g").attr("class","box-group").attr("stroke-width",1).attr("transform",x=>`translate(${f(x.xIndex)||0}, ${c}) scale(0.001,0.001)`);P.append("line").attr("class","whisker-line").attr("stroke","#aaa"),P.append("rect").attr("class","box-rect").attr("stroke","white").attr("fill","gray"),P.append("line").attr("class","median-line").attr("stroke","#ccc").attr("stroke-width",1),P.append("line").attr("class","whisker-cap lower").attr("stroke","#aaa"),P.append("line").attr("class","whisker-cap upper").attr("stroke","#aaa"),P.append("g").attr("class","points-group"),H=P.merge(H),H.transition(d()).attr("transform",x=>`translate(${f(x.xIndex)||0},0) scale(1,1)`),H.each(function(x){let M=j(this),S=x.stats,v=f.bandwidth(),B,G=l.find(ot=>ot.xIndex===x.xIndex-1);G?B=G.stats.median:x.xIndex===0&&p!==void 0&&(B=p);let K="gray";B!==void 0&&(S.median>B?K="rgb(127, 63, 63)":S.median{x.selectAll("text").attr("fill","white"),x.selectAll("line,path").attr("stroke","white")});let h=Fr(f).tickFormat(x=>{let M=l.find(S=>S.xIndex===x);return M?String(M.blockNumber):""}),T=s.append("g").attr("class","x-axis").attr("transform",`translate(0,${c})`).call(h),E=f.bandwidth();E<25&&T.selectAll(".tick").each(function(x,M){M/2%2!==0&&j(this).remove()}),T.call(x=>{x.selectAll("text").attr("fill","white"),x.selectAll("line,path").attr("stroke","white")}),s.selectAll(".median-trend").remove();let R=l.filter(x=>x.xIndex>=0).sort((x,M)=>x.xIndex-M.xIndex),g=We().x(x=>(f(x.xIndex)??0)+E/2).y(x=>m(x.stats.median)).curve(En);s.append("path").attr("class","median-trend").datum(R).attr("fill","none").attr("stroke","#FFA726").attr("stroke-width",2).transition(d()).attr("d",g)}function _(){o=t.getBoundingClientRect().width,a.attr("width",o),f.range([0,u()]),q()}function q(){s.selectAll(".box-group").transition().duration(0).attr("transform",I=>`translate(${f(I.xIndex)||0},0)`),s.selectAll(".y-axis").remove(),s.selectAll(".x-axis").remove();let A=Or(m).ticks(3);s.append("g").attr("class","y-axis").call(A).call(I=>{I.selectAll("text").attr("fill","white"),I.selectAll("line,path").attr("stroke","white")});let D=Fr(f).tickFormat(I=>{let h=l.find(T=>T.xIndex===I);return h?String(h.blockNumber):""}),L=s.append("g").attr("class","x-axis").attr("transform",`translate(0,${c})`).call(D);f.bandwidth()<25&&L.selectAll(".tick").each(function(I,h){h%2!==0&&j(this).remove()}),L.call(I=>{I.selectAll("text").attr("fill","white"),I.selectAll("line,path").attr("stroke","white")}),s.selectAll(".median-trend").remove();let N=l.filter(I=>I.xIndex>=0).sort((I,h)=>I.xIndex-h.xIndex),H=f.bandwidth(),P=We().x(I=>(f(I.xIndex)??0)+H/2).y(I=>m(I.stats.median)).curve(En);s.append("path").attr("class","median-trend").datum(N).attr("fill","none").attr("stroke","#FFA726").attr("stroke-width",2).attr("d",P)}return{update:k,resize:_}}var qr=100,ih=120,ah=qr+ih,sh=qr,wl=qr/2,uh=j("#pie-chart").append("svg").attr("width",ah).attr("height",sh).attr("overflow","visible"),kl=uh.append("g").attr("transform",`translate(${qr/2}, ${qr/2})`),lh=me().range(Ho),ch=Uo().sort(null).value(t=>t.count),oi=$o().innerRadius(0).outerRadius(wl),fh=kl.append("g").attr("class","slice-layer"),ph=kl.append("g").attr("class","label-layer");function _l(t){let e=ch(t),r=e.map(m=>{let[d,y]=oi.centroid(m);return{...m,centroidY:y}}),n=r.slice().sort((m,d)=>m.centroidY-d.centroidY),o=18,i=-((n.length-1)*o)/2,a=wl+20,s={};n.forEach((m,d)=>{s[m.data.type]={x:a,y:i+d*o}});let u=fh.selectAll("path").data(e,m=>m.data.type);u.exit().remove(),u.enter().append("path").attr("stroke","#222").style("stroke-width","1px").attr("fill",m=>lh(m.data.type)).each(function(m){this._current=m}).merge(u).transition().duration(750).attrTween("d",function(m){let d=vt(this._current,m);return this._current=d(0),y=>oi(d(y))});let l=ph.selectAll("g.label").data(r,m=>m.data.type);l.exit().remove();let p=l.enter().append("g").attr("class","label").style("pointer-events","none");p.append("polyline").attr("fill","none").attr("stroke","#fff"),p.append("text").style("alignment-baseline","middle").style("text-anchor","start").style("fill","#fff");let f=p.merge(l);f.select("polyline").transition().duration(750).attr("points",m=>{let[d,y]=oi.centroid(m),{x:k,y:_}=s[m.data.type],q=k*.6;return`${d},${y} ${q},${_} ${k},${_}`}),f.select("text").transition().duration(750).attr("transform",m=>{let d=s[m.data.type];return`translate(${d.x},${d.y})`}).tween("label",function(m){return()=>{this.textContent=`${m.data.type} (${m.data.count})`}})}function Tl(t){switch(t){case 0:return"Legacy";case 1:return"AccessList";case 2:return"Eip1559";case 3:return"Blob";case 4:return"SetCode";case 5:return"TxCreate";default:return"Unknown"}}function ii(t){switch(t){case"0x095ea7b3":return"approve";case"0xa9059cbb":return"transfer";case"0x23b872dd":return"transferFrom";case"0xd0e30db0":return"deposit";case"0xe8e33700":case"0xf305d719":return"addLiquidity";case"0xbaa2abde":case"0x02751cec":case"0xaf2979eb":case"0xded9382a":case"0x5b0d5984":case"0x2195995c":return"removeLiquidity";case"0xfb3bdb41":case"0x7ff36ab5":case"0xb6f9de95":case"0x18cbafe5":case"0x791ac947":case"0x38ed1739":case"0x5c11d795":case"0x4a25d94a":case"0x5f575529":case"0x6b68764c":case"0x845a101f":case"0x8803dbee":return"swap";case"0x24856bc3":case"0x3593564c":return"dex";case"0x":return"ETH transfer";default:return t}}function Ml(t){switch(t){case"0xdac17f958d2ee523a2206206994597c13d831ec7":return"usdt";case"0x4ecaba5870353805a9f068101a40e0f32ed605c6":return"usdt";case"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48":return"usdc";case"0xddafbb505ad214d7b80b1f830fccc89b60fb7a83":return"usdc";case"0x6b175474e89094c44da98b954eedeac495271d0f":return"dai";case"0x44fa8e6f47987339850636f88629646662444217":return"dai";case"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2":return"weth";case"0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1":return"weth";case"0x7a250d5630b4cf539739df2c5dacb4c659f2488d":return"uniswap v2";case"0x66a9893cc07d91d95644aedd05d03f95e1dba8af":return"uniswap v4";case"0x2f848984984d6c3c036174ce627703edaf780479":return"xen minter";case"0x0a252663dbcc0b073063d6420a40319e438cfa59":return"xen";case"0x881d40237659c251811cec9c364ef91dc08d300c":return"metamask";default:return t}}var Wh=tc(),Pn=class{nodeLog;ansiConvert=new Wh;logs=[];constructor(e){this.nodeLog=document.getElementById(e)}receivedLog(e){let r=JSON.parse(e.data);for(let n of r){let o=this.ansiConvert.toHtml(n);this.logs.length>=100&&this.logs.shift(),this.logs.push(o)}}appendLogs(){if(this.logs.length>0){let e=!1;(this.nodeLog.scrollHeight<500||this.nodeLog.scrollTop250;)this.nodeLog.firstChild.remove(),n--;e&&window.setTimeout(()=>this.scrollLogs(),17)}}resize(){let e=document.body.getBoundingClientRect();var n=this.nodeLog.getBoundingClientRect().top-e.top,o=window.innerHeight-n-16;o>0&&(this.nodeLog.style.height=`${o}px`)}scrollLogs(){this.nodeLog.scrollTop=this.nodeLog.scrollHeight}};function $(t,e){t.innerText!==e&&(t.innerText=e)}var $n=class{lastGasLimit=36e6;minGas;medianGas;aveGas;maxGas;gasLimit;gasLimitDelta;constructor(e,r,n,o,i,a){this.minGas=document.getElementById(e),this.medianGas=document.getElementById(r),this.aveGas=document.getElementById(n),this.maxGas=document.getElementById(o),this.gasLimit=document.getElementById(i),this.gasLimitDelta=document.getElementById(a)}parseEvent(e){if(document.hidden)return;let r=JSON.parse(e.data);$(this.minGas,r.minGas.toFixed(2)),$(this.medianGas,r.medianGas.toFixed(2)),$(this.aveGas,r.aveGas.toFixed(2)),$(this.maxGas,r.maxGas.toFixed(2)),$(this.gasLimit,dt(r.gasLimit)),$(this.gasLimitDelta,r.gasLimit>this.lastGasLimit?"\u{1F446}":r.gasLimitparseInt(t.effectiveGasPrice,16)/1e9,36);function dc(t,e){do if(!(t.matches===void 0||!t.matches(e)))return t;while(t=t.parentElement);return null}function kg(t,e,r,n,o){t.addEventListener(e,function(i){try{let a=dc(i.target,r);a!==null&&n.apply(a,arguments)}catch{}},o)}var ec=[],rc=[],nc=[],oc=[],ic=[],ac=[],sc=[],pi=0,mi=0,di=0,hi=0,gi=0,Un=0;function Te(t,e){t.push(e),t.length>60&&t.shift()}var _g=new qn("#txPoolFlow"),bi=null,uc=!1;function Tg(t){if(!uc){if(t.pooledTx==0){document.getElementById("txPoolFlow").classList.add("not-active");return}setTimeout(Ti,10),document.getElementById("txPoolFlow").classList.remove("not-active"),uc=!0}let e=performance.now(),r=e/1e3,n=r-Un,o=0,i=0,a=0,s=0;for(let c of t.links)c.target==="Received Txs"&&(o+=c.value),c.target==="Tx Pool"&&(i+=c.value),c.target==="Added To Block"&&(a+=c.value),c.target==="Duplicate"&&(s+=c.value);let u=t.hashesReceived;if(Un!==0&&(Te(ec,{t:e,v:u-gi}),Te(rc,{t:e,v:o-pi}),Te(ic,{t:e,v:s-hi}),Te(nc,{t:e,v:i-mi}),Te(oc,{t:e,v:a-di})),!document.hidden){if(!bi)return;_g.update(bi,t),$(Xh,dt(t.pooledTx)),$(jh,dt(t.pooledBlobTx)),$(Zh,dt(t.pooledTx+t.pooledBlobTx)),Un!==0&&(Xt(document.getElementById("sparkHashesTps"),ec),Xt(document.getElementById("sparkReceivedTps"),rc),Xt(document.getElementById("sparkDuplicateTps"),ic),Xt(document.getElementById("sparkTxPoolTps"),nc),Xt(document.getElementById("sparkBlockTps"),oc),$(Jh,Wt((a-di)/n)),$(Qh,Wt((o-pi)/n)),$(Kh,Wt((i-mi)/n)),$(tg,Wt((s-hi)/n)),$(eg,Wt((u-gi)/n)))}Un=r,pi=o,mi=i,di=a,hi=s,gi=u}var _i=new Pn("nodeLog"),Mg=new $n("minGas","medianGas","aveGas","maxGas","gasLimit","gasLimitDelta"),Jt=new EventSource("/data/events");Jt.addEventListener("log",t=>_i.receivedLog(t));Jt.addEventListener("processed",t=>Mg.parseEvent(t));Jt.addEventListener("nodeData",t=>{let e=JSON.parse(t.data),r=al(e.network),n=`Nethermind [${r}]${e.instance?" - "+e.instance:""}`;document.title!=n&&(document.title=n),$(rg,e.version),$(ng,r),document.getElementById("network-logo").src=`logos/${sl(e.network)}`,$(pc,Wo(e.uptime)),cl(e.gasToken)});Jt.addEventListener("txNodes",t=>{bi=JSON.parse(t.data)});Jt.addEventListener("txLinks",t=>{if(document.hidden)return;let e=JSON.parse(t.data);Tg(e)});var wi=0,hc=0,lc=!1;Jt.addEventListener("forkChoice",t=>{let e=performance.now();if(hc=e-wi,wi=e,document.hidden)return;let r=JSON.parse(t.data),n=parseInt(r.head.number,16);!lc&&n!==0&&(lc=!0,document.getElementById("lastestBlock").classList.remove("not-active"),setTimeout(Ti,10));let o=parseInt(r.safe,16),i=parseInt(r.finalized,16);$(og,n.toFixed(0)),$(ig,o.toFixed(0)),$(ag,i.toFixed(0)),$(sg,`(${(o-n).toFixed(0)})`),$(ug,`(${(i-n).toFixed(0)})`);let a=r.head;if(a.tx.length===0)return;let s=a.tx.map((u,c)=>{let l=a.receipts[c];return{block:a.number,order:c,...u,...l}});$(hg,il(a.extraData)),$(gg,dt(parseInt(a.gasUsed,16))),$(xg,dt(parseInt(a.gasLimit,16))),$(yg,ol(parseInt(a.size,16))),$(vg,nl(parseInt(a.timestamp,16))),$(bg,dt(a.tx.length)),$(wg,dt(a.tx.reduce((u,c)=>u+c.blobs,0))),vl(document.getElementById("block"),160,parseInt(r.head.gasLimit,16),s,u=>u.hash,u=>u.order,u=>parseInt(u.gasUsed,16),u=>parseInt(u.effectiveGasPrice,16)*parseInt(u.gasUsed,16)),mc.update(s,n),_t.push(...s),ki=_t.length,_t.length>25e4&&_t.slice(_t.length-25e3),gc=Lg(s)});var gc,Sg="";kg(document.getElementById("block"),"pointermove","g.node",t=>{let r=dc(t.target,"g.node").dataset.hash,n=gc[r];if(!n)return;let o=document.getElementById("txDetails");return Sg!==r&&(o.innerHTML=` +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var i=!0,a=!1,s;return{s:function(){r=r.call(t)},n:function(){var c=r.next();return i=c.done,c},e:function(c){a=!0,s=c},f:function(){try{!i&&r.return!=null&&r.return()}finally{if(a)throw s}}}}function Bh(t,e){if(t){if(typeof t=="string")return zl(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if(r==="Object"&&t.constructor&&(r=t.constructor.name),r==="Map"||r==="Set")return Array.from(t);if(r==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return zl(t,e)}}function zl(t,e){(e==null||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r0?t*40+55:0,a=e>0?e*40+55:0,s=r>0?r*40+55:0;n[o]=Oh([i,a,s])}function Jl(t){for(var e=t.toString(16);e.length<2;)e="0"+e;return e}function Oh(t){var e=[],r=Zl(t),n;try{for(r.s();!(n=r.n()).done;){var o=n.value;e.push(Jl(o))}}catch(i){r.e(i)}finally{r.f()}return"#"+e.join("")}function Wl(t,e,r,n){var o;return e==="text"?o=Gh(r,n):e==="display"?o=$h(t,r,n):e==="xterm256Foreground"?o=Fn(t,n.colors[r]):e==="xterm256Background"?o=On(t,n.colors[r]):e==="rgb"&&(o=Ph(t,r)),o}function Ph(t,e){e=e.substring(2).slice(0,-1);var r=+e.substr(0,2),n=e.substring(5).split(";"),o=n.map(function(i){return("0"+Number(i).toString(16)).substr(-2)}).join("");return Hn(t,(r===38?"color:#":"background-color:#")+o)}function $h(t,e,r){e=parseInt(e,10);var n={"-1":function(){return"
"},0:function(){return t.length&&Ql(t)},1:function(){return Zt(t,"b")},3:function(){return Zt(t,"i")},4:function(){return Zt(t,"u")},8:function(){return Hn(t,"display:none")},9:function(){return Zt(t,"strike")},22:function(){return Hn(t,"font-weight:normal;text-decoration:none;font-style:normal")},23:function(){return jl(t,"i")},24:function(){return jl(t,"u")},39:function(){return Fn(t,r.fg)},49:function(){return On(t,r.bg)},53:function(){return Hn(t,"text-decoration:overline")}},o;return n[e]?o=n[e]():4"}).join("")}function Rn(t,e){for(var r=[],n=t;n<=e;n++)r.push(n);return r}function Uh(t){return function(e){return(t===null||e.category!==t)&&t!=="all"}}function Xl(t){t=parseInt(t,10);var e=null;return t===0?e="all":t===1?e="bold":2")}function Hn(t,e){return Zt(t,"span",e)}function Fn(t,e){return Zt(t,"span","color:"+e)}function On(t,e){return Zt(t,"span","background-color:"+e)}function jl(t,e){var r;if(t.slice(-1)[0]===e&&(r=t.pop()),r)return""}function Vh(t,e,r){var n=!1,o=3;function i(){return""}function a(L,b){return r("xterm256Foreground",b),""}function s(L,b){return r("xterm256Background",b),""}function u(L){return e.newline?r("display",-1):r("text",L),""}function c(L,b){n=!0,b.trim().length===0&&(b="0"),b=b.trimRight(";").split(";");var N=Zl(b),H;try{for(N.s();!(H=N.n()).done;){var P=H.value;r("display",P)}}catch(I){N.e(I)}finally{N.f()}return""}function l(L){return r("text",L),""}function p(L){return r("rgb",L),""}var f=[{pattern:/^\x08+/,sub:i},{pattern:/^\x1b\[[012]?K/,sub:i},{pattern:/^\x1b\[\(B/,sub:i},{pattern:/^\x1b\[[34]8;2;\d+;\d+;\d+m/,sub:p},{pattern:/^\x1b\[38;5;(\d+)m/,sub:a},{pattern:/^\x1b\[48;5;(\d+)m/,sub:s},{pattern:/^\n/,sub:u},{pattern:/^\r+\n/,sub:u},{pattern:/^\r/,sub:u},{pattern:/^\x1b\[((?:\d{1,3};?)+|)m/,sub:c},{pattern:/^\x1b\[\d?J/,sub:i},{pattern:/^\x1b\[\d{0,3};\d{0,3}f/,sub:i},{pattern:/^\x1b\[?[\d;]{0,3}/,sub:i},{pattern:/^(([^\x1b\x08\r\n])+)/,sub:l}];function m(L,b){b>o&&n||(n=!1,t=t.replace(L.pattern,L.sub))}var d=[],y=t,k=y.length;t:for(;k>0;){for(var _=0,q=0,A=f.length;qe?1:t>=e?0:NaN}function Gn(t,e){return t==null||e==null?NaN:et?1:e>=t?0:NaN}function Kt(t){let e,r,n;t.length!==2?(e=ft,r=(s,u)=>ft(t(s),u),n=(s,u)=>t(s)-u):(e=t===ft||t===Gn?t:yc,r=t,n=t);function o(s,u,c=0,l=s.length){if(c>>1;r(s[p],u)<0?c=p+1:l=p}while(c>>1;r(s[p],u)<=0?c=p+1:l=p}while(cc&&n(s[p-1],u)>-n(s[p],u)?p-1:p}return{left:o,center:a,right:i}}function yc(){return 0}function Nr(t){return t===null?NaN:+t}function*Si(t,e){if(e===void 0)for(let r of t)r!=null&&(r=+r)>=r&&(yield r);else{let r=-1;for(let n of t)(n=e(n,++r,t))!=null&&(n=+n)>=n&&(yield n)}}var Li=Kt(ft),Ei=Li.right,vc=Li.left,bc=Kt(Nr).center,Vn=Ei;function Me(t,e){let r,n;if(e===void 0)for(let o of t)o!=null&&(r===void 0?o>=o&&(r=n=o):(r>o&&(r=o),n=i&&(r=n=i):(r>i&&(r=i),n{let n=t(e,r);return n||n===0?n:(t(r,r)===0)-(t(e,e)===0)}}function zn(t,e){return(t==null||!(t>=t))-(e==null||!(e>=e))||(te?1:0)}var Tc=Math.sqrt(50),Mc=Math.sqrt(10),Sc=Math.sqrt(2);function Br(t,e,r){let n=(e-t)/Math.max(0,r),o=Math.floor(Math.log10(n)),i=n/Math.pow(10,o),a=i>=Tc?10:i>=Mc?5:i>=Sc?2:1,s,u,c;return o<0?(c=Math.pow(10,-o)/a,s=Math.round(t*c),u=Math.round(e*c),s/ce&&--u,c=-c):(c=Math.pow(10,o)*a,s=Math.round(t/c),u=Math.round(e/c),s*ce&&--u),u0))return[];if(t===e)return[t];let n=e=o))return[];let s=i-o+1,u=new Array(s);if(n)if(a<0)for(let c=0;c=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r=o)&&(r=o)}return r}function Rr(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r>n||r===void 0&&n>=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r>o||r===void 0&&o>=o)&&(r=o)}return r}function Hr(t,e,r=0,n=1/0,o){if(e=Math.floor(e),r=Math.floor(Math.max(0,r)),n=Math.floor(Math.min(t.length-1,n)),!(r<=e&&e<=n))return t;for(o=o===void 0?zn:Di(o);n>r;){if(n-r>600){let u=n-r+1,c=e-r+1,l=Math.log(u),p=.5*Math.exp(2*l/3),f=.5*Math.sqrt(l*p*(u-p)/u)*(c-u/2<0?-1:1),m=Math.max(r,Math.floor(e-c*p/u+f)),d=Math.min(n,Math.floor(e+(u-c)*p/u+f));Hr(t,e,m,d,o)}let i=t[e],a=r,s=n;for(Ke(t,r,e),o(t[n],i)>0&&Ke(t,r,n);a0;)--s}o(t[r],i)===0?Ke(t,r,s):(++s,Ke(t,s,n)),s<=e&&(r=s+1),e<=s&&(n=s-1)}return t}function Ke(t,e,r){let n=t[e];t[e]=t[r],t[r]=n}function Ee(t,e,r){if(t=Float64Array.from(Si(t,r)),!(!(n=t.length)||isNaN(e=+e))){if(e<=0||n<2)return Rr(t);if(e>=1)return ee(t);var n,o=(n-1)*e,i=Math.floor(o),a=ee(Hr(t,i).subarray(0,i+1)),s=Rr(t.subarray(i+1));return a+(s-a)*(o-i)}}function Ae(t,e,r){t=+t,e=+e,r=(o=arguments.length)<2?(e=t,t=0,1):o<3?1:+r;for(var n=-1,o=Math.max(0,Math.ceil((e-t)/r))|0,i=new Array(o);++n+t(e)}function Dc(t,e){return e=Math.max(0,t.bandwidth()-e*2)/2,t.round()&&(e=Math.round(e)),r=>+t(r)+e}function Cc(){return!this.__axis}function Ii(t,e){var r=[],n=null,o=null,i=6,a=6,s=3,u=typeof window<"u"&&window.devicePixelRatio>1?0:.5,c=t===Yn||t===tr?-1:1,l=t===tr||t===Wn?"x":"y",p=t===Yn||t===Xn?Lc:Ec;function f(m){var d=n??(e.ticks?e.ticks.apply(e,r):e.domain()),y=o??(e.tickFormat?e.tickFormat.apply(e,r):Ci),k=Math.max(i,0)+s,_=e.range(),q=+_[0]+u,A=+_[_.length-1]+u,D=(e.bandwidth?Dc:Ac)(e.copy(),u),L=m.selection?m.selection():m,b=L.selectAll(".domain").data([null]),N=L.selectAll(".tick").data(d,e).order(),H=N.exit(),P=N.enter().append("g").attr("class","tick"),I=N.select("line"),h=N.select("text");b=b.merge(b.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),N=N.merge(P),I=I.merge(P.append("line").attr("stroke","currentColor").attr(l+"2",c*i)),h=h.merge(P.append("text").attr("fill","currentColor").attr(l,c*k).attr("dy",t===Yn?"0em":t===Xn?"0.71em":"0.32em")),m!==L&&(b=b.transition(m),N=N.transition(m),I=I.transition(m),h=h.transition(m),H=H.transition(m).attr("opacity",qi).attr("transform",function(T){return isFinite(T=D(T))?p(T+u):this.getAttribute("transform")}),P.attr("opacity",qi).attr("transform",function(T){var E=this.parentNode.__axis;return p((E&&isFinite(E=E(T))?E:D(T))+u)})),H.remove(),b.attr("d",t===tr||t===Wn?a?"M"+c*a+","+q+"H"+u+"V"+A+"H"+c*a:"M"+u+","+q+"V"+A:a?"M"+q+","+c*a+"V"+u+"H"+A+"V"+c*a:"M"+q+","+u+"H"+A),N.attr("opacity",1).attr("transform",function(T){return p(D(T)+u)}),I.attr(l+"2",c*i),h.attr(l,c*k).text(y),L.filter(Cc).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===Wn?"start":t===tr?"end":"middle"),L.each(function(){this.__axis=D})}return f.scale=function(m){return arguments.length?(e=m,f):e},f.ticks=function(){return r=Array.from(arguments),f},f.tickArguments=function(m){return arguments.length?(r=m==null?[]:Array.from(m),f):r.slice()},f.tickValues=function(m){return arguments.length?(n=m==null?null:Array.from(m),f):n&&n.slice()},f.tickFormat=function(m){return arguments.length?(o=m,f):o},f.tickSize=function(m){return arguments.length?(i=a=+m,f):i},f.tickSizeInner=function(m){return arguments.length?(i=+m,f):i},f.tickSizeOuter=function(m){return arguments.length?(a=+m,f):a},f.tickPadding=function(m){return arguments.length?(s=+m,f):s},f.offset=function(m){return arguments.length?(u=+m,f):u},f}function Fr(t){return Ii(Xn,t)}function Or(t){return Ii(tr,t)}var qc={value:()=>{}};function Bi(){for(var t=0,e=arguments.length,r={},n;t=0&&(n=r.slice(o+1),r=r.slice(0,o)),r&&!e.hasOwnProperty(r))throw new Error("unknown type: "+r);return{type:r,name:n}})}Pr.prototype=Bi.prototype={constructor:Pr,on:function(t,e){var r=this._,n=Ic(t+"",r),o,i=-1,a=n.length;if(arguments.length<2){for(;++i0)for(var r=new Array(o),n=0,o,i;n=0&&(e=t.slice(0,r))!=="xmlns"&&(t=t.slice(r+1)),Zn.hasOwnProperty(e)?{space:Zn[e],local:t}:t}function Bc(t){return function(){var e=this.ownerDocument,r=this.namespaceURI;return r===$r&&e.documentElement.namespaceURI===$r?e.createElement(t):e.createElementNS(r,t)}}function Rc(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Ur(t){var e=qt(t);return(e.local?Rc:Bc)(e)}function Hc(){}function re(t){return t==null?Hc:function(){return this.querySelector(t)}}function Ri(t){typeof t!="function"&&(t=re(t));for(var e=this._groups,r=e.length,n=new Array(r),o=0;o=A&&(A=q+1);!(L=k[A])&&++A=0;)(a=n[o])&&(i&&a.compareDocumentPosition(i)^4&&i.parentNode.insertBefore(a,i),i=a);return this}function Xi(t){t||(t=Zc);function e(p,f){return p&&f?t(p.__data__,f.__data__):!p-!f}for(var r=this._groups,n=r.length,o=new Array(n),i=0;ie?1:t>=e?0:NaN}function ji(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function Zi(){return Array.from(this)}function Ji(){for(var t=this._groups,e=0,r=t.length;e1?this.each((e==null?nf:typeof e=="function"?af:of)(t,e,r??"")):Ft(this.node(),t)}function Ft(t,e){return t.style.getPropertyValue(e)||zr(t).getComputedStyle(t,null).getPropertyValue(e)}function sf(t){return function(){delete this[t]}}function uf(t,e){return function(){this[t]=e}}function lf(t,e){return function(){var r=e.apply(this,arguments);r==null?delete this[t]:this[t]=r}}function na(t,e){return arguments.length>1?this.each((e==null?sf:typeof e=="function"?lf:uf)(t,e)):this.node()[t]}function oa(t){return t.trim().split(/^|\s+/)}function Qn(t){return t.classList||new ia(t)}function ia(t){this._node=t,this._names=oa(t.getAttribute("class")||"")}ia.prototype={add:function(t){var e=this._names.indexOf(t);e<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var e=this._names.indexOf(t);e>=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function aa(t,e){for(var r=Qn(t),n=-1,o=e.length;++n=0&&(r=e.slice(n+1),e=e.slice(0,n)),{type:e,name:r}})}function Lf(t){return function(){var e=this.__on;if(e){for(var r=0,n=-1,o=e.length,i;r>8&15|e>>4&240,e>>4&15|e&240,(e&15)<<4|e&15,1):r===8?Yr(e>>24&255,e>>16&255,e>>8&255,(e&255)/255):r===4?Yr(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|e&240,((e&15)<<4|e&15)/255):null):(e=If.exec(t))?new et(e[1],e[2],e[3],1):(e=Nf.exec(t))?new et(e[1]*255/100,e[2]*255/100,e[3]*255/100,1):(e=Bf.exec(t))?Yr(e[1],e[2],e[3],e[4]):(e=Rf.exec(t))?Yr(e[1]*255/100,e[2]*255/100,e[3]*255/100,e[4]):(e=Hf.exec(t))?Aa(e[1],e[2]/100,e[3]/100,1):(e=Ff.exec(t))?Aa(e[1],e[2]/100,e[3]/100,e[4]):_a.hasOwnProperty(t)?Sa(_a[t]):t==="transparent"?new et(NaN,NaN,NaN,0):null}function Sa(t){return new et(t>>16&255,t>>8&255,t&255,1)}function Yr(t,e,r,n){return n<=0&&(t=e=r=NaN),new et(t,e,r,n)}function eo(t){return t instanceof ae||(t=yt(t)),t?(t=t.rgb(),new et(t.r,t.g,t.b,t.opacity)):new et}function qe(t,e,r,n){return arguments.length===1?eo(t):new et(t,e,r,n??1)}function et(t,e,r,n){this.r=+t,this.g=+e,this.b=+r,this.opacity=+n}De(et,qe,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new et(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new et(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new et(oe(this.r),oe(this.g),oe(this.b),Xr(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:La,formatHex:La,formatHex8:$f,formatRgb:Ea,toString:Ea}));function La(){return`#${ne(this.r)}${ne(this.g)}${ne(this.b)}`}function $f(){return`#${ne(this.r)}${ne(this.g)}${ne(this.b)}${ne((isNaN(this.opacity)?1:this.opacity)*255)}`}function Ea(){let t=Xr(this.opacity);return`${t===1?"rgb(":"rgba("}${oe(this.r)}, ${oe(this.g)}, ${oe(this.b)}${t===1?")":`, ${t})`}`}function Xr(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function oe(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function ne(t){return t=oe(t),(t<16?"0":"")+t.toString(16)}function Aa(t,e,r,n){return n<=0?t=e=r=NaN:r<=0||r>=1?t=e=NaN:e<=0&&(t=NaN),new xt(t,e,r,n)}function Ca(t){if(t instanceof xt)return new xt(t.h,t.s,t.l,t.opacity);if(t instanceof ae||(t=yt(t)),!t)return new xt;if(t instanceof xt)return t;t=t.rgb();var e=t.r/255,r=t.g/255,n=t.b/255,o=Math.min(e,r,n),i=Math.max(e,r,n),a=NaN,s=i-o,u=(i+o)/2;return s?(e===i?a=(r-n)/s+(r0&&u<1?0:a,new xt(a,s,u,t.opacity)}function qa(t,e,r,n){return arguments.length===1?Ca(t):new xt(t,e,r,n??1)}function xt(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}De(xt,qa,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new xt(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new xt(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,e=isNaN(t)||isNaN(this.s)?0:this.s,r=this.l,n=r+(r<.5?r:1-r)*e,o=2*r-n;return new et(to(t>=240?t-240:t+120,o,n),to(t,o,n),to(t<120?t+240:t-120,o,n),this.opacity)},clamp(){return new xt(Da(this.h),Wr(this.s),Wr(this.l),Xr(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){let t=Xr(this.opacity);return`${t===1?"hsl(":"hsla("}${Da(this.h)}, ${Wr(this.s)*100}%, ${Wr(this.l)*100}%${t===1?")":`, ${t})`}`}}));function Da(t){return t=(t||0)%360,t<0?t+360:t}function Wr(t){return Math.max(0,Math.min(1,t||0))}function to(t,e,r){return(t<60?e+(r-e)*t/60:t<180?r:t<240?e+(r-e)*(240-t)/60:e)*255}var Ia=Math.PI/180,Na=180/Math.PI;var Fa=-.14861,ro=1.78277,no=-.29227,jr=-.90649,ar=1.97294,Ba=ar*jr,Ra=ar*ro,Ha=ro*no-jr*Fa;function Uf(t){if(t instanceof se)return new se(t.h,t.s,t.l,t.opacity);t instanceof et||(t=eo(t));var e=t.r/255,r=t.g/255,n=t.b/255,o=(Ha*n+Ba*e-Ra*r)/(Ha+Ba-Ra),i=n-o,a=(ar*(r-o)-no*i)/jr,s=Math.sqrt(a*a+i*i)/(ar*o*(1-o)),u=s?Math.atan2(a,i)*Na-120:NaN;return new se(u<0?u+360:u,s,o,t.opacity)}function mt(t,e,r,n){return arguments.length===1?Uf(t):new se(t,e,r,n??1)}function se(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}De(se,mt,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new se(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new se(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=isNaN(this.h)?0:(this.h+120)*Ia,e=+this.l,r=isNaN(this.s)?0:this.s*e*(1-e),n=Math.cos(t),o=Math.sin(t);return new et(255*(e+r*(Fa*n+ro*o)),255*(e+r*(no*n+jr*o)),255*(e+r*(ar*n)),this.opacity)}}));function oo(t,e,r,n,o){var i=t*t,a=i*t;return((1-3*t+3*i-a)*e+(4-6*i+3*a)*r+(1+3*t+3*i-3*a)*n+a*o)/6}function Oa(t){var e=t.length-1;return function(r){var n=r<=0?r=0:r>=1?(r=1,e-1):Math.floor(r*e),o=t[n],i=t[n+1],a=n>0?t[n-1]:2*o-i,s=n()=>t;function $a(t,e){return function(r){return t+r*e}}function Gf(t,e,r){return t=Math.pow(t,r),e=Math.pow(e,r)-t,r=1/r,function(n){return Math.pow(t+n*e,r)}}function Ua(t,e){var r=e-t;return r?$a(t,r>180||r<-180?r-360*Math.round(r/360):r):Ie(isNaN(t)?e:t)}function Ga(t){return(t=+t)==1?Nt:function(e,r){return r-e?Gf(e,r,t):Ie(isNaN(e)?r:e)}}function Nt(t,e){var r=e-t;return r?$a(t,r):Ie(isNaN(t)?e:t)}var ue=function t(e){var r=Ga(e);function n(o,i){var a=r((o=qe(o)).r,(i=qe(i)).r),s=r(o.g,i.g),u=r(o.b,i.b),c=Nt(o.opacity,i.opacity);return function(l){return o.r=a(l),o.g=s(l),o.b=u(l),o.opacity=c(l),o+""}}return n.gamma=t,n}(1);function Va(t){return function(e){var r=e.length,n=new Array(r),o=new Array(r),i=new Array(r),a,s;for(a=0;ar&&(i=e.slice(r,i),s[a]?s[a]+=i:s[++a]=i),(n=n[0])===(o=o[0])?s[a]?s[a]+=o:s[++a]=o:(s[++a]=null,u.push({i:a,x:Z(n,o)})),r=io.lastIndex;return r180?l+=360:l-c>180&&(c+=360),f.push({i:p.push(o(p)+"rotate(",null,n)-2,x:Z(c,l)})):l&&p.push(o(p)+"rotate("+l+n)}function s(c,l,p,f){c!==l?f.push({i:p.push(o(p)+"skewX(",null,n)-2,x:Z(c,l)}):l&&p.push(o(p)+"skewX("+l+n)}function u(c,l,p,f,m,d){if(c!==p||l!==f){var y=m.push(o(m)+"scale(",null,",",null,")");d.push({i:y-4,x:Z(c,p)},{i:y-2,x:Z(l,f)})}else(p!==1||f!==1)&&m.push(o(m)+"scale("+p+","+f+")")}return function(c,l){var p=[],f=[];return c=t(c),l=t(l),i(c.translateX,c.translateY,l.translateX,l.translateY,p,f),a(c.rotate,l.rotate,p,f),s(c.skewX,l.skewX,p,f),u(c.scaleX,c.scaleY,l.scaleX,l.scaleY,p,f),c=l=null,function(m){for(var d=-1,y=f.length,k;++d=0&&t._call.call(void 0,e),t=t._next;--Ne}function es(){le=(tn=pr.now())+en,Ne=cr=0;try{os()}finally{Ne=0,Jf(),le=0}}function Zf(){var t=pr.now(),e=t-tn;e>rs&&(en-=e,tn=t)}function Jf(){for(var t,e=Kr,r,n=1/0;e;)e._call?(n>e._time&&(n=e._time),t=e,e=e._next):(r=e._next,e._next=null,e=t?t._next=r:Kr=r);fr=t,co(n)}function co(t){if(!Ne){cr&&(cr=clearTimeout(cr));var e=t-le;e>24?(t<1/0&&(cr=setTimeout(es,t-pr.now()-en)),lr&&(lr=clearInterval(lr))):(lr||(tn=pr.now(),lr=setInterval(Zf,rs)),Ne=1,ns(es))}}function nn(t,e,r){var n=new mr;return e=e==null?0:+e,n.restart(o=>{n.stop(),t(o+e)},e,r),n}var Qf=jn("start","end","cancel","interrupt"),Kf=[],ss=0,is=1,an=2,on=3,as=4,sn=5,hr=6;function Pt(t,e,r,n,o,i){var a=t.__transition;if(!a)t.__transition={};else if(r in a)return;tp(t,r,{name:e,index:n,group:o,on:Qf,tween:Kf,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:ss})}function gr(t,e){var r=J(t,e);if(r.state>ss)throw new Error("too late; already scheduled");return r}function rt(t,e){var r=J(t,e);if(r.state>on)throw new Error("too late; already running");return r}function J(t,e){var r=t.__transition;if(!r||!(r=r[e]))throw new Error("transition not found");return r}function tp(t,e,r){var n=t.__transition,o;n[e]=r,r.timer=rn(i,0,r.time);function i(c){r.state=is,r.timer.restart(a,r.delay,r.time),r.delay<=c&&a(c-r.delay)}function a(c){var l,p,f,m;if(r.state!==is)return u();for(l in n)if(m=n[l],m.name===r.name){if(m.state===on)return nn(a);m.state===as?(m.state=hr,m.timer.stop(),m.on.call("interrupt",t,t.__data__,m.index,m.group),delete n[l]):+lan&&n.state=0&&(e=e.slice(0,r)),!e||e==="start"})}function bp(t,e,r){var n,o,i=vp(e)?gr:rt;return function(){var a=i(this,t),s=a.on;s!==n&&(o=(n=s).copy()).on(e,r),a.on=o}}function ys(t,e){var r=this._id;return arguments.length<2?J(this.node(),r).on.on(t):this.each(bp(r,t,e))}function wp(t){return function(){var e=this.parentNode;for(var r in this.__transition)if(+r!==t)return;e&&e.removeChild(this)}}function vs(){return this.on("end.remove",wp(this._id))}function bs(t){var e=this._name,r=this._id;typeof t!="function"&&(t=re(t));for(var n=this._groups,o=n.length,i=new Array(o),a=0;a=0))throw new Error(`invalid digits: ${t}`);if(e>15)return qs;let r=10**e;return function(n){this._+=n[0];for(let o=1,i=n.length;oce)if(!(Math.abs(p*u-c*l)>ce)||!i)this._append`L${this._x1=e},${this._y1=r}`;else{let m=n-a,d=o-s,y=u*u+c*c,k=m*m+d*d,_=Math.sqrt(y),q=Math.sqrt(f),A=i*Math.tan((po-Math.acos((y+f-k)/(2*_*q)))/2),D=A/q,L=A/_;Math.abs(D-1)>ce&&this._append`L${e+D*l},${r+D*p}`,this._append`A${i},${i},0,0,${+(p*m>l*d)},${this._x1=e+L*u},${this._y1=r+L*c}`}}arc(e,r,n,o,i,a){if(e=+e,r=+r,n=+n,a=!!a,n<0)throw new Error(`negative radius: ${n}`);let s=n*Math.cos(o),u=n*Math.sin(o),c=e+s,l=r+u,p=1^a,f=a?o-i:i-o;this._x1===null?this._append`M${c},${l}`:(Math.abs(this._x1-c)>ce||Math.abs(this._y1-l)>ce)&&this._append`L${c},${l}`,n&&(f<0&&(f=f%mo+mo),f>Hp?this._append`A${n},${n},0,1,${p},${e-s},${r-u}A${n},${n},0,1,${p},${this._x1=c},${this._y1=l}`:f>ce&&this._append`A${n},${n},0,${+(f>=po)},${p},${this._x1=e+n*Math.cos(i)},${this._y1=r+n*Math.sin(i)}`)}rect(e,r,n,o){this._append`M${this._x0=this._x1=+e},${this._y0=this._y1=+r}h${n=+n}v${+o}h${-n}Z`}toString(){return this._}};function Is(){return new fe}Is.prototype=fe.prototype;function Ns(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)}function pe(t,e){if((r=(t=e?t.toExponential(e-1):t.toExponential()).indexOf("e"))<0)return null;var r,n=t.slice(0,r);return[n.length>1?n[0]+n.slice(2):n,+t.slice(r+1)]}function Mt(t){return t=pe(Math.abs(t)),t?t[1]:NaN}function Bs(t,e){return function(r,n){for(var o=r.length,i=[],a=0,s=t[0],u=0;o>0&&s>0&&(u+s+1>n&&(s=Math.max(1,n-u)),i.push(r.substring(o-=s,o+s)),!((u+=s+1)>n));)s=t[a=(a+1)%t.length];return i.reverse().join(e)}}function Rs(t){return function(e){return e.replace(/[0-9]/g,function(r){return t[+r]})}}var Op=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function St(t){if(!(e=Op.exec(t)))throw new Error("invalid format: "+t);var e;return new pn({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}St.prototype=pn.prototype;function pn(t){this.fill=t.fill===void 0?" ":t.fill+"",this.align=t.align===void 0?">":t.align+"",this.sign=t.sign===void 0?"-":t.sign+"",this.symbol=t.symbol===void 0?"":t.symbol+"",this.zero=!!t.zero,this.width=t.width===void 0?void 0:+t.width,this.comma=!!t.comma,this.precision=t.precision===void 0?void 0:+t.precision,this.trim=!!t.trim,this.type=t.type===void 0?"":t.type+""}pn.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function Hs(t){t:for(var e=t.length,r=1,n=-1,o;r0&&(n=0);break}return n>0?t.slice(0,n)+t.slice(o+1):t}var ho;function Fs(t,e){var r=pe(t,e);if(!r)return t+"";var n=r[0],o=r[1],i=o-(ho=Math.max(-8,Math.min(8,Math.floor(o/3)))*3)+1,a=n.length;return i===a?n:i>a?n+new Array(i-a+1).join("0"):i>0?n.slice(0,i)+"."+n.slice(i):"0."+new Array(1-i).join("0")+pe(t,Math.max(0,e+i-1))[0]}function go(t,e){var r=pe(t,e);if(!r)return t+"";var n=r[0],o=r[1];return o<0?"0."+new Array(-o).join("0")+n:n.length>o+1?n.slice(0,o+1)+"."+n.slice(o+1):n+new Array(o-n.length+2).join("0")}var xo={"%":(t,e)=>(t*100).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:Ns,e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>go(t*100,e),r:go,s:Fs,X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function yo(t){return t}var Os=Array.prototype.map,Ps=["y","z","a","f","p","n","\xB5","m","","k","M","G","T","P","E","Z","Y"];function $s(t){var e=t.grouping===void 0||t.thousands===void 0?yo:Bs(Os.call(t.grouping,Number),t.thousands+""),r=t.currency===void 0?"":t.currency[0]+"",n=t.currency===void 0?"":t.currency[1]+"",o=t.decimal===void 0?".":t.decimal+"",i=t.numerals===void 0?yo:Rs(Os.call(t.numerals,String)),a=t.percent===void 0?"%":t.percent+"",s=t.minus===void 0?"\u2212":t.minus+"",u=t.nan===void 0?"NaN":t.nan+"";function c(p){p=St(p);var f=p.fill,m=p.align,d=p.sign,y=p.symbol,k=p.zero,_=p.width,q=p.comma,A=p.precision,D=p.trim,L=p.type;L==="n"?(q=!0,L="g"):xo[L]||(A===void 0&&(A=12),D=!0,L="g"),(k||f==="0"&&m==="=")&&(k=!0,f="0",m="=");var b=y==="$"?r:y==="#"&&/[boxX]/.test(L)?"0"+L.toLowerCase():"",N=y==="$"?n:/[%p]/.test(L)?a:"",H=xo[L],P=/[defgprs%]/.test(L);A=A===void 0?6:/[gprs]/.test(L)?Math.max(1,Math.min(21,A)):Math.max(0,Math.min(20,A));function I(h){var T=b,E=N,R,g,x;if(L==="c")E=H(h)+E,h="";else{h=+h;var M=h<0||1/h<0;if(h=isNaN(h)?u:H(Math.abs(h),A),D&&(h=Hs(h)),M&&+h==0&&d!=="+"&&(M=!1),T=(M?d==="("?d:s:d==="-"||d==="("?"":d)+T,E=(L==="s"?Ps[8+ho/3]:"")+E+(M&&d==="("?")":""),P){for(R=-1,g=h.length;++Rx||x>57){E=(x===46?o+h.slice(R+1):h.slice(R))+E,h=h.slice(0,R);break}}}q&&!k&&(h=e(h,1/0));var S=T.length+h.length+E.length,v=S<_?new Array(_-S+1).join(f):"";switch(q&&k&&(h=e(v+h,v.length?_-E.length:1/0),v=""),m){case"<":h=T+h+E+v;break;case"=":h=T+v+h+E;break;case"^":h=v.slice(0,S=v.length>>1)+T+h+E+v.slice(S);break;default:h=v+T+h+E;break}return i(h)}return I.toString=function(){return p+""},I}function l(p,f){var m=c((p=St(p),p.type="f",p)),d=Math.max(-8,Math.min(8,Math.floor(Mt(f)/3)))*3,y=Math.pow(10,-d),k=Ps[8+d/3];return function(_){return m(y*_)+k}}return{format:c,formatPrefix:l}}var mn,bt,dn;vo({thousands:",",grouping:[3],currency:["$",""]});function vo(t){return mn=$s(t),bt=mn.format,dn=mn.formatPrefix,mn}function bo(t){return Math.max(0,-Mt(Math.abs(t)))}function wo(t,e){return Math.max(0,Math.max(-8,Math.min(8,Math.floor(Mt(e)/3)))*3-Mt(Math.abs(t)))}function ko(t,e){return t=Math.abs(t),e=Math.abs(e)-t,Math.max(0,Mt(e)-Mt(t))+1}function Pp(t){var e=0,r=t.children,n=r&&r.length;if(!n)e=1;else for(;--n>=0;)e+=r[n].value;t.value=e}function Us(){return this.eachAfter(Pp)}function Gs(t,e){let r=-1;for(let n of this)t.call(e,n,++r,this);return this}function Vs(t,e){for(var r=this,n=[r],o,i,a=-1;r=n.pop();)if(t.call(e,r,++a,this),o=r.children)for(i=o.length-1;i>=0;--i)n.push(o[i]);return this}function zs(t,e){for(var r=this,n=[r],o=[],i,a,s,u=-1;r=n.pop();)if(o.push(r),i=r.children)for(a=0,s=i.length;a=0;)r+=n[o].value;e.value=r})}function Xs(t){return this.eachBefore(function(e){e.children&&e.children.sort(t)})}function js(t){for(var e=this,r=$p(e,t),n=[e];e!==r;)e=e.parent,n.push(e);for(var o=n.length;t!==r;)n.splice(o,0,t),t=t.parent;return n}function $p(t,e){if(t===e)return t;var r=t.ancestors(),n=e.ancestors(),o=null;for(t=r.pop(),e=n.pop();t===e;)o=t,t=r.pop(),e=n.pop();return o}function Zs(){for(var t=this,e=[t];t=t.parent;)e.push(t);return e}function Js(){return Array.from(this)}function Qs(){var t=[];return this.eachBefore(function(e){e.children||t.push(e)}),t}function Ks(){var t=this,e=[];return t.each(function(r){r!==t&&e.push({source:r.parent,target:r})}),e}function*tu(){var t=this,e,r=[t],n,o,i;do for(e=r.reverse(),r=[];t=e.pop();)if(yield t,n=t.children)for(o=0,i=n.length;o=0;--s)o.push(i=a[s]=new yr(a[s])),i.parent=n,i.depth=n.depth+1;return r.eachBefore(Yp)}function Up(){return Re(this).eachBefore(zp)}function Gp(t){return t.children}function Vp(t){return Array.isArray(t)?t[1]:null}function zp(t){t.data.value!==void 0&&(t.value=t.data.value),t.data=t.data.data}function Yp(t){var e=0;do t.height=e;while((t=t.parent)&&t.height<++e)}function yr(t){this.data=t,this.depth=this.height=0,this.parent=null}yr.prototype=Re.prototype={constructor:yr,count:Us,each:Gs,eachAfter:zs,eachBefore:Vs,find:Ys,sum:Ws,sort:Xs,path:js,ancestors:Zs,descendants:Js,leaves:Qs,links:Ks,copy:Up,[Symbol.iterator]:tu};function eu(t){if(typeof t!="function")throw new Error;return t}function He(){return 0}function Fe(t){return function(){return t}}function ru(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)}function nu(t,e,r,n,o){for(var i=t.children,a,s=-1,u=i.length,c=t.value&&(n-e)/t.value;++sq&&(q=c),b=k*k*L,A=Math.max(q/b,b/_),A>D){k-=c;break}D=A}a.push(u={value:k,dice:m1?n:1)},r}(Wp);function _o(){var t=vr,e=!1,r=1,n=1,o=[0],i=He,a=He,s=He,u=He,c=He;function l(f){return f.x0=f.y0=0,f.x1=r,f.y1=n,f.eachBefore(p),o=[0],e&&f.eachBefore(ru),f}function p(f){var m=o[f.depth],d=f.x0+m,y=f.y0+m,k=f.x1-m,_=f.y1-m;ke&&(r=t,t=e,e=r),function(n){return Math.max(t,Math.min(e,n))}}function Zp(t,e,r){var n=t[0],o=t[1],i=e[0],a=e[1];return o2?Jp:Zp,u=c=null,p}function p(f){return f==null||isNaN(f=+f)?i:(u||(u=s(t.map(n),e,r)))(n(a(f)))}return p.invert=function(f){return a(o((c||(c=s(e,t.map(n),Z)))(f)))},p.domain=function(f){return arguments.length?(t=Array.from(f,So),l()):t.slice()},p.range=function(f){return arguments.length?(e=Array.from(f),l()):e.slice()},p.rangeRound=function(f){return e=Array.from(f),r=ur,l()},p.clamp=function(f){return arguments.length?(a=f?!0:Ut,l()):a!==Ut},p.interpolate=function(f){return arguments.length?(r=f,l()):r},p.unknown=function(f){return arguments.length?(i=f,p):i},function(f,m){return n=f,o=m,l()}}function wr(){return Qp()(Ut,Ut)}function Eo(t,e,r,n){var o=Le(t,e,r),i;switch(n=St(n??",f"),n.type){case"s":{var a=Math.max(Math.abs(t),Math.abs(e));return n.precision==null&&!isNaN(i=wo(o,a))&&(n.precision=i),dn(n,a)}case"":case"e":case"g":case"p":case"r":{n.precision==null&&!isNaN(i=ko(o,Math.max(Math.abs(t),Math.abs(e))))&&(n.precision=i-(n.type==="e"));break}case"f":case"%":{n.precision==null&&!isNaN(i=bo(o))&&(n.precision=i-(n.type==="%")*2);break}}return bt(n)}function Kp(t){var e=t.domain;return t.ticks=function(r){var n=e();return te(n[0],n[n.length-1],r??10)},t.tickFormat=function(r,n){var o=e();return Eo(o[0],o[o.length-1],r??10,n)},t.nice=function(r){r==null&&(r=10);var n=e(),o=0,i=n.length-1,a=n[o],s=n[i],u,c,l=10;for(s0;){if(c=Qe(a,s,r),c===u)return n[o]=a,n[i]=s,e(n);if(c>0)a=Math.floor(a/c)*c,s=Math.ceil(s/c)*c;else if(c<0)a=Math.ceil(a*c)/c,s=Math.floor(s*c)/c;else break;u=c}return t},t}function de(){var t=wr();return t.copy=function(){return hn(t,de())},$t.apply(t,arguments),Kp(t)}function kr(t,e){t=t.slice();var r=0,n=t.length-1,o=t[r],i=t[n],a;return iMath.pow(t,e)}function om(t){return t===Math.E?Math.log:t===10&&Math.log10||t===2&&Math.log2||(t=Math.log(t),e=>Math.log(e)/t)}function lu(t){return(e,r)=>-t(-e,r)}function cu(t){let e=t(su,uu),r=e.domain,n=10,o,i;function a(){return o=om(n),i=nm(n),r()[0]<0?(o=lu(o),i=lu(i),t(tm,em)):t(su,uu),e}return e.base=function(s){return arguments.length?(n=+s,a()):n},e.domain=function(s){return arguments.length?(r(s),a()):r()},e.ticks=s=>{let u=r(),c=u[0],l=u[u.length-1],p=l0){for(;f<=m;++f)for(d=1;dl)break;_.push(y)}}else for(;f<=m;++f)for(d=n-1;d>=1;--d)if(y=f>0?d/i(-f):d*i(f),!(yl)break;_.push(y)}_.length*2{if(s==null&&(s=10),u==null&&(u=n===10?"s":","),typeof u!="function"&&(!(n%1)&&(u=St(u)).precision==null&&(u.trim=!0),u=bt(u)),s===1/0)return u;let c=Math.max(1,n*s/e.ticks().length);return l=>{let p=l/i(Math.round(o(l)));return p*nr(kr(r(),{floor:s=>i(Math.floor(o(s))),ceil:s=>i(Math.ceil(o(s)))})),e}var Ao=new Date,Do=new Date;function z(t,e,r,n){function o(i){return t(i=arguments.length===0?new Date:new Date(+i)),i}return o.floor=i=>(t(i=new Date(+i)),i),o.ceil=i=>(t(i=new Date(i-1)),e(i,1),t(i),i),o.round=i=>{let a=o(i),s=o.ceil(i);return i-a(e(i=new Date(+i),a==null?1:Math.floor(a)),i),o.range=(i,a,s)=>{let u=[];if(i=o.ceil(i),s=s==null?1:Math.floor(s),!(i0))return u;let c;do u.push(c=new Date(+i)),e(i,s),t(i);while(cz(a=>{if(a>=a)for(;t(a),!i(a);)a.setTime(a-1)},(a,s)=>{if(a>=a)if(s<0)for(;++s<=0;)for(;e(a,-1),!i(a););else for(;--s>=0;)for(;e(a,1),!i(a););}),r&&(o.count=(i,a)=>(Ao.setTime(+i),Do.setTime(+a),t(Ao),t(Do),Math.floor(r(Ao,Do))),o.every=i=>(i=Math.floor(i),!isFinite(i)||!(i>0)?null:i>1?o.filter(n?a=>n(a)%i===0:a=>o.count(0,a)%i===0):o)),o}var _r=z(()=>{},(t,e)=>{t.setTime(+t+e)},(t,e)=>e-t);_r.every=t=>(t=Math.floor(t),!isFinite(t)||!(t>0)?null:t>1?z(e=>{e.setTime(Math.floor(e/t)*t)},(e,r)=>{e.setTime(+e+r*t)},(e,r)=>(r-e)/t):_r);var m_=_r.range;var Lt=z(t=>{t.setTime(t-t.getMilliseconds())},(t,e)=>{t.setTime(+t+e*1e3)},(t,e)=>(e-t)/1e3,t=>t.getUTCSeconds()),fu=Lt.range;var Oe=z(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*1e3)},(t,e)=>{t.setTime(+t+e*6e4)},(t,e)=>(e-t)/6e4,t=>t.getMinutes()),im=Oe.range,gn=z(t=>{t.setUTCSeconds(0,0)},(t,e)=>{t.setTime(+t+e*6e4)},(t,e)=>(e-t)/6e4,t=>t.getUTCMinutes()),am=gn.range;var Pe=z(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*1e3-t.getMinutes()*6e4)},(t,e)=>{t.setTime(+t+e*36e5)},(t,e)=>(e-t)/36e5,t=>t.getHours()),sm=Pe.range,xn=z(t=>{t.setUTCMinutes(0,0,0)},(t,e)=>{t.setTime(+t+e*36e5)},(t,e)=>(e-t)/36e5,t=>t.getUTCHours()),um=xn.range;var Rt=z(t=>t.setHours(0,0,0,0),(t,e)=>t.setDate(t.getDate()+e),(t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*6e4)/864e5,t=>t.getDate()-1),lm=Rt.range,Mr=z(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>t.getUTCDate()-1),cm=Mr.range,yn=z(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>Math.floor(t/864e5)),fm=yn.range;function xe(t){return z(e=>{e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)},(e,r)=>{e.setDate(e.getDate()+r*7)},(e,r)=>(r-e-(r.getTimezoneOffset()-e.getTimezoneOffset())*6e4)/6048e5)}var Ht=xe(0),$e=xe(1),mu=xe(2),du=xe(3),Gt=xe(4),hu=xe(5),gu=xe(6),xu=Ht.range,pm=$e.range,mm=mu.range,dm=du.range,hm=Gt.range,gm=hu.range,xm=gu.range;function ye(t){return z(e=>{e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)},(e,r)=>{e.setUTCDate(e.getUTCDate()+r*7)},(e,r)=>(r-e)/6048e5)}var ve=ye(0),Ue=ye(1),yu=ye(2),vu=ye(3),Vt=ye(4),bu=ye(5),wu=ye(6),ku=ve.range,ym=Ue.range,vm=yu.range,bm=vu.range,wm=Vt.range,km=bu.range,_m=wu.range;var Ge=z(t=>{t.setDate(1),t.setHours(0,0,0,0)},(t,e)=>{t.setMonth(t.getMonth()+e)},(t,e)=>e.getMonth()-t.getMonth()+(e.getFullYear()-t.getFullYear())*12,t=>t.getMonth()),Tm=Ge.range,vn=z(t=>{t.setUTCDate(1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCMonth(t.getUTCMonth()+e)},(t,e)=>e.getUTCMonth()-t.getUTCMonth()+(e.getUTCFullYear()-t.getUTCFullYear())*12,t=>t.getUTCMonth()),Mm=vn.range;var pt=z(t=>{t.setMonth(0,1),t.setHours(0,0,0,0)},(t,e)=>{t.setFullYear(t.getFullYear()+e)},(t,e)=>e.getFullYear()-t.getFullYear(),t=>t.getFullYear());pt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:z(e=>{e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)},(e,r)=>{e.setFullYear(e.getFullYear()+r*t)});var Sm=pt.range,wt=z(t=>{t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCFullYear(t.getUTCFullYear()+e)},(t,e)=>e.getUTCFullYear()-t.getUTCFullYear(),t=>t.getUTCFullYear());wt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:z(e=>{e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)},(e,r)=>{e.setUTCFullYear(e.getUTCFullYear()+r*t)});var Lm=wt.range;function Tu(t,e,r,n,o,i){let a=[[Lt,1,1e3],[Lt,5,5*1e3],[Lt,15,15*1e3],[Lt,30,30*1e3],[i,1,6e4],[i,5,5*6e4],[i,15,15*6e4],[i,30,30*6e4],[o,1,36e5],[o,3,3*36e5],[o,6,6*36e5],[o,12,12*36e5],[n,1,864e5],[n,2,2*864e5],[r,1,6048e5],[e,1,2592e6],[e,3,3*2592e6],[t,1,31536e6]];function s(c,l,p){let f=lk).right(a,f);if(m===a.length)return t.every(Le(c/31536e6,l/31536e6,p));if(m===0)return _r.every(Math.max(Le(c,l,p),1));let[d,y]=a[f/a[m-1][2]53)return null;"w"in w||(w.w=1),"Z"in w?(Y=No(Sr(w.y,0,1)),lt=Y.getUTCDay(),Y=lt>4||lt===0?Ue.ceil(Y):Ue(Y),Y=Mr.offset(Y,(w.V-1)*7),w.y=Y.getUTCFullYear(),w.m=Y.getUTCMonth(),w.d=Y.getUTCDate()+(w.w+6)%7):(Y=Io(Sr(w.y,0,1)),lt=Y.getDay(),Y=lt>4||lt===0?$e.ceil(Y):$e(Y),Y=Rt.offset(Y,(w.V-1)*7),w.y=Y.getFullYear(),w.m=Y.getMonth(),w.d=Y.getDate()+(w.w+6)%7)}else("W"in w||"U"in w)&&("w"in w||(w.w="u"in w?w.u%7:"W"in w?1:0),lt="Z"in w?No(Sr(w.y,0,1)).getUTCDay():Io(Sr(w.y,0,1)).getDay(),w.m=0,w.d="W"in w?(w.w+6)%7+w.W*7-(lt+5)%7:w.w+w.U*7-(lt+6)%7);return"Z"in w?(w.H+=w.Z/100|0,w.M+=w.Z%100,No(w)):Io(w)}}function H(C,F,U,w){for(var st=0,Y=F.length,lt=U.length,ct,Qt;st=lt)return-1;if(ct=F.charCodeAt(st++),ct===37){if(ct=F.charAt(st++),Qt=L[ct in Mu?F.charAt(st++):ct],!Qt||(w=Qt(C,U,w))<0)return-1}else if(ct!=U.charCodeAt(w++))return-1}return w}function P(C,F,U){var w=c.exec(F.slice(U));return w?(C.p=l.get(w[0].toLowerCase()),U+w[0].length):-1}function I(C,F,U){var w=m.exec(F.slice(U));return w?(C.w=d.get(w[0].toLowerCase()),U+w[0].length):-1}function h(C,F,U){var w=p.exec(F.slice(U));return w?(C.w=f.get(w[0].toLowerCase()),U+w[0].length):-1}function T(C,F,U){var w=_.exec(F.slice(U));return w?(C.m=q.get(w[0].toLowerCase()),U+w[0].length):-1}function E(C,F,U){var w=y.exec(F.slice(U));return w?(C.m=k.get(w[0].toLowerCase()),U+w[0].length):-1}function R(C,F,U){return H(C,e,F,U)}function g(C,F,U){return H(C,r,F,U)}function x(C,F,U){return H(C,n,F,U)}function M(C){return a[C.getDay()]}function S(C){return i[C.getDay()]}function v(C){return u[C.getMonth()]}function B(C){return s[C.getMonth()]}function G(C){return o[+(C.getHours()>=12)]}function K(C){return 1+~~(C.getMonth()/3)}function ot(C){return a[C.getUTCDay()]}function ht(C){return i[C.getUTCDay()]}function tt(C){return u[C.getUTCMonth()]}function Dt(C){return s[C.getUTCMonth()]}function gt(C){return o[+(C.getUTCHours()>=12)]}function Je(C){return 1+~~(C.getUTCMonth()/3)}return{format:function(C){var F=b(C+="",A);return F.toString=function(){return C},F},parse:function(C){var F=N(C+="",!1);return F.toString=function(){return C},F},utcFormat:function(C){var F=b(C+="",D);return F.toString=function(){return C},F},utcParse:function(C){var F=N(C+="",!0);return F.toString=function(){return C},F}}}var Mu={"-":"",_:" ",0:"0"},Q=/^\s*\d+/,Cm=/^%/,qm=/[\\^$*+?|[\]().{}]/g;function V(t,e,r){var n=t<0?"-":"",o=(n?-t:t)+"",i=o.length;return n+(i[e.toLowerCase(),r]))}function Nm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.w=+n[0],r+n[0].length):-1}function Bm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.u=+n[0],r+n[0].length):-1}function Rm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.U=+n[0],r+n[0].length):-1}function Hm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.V=+n[0],r+n[0].length):-1}function Fm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.W=+n[0],r+n[0].length):-1}function Su(t,e,r){var n=Q.exec(e.slice(r,r+4));return n?(t.y=+n[0],r+n[0].length):-1}function Lu(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.y=+n[0]+(+n[0]>68?1900:2e3),r+n[0].length):-1}function Om(t,e,r){var n=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(r,r+6));return n?(t.Z=n[1]?0:-(n[2]+(n[3]||"00")),r+n[0].length):-1}function Pm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.q=n[0]*3-3,r+n[0].length):-1}function $m(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.m=n[0]-1,r+n[0].length):-1}function Eu(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.d=+n[0],r+n[0].length):-1}function Um(t,e,r){var n=Q.exec(e.slice(r,r+3));return n?(t.m=0,t.d=+n[0],r+n[0].length):-1}function Au(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.H=+n[0],r+n[0].length):-1}function Gm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.M=+n[0],r+n[0].length):-1}function Vm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.S=+n[0],r+n[0].length):-1}function zm(t,e,r){var n=Q.exec(e.slice(r,r+3));return n?(t.L=+n[0],r+n[0].length):-1}function Ym(t,e,r){var n=Q.exec(e.slice(r,r+6));return n?(t.L=Math.floor(n[0]/1e3),r+n[0].length):-1}function Wm(t,e,r){var n=Cm.exec(e.slice(r,r+1));return n?r+n[0].length:-1}function Xm(t,e,r){var n=Q.exec(e.slice(r));return n?(t.Q=+n[0],r+n[0].length):-1}function jm(t,e,r){var n=Q.exec(e.slice(r));return n?(t.s=+n[0],r+n[0].length):-1}function Du(t,e){return V(t.getDate(),e,2)}function Zm(t,e){return V(t.getHours(),e,2)}function Jm(t,e){return V(t.getHours()%12||12,e,2)}function Qm(t,e){return V(1+Rt.count(pt(t),t),e,3)}function Bu(t,e){return V(t.getMilliseconds(),e,3)}function Km(t,e){return Bu(t,e)+"000"}function td(t,e){return V(t.getMonth()+1,e,2)}function ed(t,e){return V(t.getMinutes(),e,2)}function rd(t,e){return V(t.getSeconds(),e,2)}function nd(t){var e=t.getDay();return e===0?7:e}function od(t,e){return V(Ht.count(pt(t)-1,t),e,2)}function Ru(t){var e=t.getDay();return e>=4||e===0?Gt(t):Gt.ceil(t)}function id(t,e){return t=Ru(t),V(Gt.count(pt(t),t)+(pt(t).getDay()===4),e,2)}function ad(t){return t.getDay()}function sd(t,e){return V($e.count(pt(t)-1,t),e,2)}function ud(t,e){return V(t.getFullYear()%100,e,2)}function ld(t,e){return t=Ru(t),V(t.getFullYear()%100,e,2)}function cd(t,e){return V(t.getFullYear()%1e4,e,4)}function fd(t,e){var r=t.getDay();return t=r>=4||r===0?Gt(t):Gt.ceil(t),V(t.getFullYear()%1e4,e,4)}function pd(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+V(e/60|0,"0",2)+V(e%60,"0",2)}function Cu(t,e){return V(t.getUTCDate(),e,2)}function md(t,e){return V(t.getUTCHours(),e,2)}function dd(t,e){return V(t.getUTCHours()%12||12,e,2)}function hd(t,e){return V(1+Mr.count(wt(t),t),e,3)}function Hu(t,e){return V(t.getUTCMilliseconds(),e,3)}function gd(t,e){return Hu(t,e)+"000"}function xd(t,e){return V(t.getUTCMonth()+1,e,2)}function yd(t,e){return V(t.getUTCMinutes(),e,2)}function vd(t,e){return V(t.getUTCSeconds(),e,2)}function bd(t){var e=t.getUTCDay();return e===0?7:e}function wd(t,e){return V(ve.count(wt(t)-1,t),e,2)}function Fu(t){var e=t.getUTCDay();return e>=4||e===0?Vt(t):Vt.ceil(t)}function kd(t,e){return t=Fu(t),V(Vt.count(wt(t),t)+(wt(t).getUTCDay()===4),e,2)}function _d(t){return t.getUTCDay()}function Td(t,e){return V(Ue.count(wt(t)-1,t),e,2)}function Md(t,e){return V(t.getUTCFullYear()%100,e,2)}function Sd(t,e){return t=Fu(t),V(t.getUTCFullYear()%100,e,2)}function Ld(t,e){return V(t.getUTCFullYear()%1e4,e,4)}function Ed(t,e){var r=t.getUTCDay();return t=r>=4||r===0?Vt(t):Vt.ceil(t),V(t.getUTCFullYear()%1e4,e,4)}function Ad(){return"+0000"}function qu(){return"%"}function Iu(t){return+t}function Nu(t){return Math.floor(+t/1e3)}var Ve,bn,Ou,Pu,$u;Ro({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function Ro(t){return Ve=Bo(t),bn=Ve.format,Ou=Ve.parse,Pu=Ve.utcFormat,$u=Ve.utcParse,Ve}function Dd(t){return new Date(t)}function Cd(t){return t instanceof Date?+t:+new Date(+t)}function Uu(t,e,r,n,o,i,a,s,u,c){var l=wr(),p=l.invert,f=l.domain,m=c(".%L"),d=c(":%S"),y=c("%I:%M"),k=c("%I %p"),_=c("%a %d"),q=c("%b %d"),A=c("%B"),D=c("%Y");function L(b){return(u(b)1?0:t<-1?ze:Math.acos(t)}function Po(t){return t>=1?Ar:t<=-1?-Ar:Math.asin(t)}function Tn(t){let e=3;return t.digits=function(r){if(!arguments.length)return e;if(r==null)e=null;else{let n=Math.floor(r);if(!(n>=0))throw new RangeError(`invalid digits: ${r}`);e=n}return t},()=>new fe(e)}function Bd(t){return t.innerRadius}function Rd(t){return t.outerRadius}function Hd(t){return t.startAngle}function Fd(t){return t.endAngle}function Od(t){return t&&t.padAngle}function Pd(t,e,r,n,o,i,a,s){var u=r-t,c=n-e,l=a-o,p=s-i,f=p*u-l*c;if(!(f*fR*R+g*g&&(H=I,P=h),{cx:H,cy:P,x01:-l,y01:-p,x11:H*(o/L-1),y11:P*(o/L-1)}}function $o(){var t=Bd,e=Rd,r=W(0),n=null,o=Hd,i=Fd,a=Od,s=null,u=Tn(c);function c(){var l,p,f=+t.apply(this,arguments),m=+e.apply(this,arguments),d=o.apply(this,arguments)-Ar,y=i.apply(this,arguments)-Ar,k=Oo(y-d),_=y>d;if(s||(s=l=u()),mat))s.moveTo(0,0);else if(k>Ye-at)s.moveTo(m*zt(d),m*kt(d)),s.arc(0,0,m,d,y,!_),f>at&&(s.moveTo(f*zt(y),f*kt(y)),s.arc(0,0,f,y,d,_));else{var q=d,A=y,D=d,L=y,b=k,N=k,H=a.apply(this,arguments)/2,P=H>at&&(n?+n.apply(this,arguments):be(f*f+m*m)),I=_n(Oo(m-f)/2,+r.apply(this,arguments)),h=I,T=I,E,R;if(P>at){var g=Po(P/f*kt(H)),x=Po(P/m*kt(H));(b-=g*2)>at?(g*=_?1:-1,D+=g,L-=g):(b=0,D=L=(d+y)/2),(N-=x*2)>at?(x*=_?1:-1,q+=x,A-=x):(N=0,q=A=(d+y)/2)}var M=m*zt(q),S=m*kt(q),v=f*zt(L),B=f*kt(L);if(I>at){var G=m*zt(A),K=m*kt(A),ot=f*zt(D),ht=f*kt(D),tt;if(kat?T>at?(E=Mn(ot,ht,M,S,m,T,_),R=Mn(G,K,v,B,m,T,_),s.moveTo(E.cx+E.x01,E.cy+E.y01),Tat)||!(b>at)?s.lineTo(v,B):h>at?(E=Mn(v,B,G,K,f,-h,_),R=Mn(M,S,ot,ht,f,-h,_),s.lineTo(E.cx+E.x01,E.cy+E.y01),ht?1:e>=t?0:NaN}function Ju(t){return t}function Uo(){var t=Ju,e=Zu,r=null,n=W(0),o=W(Ye),i=W(0);function a(s){var u,c=(s=Sn(s)).length,l,p,f=0,m=new Array(c),d=new Array(c),y=+n.apply(this,arguments),k=Math.min(Ye,Math.max(-Ye,o.apply(this,arguments)-y)),_,q=Math.min(Math.abs(k)/c,i.apply(this,arguments)),A=q*(k<0?-1:1),D;for(u=0;u0&&(f+=D);for(e!=null?m.sort(function(L,b){return e(d[L],d[b])}):r!=null&&m.sort(function(L,b){return r(s[L],s[b])}),u=0,p=f?(k-c*A)/f:0;u0?D*p:0)+A,d[l]={data:s[l],index:u,value:D,startAngle:y,endAngle:_,padAngle:q};return d}return a.value=function(s){return arguments.length?(t=typeof s=="function"?s:W(+s),a):t},a.sortValues=function(s){return arguments.length?(e=s,r=null,a):e},a.sort=function(s){return arguments.length?(r=s,e=null,a):r},a.startAngle=function(s){return arguments.length?(n=typeof s=="function"?s:W(+s),a):n},a.endAngle=function(s){return arguments.length?(o=typeof s=="function"?s:W(+s),a):o},a.padAngle=function(s){return arguments.length?(i=typeof s=="function"?s:W(+s),a):i},a}function Qu(t){return t<0?-1:1}function Ku(t,e,r){var n=t._x1-t._x0,o=e-t._x1,i=(t._y1-t._y0)/(n||o<0&&-0),a=(r-t._y1)/(o||n<0&&-0),s=(i*o+a*n)/(n+o);return(Qu(i)+Qu(a))*Math.min(Math.abs(i),Math.abs(a),.5*Math.abs(s))||0}function tl(t,e){var r=t._x1-t._x0;return r?(3*(t._y1-t._y0)/r-e)/2:e}function Go(t,e,r){var n=t._x0,o=t._y0,i=t._x1,a=t._y1,s=(i-n)/3;t._context.bezierCurveTo(n+s,o+s*e,i-s,a-s*r,i,a)}function Ln(t){this._context=t}Ln.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:Go(this,this._t0,tl(this,this._t0));break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){var r=NaN;if(t=+t,e=+e,!(t===this._x1&&e===this._y1)){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,Go(this,tl(this,r=Ku(this,t,e)),r);break;default:Go(this,this._t0,r=Ku(this,t,e));break}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e,this._t0=r}}};function $d(t){this._context=new el(t)}($d.prototype=Object.create(Ln.prototype)).point=function(t,e){Ln.prototype.point.call(this,e,t)};function el(t){this._context=t}el.prototype={moveTo:function(t,e){this._context.moveTo(e,t)},closePath:function(){this._context.closePath()},lineTo:function(t,e){this._context.lineTo(e,t)},bezierCurveTo:function(t,e,r,n,o,i){this._context.bezierCurveTo(e,t,n,r,i,o)}};function En(t){return new Ln(t)}function Yt(t,e,r){this.k=t,this.x=e,this.y=r}Yt.prototype={constructor:Yt,scale:function(t){return t===1?this:new Yt(this.k*t,this.x,this.y)},translate:function(t,e){return t===0&e===0?this:new Yt(this.k,this.x+this.k*t,this.y+this.k*e)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Vo=new Yt(1,0,0);zo.prototype=Yt.prototype;function zo(t){for(;!t.__zoom;)if(!(t=t.parentNode))return Vo;return t.__zoom}var dt=bt(",.0f"),Wt=bt(",.1f");function Wo(t){function e(c){return c.toString().padStart(2,"0")}let r=Math.floor(t/1e3),n=Math.floor(r/60),o=Math.floor(n/60),i=Math.floor(o/24),a=o%24,s=n%60,u=r%60;return i===0&&a===0&&s===0&&u===0?"0s":i>0?`${i}d ${e(a)}h ${e(s)}m ${e(u)}s`:a>0?`${a}h ${e(s)}m ${e(u)}s`:s>0?`${s}m ${e(u)}s`:`${u}s`}var Ud=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function nl(t){let e=new Date(t*1e3),r=String(e.getDate()).padStart(2,"0"),n=Ud[e.getMonth()],o=e.getFullYear(),i=String(e.getHours()).padStart(2,"0"),a=String(e.getMinutes()).padStart(2,"0"),s=String(e.getSeconds()).padStart(2,"0");return`${r} ${n} ${o} ${i}:${a}:${s}`}var Yo=["bytes","kB","MB","GB","TB","PB"];function ol(t){if(!Number.isFinite(t)||t<0)return"0 bytes";let e=0,r=t;for(;r>=1e3&&eGd(a.charCodeAt(0))).length>=o.length/2?`0x${e}`:o}function Gd(t){return t<32||t>=127&&t<160}function Vd(t){if(t.length===0||t.length%2!==0)return new Uint8Array;let e=new Uint8Array(t.length/2);for(let r=0;r=1e14){let o=t/1e18;n=`${rl(o,4)} ${ll}`}else if(t>=1e5){let o=t/1e9;n=`${rl(o,4)} gwei`}else n=`${t} wei`;return n}function An(t){return!t.startsWith("0x")||t.length<14?t:`${t.slice(0,8)}...${t.slice(-6)}`}function Xt(t,e,r=80,n=44,o=60){let i=e[e.length-1],a=i.t-o*1e3;e=e.filter(A=>A.t>=a);let s={top:2,right:2,bottom:2,left:2},u=r-s.left-s.right,c=n-s.top-s.bottom,l=j(t).select("svg");l.empty()&&(l=j(t).append("svg").attr("width",r).attr("height",n),l.append("g").attr("class","line-group").attr("transform",`translate(${s.left},${s.top})`).append("path").attr("class","sparkline-path").attr("fill","none").attr("stroke","#00bff2").attr("stroke-width",1.5),l.append("g").attr("class","y-axis").attr("transform",`translate(${s.left},${s.top})`)),l.attr("width",r).attr("height",n);let f=l.select("g.line-group").select("path.sparkline-path"),m=i.t,d=wn().domain([new Date(a),new Date(m)]).range([0,u]),[y,k]=Me(e,A=>A.v),_=de().domain([y,k]).range([c,0]).nice(),q=We().x(A=>d(new Date(A.t))).y(A=>_(A.v));if(f.datum(e).attr("d",q).attr("transform",null),e.length>1){let A=u/o;f.attr("transform",`translate(${A},0)`),f.transition().duration(300).attr("transform","translate(0,0)")}}function Cr(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r=o)&&(r=o)}return r}function Xe(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r>n||r===void 0&&n>=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r>o||r===void 0&&o>=o)&&(r=o)}return r}function je(t,e){let r=0;if(e===void 0)for(let n of t)(n=+n)&&(r+=n);else{let n=-1;for(let o of t)(o=+e(o,++n,t))&&(r+=o)}return r}function Xd(t){return t.target.depth}function Xo(t,e){return t.sourceLinks.length?t.depth:e-1}function jo(t){return t.targetLinks.length?t.depth:t.sourceLinks.length?Xe(t.sourceLinks,Xd)-1:0}function Ze(t){return function(){return t}}function fl(t,e){return Dn(t.source,e.source)||t.index-e.index}function pl(t,e){return Dn(t.target,e.target)||t.index-e.index}function Dn(t,e){return t.y0-e.y0}function Zo(t){return t.value}function jd(t){return t.index}function Zd(t){return t.nodes}function Jd(t){return t.links}function ml(t,e){let r=t.get(e);if(!r)throw new Error("missing: "+e);return r}function dl({nodes:t}){for(let e of t){let r=e.y0,n=r;for(let o of e.sourceLinks)o.y0=r+o.width/2,r+=o.width;for(let o of e.targetLinks)o.y1=n+o.width/2,n+=o.width}}function Cn(){let t=0,e=0,r=1,n=1,o=24,i=8,a,s=jd,u=Xo,c,l,p=Zd,f=Jd,m=6;function d(){let g={nodes:p.apply(null,arguments),links:f.apply(null,arguments)};return y(g),k(g),_(g),q(g),L(g),dl(g),g}d.update=function(g){return dl(g),g},d.nodeId=function(g){return arguments.length?(s=typeof g=="function"?g:Ze(g),d):s},d.nodeAlign=function(g){return arguments.length?(u=typeof g=="function"?g:Ze(g),d):u},d.nodeSort=function(g){return arguments.length?(c=g,d):c},d.nodeWidth=function(g){return arguments.length?(o=+g,d):o},d.nodePadding=function(g){return arguments.length?(i=a=+g,d):i},d.nodes=function(g){return arguments.length?(p=typeof g=="function"?g:Ze(g),d):p},d.links=function(g){return arguments.length?(f=typeof g=="function"?g:Ze(g),d):f},d.linkSort=function(g){return arguments.length?(l=g,d):l},d.size=function(g){return arguments.length?(t=e=0,r=+g[0],n=+g[1],d):[r-t,n-e]},d.extent=function(g){return arguments.length?(t=+g[0][0],r=+g[1][0],e=+g[0][1],n=+g[1][1],d):[[t,e],[r,n]]},d.iterations=function(g){return arguments.length?(m=+g,d):m};function y({nodes:g,links:x}){for(let[S,v]of g.entries())v.index=S,v.sourceLinks=[],v.targetLinks=[];let M=new Map(g.map((S,v)=>[s(S,v,g),S]));for(let[S,v]of x.entries()){v.index=S;let{source:B,target:G}=v;typeof B!="object"&&(B=v.source=ml(M,B)),typeof G!="object"&&(G=v.target=ml(M,G)),B.sourceLinks.push(v),G.targetLinks.push(v)}if(l!=null)for(let{sourceLinks:S,targetLinks:v}of g)S.sort(l),v.sort(l)}function k({nodes:g}){for(let x of g)x.value=x.fixedValue===void 0?Math.max(je(x.sourceLinks,Zo),je(x.targetLinks,Zo)):x.fixedValue}function _({nodes:g}){let x=g.length,M=new Set(g),S=new Set,v=0;for(;M.size;){for(let B of M){B.depth=v;for(let{target:G}of B.sourceLinks)S.add(G)}if(++v>x)throw new Error("circular link");M=S,S=new Set}}function q({nodes:g}){let x=g.length,M=new Set(g),S=new Set,v=0;for(;M.size;){for(let B of M){B.height=v;for(let{source:G}of B.targetLinks)S.add(G)}if(++v>x)throw new Error("circular link");M=S,S=new Set}}function A({nodes:g}){let x=Cr(g,v=>v.depth)+1,M=(r-t-o)/(x-1),S=new Array(x);for(let v of g){let B=Math.max(0,Math.min(x-1,Math.floor(u.call(null,v,x))));v.layer=B,v.x0=t+B*M,v.x1=v.x0+o,S[B]?S[B].push(v):S[B]=[v]}if(c)for(let v of S)v.sort(c);return S}function D(g){let x=Xe(g,M=>(n-e-(M.length-1)*a)/je(M,Zo));for(let M of g){let S=e;for(let v of M){v.y0=S,v.y1=S+v.value*x,S=v.y1+a;for(let B of v.sourceLinks)B.width=B.value*x}S=(n-S+a)/(M.length+1);for(let v=0;vM.length)-1)),D(x);for(let M=0;M0))continue;let ht=(K/ot-G.y0)*x;G.y0+=ht,G.y1+=ht,h(G)}c===void 0&&B.sort(Dn),H(B,M)}}function N(g,x,M){for(let S=g.length,v=S-2;v>=0;--v){let B=g[v];for(let G of B){let K=0,ot=0;for(let{target:tt,value:Dt}of G.sourceLinks){let gt=Dt*(tt.layer-G.layer);K+=R(G,tt)*gt,ot+=gt}if(!(ot>0))continue;let ht=(K/ot-G.y0)*x;G.y0+=ht,G.y1+=ht,h(G)}c===void 0&&B.sort(Dn),H(B,M)}}function H(g,x){let M=g.length>>1,S=g[M];I(g,S.y0-a,M-1,x),P(g,S.y1+a,M+1,x),I(g,n,g.length-1,x),P(g,e,0,x)}function P(g,x,M,S){for(;M1e-6&&(v.y0+=B,v.y1+=B),x=v.y1+a}}function I(g,x,M,S){for(;M>=0;--M){let v=g[M],B=(v.y1-x)*S;B>1e-6&&(v.y0-=B,v.y1-=B),x=v.y0-a}}function h({sourceLinks:g,targetLinks:x}){if(l===void 0){for(let{source:{sourceLinks:M}}of x)M.sort(pl);for(let{target:{targetLinks:M}}of g)M.sort(fl)}}function T(g){if(l===void 0)for(let{sourceLinks:x,targetLinks:M}of g)x.sort(pl),M.sort(fl)}function E(g,x){let M=g.y0-(g.sourceLinks.length-1)*a/2;for(let{target:S,width:v}of g.sourceLinks){if(S===x)break;M+=v+a}for(let{source:S,width:v}of x.targetLinks){if(S===g)break;M-=v}return M}function R(g,x){let M=x.y0-(x.targetLinks.length-1)*a/2;for(let{source:S,width:v}of x.targetLinks){if(S===g)break;M+=v+a}for(let{target:S,width:v}of g.sourceLinks){if(S===x)break;M-=v}return M}return d}var Jo=Math.PI,Qo=2*Jo,ke=1e-6,Qd=Qo-ke;function Ko(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function hl(){return new Ko}Ko.prototype=hl.prototype={constructor:Ko,moveTo:function(t,e){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)},closePath:function(){this._x1!==null&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,e){this._+="L"+(this._x1=+t)+","+(this._y1=+e)},quadraticCurveTo:function(t,e,r,n){this._+="Q"+ +t+","+ +e+","+(this._x1=+r)+","+(this._y1=+n)},bezierCurveTo:function(t,e,r,n,o,i){this._+="C"+ +t+","+ +e+","+ +r+","+ +n+","+(this._x1=+o)+","+(this._y1=+i)},arcTo:function(t,e,r,n,o){t=+t,e=+e,r=+r,n=+n,o=+o;var i=this._x1,a=this._y1,s=r-t,u=n-e,c=i-t,l=a-e,p=c*c+l*l;if(o<0)throw new Error("negative radius: "+o);if(this._x1===null)this._+="M"+(this._x1=t)+","+(this._y1=e);else if(p>ke)if(!(Math.abs(l*s-u*c)>ke)||!o)this._+="L"+(this._x1=t)+","+(this._y1=e);else{var f=r-i,m=n-a,d=s*s+u*u,y=f*f+m*m,k=Math.sqrt(d),_=Math.sqrt(p),q=o*Math.tan((Jo-Math.acos((d+p-y)/(2*k*_)))/2),A=q/_,D=q/k;Math.abs(A-1)>ke&&(this._+="L"+(t+A*c)+","+(e+A*l)),this._+="A"+o+","+o+",0,0,"+ +(l*f>c*m)+","+(this._x1=t+D*s)+","+(this._y1=e+D*u)}},arc:function(t,e,r,n,o,i){t=+t,e=+e,r=+r,i=!!i;var a=r*Math.cos(n),s=r*Math.sin(n),u=t+a,c=e+s,l=1^i,p=i?n-o:o-n;if(r<0)throw new Error("negative radius: "+r);this._x1===null?this._+="M"+u+","+c:(Math.abs(this._x1-u)>ke||Math.abs(this._y1-c)>ke)&&(this._+="L"+u+","+c),r&&(p<0&&(p=p%Qo+Qo),p>Qd?this._+="A"+r+","+r+",0,1,"+l+","+(t-a)+","+(e-s)+"A"+r+","+r+",0,1,"+l+","+(this._x1=u)+","+(this._y1=c):p>ke&&(this._+="A"+r+","+r+",0,"+ +(p>=Jo)+","+l+","+(this._x1=t+r*Math.cos(o))+","+(this._y1=e+r*Math.sin(o))))},rect:function(t,e,r,n){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +r+"v"+ +n+"h"+-r+"Z"},toString:function(){return this._}};var ti=hl;function ei(t){return function(){return t}}function gl(t){return t[0]}function xl(t){return t[1]}var yl=Array.prototype.slice;function Kd(t){return t.source}function th(t){return t.target}function eh(t){var e=Kd,r=th,n=gl,o=xl,i=null;function a(){var s,u=yl.call(arguments),c=e.apply(this,u),l=r.apply(this,u);if(i||(i=s=ti()),t(i,+n.apply(this,(u[0]=c,u)),+o.apply(this,u),+n.apply(this,(u[0]=l,u)),+o.apply(this,u)),s)return i=null,s+""||null}return a.source=function(s){return arguments.length?(e=s,a):e},a.target=function(s){return arguments.length?(r=s,a):r},a.x=function(s){return arguments.length?(n=typeof s=="function"?s:ei(+s),a):n},a.y=function(s){return arguments.length?(o=typeof s=="function"?s:ei(+s),a):o},a.context=function(s){return arguments.length?(i=s??null,a):i},a}function rh(t,e,r,n,o){t.moveTo(e,r),t.bezierCurveTo(e=(e+n)/2,r,e,o,n,o)}function ri(){return eh(rh)}function nh(t){return[t.source.x1,t.y0]}function oh(t){return[t.target.x0,t.y1]}function ni(){return ri().source(nh).target(oh)}var qn=class{svg;rectG;linkG;nodeG;sankeyGenerator;width=window.innerWidth;height=250;defs;blueColors=["#E1F5FE","#B3E5FC","#81D4FA","#4FC3F7","#29B6F6","#03A9F4","#039BE5","#0288D1","#0277BD","#01579B"];orangeColors=["#FFF5e1","#FFE0B2","#FFCC80","#FFB74D","#FFA726","#FF9800","#FB8C00","#F57C00","#EF6C00","#E65100"];constructor(e){this.svg=j(e).append("svg").attr("width",window.innerWidth).attr("height",this.height).attr("viewBox",[0,0,window.innerWidth,this.height]).style("max-width","100%").style("height","auto"),this.defs=this.svg.append("defs");let r=this.blueColors.slice(5,-1);r=[...r,...r,...r,...r],this.initGradient("blue-flow",r),this.rectG=this.svg.append("g").attr("stroke","#000"),this.linkG=this.svg.append("g").attr("fill","none").style("mix-blend-mode","normal"),this.nodeG=this.svg.append("g"),this.sankeyGenerator=Cn().nodeId(n=>n.name).nodeAlign(jo).nodeWidth(10).nodePadding(30).nodeSort((n,o)=>n.inclusion&&o.inclusion?n.namen.target.inclusion&&o.target.inclusion?n.source.namei/(r.length-1)).attr("stop-color",o=>o),n.append("animate").attr("attributeName","x1").attr("values","0%;200%").attr("dur","12s").attr("repeatCount","indefinite"),n.append("animate").attr("attributeName","x2").attr("values","100%;300%").attr("dur","12s").attr("repeatCount","indefinite")}isRightAligned(e){return!e.inclusion}update(e,r){this.sankeyGenerator.extent([[100,20],[window.innerWidth-100,this.height-25]]);let n=[],o={};this.width=window.innerWidth-56,this.svg.attr("width",this.width).attr("height",this.height).attr("viewBox",[0,0,this.width,this.height]);for(let l of r.links)l.value>0&&(n.push(l),o[l.source]=!0,o[l.target]=!0);let a={nodes:e.filter(l=>o[l.name]).map(l=>({...l})),links:n.map(l=>({...l}))},{nodes:s,links:u}=this.sankeyGenerator(a);this.rectG.selectAll("rect").data(s,l=>l.name).join("rect").attr("x",l=>l.x0).attr("y",l=>l.y0).attr("height",l=>l.y1-l.y0).attr("width",l=>l.x1-l.x0).attr("fill",l=>(l.name==="P2P Network"&&(l.value=r.hashesReceived),l.inclusion?l.name==="Tx Pool"||l.name==="Added To Block"?"#FFA726":"#00BFF2":"#555")),this.linkG.selectAll("path").data(u,l=>l.index).join("path").attr("d",ni()).attr("stroke",l=>l.target.inclusion?"url(#blue-flow)":"#333").attr("stroke-width",l=>Math.max(1,l.width??1));let c=this.nodeG.selectAll("text").data(s,l=>l.name).join(l=>l.append("text").attr("data-last","0"),l=>l,l=>l.remove());c.attr("data-last",function(l){return j(this).attr("data-current")||"0"}).attr("data-current",l=>(l.targetLinks||[]).reduce((f,m)=>f+(m.value||0),0)||l.value||0).attr("x",l=>this.isRightAligned(l)?l.x1+6:l.x0-6).attr("y",l=>(l.y0+l.y1)/2).attr("dy","-0.5em").attr("text-anchor",l=>this.isRightAligned(l)?"start":"end").text(l=>l.name).each(function(){j(this).selectAll("tspan.number").data([0]).join("tspan").attr("class","number").attr("x",()=>{let l=j(this).datum();return l&&l.inclusion?l.x1+6:l.x0-6}).attr("dy","1em")}),c.selectAll("tspan.number").transition().duration(500).tween("text",function(){let l=j(this),p=j(this.parentNode),f=p.empty()?0:parseFloat(p.attr("data-last")||"0"),m=p.empty()?0:parseFloat(p.attr("data-current")||"0"),d=Z(f,m);return function(y){l.text(bt(",.0f")(d(y)))}})}};function vl(t,e,r,n,o,i,a,s){let u=window.innerWidth-56,l={name:"root",children:[...n.map(h=>({name:o(h),item:h,size:a(h)}))]},p=Re(l).sum(h=>h.children?0:a(h.data?h.data.item:h.item)).sort(h=>h.children?0:i(h.data?h.data.item:h.item)),f=p.value??0,m=f>0?f/r:0,d=Math.min(u,u*m);_o().size([d,e-1]).round(!0).tile(vr.ratio(1)).paddingOuter(.5).paddingInner(2)(p);let[y,k]=Me(n,s),_=y&&y>0?y:1e-6,q=k||1,A=kn(Fo).domain([_,q]);function D(h){let T=s(h),E=T>0?T:1e-6;return A(E)}let L=j(t).select("svg");if(L.empty()){L=j(t).append("svg").attr("width",u).attr("height",e).attr("viewBox",[0,0,u,e]);let h=L.append("defs"),T=h.append("pattern").attr("id","unusedStripes").attr("patternUnits","userSpaceOnUse").attr("width",8).attr("height",8);T.append("rect").attr("class","pattern-bg").attr("width",8).attr("height",8).attr("fill","#444"),T.append("path").attr("d","M0,0 l8,8").attr("stroke","#000").attr("stroke-width",1),L.append("rect").attr("class","unused").attr("fill","url(#unusedStripes)").attr("opacity",1).attr("width",u).attr("height",e).attr("stroke","#fff").attr("stroke-width",1),h.append("marker").attr("id","arrowStart").attr("markerWidth",10).attr("markerHeight",10).attr("refX",5).attr("refY",5).attr("orient","auto").attr("markerUnits","strokeWidth").append("path").attr("d","M10,0 L0,5 L10,10").attr("fill","#ccc"),h.append("marker").attr("id","arrowEnd").attr("markerWidth",10).attr("markerHeight",10).attr("refX",5).attr("refY",5).attr("orient","auto").attr("markerUnits","strokeWidth").append("path").attr("d","M0,0 L10,5 L0,10").attr("fill","#ccc")}L.attr("width",u).attr("height",e).attr("viewBox",[0,0,u,e]),L.selectAll("rect.unused").attr("width",u);let b=p.leaves();L.selectAll("g.node").data(b,h=>h.data.name).join(h=>{let T=h.append("g").attr("class","node").attr("data-hash",E=>E.data.name).attr("transform",E=>`translate(${E.x0},${E.y0})`).attr("opacity",0);return T.append("rect").attr("stroke","#000").attr("stroke-width",.5).attr("width",0).attr("height",0).attr("fill",E=>D(E.data.item)),T.transition().duration(600).attr("opacity",1),T.select("rect").transition().duration(600).attr("width",E=>E.x1-E.x0).attr("height",E=>E.y1-E.y0),T},h=>(h.transition().duration(600).attr("transform",T=>`translate(${T.x0},${T.y0})`).attr("opacity",1),h.select("rect").transition().duration(600).attr("width",T=>T.x1-T.x0).attr("height",T=>T.y1-T.y0).attr("fill",T=>D(T.data.item)),h),h=>{h.transition().duration(600).attr("opacity",0).remove()});let H=(r-f)/r,I=H>=.1?[{key:"unused-label",x:d,w:u-d,ratio:H}]:[];L.selectAll("line.unused-arrow").data(I,h=>h.key).join(h=>h.append("line").attr("class","unused-arrow").attr("x1",T=>T.x+10).attr("x2",T=>T.x+T.w-10).attr("y1",145).attr("y2",145).attr("stroke","#ccc").attr("stroke-width",2).attr("marker-start","url(#arrowStart)").attr("marker-end","url(#arrowEnd)").attr("opacity",0).call(T=>T.transition().duration(600).attr("opacity",1)),h=>h.transition().duration(600).attr("x1",T=>T.x+10).attr("x2",T=>T.x+T.w-10),h=>h.transition().duration(600).attr("opacity",0).remove()),L.selectAll("text.unused-label").data(I,h=>h.key).join(h=>h.append("text").attr("class","unused-label").attr("x",T=>T.x+T.w/2).attr("y",135).attr("fill","#ccc").attr("font-size",14).attr("text-anchor","middle").attr("opacity",0).text(T=>`${(T.ratio*100).toFixed(1)}% available`).call(T=>T.transition().duration(600).attr("opacity",1)),h=>h.transition().duration(600).attr("x",T=>T.x+T.w/2).text(T=>`${(T.ratio*100).toFixed(1)}% available`),h=>h.transition().duration(600).attr("opacity",0).remove())}function bl(t,e,r=36){let n={top:4,right:4,bottom:20,left:20},o=t.getBoundingClientRect().width,i=100,a=j(t).append("svg").style("display","block").style("background","black").attr("width",o).attr("height",i),s=a.append("g").attr("transform",`translate(${n.left},${n.top})`);function u(){return o-n.left-n.right}let c=i-n.top-n.bottom,l=[],p,f=br().domain(Ae(r)).range([0,u()]).paddingInner(.3).paddingOuter(.1),m=de().range([c,0]);function d(){return xr().duration(750)}function y(A){if(!A.length)return{min:0,q1:0,median:0,q3:0,max:0,whiskerLow:0,whiskerHigh:0};let D=A.slice().sort(ft),L=D[0],b=D[D.length-1],N=Ee(D,.25),H=Ee(D,.5),P=Ee(D,.75),I=P-N,h=Math.max(L,N-1.5*I),T=Math.min(b,P+1.5*I);return{min:L,q1:N,median:H,q3:P,max:b,whiskerLow:h,whiskerHigh:T}}function k(A,D){let L=A.map(e).filter(x=>Number.isFinite(x)&&x>=0),b=y(L);if(l.length{x.xIndex-=1});l.length&&l[0].xIndex<0;){let x=l.shift();x&&(p=x.stats.median)}l.push({xIndex:r-1,blockNumber:D,stats:b,values:L})}let N=ee(l,x=>x.stats.whiskerHigh)||1;m.domain([0,N]);let H=s.selectAll(".box-group").data(l,x=>x.xIndex);H.exit().transition(d()).attr("transform",x=>`translate(${f(x.xIndex)||0},${c}) scale(0.001,0.001)`).remove();let P=H.enter().append("g").attr("class","box-group").attr("stroke-width",1).attr("transform",x=>`translate(${f(x.xIndex)||0}, ${c}) scale(0.001,0.001)`);P.append("line").attr("class","whisker-line").attr("stroke","#aaa"),P.append("rect").attr("class","box-rect").attr("stroke","white").attr("fill","gray"),P.append("line").attr("class","median-line").attr("stroke","#ccc").attr("stroke-width",1),P.append("line").attr("class","whisker-cap lower").attr("stroke","#aaa"),P.append("line").attr("class","whisker-cap upper").attr("stroke","#aaa"),P.append("g").attr("class","points-group"),H=P.merge(H),H.transition(d()).attr("transform",x=>`translate(${f(x.xIndex)||0},0) scale(1,1)`),H.each(function(x){let M=j(this),S=x.stats,v=f.bandwidth(),B,G=l.find(ot=>ot.xIndex===x.xIndex-1);G?B=G.stats.median:x.xIndex===0&&p!==void 0&&(B=p);let K="gray";B!==void 0&&(S.median>B?K="rgb(127, 63, 63)":S.median{x.selectAll("text").attr("fill","white"),x.selectAll("line,path").attr("stroke","white")});let h=Fr(f).tickFormat(x=>{let M=l.find(S=>S.xIndex===x);return M?String(M.blockNumber):""}),T=s.append("g").attr("class","x-axis").attr("transform",`translate(0,${c})`).call(h),E=f.bandwidth();E<25&&T.selectAll(".tick").each(function(x,M){M/2%2!==0&&j(this).remove()}),T.call(x=>{x.selectAll("text").attr("fill","white"),x.selectAll("line,path").attr("stroke","white")}),s.selectAll(".median-trend").remove();let R=l.filter(x=>x.xIndex>=0).sort((x,M)=>x.xIndex-M.xIndex),g=We().x(x=>(f(x.xIndex)??0)+E/2).y(x=>m(x.stats.median)).curve(En);s.append("path").attr("class","median-trend").datum(R).attr("fill","none").attr("stroke","#FFA726").attr("stroke-width",2).transition(d()).attr("d",g)}function _(){o=t.getBoundingClientRect().width,a.attr("width",o),f.range([0,u()]),q()}function q(){s.selectAll(".box-group").transition().duration(0).attr("transform",I=>`translate(${f(I.xIndex)||0},0)`),s.selectAll(".y-axis").remove(),s.selectAll(".x-axis").remove();let A=Or(m).ticks(3);s.append("g").attr("class","y-axis").call(A).call(I=>{I.selectAll("text").attr("fill","white"),I.selectAll("line,path").attr("stroke","white")});let D=Fr(f).tickFormat(I=>{let h=l.find(T=>T.xIndex===I);return h?String(h.blockNumber):""}),L=s.append("g").attr("class","x-axis").attr("transform",`translate(0,${c})`).call(D);f.bandwidth()<25&&L.selectAll(".tick").each(function(I,h){h%2!==0&&j(this).remove()}),L.call(I=>{I.selectAll("text").attr("fill","white"),I.selectAll("line,path").attr("stroke","white")}),s.selectAll(".median-trend").remove();let N=l.filter(I=>I.xIndex>=0).sort((I,h)=>I.xIndex-h.xIndex),H=f.bandwidth(),P=We().x(I=>(f(I.xIndex)??0)+H/2).y(I=>m(I.stats.median)).curve(En);s.append("path").attr("class","median-trend").datum(N).attr("fill","none").attr("stroke","#FFA726").attr("stroke-width",2).attr("d",P)}return{update:k,resize:_}}var qr=100,ih=120,ah=qr+ih,sh=qr,wl=qr/2,uh=j("#pie-chart").append("svg").attr("width",ah).attr("height",sh).attr("overflow","visible"),kl=uh.append("g").attr("transform",`translate(${qr/2}, ${qr/2})`),lh=me().range(Ho),ch=Uo().sort(null).value(t=>t.count),oi=$o().innerRadius(0).outerRadius(wl),fh=kl.append("g").attr("class","slice-layer"),ph=kl.append("g").attr("class","label-layer");function _l(t){let e=ch(t),r=e.map(m=>{let[d,y]=oi.centroid(m);return{...m,centroidY:y}}),n=r.slice().sort((m,d)=>m.centroidY-d.centroidY),o=18,i=-((n.length-1)*o)/2,a=wl+20,s={};n.forEach((m,d)=>{s[m.data.type]={x:a,y:i+d*o}});let u=fh.selectAll("path").data(e,m=>m.data.type);u.exit().remove(),u.enter().append("path").attr("stroke","#222").style("stroke-width","1px").attr("fill",m=>lh(m.data.type)).each(function(m){this._current=m}).merge(u).transition().duration(750).attrTween("d",function(m){let d=vt(this._current,m);return this._current=d(0),y=>oi(d(y))});let l=ph.selectAll("g.label").data(r,m=>m.data.type);l.exit().remove();let p=l.enter().append("g").attr("class","label").style("pointer-events","none");p.append("polyline").attr("fill","none").attr("stroke","#fff"),p.append("text").style("alignment-baseline","middle").style("text-anchor","start").style("fill","#fff");let f=p.merge(l);f.select("polyline").transition().duration(750).attr("points",m=>{let[d,y]=oi.centroid(m),{x:k,y:_}=s[m.data.type],q=k*.6;return`${d},${y} ${q},${_} ${k},${_}`}),f.select("text").transition().duration(750).attr("transform",m=>{let d=s[m.data.type];return`translate(${d.x},${d.y})`}).tween("label",function(m){return()=>{this.textContent=`${m.data.type} (${m.data.count})`}})}function Tl(t){switch(t){case 0:return"Legacy";case 1:return"AccessList";case 2:return"Eip1559";case 3:return"Blob";case 4:return"SetCode";case 5:return"TxCreate";default:return"Unknown"}}function ii(t){switch(t){case"0x095ea7b3":return"approve";case"0xa9059cbb":return"transfer";case"0x23b872dd":return"transferFrom";case"0xd0e30db0":return"deposit";case"0xe8e33700":case"0xf305d719":return"addLiquidity";case"0xbaa2abde":case"0x02751cec":case"0xaf2979eb":case"0xded9382a":case"0x5b0d5984":case"0x2195995c":return"removeLiquidity";case"0xfb3bdb41":case"0x7ff36ab5":case"0xb6f9de95":case"0x18cbafe5":case"0x791ac947":case"0x38ed1739":case"0x5c11d795":case"0x4a25d94a":case"0x5f575529":case"0x6b68764c":case"0x845a101f":case"0x8803dbee":return"swap";case"0x24856bc3":case"0x3593564c":return"dex";case"0x":return"ETH transfer";default:return t}}function Ml(t){switch(t){case"0xdac17f958d2ee523a2206206994597c13d831ec7":return"usdt";case"0x4ecaba5870353805a9f068101a40e0f32ed605c6":return"usdt";case"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48":return"usdc";case"0xddafbb505ad214d7b80b1f830fccc89b60fb7a83":return"usdc";case"0x6b175474e89094c44da98b954eedeac495271d0f":return"dai";case"0x44fa8e6f47987339850636f88629646662444217":return"dai";case"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2":return"weth";case"0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1":return"weth";case"0x7a250d5630b4cf539739df2c5dacb4c659f2488d":return"uniswap v2";case"0x66a9893cc07d91d95644aedd05d03f95e1dba8af":return"uniswap v4";case"0x2f848984984d6c3c036174ce627703edaf780479":return"xen minter";case"0x0a252663dbcc0b073063d6420a40319e438cfa59":return"xen";case"0x881d40237659c251811cec9c364ef91dc08d300c":return"metamask";default:return t}}var Wh=tc(),Pn=class{nodeLog;ansiConvert=new Wh;logs=[];constructor(e){this.nodeLog=document.getElementById(e)}receivedLog(e){let r=JSON.parse(e.data);for(let n of r){let o=this.ansiConvert.toHtml(n);this.logs.length>=100&&this.logs.shift(),this.logs.push(o)}}appendLogs(){if(this.logs.length>0){let e=!1;(this.nodeLog.scrollHeight<500||this.nodeLog.scrollTop250;)this.nodeLog.firstChild.remove(),n--;e&&window.setTimeout(()=>this.scrollLogs(),17)}}resize(){let e=document.body.getBoundingClientRect();var n=this.nodeLog.getBoundingClientRect().top-e.top,o=window.innerHeight-n-16;o>0&&(this.nodeLog.style.height=`${o}px`)}scrollLogs(){this.nodeLog.scrollTop=this.nodeLog.scrollHeight}};function $(t,e){t.innerText!==e&&(t.innerText=e)}var $n=class{lastGasLimit=36e6;minGas;medianGas;aveGas;maxGas;gasLimit;gasLimitDelta;constructor(e,r,n,o,i,a){this.minGas=document.getElementById(e),this.medianGas=document.getElementById(r),this.aveGas=document.getElementById(n),this.maxGas=document.getElementById(o),this.gasLimit=document.getElementById(i),this.gasLimitDelta=document.getElementById(a)}parseEvent(e){if(document.hidden)return;let r=JSON.parse(e.data);$(this.minGas,r.minGas.toFixed(2)),$(this.medianGas,r.medianGas.toFixed(2)),$(this.aveGas,r.aveGas.toFixed(2)),$(this.maxGas,r.maxGas.toFixed(2)),$(this.gasLimit,dt(r.gasLimit)),$(this.gasLimitDelta,r.gasLimit>this.lastGasLimit?"\u{1F446}":r.gasLimitparseInt(t.effectiveGasPrice,16)/1e9,36);function dc(t,e){do if(!(t.matches===void 0||!t.matches(e)))return t;while(t=t.parentElement);return null}function kg(t,e,r,n,o){t.addEventListener(e,function(i){try{let a=dc(i.target,r);a!==null&&n.apply(a,arguments)}catch{}},o)}var ec=[],rc=[],nc=[],oc=[],ic=[],ac=[],sc=[],pi=0,mi=0,di=0,hi=0,gi=0,Un=0;function Te(t,e){t.push(e),t.length>60&&t.shift()}var _g=new qn("#txPoolFlow"),bi=null,uc=!1;function Tg(t){if(!uc){if(t.pooledTx==0){document.getElementById("txPoolFlow").classList.add("not-active");return}setTimeout(Ti,10),document.getElementById("txPoolFlow").classList.remove("not-active"),uc=!0}let e=performance.now(),r=e/1e3,n=r-Un,o=0,i=0,a=0,s=0;for(let c of t.links)c.target==="Received Txs"&&(o+=c.value),c.target==="Tx Pool"&&(i+=c.value),c.target==="Added To Block"&&(a+=c.value),c.target==="Duplicate"&&(s+=c.value);let u=t.hashesReceived;if(Un!==0&&(Te(ec,{t:e,v:u-gi}),Te(rc,{t:e,v:o-pi}),Te(ic,{t:e,v:s-hi}),Te(nc,{t:e,v:i-mi}),Te(oc,{t:e,v:a-di})),!document.hidden){if(!bi)return;_g.update(bi,t),$(Xh,dt(t.pooledTx)),$(jh,dt(t.pooledBlobTx)),$(Zh,dt(t.pooledTx+t.pooledBlobTx)),Un!==0&&(Xt(document.getElementById("sparkHashesTps"),ec),Xt(document.getElementById("sparkReceivedTps"),rc),Xt(document.getElementById("sparkDuplicateTps"),ic),Xt(document.getElementById("sparkTxPoolTps"),nc),Xt(document.getElementById("sparkBlockTps"),oc),$(Jh,Wt((a-di)/n)),$(Qh,Wt((o-pi)/n)),$(Kh,Wt((i-mi)/n)),$(tg,Wt((s-hi)/n)),$(eg,Wt((u-gi)/n)))}Un=r,pi=o,mi=i,di=a,hi=s,gi=u}var _i=new Pn("nodeLog"),Mg=new $n("minGas","medianGas","aveGas","maxGas","gasLimit","gasLimitDelta"),Jt=new EventSource("/data/events");Jt.addEventListener("log",t=>_i.receivedLog(t));Jt.addEventListener("processed",t=>Mg.parseEvent(t));Jt.addEventListener("nodeData",t=>{let e=JSON.parse(t.data),r=al(e.network),n=`Nethermind [${r}]${e.instance?" - "+e.instance:""}`;document.title!=n&&(document.title=n),$(rg,e.version),$(ng,r),document.getElementById("network-logo").src=`logos/${sl(e.network)}`,$(pc,Wo(e.uptime)),cl(e.gasToken)});Jt.addEventListener("txNodes",t=>{bi=JSON.parse(t.data)});Jt.addEventListener("txLinks",t=>{if(document.hidden)return;let e=JSON.parse(t.data);Tg(e)});var wi=0,hc=0,lc=!1;Jt.addEventListener("forkChoice",t=>{let e=performance.now();if(hc=e-wi,wi=e,document.hidden)return;let r=JSON.parse(t.data),n=parseInt(r.head.number,16);!lc&&n!==0&&(lc=!0,document.getElementById("latestBlock").classList.remove("not-active"),setTimeout(Ti,10));let o=parseInt(r.safe,16),i=parseInt(r.finalized,16);$(og,n.toFixed(0)),$(ig,o.toFixed(0)),$(ag,i.toFixed(0)),$(sg,`(${(o-n).toFixed(0)})`),$(ug,`(${(i-n).toFixed(0)})`);let a=r.head;if(a.tx.length===0)return;let s=a.tx.map((u,c)=>{let l=a.receipts[c];return{block:a.number,order:c,...u,...l}});$(hg,il(a.extraData)),$(gg,dt(parseInt(a.gasUsed,16))),$(xg,dt(parseInt(a.gasLimit,16))),$(yg,ol(parseInt(a.size,16))),$(vg,nl(parseInt(a.timestamp,16))),$(bg,dt(a.tx.length)),$(wg,dt(a.tx.reduce((u,c)=>u+c.blobs,0))),vl(document.getElementById("block"),160,parseInt(r.head.gasLimit,16),s,u=>u.hash,u=>u.order,u=>parseInt(u.gasUsed,16),u=>parseInt(u.effectiveGasPrice,16)*parseInt(u.gasUsed,16)),mc.update(s,n),_t.push(...s),ki=_t.length,_t.length>25e4&&_t.slice(_t.length-25e3),gc=Lg(s)});var gc,Sg="";kg(document.getElementById("block"),"pointermove","g.node",t=>{let r=dc(t.target,"g.node").dataset.hash,n=gc[r];if(!n)return;let o=document.getElementById("txDetails");return Sg!==r&&(o.innerHTML=`

Transaction ${An(n.hash)}

diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/NethermindBuffers.cs b/src/Nethermind/Nethermind.Serialization.Rlp/NethermindBuffers.cs index 1b8df5ce7a6..2f9c0b87557 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/NethermindBuffers.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/NethermindBuffers.cs @@ -67,7 +67,7 @@ public static class Metrics [KeyIsLabel("allocator")] public static ConcurrentDictionary AllocatorActiveAllocationBytes { get; } = new(); - [Description("Allocatioons")] + [Description("Allocations")] [KeyIsLabel("allocator")] public static ConcurrentDictionary AllocatorAllocations { get; } = new(); } diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoders/BlobTxDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoders/BlobTxDecoder.cs index 3f1fc2ea10f..dd548dd4a4a 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoders/BlobTxDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoders/BlobTxDecoder.cs @@ -56,9 +56,9 @@ public override void Decode(ref Transaction? transaction, int txSequenceStart, R { int networkWrapperLength = decoderContext.ReadSequenceLength(); networkWrapperCheck = decoderContext.Position + networkWrapperLength; - int rlpRength = decoderContext.PeekNextRlpLength(); + int rlpLength = decoderContext.PeekNextRlpLength(); txSequenceStart = decoderContext.Position; - transactionSequence = decoderContext.Peek(rlpRength); + transactionSequence = decoderContext.Peek(rlpLength); } base.Decode(ref transaction, txSequenceStart, transactionSequence, ref decoderContext, rlpBehaviors | RlpBehaviors.ExcludeHashes); diff --git a/src/Nethermind/Nethermind.Serialization.SszGenerator/Nethermind.Serialization.SszGenerator.csproj b/src/Nethermind/Nethermind.Serialization.SszGenerator/Nethermind.Serialization.SszGenerator.csproj index ae6ab740113..f9b4add506e 100644 --- a/src/Nethermind/Nethermind.Serialization.SszGenerator/Nethermind.Serialization.SszGenerator.csproj +++ b/src/Nethermind/Nethermind.Serialization.SszGenerator/Nethermind.Serialization.SszGenerator.csproj @@ -12,7 +12,7 @@ Generated - + diff --git a/src/Nethermind/Nethermind.Serialization.SszGenerator/SszProperty.cs b/src/Nethermind/Nethermind.Serialization.SszGenerator/SszProperty.cs index 1277e0b2805..8d27fec8e31 100644 --- a/src/Nethermind/Nethermind.Serialization.SszGenerator/SszProperty.cs +++ b/src/Nethermind/Nethermind.Serialization.SszGenerator/SszProperty.cs @@ -39,9 +39,9 @@ public static SszProperty From(SemanticModel semanticModel, List types, return array.ElementType!; } - INamedTypeSymbol? ienumerableOfT = compilation.GetTypeByMetadataName("System.Collections.Generic.IList`1"); - INamedTypeSymbol? enumerable = typeSymbol.AllInterfaces.FirstOrDefault(i => SymbolEqualityComparer.Default.Equals(i.OriginalDefinition, ienumerableOfT)); - if (ienumerableOfT != null && enumerable is not null) + INamedTypeSymbol? iListOfT = compilation.GetTypeByMetadataName("System.Collections.Generic.IList`1"); + INamedTypeSymbol? enumerable = typeSymbol.AllInterfaces.FirstOrDefault(i => SymbolEqualityComparer.Default.Equals(i.OriginalDefinition, iListOfT)); + if (iListOfT != null && enumerable is not null) { return enumerable.TypeArguments.First(); } diff --git a/src/Nethermind/Nethermind.Shutter/ShutterBlockImprovementContext.cs b/src/Nethermind/Nethermind.Shutter/ShutterBlockImprovementContext.cs index 09617cc288c..bc213677c2e 100644 --- a/src/Nethermind/Nethermind.Shutter/ShutterBlockImprovementContext.cs +++ b/src/Nethermind/Nethermind.Shutter/ShutterBlockImprovementContext.cs @@ -118,7 +118,7 @@ public void Dispose() { (slot, offset) = _time.GetBuildingSlotAndOffset(_slotTimestampMs); } - catch (SlotTime.SlotCalulationException e) + catch (SlotTime.SlotCalculationException e) { if (_logger.IsWarn) _logger.Warn($"Could not calculate Shutter building slot: {e}"); await BuildBlock(); diff --git a/src/Nethermind/Nethermind.Shutter/ShutterCrypto.cs b/src/Nethermind/Nethermind.Shutter/ShutterCrypto.cs index b3f6275ddec..8325863d8f9 100644 --- a/src/Nethermind/Nethermind.Shutter/ShutterCrypto.cs +++ b/src/Nethermind/Nethermind.Shutter/ShutterCrypto.cs @@ -315,7 +315,7 @@ private static void ComputeR(scoped ReadOnlySpan sigma, scoped ReadOnlySpa internal static Hash256 GenerateHash(ulong instanceId, ulong eon, ulong slot, ulong txPointer, IEnumerable> identityPreimages) { - SlotDecryptionIdentites container = new() + SlotDecryptionIdentities container = new() { InstanceID = instanceId, Eon = eon, @@ -356,7 +356,7 @@ private static ValueHash256 Hash4(ReadOnlySpan bytes) return ValueKeccak.Compute(preimage); } - private readonly struct SlotDecryptionIdentites + private readonly struct SlotDecryptionIdentities { public ulong InstanceID { get; init; } public ulong Eon { get; init; } diff --git a/src/Nethermind/Nethermind.Shutter/ShutterTxLoader.cs b/src/Nethermind/Nethermind.Shutter/ShutterTxLoader.cs index 6c6f03813ce..7ba443fd9db 100644 --- a/src/Nethermind/Nethermind.Shutter/ShutterTxLoader.cs +++ b/src/Nethermind/Nethermind.Shutter/ShutterTxLoader.cs @@ -51,7 +51,7 @@ public ShutterTransactions LoadTransactions(Block? head, BlockHeader parentHeade long offset = time.GetCurrentOffsetMs(keys.Slot); Metrics.ShutterKeysReceivedTimeOffset = offset; - string offsetText = offset < 0 ? $"{-offset}ms before" : $"{offset}ms fter"; + string offsetText = offset < 0 ? $"{-offset}ms before" : $"{offset}ms after"; if (_logger.IsInfo) _logger.Info($"Got {sequencedTransactions.Count} encrypted transactions from Shutter sequencer contract for slot {keys.Slot} at time {offsetText} slot start..."); using ArrayPoolList<(Transaction Tx, UInt256 GasLimit)>? decrypted = DecryptSequencedTransactions(sequencedTransactions, keys.Keys); diff --git a/src/Nethermind/Nethermind.Shutter/ShutterTxSource.cs b/src/Nethermind/Nethermind.Shutter/ShutterTxSource.cs index fb02c03416d..705a9296745 100644 --- a/src/Nethermind/Nethermind.Shutter/ShutterTxSource.cs +++ b/src/Nethermind/Nethermind.Shutter/ShutterTxSource.cs @@ -43,7 +43,7 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi { (buildingSlot, _) = slotTime.GetBuildingSlotAndOffset(payloadAttributes!.Timestamp * 1000); } - catch (SlotTime.SlotCalulationException e) + catch (SlotTime.SlotCalculationException e) { if (_logger.IsDebug) _logger.Warn($"DEBUG/ERROR Could not calculate Shutter building slot: {e}"); return []; diff --git a/src/Nethermind/Nethermind.Shutter/SlotDecryptionIdentites.cs b/src/Nethermind/Nethermind.Shutter/SlotDecryptionIdentities.cs similarity index 93% rename from src/Nethermind/Nethermind.Shutter/SlotDecryptionIdentites.cs rename to src/Nethermind/Nethermind.Shutter/SlotDecryptionIdentities.cs index 52dfbf69fdd..e62685271cc 100644 --- a/src/Nethermind/Nethermind.Shutter/SlotDecryptionIdentites.cs +++ b/src/Nethermind/Nethermind.Shutter/SlotDecryptionIdentities.cs @@ -7,7 +7,7 @@ namespace Nethermind.Shutter; [SszSerializable] -public struct SlotDecryptionIdentites +public struct SlotDecryptionIdentities { public ulong InstanceID { get; set; } public ulong Eon { get; set; } diff --git a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs index a1f1d9606ef..25e2158cc4e 100644 --- a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs @@ -378,10 +378,10 @@ public static IEnumerable GnosisActivations { yield return new TestCaseData((ForkActivation)0) { TestName = "Genesis" }; yield return new TestCaseData((ForkActivation)1) { TestName = "Genesis + 1" }; - yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.ConstantinopoleBlockNumber - 1)) { TestName = "Before Constantinopole" }; - yield return new TestCaseData((ForkActivation)GnosisSpecProvider.ConstantinopoleBlockNumber) { TestName = "Constantinopole" }; - yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.ConstantinopoleFixBlockNumber - 1)) { TestName = "Before ConstantinopoleFix" }; - yield return new TestCaseData((ForkActivation)GnosisSpecProvider.ConstantinopoleFixBlockNumber) { TestName = "ConstantinopoleFix" }; + yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.ConstantinopleBlockNumber - 1)) { TestName = "Before Constantinople" }; + yield return new TestCaseData((ForkActivation)GnosisSpecProvider.ConstantinopleBlockNumber) { TestName = "Constantinople" }; + yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.ConstantinopleFixBlockNumber - 1)) { TestName = "Before ConstantinopleFix" }; + yield return new TestCaseData((ForkActivation)GnosisSpecProvider.ConstantinopleFixBlockNumber) { TestName = "ConstantinopleFix" }; yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.IstanbulBlockNumber - 1)) { TestName = "Before Istanbul" }; yield return new TestCaseData((ForkActivation)GnosisSpecProvider.IstanbulBlockNumber) { TestName = "Istanbul" }; yield return new TestCaseData((ForkActivation)(GnosisSpecProvider.BerlinBlockNumber - 1)) { TestName = "Before Berlin" }; @@ -506,10 +506,10 @@ private static void VerifyGnosisPreShanghaiSpecifics(ISpecProvider specProvider) using (Assert.EnterMultipleScope()) { Assert.That(specProvider.GenesisSpec.MaximumUncleCount, Is.Zero); - Assert.That(specProvider.GetSpec((ForkActivation)(GnosisSpecProvider.ConstantinopoleBlockNumber - 1)).IsEip1283Enabled, Is.False); - Assert.That(specProvider.GetSpec((ForkActivation)(GnosisSpecProvider.ConstantinopoleBlockNumber)).IsEip1283Enabled, Is.True); - Assert.That(specProvider.GetSpec((ForkActivation)(GnosisSpecProvider.ConstantinopoleBlockNumber - 1)).UseConstantinopleNetGasMetering, Is.False); - Assert.That(specProvider.GetSpec((ForkActivation)(GnosisSpecProvider.ConstantinopoleBlockNumber)).UseConstantinopleNetGasMetering, Is.True); + Assert.That(specProvider.GetSpec((ForkActivation)(GnosisSpecProvider.ConstantinopleBlockNumber - 1)).IsEip1283Enabled, Is.False); + Assert.That(specProvider.GetSpec((ForkActivation)(GnosisSpecProvider.ConstantinopleBlockNumber)).IsEip1283Enabled, Is.True); + Assert.That(specProvider.GetSpec((ForkActivation)(GnosisSpecProvider.ConstantinopleBlockNumber - 1)).UseConstantinopleNetGasMetering, Is.False); + Assert.That(specProvider.GetSpec((ForkActivation)(GnosisSpecProvider.ConstantinopleBlockNumber)).UseConstantinopleNetGasMetering, Is.True); } } diff --git a/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs b/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs index a29bb603ed8..5dd0d445065 100644 --- a/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs @@ -133,31 +133,31 @@ public UInt256 BlockReward public bool IsEip158IgnoredAccount(Address address) => spec.IsEip158IgnoredAccount(address); - private long? _overridenEip1559TransitionBlock; + private long? _overriddenEip1559TransitionBlock; public long Eip1559TransitionBlock { - get => _overridenEip1559TransitionBlock ?? spec.Eip1559TransitionBlock; - set => _overridenEip1559TransitionBlock = value; + get => _overriddenEip1559TransitionBlock ?? spec.Eip1559TransitionBlock; + set => _overriddenEip1559TransitionBlock = value; } - private Address? _overridenFeeCollector; + private Address? _overriddenFeeCollector; public Address? FeeCollector { - get => _overridenFeeCollector ?? spec.FeeCollector; - set => _overridenFeeCollector = value; + get => _overriddenFeeCollector ?? spec.FeeCollector; + set => _overriddenFeeCollector = value; } - private ulong? _overridenEip4844TransitionTimeStamp; + private ulong? _overriddenEip4844TransitionTimestamp; public ulong Eip4844TransitionTimestamp { get { - return _overridenEip4844TransitionTimeStamp ?? spec.Eip4844TransitionTimestamp; + return _overriddenEip4844TransitionTimestamp ?? spec.Eip4844TransitionTimestamp; } set { - _overridenEip4844TransitionTimeStamp = value; + _overriddenEip4844TransitionTimestamp = value; } } diff --git a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs index 479c7803097..bef4339d291 100644 --- a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs @@ -11,8 +11,8 @@ namespace Nethermind.Specs; public class GnosisSpecProvider : ISpecProvider { - public const long ConstantinopoleBlockNumber = 1_604_400; - public const long ConstantinopoleFixBlockNumber = 2_508_800; + public const long ConstantinopleBlockNumber = 1_604_400; + public const long ConstantinopleFixBlockNumber = 2_508_800; public const long IstanbulBlockNumber = 7_298_030; public const long BerlinBlockNumber = 16_101_500; public const long LondonBlockNumber = 19_040_000; @@ -28,8 +28,8 @@ IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) { return forkActivation.BlockNumber switch { - < ConstantinopoleBlockNumber => GenesisSpec, - < ConstantinopoleFixBlockNumber => Constantinople.Instance, + < ConstantinopleBlockNumber => GenesisSpec, + < ConstantinopleFixBlockNumber => Constantinople.Instance, < IstanbulBlockNumber => ConstantinopleFix.Instance, < BerlinBlockNumber => Istanbul.Instance, < LondonBlockNumber => Berlin.Instance, diff --git a/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs b/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs index e5a15566f4b..a0e3055f785 100644 --- a/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs +++ b/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs @@ -415,7 +415,7 @@ public void No_writes_without_commit() } [Test] - public void Can_ask_about_root_hash_without_commiting() + public void Can_ask_about_root_hash_without_committing() { MemDb db = new(); StateTree tree = new(new RawScopedTrieStore(db), LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.State/OverridableEnv/DisposableScopeOverridableEnv.cs b/src/Nethermind/Nethermind.State/OverridableEnv/DisposableScopeOverridableEnv.cs index e46021c9b95..cee75b483f6 100644 --- a/src/Nethermind/Nethermind.State/OverridableEnv/DisposableScopeOverridableEnv.cs +++ b/src/Nethermind/Nethermind.State/OverridableEnv/DisposableScopeOverridableEnv.cs @@ -11,7 +11,7 @@ namespace Nethermind.State.OverridableEnv; /// /// A utility that provide `IOverridableEnv` -/// Dont forget do dispose it! +/// Don't forget to dispose it! /// /// /// diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs index 3ef05a221fc..a3a70527e1d 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs @@ -182,12 +182,12 @@ public async Task ShouldRecoverOnInsertFailure() [TestCase(1, 99, false, null, false)] [TestCase(1, 99, true, null, false)] [TestCase(1, 99, false, 0, false)] - public void When_finished_sync_with_old_default_barrier_then_finishes_imedietely( + public void When_finished_sync_with_old_default_barrier_then_finishes_immediately( long AncientBarrierInConfig, long lowestInsertedBlockNumber, bool JustStarted, long? previousBarrierInDb, - bool shouldfinish) + bool shouldFinish) { _syncConfig.AncientBodiesBarrier = AncientBarrierInConfig; _syncConfig.AncientReceiptsBarrier = AncientBarrierInConfig; @@ -198,7 +198,7 @@ public void When_finished_sync_with_old_default_barrier_then_finishes_imedietely _feed.InitializeFeed(); _syncPointers.LowestInsertedBodyNumber = lowestInsertedBlockNumber; - _feed.IsFinished.Should().Be(shouldfinish); + _feed.IsFinished.Should().Be(shouldFinish); } [Test] diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs index 61260d3ddeb..f8adb18a78f 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs @@ -471,9 +471,9 @@ public async Task Can_resume_downloading_from_parent_of_lowest_inserted_header() [TestCase(190, 1, 1, true, true)] [TestCase(80, 1, 1, true, false)] [TestCase(80, 1, 1, true, true)] - //All empty reponse + // All empty response [TestCase(0, 192, 1, false, false)] - //All null reponse + // All null response [TestCase(0, 192, 1, false, true)] public async Task Can_insert_all_good_headers_from_dependent_batch_with_missing_or_null_headers(int nullIndex, int count, int increment, bool shouldReport, bool useNulls) { @@ -518,13 +518,13 @@ void FillBatch(HeadersSyncBatch batch, long start, bool applyNulls) feed.HandleResponse(dependentBatch); feed.HandleResponse(firstBatch); - using HeadersSyncBatch? thirdbatch = await feed.PrepareRequest(); - FillBatch(thirdbatch!, thirdbatch!.StartNumber, false); - feed.HandleResponse(thirdbatch); - using HeadersSyncBatch? fourthbatch = await feed.PrepareRequest(); - FillBatch(fourthbatch!, fourthbatch!.StartNumber, false); - feed.HandleResponse(fourthbatch); - using HeadersSyncBatch? fifthbatch = await feed.PrepareRequest(); + using HeadersSyncBatch? thirdBatch = await feed.PrepareRequest(); + FillBatch(thirdBatch!, thirdBatch!.StartNumber, false); + feed.HandleResponse(thirdBatch); + using HeadersSyncBatch? fourthBatch = await feed.PrepareRequest(); + FillBatch(fourthBatch!, fourthBatch!.StartNumber, false); + feed.HandleResponse(fourthBatch); + using HeadersSyncBatch? fifthBatch = await feed.PrepareRequest(); Assert.That(localBlockTree.LowestInsertedHeader!.Number, Is.LessThanOrEqualTo(targetHeaderInDependentBatch)); syncPeerPool.Received(shouldReport ? 1 : 0).ReportBreachOfProtocol(Arg.Any(), Arg.Any(), Arg.Any()); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs index ac96d287138..6899a675222 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs @@ -255,12 +255,12 @@ public async Task When_configured_to_skip_receipts_then_finishes_immediately() [TestCase(1, 1024, false, null, false)] [TestCase(1, 1024, true, null, false)] [TestCase(1, 1024, false, 0, false)] - public void When_finished_sync_with_old_default_barrier_then_finishes_imedietely( + public void When_finished_sync_with_old_default_barrier_then_finishes_immediately( long AncientBarrierInConfig, long? lowestInsertedReceiptBlockNumber, bool JustStarted, long? previousBarrierInDb, - bool shouldfinish) + bool shouldFinish) { _syncPointers = Substitute.For(); _syncConfig.AncientBodiesBarrier = AncientBarrierInConfig; @@ -271,7 +271,7 @@ public void When_finished_sync_with_old_default_barrier_then_finishes_imedietely _metadataDb.Set(MetadataDbKeys.ReceiptsBarrierWhenStarted, previousBarrierInDb.Value.ToBigEndianByteArrayWithoutLeadingZeros()); LoadScenario(_256BodiesWithOneTxEach); _syncPointers.LowestInsertedReceiptBlockNumber.Returns(lowestInsertedReceiptBlockNumber); - _feed.IsFinished.Should().Be(shouldfinish); + _feed.IsFinished.Should().Be(shouldFinish); } private void LoadScenario(Scenario scenario) diff --git a/src/Nethermind/Nethermind.Synchronization.Test/Trie/HealingTreeTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/Trie/HealingTreeTests.cs index 6491496fecd..c8e19f03e07 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/Trie/HealingTreeTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/Trie/HealingTreeTests.cs @@ -193,7 +193,7 @@ void RandomCopyState(IContainer server, IContainer client) Random random = new Random(0); using ArrayPoolList> allValues = serverStateDb.GetAll().ToPooledList(10); - // Sort for reproducability + // Sort for reproducibility allValues.AsSpan().Sort(((k1, k2) => ((IComparer)Bytes.Comparer).Compare(k1.Key, k2.Key))); // Copy from server to client, but randomly remove some of them. diff --git a/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs b/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs index 3b2ea7ca142..3ad89149e6b 100644 --- a/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs +++ b/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs @@ -497,7 +497,7 @@ public SyncResponseHandlingResult HandleResponse(BlocksRequest response, PeerInf if (result == SyncResponseHandlingResult.OK) { - // Request and body does not have the same size so this hueristic is wrong. + // Request and body does not have the same size so this heuristic is wrong. if (bodiesCount + receiptsCount == 0) { // Trigger sleep diff --git a/src/Nethermind/Nethermind.Synchronization/Blocks/PowForwardHeaderProvider.cs b/src/Nethermind/Nethermind.Synchronization/Blocks/PowForwardHeaderProvider.cs index b2905f365de..ac0020b155b 100644 --- a/src/Nethermind/Nethermind.Synchronization/Blocks/PowForwardHeaderProvider.cs +++ b/src/Nethermind/Nethermind.Synchronization/Blocks/PowForwardHeaderProvider.cs @@ -160,7 +160,7 @@ private void OnNewBestPeer(PeerInfo newBestPeer) await RequestHeaders(bestPeer, cancellation, _currentNumber, headersToRequest); if (headers.Count < 2) { - // Peer dont have new header + // Peer doesn't have a new header headers.Dispose(); return null; } diff --git a/src/Nethermind/Nethermind.Synchronization/DbTuner/SyncDbOptimizer.cs b/src/Nethermind/Nethermind.Synchronization/DbTuner/SyncDbOptimizer.cs index bb5e64e6059..6f5d1625f32 100644 --- a/src/Nethermind/Nethermind.Synchronization/DbTuner/SyncDbOptimizer.cs +++ b/src/Nethermind/Nethermind.Synchronization/DbTuner/SyncDbOptimizer.cs @@ -39,7 +39,7 @@ public SyncDbTuner( // Only these three make sense as they are write heavy // Headers is used everywhere, so slowing read might slow the whole sync. - // Statesync is read heavy, Forward sync is just plain too slow to saturate IO. + // State sync is read heavy, Forward sync is just plain too slow to saturate IO. if (snapSyncFeed is not NoopSyncFeed) { snapSyncFeed.StateChanged += SnapStateChanged; diff --git a/src/Nethermind/Nethermind.Synchronization/FastSync/PendingSyncItems.cs b/src/Nethermind/Nethermind.Synchronization/FastSync/PendingSyncItems.cs index c2d0433d382..da1923c80e7 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastSync/PendingSyncItems.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastSync/PendingSyncItems.cs @@ -174,7 +174,7 @@ public List TakeBatch(int maxSize) } else { - // With snap sync, we want the top level nodes. Low level nodes are mostly snapsyncd. + // With snap sync, we want the top-level nodes. Low-level nodes are mostly snap-synced. length = maxSize; } diff --git a/src/Nethermind/Nethermind.Synchronization/Metrics.cs b/src/Nethermind/Nethermind.Synchronization/Metrics.cs index 6eb17051077..c383389c824 100644 --- a/src/Nethermind/Nethermind.Synchronization/Metrics.cs +++ b/src/Nethermind/Nethermind.Synchronization/Metrics.cs @@ -88,7 +88,7 @@ public static class Metrics public static IMetricObserver SyncDispatcherPrepareRequestTimeMicros = NoopMetricObserver.Instance; [ExponentialPowerHistogramMetric(LabelNames = ["sync_type"], Start = 10, Factor = 10, Count = 5)] - [Description("Sinc dispatcher time in dispatch. High value indicate slow peer or internet.")] + [Description("Sync dispatcher time in dispatch. High value indicates a slow peer or internet.")] [DetailedMetric] public static IMetricObserver SyncDispatcherDispatchTimeMicros = NoopMetricObserver.Instance; diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs index 48c8403e798..3eb5e9e616a 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs @@ -846,7 +846,7 @@ long pivotNumber /// /// The best block that we want to go to. best.Peer.Block for PoW, beaconSync.ProcessDestination for PoS, - /// whith is the NewPayload/FCU block. + /// which is the NewPayload/FCU block. /// public long TargetBlock { get; } diff --git a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerExtensions.cs b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerExtensions.cs index e477c1b0b5a..7dabd1b0680 100644 --- a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerExtensions.cs +++ b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerExtensions.cs @@ -24,8 +24,8 @@ public static bool SupportsAllocation(this PeerInfo peerInfo, AllocationContexts Version? openEthereumVersion = peerInfo.SyncPeer.GetOpenEthereumVersion(out _); if (openEthereumVersion is not null) { - int versionComparision = openEthereumVersion.CompareTo(_openEthereumSecondRemoveGetNodeDataVersion); - return versionComparision >= 0 || openEthereumVersion < _openEthereumFirstRemoveGetNodeDataVersion; + int versionComparison = openEthereumVersion.CompareTo(_openEthereumSecondRemoveGetNodeDataVersion); + return versionComparison >= 0 || openEthereumVersion < _openEthereumFirstRemoveGetNodeDataVersion; } } diff --git a/src/Nethermind/Nethermind.Synchronization/Reporting/SnapshotReport.cs b/src/Nethermind/Nethermind.Synchronization/Reporting/SnapshotReport.cs index a882403ea4e..232e1a495b0 100644 --- a/src/Nethermind/Nethermind.Synchronization/Reporting/SnapshotReport.cs +++ b/src/Nethermind/Nethermind.Synchronization/Reporting/SnapshotReport.cs @@ -3,7 +3,7 @@ namespace Nethermind.Synchronization.Reporting { - public class SyncReportSymmary + public class SyncReportSummary { public string CurrentStage { get; set; } } diff --git a/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs b/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs index ff56c9df8fa..20ee5685621 100644 --- a/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs +++ b/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs @@ -496,9 +496,9 @@ private void LogRequest(string reqType) int totalPathProgress = 0; foreach (KeyValuePair kv in AccountRangePartitions) { - AccountRangePartition? partiton = kv.Value; - int nextAccount = partiton.NextAccountPath.Bytes[0] * 256 + partiton.NextAccountPath.Bytes[1]; - int startAccount = partiton.AccountPathStart.Bytes[0] * 256 + partiton.AccountPathStart.Bytes[1]; + AccountRangePartition? partition = kv.Value; + int nextAccount = partition.NextAccountPath.Bytes[0] * 256 + partition.NextAccountPath.Bytes[1]; + int startAccount = partition.AccountPathStart.Bytes[0] * 256 + partition.AccountPathStart.Bytes[1]; totalPathProgress += nextAccount - startAccount; } diff --git a/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProvider.cs b/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProvider.cs index eee17b694d8..26217d22f52 100644 --- a/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProvider.cs +++ b/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProvider.cs @@ -254,13 +254,13 @@ public void RefreshAccounts(AccountsToRefreshRequest request, IOwnedReadOnlyList { int respLength = response.Count; IScopedTrieStore stateStore = _stateTrieStore; - for (int reqi = 0; reqi < request.Paths.Count; reqi++) + for (int reqIndex = 0; reqIndex < request.Paths.Count; reqIndex++) { - var requestedPath = request.Paths[reqi]; + var requestedPath = request.Paths[reqIndex]; - if (reqi < respLength) + if (reqIndex < respLength) { - byte[] nodeData = response[reqi]; + byte[] nodeData = response[reqIndex]; if (nodeData.Length == 0) { diff --git a/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProviderHelper.cs b/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProviderHelper.cs index cd30e4a6649..ebdd23dfd1c 100644 --- a/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProviderHelper.cs +++ b/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProviderHelper.cs @@ -97,7 +97,7 @@ public static (AddRangeResult result, bool moreChildrenToRight, List> task = null; HashList? hashList = null; GetTrieNodesRequest? getTrieNodesRequest = null; - // Use GETNODEDATA if possible. Firstly via dedicated NODEDATA protocol + // Use GetNodeData if possible, starting with the dedicated NodeData protocol if (peer.TryGetSatelliteProtocol(Protocol.NodeData, out INodeDataPeer nodeDataHandler)) { if (Logger.IsTrace) Logger.Trace($"Requested NodeData via NodeDataProtocol from peer {peer}"); hashList = HashList.Rent(batch.RequestedNodes); task = nodeDataHandler.GetNodeData(hashList, cancellationToken); } - // If NODEDATA protocol is not supported, try eth66 + // If the NodeData protocol is not supported, try eth66 else if (peer.ProtocolVersion < EthVersions.Eth67) { if (Logger.IsTrace) Logger.Trace($"Requested NodeData via EthProtocol from peer {peer}"); hashList = HashList.Rent(batch.RequestedNodes); task = peer.GetNodeData(hashList, cancellationToken); } - // GETNODEDATA is not supported so we try with SNAP protocol + // If GetNodeData is not supported, fall back to the Snap protocol else if (peer.TryGetSatelliteProtocol(Protocol.Snap, out ISnapSyncPeer snapHandler)) { if (batch.NodeDataType == NodeDataType.Code) diff --git a/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs b/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs index 9eb2b50f189..200cabd887e 100644 --- a/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs +++ b/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs @@ -312,7 +312,7 @@ protected override void Load(ContainerBuilder builder) .AddScoped>() // The direct implementation is decorated by merge plugin (not the interface) - // so its declared on its own and other use is binded. + // so it's declared on its own and other usage is bound. .AddSingleton() .Bind() diff --git a/src/Nethermind/Nethermind.Taiko.Test/SurgeGasPriceOracleTests.cs b/src/Nethermind/Nethermind.Taiko.Test/SurgeGasPriceOracleTests.cs index adfa00daaa5..82b0daed91b 100644 --- a/src/Nethermind/Nethermind.Taiko.Test/SurgeGasPriceOracleTests.cs +++ b/src/Nethermind/Nethermind.Taiko.Test/SurgeGasPriceOracleTests.cs @@ -144,7 +144,7 @@ public async ValueTask GetGasPriceEstimate_WithValidL1FeeHistory_CalculatesCorre } [Test] - public async ValueTask GetGasPriceEstimate_WithZeroGasUsed_ReturnsAtleastMinGasPrice() + public async ValueTask GetGasPriceEstimate_WithZeroGasUsed_ReturnsAtLeastMinGasPrice() { Block headBlock = Build.A.Block.WithNumber(1).WithGasUsed(0).TestObject; _blockFinder.Head.Returns(headBlock); diff --git a/src/Nethermind/Nethermind.Taiko.Test/TaikoEngineApiTests.cs b/src/Nethermind/Nethermind.Taiko.Test/TaikoEngineApiTests.cs index 4765b12036b..eb9a581d29b 100644 --- a/src/Nethermind/Nethermind.Taiko.Test/TaikoEngineApiTests.cs +++ b/src/Nethermind/Nethermind.Taiko.Test/TaikoEngineApiTests.cs @@ -52,8 +52,8 @@ public async Task Test_ForkchoiceUpdatedHandler_Allows_UnknownFinalizedSafeBlock Substitute.For() ); - ResultWrapper beforeNewBlockAadded = await forkchoiceUpdatedHandler.Handle(new ForkchoiceStateV1(genesisBlock.Hash!, futureBlock.Hash!, futureBlock.Hash!), null, 2); - Assert.That(beforeNewBlockAadded.Data.PayloadStatus.Status, Is.EqualTo(PayloadStatus.Valid)); + ResultWrapper beforeNewBlockAdded = await forkchoiceUpdatedHandler.Handle(new ForkchoiceStateV1(genesisBlock.Hash!, futureBlock.Hash!, futureBlock.Hash!), null, 2); + Assert.That(beforeNewBlockAdded.Data.PayloadStatus.Status, Is.EqualTo(PayloadStatus.Valid)); AddBlock(blockTree, futureBlock); diff --git a/src/Nethermind/Nethermind.Taiko.Test/TransactionProcessorTests.cs b/src/Nethermind/Nethermind.Taiko.Test/TransactionProcessorTests.cs index 5c69b7240f8..2bb09f03b45 100644 --- a/src/Nethermind/Nethermind.Taiko.Test/TransactionProcessorTests.cs +++ b/src/Nethermind/Nethermind.Taiko.Test/TransactionProcessorTests.cs @@ -62,10 +62,10 @@ public void TearDown() } [TestCaseSource(nameof(FeesDistributionTests))] - public void Fees_distributed_correctly(byte basefeeSharingPctg, UInt256 goesToTreasury, UInt256 goesToBeneficiary, ulong gasPrice) + public void Fees_distributed_correctly(byte basefeeSharingPct, UInt256 goesToTreasury, UInt256 goesToBeneficiary, ulong gasPrice) { long gasLimit = 100000; - Address benefeciaryAddress = TestItem.AddressC; + Address beneficiaryAddress = TestItem.AddressC; Transaction tx = Build.A.Transaction .WithValue(1) @@ -74,12 +74,12 @@ public void Fees_distributed_correctly(byte basefeeSharingPctg, UInt256 goesToTr .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; var extraData = new byte[32]; - extraData[31] = basefeeSharingPctg; + extraData[31] = basefeeSharingPct; Block block = Build.A.Block.WithNumber(1).WithTransactions(tx) .WithBaseFeePerGas(gasPrice) .WithExtraData(extraData) - .WithBeneficiary(benefeciaryAddress).WithGasLimit(gasLimit).TestObject; + .WithBeneficiary(beneficiaryAddress).WithGasLimit(gasLimit).TestObject; _transactionProcessor!.SetBlockExecutionContext(new BlockExecutionContext(block.Header, _specProvider.GetSpec(block.Header))); _transactionProcessor!.Execute(tx, NullTxTracer.Instance); @@ -87,7 +87,7 @@ public void Fees_distributed_correctly(byte basefeeSharingPctg, UInt256 goesToTr Assert.Multiple(() => { Assert.That(_stateProvider!.GetBalance(_spec.FeeCollector!), Is.EqualTo(goesToTreasury)); - Assert.That(_stateProvider.GetBalance(benefeciaryAddress), Is.EqualTo(goesToBeneficiary)); + Assert.That(_stateProvider.GetBalance(beneficiaryAddress), Is.EqualTo(goesToBeneficiary)); }); } @@ -95,8 +95,8 @@ public static IEnumerable FeesDistributionTests { get { - static object[] Typed(int basefeeSharingPctg, ulong goesToTreasury, ulong goesToBeneficiary, ulong gasPrice) - => [(byte)basefeeSharingPctg, (UInt256)goesToTreasury, (UInt256)goesToBeneficiary, gasPrice]; + static object[] Typed(int basefeeSharingPct, ulong goesToTreasury, ulong goesToBeneficiary, ulong gasPrice) + => [(byte)basefeeSharingPct, (UInt256)goesToTreasury, (UInt256)goesToBeneficiary, gasPrice]; yield return new TestCaseData(Typed(0, 21000, 0, 1)) { TestName = "All goes to treasury" }; yield return new TestCaseData(Typed(100, 0, 21000, 1)) { TestName = "All goes to beneficiary" }; @@ -176,7 +176,7 @@ public void Check_fees_with_fee_collector_destroy_coinbase_taiko(bool isOntakeEn { _spec.FeeCollector = TestItem.AddressC; _spec.IsOntakeEnabled = isOntakeEnabled; - byte defaultBasefeeSharingPctg = 25; + byte defaultBaseFeeSharingPct = 25; _stateProvider!.CreateAccount(TestItem.AddressB, 100.Ether()); @@ -194,7 +194,7 @@ public void Check_fees_with_fee_collector_destroy_coinbase_taiko(bool isOntakeEn .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyB).TestObject; var extraData = new byte[32]; - extraData[31] = defaultBasefeeSharingPctg; + extraData[31] = defaultBaseFeeSharingPct; Block block = Build.A.Block.WithNumber(1) .WithBeneficiary(SelfDestructAddress) @@ -220,7 +220,7 @@ public void Check_fees_with_fee_collector_destroy_coinbase_taiko(bool isOntakeEn UInt256 expectedBaseFees = tracer.BurntFees; if (isOntakeEnabled) { - expectedBaseFees -= expectedBaseFees * defaultBasefeeSharingPctg / 100; + expectedBaseFees -= expectedBaseFees * defaultBaseFeeSharingPct / 100; } receivedBaseFees.Should().Be(expectedBaseFees, "Burnt fees should be paid to treasury"); diff --git a/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs b/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs index 6fb161f7848..25f5670247e 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs @@ -89,7 +89,7 @@ private bool ValidateAnchorTransaction(Transaction tx, Block block, ITaikoReleas return false; } - // We dont set the tx.SenderAddress here, as it will stop the rest of the transactions in the block + // We don't set the tx.SenderAddress here, as it will stop the rest of the transactions in the block // from getting their sender address recovered Address? senderAddress = tx.SenderAddress ?? ecdsa.RecoverAddress(tx); diff --git a/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs b/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs index 1b86e2c2bf8..51806561bc3 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs @@ -61,9 +61,9 @@ protected override void PayFees(Transaction tx, BlockHeader header, IReleaseSpec { if (((ITaikoReleaseSpec)spec).IsOntakeEnabled) { - byte basefeeSharingPctg = header.DecodeOntakeExtraData() ?? 0; + byte basefeeSharingPct = header.DecodeOntakeExtraData() ?? 0; - UInt256 feeCoinbase = baseFees * basefeeSharingPctg / 100; + UInt256 feeCoinbase = baseFees * basefeeSharingPct / 100; if (statusCode == StatusCode.Failure || gasBeneficiaryNotDestroyed) { diff --git a/src/Nethermind/Nethermind.Trie.Test/NodeStorageTests.cs b/src/Nethermind/Nethermind.Trie.Test/NodeStorageTests.cs index 72caff99b39..51702876eec 100644 --- a/src/Nethermind/Nethermind.Trie.Test/NodeStorageTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/NodeStorageTests.cs @@ -107,7 +107,7 @@ public void When_EntryOfDifferentScheme_Should_StillBeAbleToRead() [TestCase(true, 5, "0211111111111111111111111111111111111111111111111111111111111111112222200000000000053333333333333333333333333333333333333333333333333333333333333333")] [TestCase(true, 10, "02111111111111111111111111111111111111111111111111111111111111111122222222220000000a3333333333333333333333333333333333333333333333333333333333333333")] [TestCase(true, 32, "0211111111111111111111111111111111111111111111111111111111111111112222222222222222203333333333333333333333333333333333333333333333333333333333333333")] - public void Test_HalfPathEncodng(bool hasAddress, int pathLength, string expectedKey) + public void Test_HalfPathEncoding(bool hasAddress, int pathLength, string expectedKey) { if (_currentKeyScheme == INodeStorage.KeyScheme.Hash) return; diff --git a/src/Nethermind/Nethermind.Trie.Test/OverlayTrieStoreTests.cs b/src/Nethermind/Nethermind.Trie.Test/OverlayTrieStoreTests.cs index 29cf8d7767f..ed8c23ee264 100644 --- a/src/Nethermind/Nethermind.Trie.Test/OverlayTrieStoreTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/OverlayTrieStoreTests.cs @@ -37,36 +37,36 @@ public void TrieStore_OverlayExistingStore() ITrieStore overlayStore = new OverlayTrieStore(readOnlyDbProvider.GetDb(DbNames.State), existingStore.AsReadOnly()); // Modify the overlay tree - PatriciaTree overlayedTree = new PatriciaTree(overlayStore, LimboLogs.Instance); - overlayedTree.RootHash = originalRoot; - overlayedTree.Get(TestItem.Keccaks[0].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[0].BytesToArray()); - overlayedTree.Get(TestItem.Keccaks[1].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[1].BytesToArray()); - overlayedTree.Set(TestItem.Keccaks[2].Bytes, TestItem.Keccaks[2].BytesToArray()); - overlayedTree.Set(TestItem.Keccaks[3].Bytes, TestItem.Keccaks[3].BytesToArray()); - overlayedTree.Commit(); - Hash256 newRoot = overlayedTree.RootHash; + PatriciaTree overlaidTree = new PatriciaTree(overlayStore, LimboLogs.Instance); + overlaidTree.RootHash = originalRoot; + overlaidTree.Get(TestItem.Keccaks[0].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[0].BytesToArray()); + overlaidTree.Get(TestItem.Keccaks[1].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[1].BytesToArray()); + overlaidTree.Set(TestItem.Keccaks[2].Bytes, TestItem.Keccaks[2].BytesToArray()); + overlaidTree.Set(TestItem.Keccaks[3].Bytes, TestItem.Keccaks[3].BytesToArray()); + overlaidTree.Commit(); + Hash256 newRoot = overlaidTree.RootHash; // Verify that the db is modified readOnlyDbProvider.GetDb(DbNames.State).GetAllKeys().Count().Should().NotBe(originalKeyCount); // It can read the modified db - overlayedTree = new PatriciaTree(overlayStore, LimboLogs.Instance); - overlayedTree.RootHash = newRoot; - overlayedTree.Get(TestItem.Keccaks[0].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[0].BytesToArray()); - overlayedTree.Get(TestItem.Keccaks[1].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[1].BytesToArray()); - overlayedTree.Get(TestItem.Keccaks[2].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[2].BytesToArray()); - overlayedTree.Get(TestItem.Keccaks[3].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[3].BytesToArray()); + overlaidTree = new PatriciaTree(overlayStore, LimboLogs.Instance); + overlaidTree.RootHash = newRoot; + overlaidTree.Get(TestItem.Keccaks[0].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[0].BytesToArray()); + overlaidTree.Get(TestItem.Keccaks[1].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[1].BytesToArray()); + overlaidTree.Get(TestItem.Keccaks[2].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[2].BytesToArray()); + overlaidTree.Get(TestItem.Keccaks[3].Bytes).ToArray().Should().BeEquivalentTo(TestItem.Keccaks[3].BytesToArray()); // Now we clear it readOnlyDbProvider.ClearTempChanges(); - // It should throw because the overlayed keys are now missing. + // It should throw because the overlaid keys are now missing. readOnlyDbProvider.GetDb(DbNames.State).GetAllKeys().Count().Should().Be(originalKeyCount); - overlayedTree = new PatriciaTree(overlayStore, LimboLogs.Instance); + overlaidTree = new PatriciaTree(overlayStore, LimboLogs.Instance); Action act = () => { - overlayedTree.RootHash = newRoot; - overlayedTree.Get(TestItem.Keccaks[0].Bytes).ToArray().Should() + overlaidTree.RootHash = newRoot; + overlaidTree.Get(TestItem.Keccaks[0].Bytes).ToArray().Should() .BeEquivalentTo(TestItem.Keccaks[0].BytesToArray()); }; act.Should().Throw(); // The root is now missing. diff --git a/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs b/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs index 9d372ea1824..30d8de15fbb 100644 --- a/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs @@ -1492,7 +1492,7 @@ void VerifyAllTrieExceptGenesis() } } - // Start from genesis for simplicty + // Start from genesis for simplicity BlockHeader baseBlock = Build.A.BlockHeader.WithStateRoot(Keccak.EmptyTreeHash).TestObject; int blockNum = 100; int lastNRoots = 0; diff --git a/src/Nethermind/Nethermind.Trie.Test/TrieNodeResolverWithReadFlagsTests.cs b/src/Nethermind/Nethermind.Trie.Test/TrieNodeResolverWithReadFlagsTests.cs index 20567786340..df8fcf6dac1 100644 --- a/src/Nethermind/Nethermind.Trie.Test/TrieNodeResolverWithReadFlagsTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/TrieNodeResolverWithReadFlagsTests.cs @@ -29,7 +29,7 @@ public void LoadRlp_shouldPassTheFlag() } [Test] - public void LoadRlp_combine_passed_flaeg() + public void LoadRlp_combine_passed_flag() { ReadFlags theFlags = ReadFlags.HintCacheMiss; TestMemDb memDb = new(); diff --git a/src/Nethermind/Nethermind.Trie.Test/VisitingTests.cs b/src/Nethermind/Nethermind.Trie.Test/VisitingTests.cs index 01b56210412..2fd6f53b2b6 100644 --- a/src/Nethermind/Nethermind.Trie.Test/VisitingTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/VisitingTests.cs @@ -73,10 +73,10 @@ public void Visitors_storage(VisitingOptions options, INodeStorage.KeyScheme sch var blockCommit = trieStore.BeginBlockCommit(0); - for (int outi = 0; outi < 64; outi++) + for (int outerIndex = 0; outerIndex < 64; outerIndex++) { ValueHash256 stateKey = default; - stateKey.BytesAsSpan[outi / 2] = (byte)(1 << (4 * (1 - outi % 2))); + stateKey.BytesAsSpan[outerIndex / 2] = (byte)(1 << (4 * (1 - outerIndex % 2))); StorageTree storage = new(trieStore.GetTrieStore(stateKey.ToCommitment()), LimboLogs.Instance); for (int i = 0; i < 64; i++) diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs index 127d396c500..482e9aaa784 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs @@ -339,7 +339,7 @@ internal static int BucketSort16Large( Span indexes) { // You know, I originally used another buffer to keep track of the entries per nibble. then ChatGPT gave me this. - // I dont know what is worst, that ChatGPT beat me to it, or that it is simpler. + // I don't know what is worse, that ChatGPT beat me to it, or that it is simpler. Span counts = stackalloc int[TrieNode.BranchesCount]; for (int i = 0; i < entries.Length; i++) diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index 8f872496a4b..0e80d8f4cb0 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -22,7 +22,7 @@ namespace Nethermind.Trie.Pruning; /// /// Trie store helps to manage trie commits block by block. -/// If persistence and pruning are needed they have a chance to execute their behaviour on commits. +/// If persistence and pruning are needed they have a chance to execute their behavior on commits. /// public sealed class TrieStore : ITrieStore, IPruningTrieStore { @@ -617,7 +617,7 @@ internal void PersistAndPruneDirtyCache() SaveSnapshot(); // Full pruning may set delete obsolete keys to false - PruneCache(dontRemoveNodes: !_pruningStrategy.DeleteObsoleteKeys); + PruneCache(doNotRemoveNodes: !_pruningStrategy.DeleteObsoleteKeys); TimeSpan sw = Stopwatch.GetElapsedTime(start); long ms = (long)sw.TotalMilliseconds; @@ -652,11 +652,11 @@ private void SaveSnapshot() // Full pruning need to visit all node, so can't delete anything. // If more than one candidate set, its a reorg, we can't remove node as persisted node may not be canonical - // For archice node, it is safe to remove canon key from cache as it will just get re-loaded. + // For archive node, it is safe to remove canon key from cache as it will just get re-loaded. _deleteOldNodes && finalizedBlockNumber.HasValue; - if (_logger.IsDebug) _logger.Debug($"Persisting {candidateSets.Count} commitsets. Finalized block number {finalizedBlockNumber}. Should track past keys {shouldTrackPastKey}"); + if (_logger.IsDebug) _logger.Debug($"Persisting {candidateSets.Count} commit sets. Finalized block number {finalizedBlockNumber}. Should track past keys {shouldTrackPastKey}"); if (!finalizedBlockNumber.HasValue) { @@ -739,7 +739,7 @@ private void SaveSnapshot() } else { - // This can happen if the Max-Min of the commitsetqueue is less than pruning boundary + // This can happen if the Max-Min of the commit set queue is less than pruning boundary if (_logger.IsDebug) _logger.Debug($"Block commits are all after finalized block. Min block commit: {_commitSetQueue.MinBlockNumber}, Effective finalized block: {effectiveFinalizedBlockNumber}, Finalized block number: {finalizedBlockNumber}"); } return (candidateSets, null); @@ -840,7 +840,7 @@ private void PersistedNodeRecorderNoop(TreePath treePath, Hash256 address, TrieN /// This is done after a `SaveSnapshot`. /// /// - private void PruneCache(bool prunePersisted = false, bool dontRemoveNodes = false, bool forceRemovePersistedNodes = false) + private void PruneCache(bool prunePersisted = false, bool doNotRemoveNodes = false, bool forceRemovePersistedNodes = false) { if (_logger.IsDebug) _logger.Debug($"Pruning nodes {DirtyMemoryUsedByDirtyCache / 1.MB()} MB , last persisted block: {LastPersistedBlockNumber} current: {LatestCommittedBlockNumber}."); long start = Stopwatch.GetTimestamp(); @@ -858,7 +858,7 @@ private void PruneCache(bool prunePersisted = false, bool dontRemoveNodes = fals } INodeStorage nodeStorage = _nodeStorage; - if (dontRemoveNodes) nodeStorage = null; + if (doNotRemoveNodes) nodeStorage = null; dirtyNode .PruneCache( @@ -1199,14 +1199,14 @@ private void PersistOnShutdown() (ArrayPoolList candidateSets, long? finalizedBlockNumber) = DetermineCommitSetToPersistInSnapshot(_commitSetQueue.Count); using var _ = candidateSets; - if (LastPersistedBlockNumber == 0 && candidateSets.Count == 0 && _commitSetQueue.TryDequeue(out BlockCommitSet anyCommmitSet)) + if (LastPersistedBlockNumber == 0 && candidateSets.Count == 0 && _commitSetQueue.TryDequeue(out BlockCommitSet anyCommitSet)) { - // No commitset to persist, likely as not enough block was processed to reached prune boundary + // No commit set to persist, likely as not enough block was processed to reached prune boundary // This happens when node is shutdown right after sync. // we need to persist at least something or in case of fresh sync or the best persisted state will not be set - // at all. This come at a risk that this commitset is not canon though. - candidateSets.Add(anyCommmitSet); - if (_logger.IsDebug) _logger.Debug($"Force persisting commitset {anyCommmitSet} on shutdown."); + // at all. This come at a risk that this commit set is not canon though. + candidateSets.Add(anyCommitSet); + if (_logger.IsDebug) _logger.Debug($"Force persisting commit set {anyCommitSet} on shutdown."); } if (_logger.IsDebug) _logger.Debug($"On shutdown persisting {candidateSets.Count} commit sets. Finalized block is {finalizedBlockNumber}."); @@ -1223,7 +1223,7 @@ private void PersistOnShutdown() if (candidateSets.Count == 0) { - if (_logger.IsDebug) _logger.Debug("No commitset to persist at all."); + if (_logger.IsDebug) _logger.Debug("No commit set to persist at all."); } else { @@ -1238,7 +1238,7 @@ public void PersistCache(CancellationToken cancellationToken) long start = Stopwatch.GetTimestamp(); int commitSetCount = 0; - // We persist all sealed Commitset causing PruneCache to almost completely clear the cache. Any new block that + // We persist all sealed commit sets causing PruneCache to almost completely clear the cache. Any new block that // need existing node will have to read back from db causing copy-on-read mechanism to copy the node. CommitSetQueue commitSetQueue = _commitSetQueue; @@ -1270,7 +1270,7 @@ void ClearCommitSetQueue() // All persisted node including recommitted nodes between head and reorg depth must be removed so that // it will be re-persisted or at least re-read in order to be cloned. // This should clear most nodes. For some reason, not all. - PruneCache(prunePersisted: true, dontRemoveNodes: true, forceRemovePersistedNodes: true); + PruneCache(prunePersisted: true, doNotRemoveNodes: true, forceRemovePersistedNodes: true); if (cancellationToken.IsCancellationRequested) return; int totalPersistedCount = 0; @@ -1288,12 +1288,12 @@ void ClearCommitSetQueue() if (cancellationToken.IsCancellationRequested) return; - PruneCache(prunePersisted: true, dontRemoveNodes: true, forceRemovePersistedNodes: true); + PruneCache(prunePersisted: true, doNotRemoveNodes: true, forceRemovePersistedNodes: true); long nodesCount = NodesCount(); if (nodesCount != 0) { - if (_logger.IsWarn) _logger.Warn($"{nodesCount} cache entry remains. {DirtyCachedNodesCount} dirty, total persistec count is {totalPersistedCount}."); + if (_logger.IsWarn) _logger.Warn($"{nodesCount} cache entry remains. {DirtyCachedNodesCount} dirty, total persisted count is {totalPersistedCount}."); } if (_logger.IsInfo) _logger.Info($"Clear cache took {Stopwatch.GetElapsedTime(start)}."); diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs index 98009ab93f1..b1604a1fd37 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs @@ -205,7 +205,7 @@ private static NodeRecord RecordReplacementLogic(Hash256AsKey keyHash, NodeRecor // This is because although very rare, it is possible that this node is persisted, but its child is not // persisted. This can happen when a path is not replaced with another node, but its child is and hence, // the child is removed, but the parent is not and remain in the cache as persisted node. - // Additionally, it may hold a reference to its child which is marked as persisted eventhough it was + // Additionally, it may hold a reference to its child which is marked as persisted even though it was // deleted from the cached map. node = arg.Node; } diff --git a/src/Nethermind/Nethermind.Trie/TrieNode.cs b/src/Nethermind/Nethermind.Trie/TrieNode.cs index 6f14f86b2f6..7225f0ab073 100644 --- a/src/Nethermind/Nethermind.Trie/TrieNode.cs +++ b/src/Nethermind/Nethermind.Trie/TrieNode.cs @@ -732,7 +732,7 @@ public int AppendChildPath(ref TreePath currentPath, int childIndex) } // pruning trick so we never store long persisted paths - // Dont unresolve node of path length <= 4. there should be a relatively small number of these, enough to fit + // Don't unresolve nodes with path length <= 4; there should be relatively few and they should fit // in RAM, but they are hit quite a lot, and don't have very good data locality. // That said, in practice, it does nothing notable, except for significantly improving benchmark score. if (child?.IsPersisted == true && childPath.Length > 4 && childPath.Length % 2 == 0) @@ -1146,7 +1146,7 @@ public void PrunePersistedRecursively(int maxLevelsDeep) // else // { // // we assume that the storage root will get resolved during persistence even if not persisted yet - // // if this is not true then the code above that is commented out would be critical to call isntead + // // if this is not true then the code above that is commented out would be critical to call instead // _storageRoot = null; // } } @@ -1496,7 +1496,7 @@ public ref struct ChildIterator(TrieNode node) } // pruning trick so we never store long persisted paths - // Dont unresolve node of path length <= 4. there should be a relatively small number of these, enough to fit + // Don't unresolve nodes with path length <= 4; there should be relatively few and they should fit // in RAM, but they are hit quite a lot, and don't have very good data locality. // That said, in practice, it does nothing notable, except for significantly improving benchmark score. if (child?.IsPersisted == true && childPath.Length > 4 && childPath.Length % 2 == 0) diff --git a/src/Nethermind/Nethermind.TxPool.Test/RetryCacheTests.cs b/src/Nethermind/Nethermind.TxPool.Test/RetryCacheTests.cs index 87990c5ac31..8cd47a0a4e7 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/RetryCacheTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/RetryCacheTests.cs @@ -66,7 +66,7 @@ public void Announced_AfterTimeout_ExecutesRetryRequests() } [Test] - public void Announced_MultipleResources_ExecutesAllRetryRequestsExceptInititalOne() + public void Announced_MultipleResources_ExecutesAllRetryRequestsExceptInitialOne() { ITestHandler request1 = Substitute.For(); ITestHandler request2 = Substitute.For(); diff --git a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs index c432bce991f..6f431b074d4 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs @@ -626,7 +626,7 @@ public void should_not_count_txs_with_stale_nonces_when_calculating_cumulative_c } [Test] - public void should_add_tx_if_cost_of_executing_all_txs_in_bucket_exceeds_balance_but_these_with_lower_nonces_doesnt() + public void should_add_tx_if_cost_of_executing_all_txs_in_bucket_exceeds_balance_but_these_with_lower_nonces_do_not() { const int count = 10; const int gasPrice = 10; diff --git a/src/Nethermind/Nethermind.TxPool/RetryCache.cs b/src/Nethermind/Nethermind.TxPool/RetryCache.cs index 6cd69a89cd6..e4d918f7227 100644 --- a/src/Nethermind/Nethermind.TxPool/RetryCache.cs +++ b/src/Nethermind/Nethermind.TxPool/RetryCache.cs @@ -97,7 +97,7 @@ public AnnounceResult Announced(TResourceId resourceId, IMessageHandler=12" } diff --git a/src/Nethermind/Nethermind.UI/scripts/app.ts b/src/Nethermind/Nethermind.UI/scripts/app.ts index d802ecb7b10..0de9516d3c4 100644 --- a/src/Nethermind/Nethermind.UI/scripts/app.ts +++ b/src/Nethermind/Nethermind.UI/scripts/app.ts @@ -246,7 +246,7 @@ sse.addEventListener("forkChoice", (e) => { const number = parseInt(data.head.number, 16); if (!setActiveBlock && number !== 0) { setActiveBlock = true; - document.getElementById("lastestBlock").classList.remove("not-active"); + document.getElementById("latestBlock").classList.remove("not-active"); setTimeout(resize, 10); } const safe = parseInt(data.safe, 16); diff --git a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/ProposedBlockTests.cs b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/ProposedBlockTests.cs index 86754fa94ee..64e17c02712 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/ProposedBlockTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/ProposedBlockTests.cs @@ -17,7 +17,7 @@ namespace Nethermind.Xdc.Test; internal class ProposedBlockTests { [Test] - public async Task TestShouldSendVoteMsgAndCommitGrandGrandParentBlockAsync() + public async Task TestShouldSendVoteMsgAndCommitGreatGrandparentBlockAsync() { var blockChain = await XdcTestBlockchain.Create(2, true); diff --git a/src/Nethermind/Nethermind.Xdc/XdcBlockTree.cs b/src/Nethermind/Nethermind.Xdc/XdcBlockTree.cs index c8b7955a4a1..b9af6d8fd01 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcBlockTree.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcBlockTree.cs @@ -53,7 +53,7 @@ protected override AddBlockResult Suggest(Block? block, BlockHeader header, Bloc } if (header.Number - finalizedBlockInfo.BlockNumber > MaxSearchDepth) { - //Theoretically very deep reorgs could happen, if the chain doesnt finalize for a long time + //Theoretically very deep reorgs could happen, if the chain doesn't finalize for a long time //TODO Maybe this needs to be revisited later Logger.Warn($"Deep reorg past {MaxSearchDepth} blocks detected! Rejecting block {header.ToString(BlockHeader.Format.Full)}"); return AddBlockResult.InvalidBlock; diff --git a/src/Nethermind/cspell.json b/src/Nethermind/cspell.json new file mode 100644 index 00000000000..474d387832b --- /dev/null +++ b/src/Nethermind/cspell.json @@ -0,0 +1,95 @@ +{ + "version": "0.2", + "language": "en", + "files": [ + "**/*.{cs,csproj,fs,fsproj,vb,vbproj,props,targets,sln,tt,ttinclude,config,json,yml,yaml,md,txt,ps1,psm1,sh}", + "**/*.{ts,tsx,js,jsx,html,css,scss,xml}", + "**/*.proto" + ], + "ignorePaths": [ + "src/bench_precompiles/**", + "src/tests/**", + "src/Nethermind/artifacts/**", + "src/Nethermind/Chains/**", + "src/Nethermind/TestResults/**", + "**/bin/**", + "**/obj/**", + "**/node_modules/**", + "**/.git/**", + "**/.vs/**" + ], + "ignoreRegExpList": [ + "/0x[0-9a-fA-F]+/g", + "/https?:\\/\\/\\S+/g" + ], + "words": [ + "Autofac", + "Blobpool", + "Blobtransactions", + "Blockhash", + "Chiado", + "Commitset", + "Configurer", + "Demerzel", + "Dont", + "Ethash", + "Forkchoice", + "Hoodi", + "Hashtable", + "Keccak", + "Linea", + "Masternodes", + "Nethermind", + "Nethermind's", + "Parallelizable", + "Posdao", + "Randao", + "Readahead", + "Rlps", + "Rlpx", + "Scopable", + "Spaceneth", + "Stelem", + "Szalay", + "Taiko", + "Timestamper", + "Unresolve", + "blobgasused", + "blobpool", + "blobtransactions", + "blobversionedhashes", + "blockhash", + "chiado", + "commitset", + "configurer", + "dont", + "ethash", + "forkchoice", + "hashcode", + "hashtable", + "hoodi", + "keccaks", + "linea", + "nethermind", + "nodestore", + "posdao", + "ptree", + "randao", + "scopable", + "spaceneth", + "stelem", + "taiko", + "timestamper", + "triestore", + "unreferred", + "unresolve" + ], + "overrides": [ + { + "filename": "**/*.json", + "ignoreRegExpList": [ + "/\\\\u[0-9a-fA-F]{4}/g" + ] + } + ] +} From 54192516d489f79f927d841f21b11a3c07f6c791 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Tue, 2 Dec 2025 08:52:56 -0300 Subject: [PATCH 043/255] Fail fast for missing precompile (#9862) * Fail fast for missing precompile * fomatting --- src/Nethermind/Nethermind.Config/ExitCodes.cs | 1 + src/Nethermind/Nethermind.Evm/VirtualMachine.cs | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Config/ExitCodes.cs b/src/Nethermind/Nethermind.Config/ExitCodes.cs index 50e7f86b0f4..f20c402193f 100644 --- a/src/Nethermind/Nethermind.Config/ExitCodes.cs +++ b/src/Nethermind/Nethermind.Config/ExitCodes.cs @@ -20,6 +20,7 @@ public static class ExitCodes public const int ForbiddenOptionValue = 107; public const int MissingChainspecEipConfiguration = 108; public const int DbCorruption = 109; + public const int MissingPrecompile = 110; // Posix exit code // https://tldp.org/LDP/abs/html/exitcodes.html diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index 9a91d5f760b..49568b4e808 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -8,6 +8,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; +using Nethermind.Config; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -1026,10 +1027,11 @@ private CallResult RunPrecompile(EvmState state) SubstateError = success ? null : GetErrorString(precompile, output.Error) }; } - catch (DllNotFoundException exception) + catch (Exception exception) when (exception is DllNotFoundException or { InnerException: DllNotFoundException }) { - if (_logger.IsError) LogMissingDependency(precompile, exception); - throw; + if (_logger.IsError) LogMissingDependency(precompile, exception as DllNotFoundException ?? exception.InnerException as DllNotFoundException); + Environment.Exit(ExitCodes.MissingPrecompile); + throw; // Unreachable } catch (Exception exception) { From 15e3f0d3c06d0b9fcaf2906af955307851943b33 Mon Sep 17 00:00:00 2001 From: bigbear <155267841+aso20455@users.noreply.github.com> Date: Tue, 2 Dec 2025 14:06:55 +0200 Subject: [PATCH 044/255] fix(txpool): race condition in NonceManager.TxWithNonceReceived (#9861) --- src/Nethermind/Nethermind.TxPool/NonceManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.TxPool/NonceManager.cs b/src/Nethermind/Nethermind.TxPool/NonceManager.cs index 074b7687f6c..b69692ce71f 100644 --- a/src/Nethermind/Nethermind.TxPool/NonceManager.cs +++ b/src/Nethermind/Nethermind.TxPool/NonceManager.cs @@ -63,8 +63,9 @@ private void TxAccepted() public NonceLocker TxWithNonceReceived(UInt256 nonce) { + NonceLocker locker = new(_accountLock, TxAccepted); _reservedNonce = nonce; - return new(_accountLock, TxAccepted); + return locker; } private void ReleaseNonces(UInt256 accountNonce) From 68c4fe5f546664b06f418229dab107c0e6fae593 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Tue, 2 Dec 2025 15:07:54 +0300 Subject: [PATCH 045/255] Dispose plugins when supported (#9848) * Dispose plugins if needed --- .../ContainerBuilderExtensions.cs | 12 ++- .../PluginDisposalTests.cs | 79 +++++++++++++++++++ .../Modules/NethermindRunnerModule.cs | 5 +- 3 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 src/Nethermind/Nethermind.Runner.Test/PluginDisposalTests.cs diff --git a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs index 512dea16d9b..3cad05bac4b 100644 --- a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs +++ b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.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; @@ -32,13 +32,17 @@ public static ContainerBuilder AddSingleton(this ContainerBuilder builder) wh return builder; } - public static ContainerBuilder AddSingleton(this ContainerBuilder builder, T instance) where T : class + public static ContainerBuilder AddSingleton(this ContainerBuilder builder, T instance, bool takeOwnership = false) where T : class { - builder.RegisterInstance(instance) + IRegistrationBuilder registrationBuilder = builder.RegisterInstance(instance) .As() - .ExternallyOwned() .SingleInstance(); + if (!takeOwnership) + { + registrationBuilder.ExternallyOwned(); + } + return builder; } diff --git a/src/Nethermind/Nethermind.Runner.Test/PluginDisposalTests.cs b/src/Nethermind/Nethermind.Runner.Test/PluginDisposalTests.cs new file mode 100644 index 00000000000..efc6b452145 --- /dev/null +++ b/src/Nethermind/Nethermind.Runner.Test/PluginDisposalTests.cs @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Threading.Tasks; +using Autofac; +using Nethermind.Api; +using Nethermind.Api.Extensions; +using Nethermind.Config; +using Nethermind.Core; +using Nethermind.Logging; +using Nethermind.Runner.Ethereum.Modules; +using Nethermind.Serialization.Json; +using Nethermind.Specs.ChainSpecStyle; +using NSubstitute; +using NSubstitute.Core; +using NUnit.Framework; + +namespace Nethermind.Runner.Test; + +[TestFixture] +public class PluginDisposalTests +{ + private IConsensusPlugin _consensusPlugin = null!; + + [SetUp] + public void Setup() + { + SubstitutionContext.Current?.ThreadContext?.DequeueAllArgumentSpecifications(); + _consensusPlugin = Substitute.For(); + _consensusPlugin.ApiType.Returns(typeof(NethermindApi)); + } + + [Test] + public void Sync_plugin_is_disposed_when_container_is_disposed() + { + INethermindPlugin plugin = Substitute.For(); + + using (BuildContainer(plugin)) { } + + ((IDisposable)plugin).Received(1).Dispose(); + } + + [Test] + public async Task Async_plugin_is_disposed_when_container_is_disposed_async() + { + INethermindPlugin plugin = Substitute.For(); + + await using (BuildContainer(plugin)) { } + + await ((IAsyncDisposable)plugin).Received(1).DisposeAsync(); + } + + [Test] + public void Async_plugin_is_disposed_when_container_is_disposed_sync() + { + INethermindPlugin plugin = Substitute.For(); + + using (BuildContainer(plugin)) { } + + _ = ((IAsyncDisposable)plugin).Received(1).DisposeAsync(); + } + + private IContainer BuildContainer(INethermindPlugin plugin) => new ContainerBuilder() + .AddModule(new NethermindRunnerModule( + new EthereumJsonSerializer(), + new ChainSpec + { + Name = "test", + Parameters = new ChainParameters(), + SealEngineType = SealEngineType.NethDev, + EngineChainSpecParametersProvider = Substitute.For(), + }, + new ConfigProvider(), + Substitute.For(), + new INethermindPlugin[] { _consensusPlugin, plugin }, + LimboLogs.Instance)) + .Build(); +} diff --git a/src/Nethermind/Nethermind.Runner/Ethereum/Modules/NethermindRunnerModule.cs b/src/Nethermind/Nethermind.Runner/Ethereum/Modules/NethermindRunnerModule.cs index a196e786b09..8378db80d5d 100644 --- a/src/Nethermind/Nethermind.Runner/Ethereum/Modules/NethermindRunnerModule.cs +++ b/src/Nethermind/Nethermind.Runner/Ethereum/Modules/NethermindRunnerModule.cs @@ -78,13 +78,14 @@ protected override void Load(ContainerBuilder builder) .AddSingleton(consensusPlugin) ; - foreach (var plugin in plugins) + foreach (INethermindPlugin plugin in plugins) { if (plugin.Module is not null) { builder.AddModule(plugin.Module); } - builder.AddSingleton(plugin); + + builder.AddSingleton(plugin, takeOwnership: true); } builder.OnBuild((ctx) => From af2d67b6183b784ed7387743eb1a8b8fed027008 Mon Sep 17 00:00:00 2001 From: oxBoni Date: Tue, 2 Dec 2025 15:49:11 +0100 Subject: [PATCH 046/255] Fix redundant allocation in IXdcHeaderStore.BulkInsert (#9829) Update IXdcHeaderStore.cs --- src/Nethermind/Nethermind.Xdc/IXdcHeaderStore.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc/IXdcHeaderStore.cs b/src/Nethermind/Nethermind.Xdc/IXdcHeaderStore.cs index 2c9e16de375..1720c7cf22d 100644 --- a/src/Nethermind/Nethermind.Xdc/IXdcHeaderStore.cs +++ b/src/Nethermind/Nethermind.Xdc/IXdcHeaderStore.cs @@ -5,14 +5,13 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using System.Collections.Generic; -using System.Linq; namespace Nethermind.Xdc; internal interface IXdcHeaderStore : IHeaderStore { void Insert(XdcBlockHeader header) => ((IHeaderStore)this).Insert(header); - void BulkInsert(IReadOnlyList headers) => BulkInsert(headers.Cast().ToList()); + void BulkInsert(IReadOnlyList headers) => ((IHeaderStore)this).BulkInsert(headers); new XdcBlockHeader? Get(Hash256 blockHash, bool shouldCache, long? blockNumber = null) => ((IHeaderStore)this).Get(blockHash, shouldCache, blockNumber) as XdcBlockHeader; void Cache(XdcBlockHeader header) => ((IHeaderStore)this).Cache(header); From 1a665028aa66307e621beb72b2bfff1a51b22d0c Mon Sep 17 00:00:00 2001 From: Fibonacci747 Date: Tue, 2 Dec 2025 16:31:31 +0100 Subject: [PATCH 047/255] perf: avoid extra allocation by iterating snapshot (#9842) --- src/Nethermind/Nethermind.Core/Collections/LinkedHashSet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Core/Collections/LinkedHashSet.cs b/src/Nethermind/Nethermind.Core/Collections/LinkedHashSet.cs index 85930124744..047d96412e1 100644 --- a/src/Nethermind/Nethermind.Core/Collections/LinkedHashSet.cs +++ b/src/Nethermind/Nethermind.Core/Collections/LinkedHashSet.cs @@ -72,7 +72,7 @@ public void IntersectWith(IEnumerable? other) T[] ts = new T[Count]; CopyTo(ts, 0); HashSet set = other.ToHashSet(); - foreach (T t in this.ToArray()) + foreach (T t in ts) { if (!set.Contains(t)) { From 18b5b62aa3a61248893d14e42cf8fe0246283f80 Mon Sep 17 00:00:00 2001 From: anhnhx131 <106639913+anhnhx131@users.noreply.github.com> Date: Wed, 3 Dec 2025 15:54:07 +0700 Subject: [PATCH 048/255] Adjust JOC Bootnodes according to recent changes (#9869) fix: adjust joc bootnodes --- src/Nethermind/Chains/joc-mainnet.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Chains/joc-mainnet.json b/src/Nethermind/Chains/joc-mainnet.json index d4d361d7184..6fe008cb3b8 100644 --- a/src/Nethermind/Chains/joc-mainnet.json +++ b/src/Nethermind/Chains/joc-mainnet.json @@ -61,9 +61,8 @@ "timestamp": "0x5bfbe6b5" }, "nodes": [ - "enode://d4c1196326527c13cb318fb062571d9ae25393cbaa06222b3e57ca6407eeac550cf0fd148250282fdcb48e64877f3451d7a8cca281d9a0364c5739462976dfb5@54.199.51.112:30303", - "enode://a0662a1fb5d0b707c527355e03a59b1b5a63ffef76a3a758b2a0696c3f9e6205361db55906b91cdaa455c879aa8eb725536414fb0046990cc9e3611f4b130ef1@13.115.231.63:30303", - "enode://fcaa8046c7a81525882c409f70de7fcd3b9eab1fb4c8361fc62bc4d97459a619bedcc274d04212bf7631be6873b8547bf87e0057a4243da5919d15d58e42ab8c@54.178.230.138:30303" + "enode://c387e2b4e5231022ef30144c41fbd883139e9b5f1f4649c3d51c1611adbfaeadfd050c1bd9ac02eec6fa4c234b49a77fb5fb54f739c06d431eabfd981edc51f2@13.56.117.179:30303", + "enode://db803c26db9dac21e58452646a785b94a466eebffd6038621f78de92ccc6141fcb297650c290487375ab32a6dbc693d5dab49dba9785450002c68944ab0435a2@54.241.98.152:30303" ], "accounts": { "0000000000000000000000000000000000000000": { From 9b49f88cbdb3d75609d4e45abb0c14916ac705f4 Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Wed, 3 Dec 2025 13:17:47 +0100 Subject: [PATCH 049/255] fix leak in NettyDiscoveryBaseHandler (#9873) --- .../Nethermind.Network.Discovery/NettyDiscoveryBaseHandler.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryBaseHandler.cs b/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryBaseHandler.cs index 17a3c34b12d..d733d4fe6a1 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryBaseHandler.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryBaseHandler.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; using DotNetty.Transport.Channels.Sockets; using Nethermind.Logging; @@ -18,7 +19,10 @@ public abstract class NettyDiscoveryBaseHandler(ILogManager? logManager) : Simpl public override void ChannelRead(IChannelHandlerContext ctx, object msg) { if (msg is DatagramPacket packet && AcceptInboundMessage(packet) && !ValidatePacket(packet)) + { + ReferenceCountUtil.Release(msg); return; + } base.ChannelRead(ctx, msg); } From fd29878e157668ed15bebe611f708bc877309728 Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Wed, 3 Dec 2025 14:38:29 +0100 Subject: [PATCH 050/255] Don't cache current block cache (#9852) * Don't cache current block cache, this makes cache usable for block production where current block hash is unknown * refactors * slight refactor * more simplification * fix * fixes for Hash being null - block production * fix for prefetch * fix test * remove redundant check --- .../BlockhashCacheTests.cs | 44 +++++++++++++++++-- .../Nethermind.Blockchain/BlockhashCache.cs | 35 +++++++++------ .../BlockhashProvider.cs | 32 +++++++++----- 3 files changed, 84 insertions(+), 27 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs index cc79815311e..f1732833707 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs @@ -311,9 +311,8 @@ public async Task Prefetch_reuses_parent_data(int chainDepth) Assert.Multiple(() => { int compareLength = headHashes.Length - 1; - Assert.That(prevHashes.AsSpan(0, compareLength) - .SequenceEqual(headHashes.AsSpan(1, compareLength))); - Assert.That(headHashes[0], Is.EqualTo(head.Hash)); + Assert.That(prevHashes.AsSpan(0, compareLength).SequenceEqual(headHashes.AsSpan(1, compareLength))); + Assert.That(headHashes[0], Is.EqualTo(head.ParentHash)); } ); } @@ -330,6 +329,45 @@ public async Task DoesNot_cache_cancelled_searches() cache.GetStats().Should().Be(new BlockhashCache.Stats(0, 0, 0)); } + [Test] + public void Doesnt_cache_null_hashes() + { + (BlockTree tree, BlockhashCache cache) = BuildTest(100); + BlockHeader head = tree.FindHeader(99, BlockTreeLookupOptions.None)!; + BlockHeader headMinus4 = tree.FindHeader(95, BlockTreeLookupOptions.None)!; + BlockHeader headerOnHeadMinus4 = Build.A.BlockHeader.WithParent(headMinus4).WithHash(null!).TestObject; + BlockHeader headerOnHead = Build.A.BlockHeader.WithParent(head).WithHash(null!).TestObject; + Hash256? hashOnHeadMinus8 = cache.GetHash(headerOnHeadMinus4, 4); + cache.GetHash(headerOnHead, 5).Should().Be(headMinus4.Hash!); + hashOnHeadMinus8.Should().Be(cache.GetHash(headerOnHead, 8)!); + } + + [Test] + public async Task Prefetch_with_null_hash_does_not_cache([Values] bool prefetchParent) + { + (BlockTree tree, BlockhashCache cache) = BuildTest(10); + + BlockHeader parent = tree.FindHeader(9, BlockTreeLookupOptions.None)!; + if (prefetchParent) + { + await cache.Prefetch(parent); + } + + int cacheCountBefore = cache.GetStats().FlatCache; + + BlockHeader production = Build.A.BlockHeader.WithParent(parent).WithNumber(10).TestObject; + production.Hash = null; + Hash256[] hashes = (await cache.Prefetch(production))!; + + hashes.Should().NotBeNull(); + hashes[0].Should().Be(parent.Hash!); + + if (prefetchParent) + { + cache.GetStats().FlatCache.Should().Be(cacheCountBefore); + } + } + private static (BlockTree, BlockhashCache) BuildTest(int chainLength, IHeaderStore? headerStore = null) { Block genesis = Build.A.Block.Genesis.TestObject; diff --git a/src/Nethermind/Nethermind.Blockchain/BlockhashCache.cs b/src/Nethermind/Nethermind.Blockchain/BlockhashCache.cs index 91e10d97cc2..2147e771fd9 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockhashCache.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockhashCache.cs @@ -31,7 +31,7 @@ public class BlockhashCache(IHeaderFinder headerFinder, ILogManager logManager) depth == 0 ? headBlock.Hash : depth == 1 ? headBlock.ParentHash : depth > MaxDepth ? null - : _flatCache.TryGet(headBlock.ParentHash!, out Hash256[] array) ? array[depth - 1] + : _flatCache.TryGet(headBlock.ParentHash!, out Hash256[] array) ? array[depth - 2] : Load(headBlock, depth, out _)?.Hash; private CacheNode? Load(BlockHeader blockHeader, int depth, out Hash256[]? hashes, CancellationToken cancellationToken = default) @@ -58,8 +58,7 @@ public class BlockhashCache(IHeaderFinder headerFinder, ILogManager logManager) } currentNode = new CacheNode(currentHeader); - needToAdd = true; - needToAddAny = true; + needToAddAny |= needToAdd = currentHeader.Hash is not null; } } @@ -101,14 +100,19 @@ public class BlockhashCache(IHeaderFinder headerFinder, ILogManager logManager) } } - if (blocks.Count == FlatCacheLength(blockHeader)) + int ancestorCount = blocks.Count - 1; + if (ancestorCount == FlatCacheLength(blockHeader)) { - hashes = new Hash256[blocks.Count]; - for (int i = 0; i < blocks.Count; i++) + hashes = new Hash256[ancestorCount]; + for (int i = 1; i < blocks.Count; i++) { - hashes[i] = blocks[i].Node.Hash; + hashes[i - 1] = blocks[i].Node.Hash; + } + + if (blockHeader.Hash is not null) + { + _flatCache.Set(blockHeader.Hash, hashes); } - _flatCache.Set(blockHeader.Hash, hashes); } int index = depth - skipped; @@ -118,7 +122,7 @@ public class BlockhashCache(IHeaderFinder headerFinder, ILogManager logManager) : null; } - private static int FlatCacheLength(BlockHeader blockHeader) => (int)(Math.Min(MaxDepth, blockHeader.Number) + 1); + private static int FlatCacheLength(BlockHeader blockHeader) => (int)Math.Min(MaxDepth, blockHeader.Number); public Task Prefetch(BlockHeader blockHeader, CancellationToken cancellationToken = default) { @@ -129,15 +133,20 @@ public class BlockhashCache(IHeaderFinder headerFinder, ILogManager logManager) { if (!cancellationToken.IsCancellationRequested) { - if (!_flatCache.TryGet(blockHeader.Hash, out hashes)) + bool emptyHash = blockHeader.Hash is null; + + if (emptyHash || !_flatCache.TryGet(blockHeader.Hash, out hashes)) { if (_flatCache.TryGet(blockHeader.ParentHash, out Hash256[] parentHashes)) { int length = FlatCacheLength(blockHeader); hashes = new Hash256[length]; - hashes[0] = blockHeader.Hash; - Array.Copy(parentHashes, 0, hashes, 1, Math.Min(length - 1, MaxDepth)); - _flatCache.Set(blockHeader.Hash, hashes); + hashes[0] = blockHeader.ParentHash; + Array.Copy(parentHashes, 0, hashes, 1, length - 1); + if (!emptyHash) + { + _flatCache.Set(blockHeader.Hash, hashes); + } } else { diff --git a/src/Nethermind/Nethermind.Blockchain/BlockhashProvider.cs b/src/Nethermind/Nethermind.Blockchain/BlockhashProvider.cs index 513df956658..ea638750cea 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockhashProvider.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockhashProvider.cs @@ -28,24 +28,34 @@ public class BlockhashProvider( public Hash256? GetBlockhash(BlockHeader currentBlock, long number, IReleaseSpec spec) { - if (spec.IsBlockHashInStateAvailable) + if (number < 0) { - return _blockhashStore.GetBlockHashFromState(currentBlock, number, spec); + return ReturnOutOfBounds(currentBlock, number); } - long current = currentBlock.Number; - long depth = current - number; - if (number >= current || number < 0 || depth > MaxDepth) + if (spec.IsBlockHashInStateAvailable) { - if (_logger.IsTrace) _logger.Trace($"BLOCKHASH opcode returning null for {currentBlock.Number} -> {number}"); - return null; + return _blockhashStore.GetBlockHashFromState(currentBlock, number, spec); } + long depth = currentBlock.Number - number; Hash256[]? hashes = _hashes; - return hashes is not null - ? hashes[depth] - : blockhashCache.GetHash(currentBlock, (int)depth) - ?? throw new InvalidDataException("Hash cannot be found when executing BLOCKHASH operation"); + + return depth switch + { + <= 0 or > MaxDepth => ReturnOutOfBounds(currentBlock, number), + 1 => currentBlock.ParentHash, + _ => hashes is not null + ? hashes[depth - 1] + : blockhashCache.GetHash(currentBlock, (int)depth) + ?? throw new InvalidDataException("Hash cannot be found when executing BLOCKHASH operation") + }; + } + + private Hash256? ReturnOutOfBounds(BlockHeader currentBlock, long number) + { + if (_logger.IsTrace) _logger.Trace($"BLOCKHASH opcode returning null for {currentBlock.Number} -> {number}"); + return null; } public async Task Prefetch(BlockHeader currentBlock, CancellationToken token) From 043b8374ee26a639fedec2634f9dfc8405b65f11 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Wed, 3 Dec 2025 10:50:55 -0300 Subject: [PATCH 051/255] Reduce Evm Exceptions (#9808) * Reduce Evm Memory Exceptions * Reduce exceptions further * Compile issue * AI feedback * AI feedback * Add test coverage for out-of-gas conditions in memory operations (#9811) * Initial plan * Add out-of-gas test coverage for memory operations Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> * Reduce casts * Change to tryX pattern --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> --- .../Evm/MemoryCostBenchmark.cs | 2 +- .../Nethermind.Evm.Test/EvmMemoryTestsBase.cs | 27 ++- .../EvmPooledMemoryTests.cs | 135 +++++++++++++- .../Tracing/DebugTracerTests.cs | 2 +- .../Nethermind.Evm/EvmPooledMemory.cs | 165 ++++++++---------- src/Nethermind/Nethermind.Evm/IEvmMemory.cs | 16 +- .../Instructions/EvmCalculations.cs | 4 +- .../Instructions/EvmInstructions.Call.cs | 11 +- .../Instructions/EvmInstructions.CodeCopy.cs | 4 +- .../EvmInstructions.ControlFlow.cs | 6 +- .../Instructions/EvmInstructions.Create.cs | 3 +- .../Instructions/EvmInstructions.Crypto.cs | 10 +- .../Instructions/EvmInstructions.Eof.cs | 18 +- .../Instructions/EvmInstructions.Stack.cs | 4 +- .../Instructions/EvmInstructions.Storage.cs | 38 ++-- .../Nethermind.Evm/VirtualMachine.cs | 5 +- 16 files changed, 288 insertions(+), 162 deletions(-) diff --git a/src/Nethermind/Nethermind.Benchmark/Evm/MemoryCostBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Evm/MemoryCostBenchmark.cs index 54092dc5652..be9e86212db 100644 --- a/src/Nethermind/Nethermind.Benchmark/Evm/MemoryCostBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Evm/MemoryCostBenchmark.cs @@ -35,7 +35,7 @@ public void Setup() public long Current() { UInt256 dest = _location; - return _current.CalculateMemoryCost(in dest, _length); + return _current.CalculateMemoryCost(in dest, _length, out _); } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/EvmMemoryTestsBase.cs b/src/Nethermind/Nethermind.Evm.Test/EvmMemoryTestsBase.cs index c4b6c63bfc1..7838ed213ef 100644 --- a/src/Nethermind/Nethermind.Evm.Test/EvmMemoryTestsBase.cs +++ b/src/Nethermind/Nethermind.Evm.Test/EvmMemoryTestsBase.cs @@ -18,7 +18,8 @@ public void Save_empty_beyond_reasonable_size_does_not_throw() { IEvmMemory memory = CreateEvmMemory(); UInt256 dest = (UInt256)int.MaxValue + 1; - memory.Save(in dest, Array.Empty()); + bool outOfGas = !memory.TrySave(in dest, Array.Empty()); + Assert.That(outOfGas, Is.EqualTo(false)); } [Test] @@ -26,7 +27,8 @@ public void Trace_one_word() { IEvmMemory memory = CreateEvmMemory(); UInt256 dest = UInt256.Zero; - memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); + bool outOfGas = !memory.TrySaveWord(in dest, new byte[EvmPooledMemory.WordSize]); + Assert.That(outOfGas, Is.EqualTo(false)); var trace = memory.GetTrace(); Assert.That(trace.ToHexWordList().Count, Is.EqualTo(1)); } @@ -36,7 +38,8 @@ public void Trace_two_words() { IEvmMemory memory = CreateEvmMemory(); UInt256 dest = EvmPooledMemory.WordSize; - memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); + bool outOfGas = !memory.TrySaveWord(in dest, new byte[EvmPooledMemory.WordSize]); + Assert.That(outOfGas, Is.EqualTo(false)); var trace = memory.GetTrace(); Assert.That(trace.ToHexWordList().Count, Is.EqualTo(2)); } @@ -46,8 +49,10 @@ public void Trace_overwrite() { IEvmMemory memory = CreateEvmMemory(); UInt256 dest = EvmPooledMemory.WordSize; - memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); - memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); + bool outOfGas = !memory.TrySaveWord(in dest, new byte[EvmPooledMemory.WordSize]); + Assert.That(outOfGas, Is.EqualTo(false)); + outOfGas = !memory.TrySaveWord(in dest, new byte[EvmPooledMemory.WordSize]); + Assert.That(outOfGas, Is.EqualTo(false)); var trace = memory.GetTrace(); Assert.That(trace.ToHexWordList().Count, Is.EqualTo(2)); } @@ -57,7 +62,8 @@ public void Trace_when_position_not_on_word_border() { IEvmMemory memory = CreateEvmMemory(); UInt256 dest = EvmPooledMemory.WordSize / 2; - memory.SaveByte(in dest, 1); + bool outOfGas = !memory.TrySaveByte(in dest, 1); + Assert.That(outOfGas, Is.EqualTo(false)); var trace = memory.GetTrace(); Assert.That(trace.ToHexWordList().Count, Is.EqualTo(1)); } @@ -67,8 +73,10 @@ public void Calculate_memory_cost_returns_0_for_subsequent_calls() { IEvmMemory memory = CreateEvmMemory(); UInt256 dest = UInt256.One; - memory.CalculateMemoryCost(in dest, UInt256.One); - long cost = memory.CalculateMemoryCost(in dest, UInt256.One); + memory.CalculateMemoryCost(in dest, UInt256.One, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(false)); + long cost = memory.CalculateMemoryCost(in dest, UInt256.One, out outOfGas); + Assert.That(outOfGas, Is.EqualTo(false)); Assert.That(cost, Is.EqualTo(0L)); } @@ -77,7 +85,8 @@ public void Calculate_memory_cost_returns_0_for_0_length() { IEvmMemory memory = CreateEvmMemory(); UInt256 dest = long.MaxValue; - long cost = memory.CalculateMemoryCost(in dest, UInt256.Zero); + long cost = memory.CalculateMemoryCost(in dest, UInt256.Zero, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(false)); Assert.That(cost, Is.EqualTo(0L)); } } diff --git a/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs b/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs index 47b649cff51..684d35b124c 100644 --- a/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs @@ -59,15 +59,134 @@ public void MemoryCost(int destination, int memoryAllocation) { EvmPooledMemory memory = new(); UInt256 dest = (UInt256)destination; - long result = memory.CalculateMemoryCost(in dest, (UInt256)memoryAllocation); + long result = memory.CalculateMemoryCost(in dest, (UInt256)memoryAllocation, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(false)); TestContext.Out.WriteLine($"Gas cost of allocating {memoryAllocation} starting from {dest}: {result}"); } + [Test] + public void CalculateMemoryCost_LocationExceedsULong_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 location = new(0, 1, 0, 0); // value larger than ulong max (u1 != 0) + long result = memory.CalculateMemoryCost(in location, 32, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(true)); + Assert.That(result, Is.EqualTo(0L)); + } + + [Test] + public void CalculateMemoryCost_LengthExceedsULong_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 length = new(0, 1, 0, 0); // value larger than ulong max (u1 != 0) + long result = memory.CalculateMemoryCost(0, in length, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(true)); + Assert.That(result, Is.EqualTo(0L)); + } + + [Test] + public void CalculateMemoryCost_LengthExceedsLongMax_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 length = (UInt256)long.MaxValue + 1; // just over long.MaxValue + long result = memory.CalculateMemoryCost(0, in length, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(true)); + Assert.That(result, Is.EqualTo(0L)); + } + + [Test] + public void CalculateMemoryCost_LocationPlusLengthOverflows_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 location = ulong.MaxValue; + long result = memory.CalculateMemoryCost(in location, 1, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(true)); + Assert.That(result, Is.EqualTo(0L)); + } + + [Test] + public void CalculateMemoryCost_TotalSizeExceedsLongMax_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 location = (UInt256)long.MaxValue; + long result = memory.CalculateMemoryCost(in location, 1, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(true)); + Assert.That(result, Is.EqualTo(0L)); + } + + [Test] + public void Save_LocationExceedsULong_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 location = new(0, 1, 0, 0); + bool outOfGas = !memory.TrySave(in location, new byte[32]); + Assert.That(outOfGas, Is.EqualTo(true)); + } + + [Test] + public void SaveWord_LocationExceedsULong_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 location = new(0, 1, 0, 0); + bool outOfGas = !memory.TrySaveWord(in location, new byte[32]); + Assert.That(outOfGas, Is.EqualTo(true)); + } + + [Test] + public void SaveByte_LocationExceedsULong_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 location = new(0, 1, 0, 0); + bool outOfGas = !memory.TrySaveByte(in location, 0x42); + Assert.That(outOfGas, Is.EqualTo(true)); + } + + [Test] + public void LoadSpan_LocationExceedsULong_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 location = new(0, 1, 0, 0); + bool outOfGas = !memory.TryLoadSpan(in location, out Span result); + Assert.That(outOfGas, Is.EqualTo(true)); + Assert.That(result.IsEmpty, Is.EqualTo(true)); + } + + [Test] + public void LoadSpan_LengthExceedsULong_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 length = new(0, 1, 0, 0); + bool outOfGas = !memory.TryLoadSpan(0, in length, out Span result); + Assert.That(outOfGas, Is.EqualTo(true)); + Assert.That(result.IsEmpty, Is.EqualTo(true)); + } + + [Test] + public void Load_LocationExceedsULong_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 location = new(0, 1, 0, 0); + bool outOfGas = !memory.TryLoad(in location, 32, out ReadOnlyMemory result); + Assert.That(outOfGas, Is.EqualTo(true)); + Assert.That(result.IsEmpty, Is.EqualTo(true)); + } + + [Test] + public void Load_LengthExceedsULong_ShouldReturnOutOfGas() + { + EvmPooledMemory memory = new(); + UInt256 length = new(0, 1, 0, 0); + bool outOfGas = !memory.TryLoad(0, in length, out ReadOnlyMemory result); + Assert.That(outOfGas, Is.EqualTo(true)); + Assert.That(result.IsEmpty, Is.EqualTo(true)); + } + [Test] public void Inspect_should_not_change_evm_memory() { EvmPooledMemory memory = new(); - memory.Save(3, TestItem.KeccakA.Bytes); + bool outOfGas = !memory.TrySave(3, TestItem.KeccakA.Bytes); + Assert.That(outOfGas, Is.EqualTo(false)); ulong initialSize = memory.Size; ReadOnlyMemory result = memory.Inspect(initialSize + 32, 32); Assert.That(memory.Size, Is.EqualTo(initialSize)); @@ -81,7 +200,8 @@ public void Inspect_can_read_memory() byte[] expectedEmptyRead = new byte[32 - offset]; byte[] expectedKeccakRead = TestItem.KeccakA.BytesToArray(); EvmPooledMemory memory = new(); - memory.Save((UInt256)offset, expectedKeccakRead); + bool outOfGas = !memory.TrySave((UInt256)offset, expectedKeccakRead); + Assert.That(outOfGas, Is.EqualTo(false)); ulong initialSize = memory.Size; ReadOnlyMemory actualKeccakMemoryRead = memory.Inspect((UInt256)offset, 32); ReadOnlyMemory actualEmptyRead = memory.Inspect(32 + (UInt256)offset, 32 - (UInt256)offset); @@ -95,9 +215,11 @@ public void Load_should_update_size_of_memory() { byte[] expectedResult = new byte[32]; EvmPooledMemory memory = new(); - memory.Save(3, TestItem.KeccakA.Bytes); + bool outOfGas = !memory.TrySave(3, TestItem.KeccakA.Bytes); + Assert.That(outOfGas, Is.EqualTo(false)); ulong initialSize = memory.Size; - ReadOnlyMemory result = memory.Load(initialSize + 32, 32); + outOfGas = !memory.TryLoad(initialSize + 32, 32, out ReadOnlyMemory result); + Assert.That(outOfGas, Is.EqualTo(false)); Assert.That(memory.Size, Is.Not.EqualTo(initialSize)); Assert.That(result.ToArray(), Is.EqualTo(expectedResult)); } @@ -106,7 +228,8 @@ public void Load_should_update_size_of_memory() public void GetTrace_should_not_throw_on_not_initialized_memory() { EvmPooledMemory memory = new(); - memory.CalculateMemoryCost(0, 32); + memory.CalculateMemoryCost(0, 32, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(false)); memory.GetTrace().ToHexWordList().Should().BeEquivalentTo(new string[] { "0000000000000000000000000000000000000000000000000000000000000000" }); } diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs index 65f4205c798..cb484f6aadb 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs @@ -313,7 +313,7 @@ public void Debugger_Can_Alter_Memory(string bytecodeHex) if (tracer.CanReadState) { // we alter the value stored in memory to force EQ check at the end to fail - tracer.CurrentState.Memory.SaveByte(31, 0x0A); + tracer.CurrentState.Memory.TrySaveByte(31, 0x0A); tracer.MoveNext(); } diff --git a/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs b/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs index e466680673c..6ac9a8d93d6 100644 --- a/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs +++ b/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs @@ -23,11 +23,13 @@ public struct EvmPooledMemory : IEvmMemory public ulong Length { get; private set; } public ulong Size { get; private set; } - public void SaveWord(in UInt256 location, Span word) + public bool TrySaveWord(in UInt256 location, Span word) { if (word.Length != WordSize) ThrowArgumentOutOfRangeException(); - CheckMemoryAccessViolation(in location, WordSize, out ulong newLength); + CheckMemoryAccessViolation(in location, WordSize, out ulong newLength, out bool outOfGas); + if (outOfGas) return false; + UpdateSize(newLength); int offset = (int)location; @@ -37,73 +39,60 @@ public void SaveWord(in UInt256 location, Span word) ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_memory), offset), Unsafe.As>(ref MemoryMarshal.GetReference(word)) ); + + return true; } - public void SaveByte(in UInt256 location, byte value) + public bool TrySaveByte(in UInt256 location, byte value) { - CheckMemoryAccessViolation(in location, WordSize, out _); - UpdateSize(in location, in UInt256.One); + CheckMemoryAccessViolation(in location, WordSize, out _, out bool outOfGas); + if (outOfGas) return false; + + UpdateSize(location.u0 + 1); _memory![(long)location] = value; + return true; } - public void Save(in UInt256 location, Span value) + public bool TrySave(in UInt256 location, Span value) { if (value.Length == 0) { - return; + return true; } - CheckMemoryAccessViolation(in location, (ulong)value.Length, out ulong newLength); + CheckMemoryAccessViolation(in location, (ulong)value.Length, out ulong newLength, out bool outOfGas); + if (outOfGas) return false; + UpdateSize(newLength); value.CopyTo(_memory.AsSpan((int)location, value.Length)); + return true; } private static void CheckMemoryAccessViolation(in UInt256 location, in UInt256 length, out ulong newLength, out bool outOfGas) { - if (location.IsLargerThanULong() || length.IsLargerThanULong()) + if (length.IsLargerThanULong()) { outOfGas = true; newLength = 0; return; } - CheckMemoryAccessViolationInner(location.u0, length.u0, out newLength, out outOfGas); + CheckMemoryAccessViolation(in location, length.u0, out newLength, out outOfGas); } - private static void CheckMemoryAccessViolation(in UInt256 location, in UInt256 length, out ulong newLength) + private static void CheckMemoryAccessViolation(in UInt256 location, ulong length, out ulong newLength, out bool outOfGas) { - if (location.IsLargerThanULong() || length.IsLargerThanULong()) - { - ThrowOutOfGasException(); - } - - CheckMemoryAccessViolationInner(location.u0, length.u0, out newLength, out bool outOfGas); - if (outOfGas) + if (location.IsLargerThanULong() || length > long.MaxValue) { - ThrowOutOfGasException(); - } - } - - private static void CheckMemoryAccessViolation(in UInt256 location, ulong length, out ulong newLength) - { - if (location.IsLargerThanULong()) - { - ThrowOutOfGasException(); - } - - CheckMemoryAccessViolationInner(location.u0, length, out newLength, out bool outOfGas); - if (outOfGas) - { - ThrowOutOfGasException(); + outOfGas = true; + newLength = 0; + return; } - } - private static void CheckMemoryAccessViolationInner(ulong location, ulong length, out ulong newLength, out bool outOfGas) - { - ulong totalSize = location + length; - if (totalSize < location || totalSize > long.MaxValue) + ulong totalSize = location.u0 + length; + if (totalSize < location.u0 || totalSize > long.MaxValue) { outOfGas = true; newLength = 0; @@ -114,36 +103,38 @@ private static void CheckMemoryAccessViolationInner(ulong location, ulong length newLength = totalSize; } - public void Save(in UInt256 location, byte[] value) + public bool TrySave(in UInt256 location, byte[] value) { if (value.Length == 0) { - return; + return true; } ulong length = (ulong)value.Length; - CheckMemoryAccessViolation(in location, length, out ulong newLength); + CheckMemoryAccessViolation(in location, length, out ulong newLength, out bool outOfGas); + if (outOfGas) return false; + UpdateSize(newLength); Array.Copy(value, 0, _memory!, (long)location, value.Length); + return true; } - public void Save(in UInt256 location, in ZeroPaddedSpan value) + public bool TrySave(in UInt256 location, in ZeroPaddedSpan value) { if (value.Length == 0) { // Nothing to do - return; + return true; } ulong length = (ulong)value.Length; - CheckMemoryAccessViolation(in location, length, out ulong newLength); - UpdateSize(newLength); + CheckMemoryAccessViolation(in location, length, out ulong newLength, out bool outOfGas); + outOfGas |= location.u0 > int.MaxValue; - if (location.u0 > int.MaxValue) - { - ThrowOutOfGas(); - } + if (outOfGas) return false; + + UpdateSize(newLength); int intLocation = (int)location.u0; value.Span.CopyTo(_memory.AsSpan(intLocation, value.Span.Length)); @@ -152,47 +143,66 @@ public void Save(in UInt256 location, in ZeroPaddedSpan value) ClearPadding(_memory, intLocation + value.Span.Length, value.PaddingLength); } + return true; + [MethodImpl(MethodImplOptions.NoInlining)] static void ClearPadding(byte[] memory, int offset, int length) => memory.AsSpan(offset, length).Clear(); } - public Span LoadSpan(scoped in UInt256 location) + public bool TryLoadSpan(scoped in UInt256 location, out Span data) { - CheckMemoryAccessViolation(in location, WordSize, out ulong newLength); - UpdateSize(newLength); + CheckMemoryAccessViolation(in location, WordSize, out ulong newLength, out bool outOfGas); + if (outOfGas) + { + data = default; + return false; + } - return _memory.AsSpan((int)location, WordSize); + UpdateSize(newLength); + data = _memory.AsSpan((int)location, WordSize); + return true; } - public Span LoadSpan(scoped in UInt256 location, scoped in UInt256 length) + public bool TryLoadSpan(scoped in UInt256 location, scoped in UInt256 length, out Span data) { if (length.IsZero) { - return []; + data = []; + return true; } - CheckMemoryAccessViolation(in location, in length, out ulong newLength); - UpdateSize(newLength); + CheckMemoryAccessViolation(in location, in length, out ulong newLength, out bool outOfGas); + if (outOfGas) + { + data = default; + return false; + } - return _memory.AsSpan((int)location, (int)length); + UpdateSize(newLength); + data = _memory.AsSpan((int)location, (int)length); + return true; } - public ReadOnlyMemory Load(in UInt256 location, in UInt256 length) + public bool TryLoad(in UInt256 location, in UInt256 length, out ReadOnlyMemory data) { if (length.IsZero) { - return default; + data = default; + return true; } - if (location > int.MaxValue) + CheckMemoryAccessViolation(in location, in length, out ulong newLength, out bool outOfGas); + if (outOfGas) { - return new byte[(long)length]; + data = default; + return false; } - UpdateSize(in location, in length); + UpdateSize(newLength); - return _memory.AsMemory((int)location, (int)length); + data = _memory.AsMemory((int)location, (int)length); + return true; } public ReadOnlyMemory Inspect(in UInt256 location, in UInt256 length) @@ -273,21 +283,6 @@ public long CalculateMemoryCost(in UInt256 location, in UInt256 length, out bool return 0L; } - public long CalculateMemoryCost(in UInt256 location, in UInt256 length) - { - long result = CalculateMemoryCost(in location, in length, out bool outOfGas); - if (outOfGas) - { - ThrowOutOfGas(); - } - - return result; - - } - - [DoesNotReturn, StackTraceHidden] - private static void ThrowOutOfGas() => throw new OutOfGasException(); - public TraceMemory GetTrace() { ulong size = Size; @@ -305,11 +300,6 @@ public void Dispose() } } - private void UpdateSize(in UInt256 location, in UInt256 length, bool rentIfNeeded = true) - { - UpdateSize((ulong)(location + length), rentIfNeeded); - } - private void UpdateSize(ulong length, bool rentIfNeeded = true) { const int MinRentSize = 1_024; @@ -359,13 +349,6 @@ private static void ThrowArgumentOutOfRangeException() Metrics.EvmExceptions++; throw new ArgumentOutOfRangeException("Word size must be 32 bytes"); } - - [DoesNotReturn, StackTraceHidden] - private static void ThrowOutOfGasException() - { - Metrics.EvmExceptions++; - throw new OutOfGasException(); - } } public static class UInt256Extensions diff --git a/src/Nethermind/Nethermind.Evm/IEvmMemory.cs b/src/Nethermind/Nethermind.Evm/IEvmMemory.cs index 4cd68736f31..5f443910984 100644 --- a/src/Nethermind/Nethermind.Evm/IEvmMemory.cs +++ b/src/Nethermind/Nethermind.Evm/IEvmMemory.cs @@ -10,13 +10,13 @@ namespace Nethermind.Evm; public interface IEvmMemory : IDisposable { ulong Size { get; } - void SaveWord(in UInt256 location, Span word); - void SaveByte(in UInt256 location, byte value); - void Save(in UInt256 location, Span value); - void Save(in UInt256 location, byte[] value); - Span LoadSpan(in UInt256 location); - Span LoadSpan(in UInt256 location, in UInt256 length); - ReadOnlyMemory Load(in UInt256 location, in UInt256 length); - long CalculateMemoryCost(in UInt256 location, in UInt256 length); + bool TrySaveWord(in UInt256 location, Span word); + bool TrySaveByte(in UInt256 location, byte value); + bool TrySave(in UInt256 location, Span value); + bool TrySave(in UInt256 location, byte[] value); + bool TryLoadSpan(in UInt256 location, out Span data); + bool TryLoadSpan(in UInt256 location, in UInt256 length, out Span data); + bool TryLoad(in UInt256 location, in UInt256 length, out ReadOnlyMemory data); + long CalculateMemoryCost(in UInt256 location, in UInt256 length, out bool outOfGas); TraceMemory GetTrace(); } diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmCalculations.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmCalculations.cs index 79de1c3389f..9e1ee181851 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmCalculations.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmCalculations.cs @@ -133,7 +133,7 @@ public static bool ChargeStorageAccessGas( public static bool UpdateMemoryCost(EvmState vmState, ref long gasAvailable, in UInt256 position, in UInt256 length) { // Calculate additional gas cost for any memory expansion. - long memoryCost = vmState.Memory.CalculateMemoryCost(in position, length); + long memoryCost = vmState.Memory.CalculateMemoryCost(in position, length, out bool outOfGas); if (memoryCost != 0L) { if (!UpdateGas(memoryCost, ref gasAvailable)) @@ -142,7 +142,7 @@ public static bool UpdateMemoryCost(EvmState vmState, ref long gasAvailable, in } } - return true; + return !outOfGas; } /// diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs index a3db55e61c0..cf20f33a69d 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs @@ -252,7 +252,8 @@ public static EvmExceptionType InstructionCall( } // Load call data from memory. - ReadOnlyMemory callData = vm.EvmState.Memory.Load(in dataOffset, dataLength); + if (!vm.EvmState.Memory.TryLoad(in dataOffset, dataLength, out ReadOnlyMemory callData)) + goto OutOfGas; // Construct the execution environment for the call. ExecutionEnvironment callEnv = new( codeInfo: codeInfo, @@ -347,15 +348,13 @@ public static EvmExceptionType InstructionReturn( goto StackUnderflow; // Update the memory cost for the region being returned. - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in position, in length)) + if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in position, in length) || + !vm.EvmState.Memory.TryLoad(in position, in length, out ReadOnlyMemory returnData)) { goto OutOfGas; } - // Load the return data from memory and copy it to an array, - // so the return value isn't referencing live memory, - // which is being unwound in return. - vm.ReturnData = vm.EvmState.Memory.Load(in position, in length).ToArray(); + vm.ReturnData = returnData.ToArray(); return EvmExceptionType.None; // Jump forward to be unpredicted by the branch predictor. diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs index 04602858408..af7e0c8a0b0 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs @@ -76,7 +76,7 @@ public static EvmExceptionType InstructionCodeCopy( // Obtain the code slice with zero-padding if needed. ZeroPaddedSpan slice = TOpCodeCopy.GetCode(vm).SliceWithZeroPadding(in b, (int)result); // Save the slice into memory at the destination offset. - vm.EvmState.Memory.Save(in a, in slice); + if (!vm.EvmState.Memory.TrySave(in a, in slice)) goto OutOfGas; // If tracing is enabled, report the memory change. if (TTracingInst.IsActive) @@ -180,7 +180,7 @@ public static EvmExceptionType InstructionExtCodeCopy( // Slice the external code starting at the source offset with appropriate zero-padding. ZeroPaddedSpan slice = externalCode.SliceWithZeroPadding(in b, (int)result); // Save the slice into memory at the destination offset. - vm.EvmState.Memory.Save(in a, in slice); + if (!vm.EvmState.Memory.TrySave(in a, in slice)) goto OutOfGas; // Report memory changes if tracing is enabled. if (TTracingInst.IsActive) diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs index 1bd918970b9..c9ff58328c6 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs @@ -173,13 +173,13 @@ public static EvmExceptionType InstructionRevert(VirtualMachine vm, ref EvmStack } // Ensure sufficient gas for any required memory expansion. - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in position, in length)) + if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in position, in length) || + !vm.EvmState.Memory.TryLoad(in position, in length, out ReadOnlyMemory returnData)) { goto OutOfGas; } - // Copy the specified memory region as return data. - vm.ReturnData = vm.EvmState.Memory.Load(in position, in length).ToArray(); + vm.ReturnData = returnData.ToArray(); return EvmExceptionType.Revert; // Jump forward to be unpredicted by the branch predictor. diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs index 06618582ea9..802d2d67a66 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs @@ -136,7 +136,8 @@ public static EvmExceptionType InstructionCreate( } // Load the initialization code from memory based on the specified position and length. - ReadOnlyMemory initCode = vm.EvmState.Memory.Load(in memoryPositionOfInitCode, in initCodeLength); + if (!vm.EvmState.Memory.TryLoad(in memoryPositionOfInitCode, in initCodeLength, out ReadOnlyMemory initCode)) + goto OutOfGas; // Check that the executing account has sufficient balance to transfer the specified value. UInt256 balance = state.GetBalance(env.ExecutingAccount); diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Crypto.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Crypto.cs index 374a6914851..53ec615ac20 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Crypto.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Crypto.cs @@ -27,16 +27,16 @@ public static EvmExceptionType InstructionKeccak256(VirtualMachine // Deduct gas: base cost plus additional cost per 32-byte word. gasAvailable -= GasCostOf.Sha3 + GasCostOf.Sha3Word * EvmCalculations.Div32Ceiling(in b, out bool outOfGas); - if (outOfGas) - goto OutOfGas; + if (outOfGas) goto OutOfGas; EvmState vmState = vm.EvmState; // Charge gas for any required memory expansion. - if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in a, b)) + if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in a, b) || + !vmState.Memory.TryLoadSpan(in a, b, out Span bytes)) + { goto OutOfGas; + } - // Load the target memory region. - Span bytes = vmState.Memory.LoadSpan(in a, b); // Compute the Keccak-256 hash. KeccakCache.ComputeTo(bytes, out ValueHash256 keccak); // Push the 256-bit hash result onto the stack. diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs index 3ec3bd0b93e..f83c470b19f 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs @@ -124,7 +124,7 @@ public static EvmExceptionType InstructionReturnDataCopy(VirtualMa // Get the source slice; if the requested range exceeds the buffer length, it is zero-padded. ZeroPaddedSpan slice = returnDataBuffer.Span.SliceWithZeroPadding(sourceOffset, (int)size); - vm.EvmState.Memory.Save(in destOffset, in slice); + if (!vm.EvmState.Memory.TrySave(in destOffset, in slice)) goto OutOfGas; // Report the memory change if tracing is active. if (TTracingInst.IsActive) @@ -269,7 +269,7 @@ public static EvmExceptionType InstructionDataCopy(VirtualMachine goto OutOfGas; // Retrieve the slice from the data section with zero padding if necessary. ZeroPaddedSpan dataSectionSlice = codeInfo.DataSection.SliceWithZeroPadding(offset, (int)size); - vm.EvmState.Memory.Save(in memOffset, dataSectionSlice); + if (!vm.EvmState.Memory.TrySave(in memOffset, in dataSectionSlice)) goto OutOfGas; if (TTracingInst.IsActive) { @@ -726,7 +726,8 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine ICodeInfo codeInfo = CodeInfoFactory.CreateCodeInfo(initContainer.ToArray(), spec, ValidationStrategy.ExtractHeader); // 8. Prepare the callData from the caller’s memory slice. - ReadOnlyMemory callData = vm.EvmState.Memory.Load(dataOffset, dataSize); + if (!vm.EvmState.Memory.TryLoad(dataOffset, dataSize, out ReadOnlyMemory callData)) + goto OutOfGas; // Set up the execution environment for the new contract. ExecutionEnvironment callEnv = new( @@ -798,7 +799,9 @@ public static EvmExceptionType InstructionReturnCode(VirtualMachine vm, ref EvmS } // Load the memory slice as the return data buffer. - vm.ReturnDataBuffer = vm.EvmState.Memory.Load(a, b); + if (!vm.EvmState.Memory.TryLoad(a, b, out vm.ReturnDataBuffer)) + goto OutOfGas; + vm.ReturnData = deployCodeInfo; return EvmExceptionType.None; @@ -972,10 +975,11 @@ public static EvmExceptionType InstructionEofCall(Virt } // 12. Deduct gas for the call and prepare the call data. - if (!EvmCalculations.UpdateGas(callGas, ref gasAvailable)) + if (!EvmCalculations.UpdateGas(callGas, ref gasAvailable) || + !vm.EvmState.Memory.TryLoad(in dataOffset, dataLength, out ReadOnlyMemory callData)) + { goto OutOfGas; - - ReadOnlyMemory callData = vm.EvmState.Memory.Load(in dataOffset, dataLength); + } // Snapshot the state before the call. Snapshot snapshot = state.TakeSnapshot(); diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs index b24a08cd8bc..354b8bb798b 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs @@ -594,7 +594,9 @@ public static EvmExceptionType InstructionLog(VirtualMachine vm, ref E (long)length * GasCostOf.LogData, ref gasAvailable)) goto OutOfGas; // Load the log data from memory. - ReadOnlyMemory data = vmState.Memory.Load(in position, length); + if (!vmState.Memory.TryLoad(in position, length, out ReadOnlyMemory data)) + goto OutOfGas; + // Prepare the topics array by popping the corresponding number of words from the stack. Hash256[] topics = new Hash256[topicsCount]; for (int i = 0; i < topics.Length; i++) diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Storage.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Storage.cs index 9d174c9053c..dd8abad4ee6 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Storage.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Storage.cs @@ -151,10 +151,11 @@ public static EvmExceptionType InstructionMStore(VirtualMachine vm EvmState vmState = vm.EvmState; // Update the memory cost for a 32-byte store; if insufficient gas, signal out-of-gas. - if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in result, in BigInt32)) goto OutOfGas; - - // Write the 32-byte word into memory. - vmState.Memory.SaveWord(in result, bytes); + if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in result, in BigInt32) || + !vmState.Memory.TrySaveWord(in result, bytes)) + { + goto OutOfGas; + } // Report memory changes if tracing is active. if (TTracingInst.IsActive) @@ -196,10 +197,11 @@ public static EvmExceptionType InstructionMStore8(VirtualMachine v EvmState vmState = vm.EvmState; // Update the memory cost for a single-byte extension; if insufficient, signal out-of-gas. - if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in result, in UInt256.One)) goto OutOfGas; - - // Write the single byte to memory. - vmState.Memory.SaveByte(in result, data); + if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in result, in UInt256.One) || + !vmState.Memory.TrySaveByte(in result, data)) + { + goto OutOfGas; + } // Report the memory change if tracing is active. if (TTracingInst.IsActive) @@ -238,10 +240,11 @@ public static EvmExceptionType InstructionMLoad(VirtualMachine vm, EvmState vmState = vm.EvmState; // Update memory cost for a 32-byte load. - if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in result, in BigInt32)) goto OutOfGas; - - // Load the 32-byte word from memory. - Span bytes = vmState.Memory.LoadSpan(in result); + if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in result, in BigInt32) || + !vmState.Memory.TryLoadSpan(in result, out Span bytes)) + { + goto OutOfGas; + } // Report the memory load if tracing is active. if (TTracingInst.IsActive) @@ -288,17 +291,18 @@ public static EvmExceptionType InstructionMCopy(VirtualMachine vm, EvmState vmState = vm.EvmState; // Update memory cost for the destination area (largest offset among source and destination) over the specified length. - if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, UInt256.Max(b, a), c)) goto OutOfGas; - - // Load the specified memory segment from the source offset. - Span bytes = vmState.Memory.LoadSpan(in b, c); + if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, UInt256.Max(b, a), c) || + !vmState.Memory.TryLoadSpan(in b, c, out Span bytes)) + { + goto OutOfGas; + } // Report the memory change at the source if tracing is active. if (TTracingInst.IsActive) vm.TxTracer.ReportMemoryChange(b, bytes); // Write the bytes into memory at the destination offset. - vmState.Memory.Save(in a, bytes); + if (!vmState.Memory.TrySave(in a, bytes)) goto OutOfGas; // Report the memory change at the destination if tracing is active. if (TTracingInst.IsActive) diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index 49568b4e808..98366b35ef5 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -90,6 +90,7 @@ public unsafe partial class VirtualMachine( private OpCode[] _opcodeMethods; private static long _txCount; + private ReadOnlyMemory _returnDataBuffer = Array.Empty(); protected EvmState _currentState; protected ReadOnlyMemory? _previousCallResult; protected UInt256 _previousCallOutputDestination; @@ -100,7 +101,7 @@ public unsafe partial class VirtualMachine( public ITxTracer TxTracer => _txTracer; public IWorldState WorldState => _worldState; public ref readonly ValueHash256 ChainId => ref _chainId; - public ReadOnlyMemory ReturnDataBuffer { get; set; } = Array.Empty(); + public ref ReadOnlyMemory ReturnDataBuffer => ref _returnDataBuffer; public object ReturnData { get; set; } public IBlockhashProvider BlockHashProvider => _blockHashProvider; protected Stack StateStack => _stateStack; @@ -1152,7 +1153,7 @@ protected CallResult ExecuteCall( } // Save the previous call's output into the VM state's memory. - vmState.Memory.Save(in localPreviousDest, previousCallOutput); + if (!vmState.Memory.TrySave(in localPreviousDest, previousCallOutput)) goto OutOfGas; } // Dispatch the bytecode interpreter. From de4342fdf1db049c950a7fda983a6b3229f4ef36 Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Wed, 3 Dec 2025 21:34:17 +0100 Subject: [PATCH 052/255] Bump up the version to 1.37.0-unstable (#9871) Co-authored-by: stdevMac --- src/Nethermind/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Directory.Build.props b/src/Nethermind/Directory.Build.props index fa845ca3670..b46ea4a88f4 100644 --- a/src/Nethermind/Directory.Build.props +++ b/src/Nethermind/Directory.Build.props @@ -5,7 +5,7 @@ $(SOURCE_DATE_EPOCH) $([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()) - 1.36.0 + 1.37.0 unstable From 6188b20980a1fa23a08d72ffbd2fb7e6613165bc Mon Sep 17 00:00:00 2001 From: Diptanshu Kakwani Date: Thu, 4 Dec 2025 13:33:22 +0530 Subject: [PATCH 053/255] Taiko Shasta Changes (#9709) * initial changes * make l1BlockHeight optional in L1Origin * fix field name inconsistency in NMC and Geth * undo field name change (catalyst fixed) * shasta devnet fixes * address review comments and fix issues --------- Co-authored-by: Ahmad Bitar <33181301+smartprogrammer93@users.noreply.github.com> --- .../Validators/HeaderValidator.cs | 2 +- .../L1OriginStoreTests.cs | 206 ++++++++++++++++++ .../TaikoExtendedEthModuleTests.cs | 12 +- .../Nethermind.Taiko/BlockMetadata.cs | 3 + .../Nethermind.Taiko/IL1OriginStore.cs | 3 + src/Nethermind/Nethermind.Taiko/L1Origin.cs | 16 +- .../Nethermind.Taiko/L1OriginDecoder.cs | 66 +++++- .../Nethermind.Taiko/L1OriginStore.cs | 56 ++++- .../Rpc/ITaikoEngineRpcModule.cs | 12 + .../Rpc/ITaikoExtendedEthRpcModule.cs | 12 + .../Rpc/TaikoEngineRpcModule.cs | 20 ++ .../Rpc/TaikoExtendedEthModule.cs | 114 +++++++++- .../Nethermind.Taiko/TaikoBlockValidator.cs | 8 +- .../Nethermind.Taiko/TaikoHeaderHelper.cs | 6 + .../Nethermind.Taiko/TaikoHeaderValidator.cs | 118 +++++++++- .../TaikoPayloadPreparationService.cs | 6 + .../TaikoSpec/ITaikoReleaseSpec.cs | 1 + .../TaikoSpec/TaikoCancunReleaseSpec.cs | 21 +- .../TaikoChainSpecBasedSpecProvider.cs | 1 + .../TaikoChainSpecEngineParameters.cs | 6 + .../TaikoSpec/TaikoReleaseSpec.cs | 1 + .../TaikoTransactionProcessor.cs | 5 +- 22 files changed, 645 insertions(+), 50 deletions(-) create mode 100644 src/Nethermind/Nethermind.Taiko.Test/L1OriginStoreTests.cs diff --git a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs index 1f3d352dc10..3236ae5fa5d 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs @@ -29,7 +29,7 @@ public class HeaderValidator( protected readonly ISpecProvider _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); private readonly long? _daoBlockNumber = specProvider.DaoBlockNumber; protected readonly ILogger _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - private readonly IBlockTree _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); + protected readonly IBlockTree _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); public static bool ValidateHash(BlockHeader header, out Hash256 actualHash) { diff --git a/src/Nethermind/Nethermind.Taiko.Test/L1OriginStoreTests.cs b/src/Nethermind/Nethermind.Taiko.Test/L1OriginStoreTests.cs new file mode 100644 index 00000000000..954bfacd308 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko.Test/L1OriginStoreTests.cs @@ -0,0 +1,206 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Linq; +using FluentAssertions; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test; +using Nethermind.Db; +using Nethermind.Int256; +using Nethermind.Serialization.Rlp; +using NUnit.Framework; + +namespace Nethermind.Taiko.Test; + +public class L1OriginStoreTests +{ + private IDb _db = null!; + private L1OriginStore _store = null!; + private L1OriginDecoder _decoder = null!; + + [SetUp] + public void Setup() + { + _db = new TestMemDb(); + _decoder = new L1OriginDecoder(); + _store = new L1OriginStore(_db, _decoder); + } + + [Test] + public void Can_write_and_read_l1_origin() + { + UInt256 blockId = 123; + L1Origin origin = new(blockId, Hash256.Zero, 456, Hash256.Zero, null); + + _store.WriteL1Origin(blockId, origin); + L1Origin? retrieved = _store.ReadL1Origin(blockId); + + retrieved.Should().NotBeNull(); + retrieved!.BlockId.Should().Be(blockId); + retrieved.L1BlockHeight.Should().Be(456); + } + + [Test] + public void Returns_null_for_non_existent_l1_origin() + { + L1Origin? retrieved = _store.ReadL1Origin(999); + retrieved.Should().BeNull(); + } + + [Test] + public void Can_write_and_read_head_l1_origin() + { + UInt256 headBlockId = 789; + + _store.WriteHeadL1Origin(headBlockId); + UInt256? retrieved = _store.ReadHeadL1Origin(); + + retrieved.Should().Be((UInt256)789); + } + + [Test] + public void Returns_null_for_non_existent_head() + { + UInt256? retrieved = _store.ReadHeadL1Origin(); + retrieved.Should().BeNull(); + } + + [Test] + public void Can_write_and_read_batch_to_block_mapping() + { + UInt256 batchId = 100; + UInt256 blockId = 200; + + _store.WriteBatchToLastBlockID(batchId, blockId); + UInt256? retrieved = _store.ReadBatchToLastBlockID(batchId); + + retrieved.Should().Be((UInt256)200); + } + + [Test] + public void Returns_null_for_non_existent_batch_mapping() + { + UInt256? retrieved = _store.ReadBatchToLastBlockID(999); + retrieved.Should().BeNull(); + } + + [Test] + public void Different_batch_ids_store_separately() + { + _store.WriteBatchToLastBlockID(1, 100); + _store.WriteBatchToLastBlockID(2, 200); + + _store.ReadBatchToLastBlockID(1).Should().Be((UInt256)100); + _store.ReadBatchToLastBlockID(2).Should().Be((UInt256)200); + } + + [Test] + public void Different_block_ids_store_separately() + { + L1Origin origin1 = new(1, Hash256.Zero, 100, Hash256.Zero, null); + L1Origin origin2 = new(2, Hash256.Zero, 200, Hash256.Zero, null); + + _store.WriteL1Origin(1, origin1); + _store.WriteL1Origin(2, origin2); + + _store.ReadL1Origin(1)!.L1BlockHeight.Should().Be(100); + _store.ReadL1Origin(2)!.L1BlockHeight.Should().Be(200); + } + + [Test] + public void Can_overwrite_existing_values() + { + UInt256 blockId = 1; + L1Origin origin1 = new(blockId, Hash256.Zero, 100, Hash256.Zero, null); + L1Origin origin2 = new(blockId, Hash256.Zero, 200, Hash256.Zero, null); + + _store.WriteL1Origin(blockId, origin1); + _store.WriteL1Origin(blockId, origin2); + + _store.ReadL1Origin(blockId)!.L1BlockHeight.Should().Be(200); + } + + [Test] + public void Keys_use_correct_33_byte_format() + { + UInt256 blockId = 42; + L1Origin origin = new(blockId, Hash256.Zero, 100, Hash256.Zero, null); + + _store.WriteL1Origin(blockId, origin); + + var testDb = (TestMemDb)_db; + var allKeys = testDb.Keys.ToArray(); + allKeys.Should().HaveCount(1); + allKeys[0].Length.Should().Be(33, "Keys should be 33 bytes (1 prefix + 32 UInt256)"); + allKeys[0][0].Should().Be(0x00, "L1Origin keys should have prefix 0x00"); + } + + [Test] + public void Batch_keys_use_correct_prefix() + { + _store.WriteBatchToLastBlockID(1, 100); + + var testDb = (TestMemDb)_db; + var allKeys = testDb.Keys.ToArray(); + allKeys.Should().HaveCount(1); + allKeys[0].Length.Should().Be(33); + allKeys[0][0].Should().Be(0x01, "Batch keys should have prefix 0x01"); + } + + [Test] + public void Head_key_uses_correct_prefix() + { + _store.WriteHeadL1Origin(1); + + var testDb = (TestMemDb)_db; + var allKeys = testDb.Keys.ToArray(); + allKeys.Should().HaveCount(1); + allKeys[0].Length.Should().Be(1); + allKeys[0][0].Should().Be(0xFF, "Head key should have prefix 0xFF"); + } + + [Test] + public void Can_store_and_retrieve_signature() + { + UInt256 blockId = 123; + int[] signature = Enumerable.Range(0, 65).ToArray(); + L1Origin origin = new(blockId, Hash256.Zero, 456, Hash256.Zero, null) { Signature = signature }; + + _store.WriteL1Origin(blockId, origin); + L1Origin? retrieved = _store.ReadL1Origin(blockId); + + retrieved.Should().NotBeNull(); + retrieved!.Signature.Should().NotBeNull(); + retrieved.Signature!.Length.Should().Be(65); + retrieved.Signature.Should().BeEquivalentTo(signature); + } + + [Test] + public void Can_write_and_read_l1_origin_with_null_block_height() + { + UInt256 blockId = 456; + L1Origin origin = new(blockId, Hash256.Zero, null, Hash256.Zero, null); + + _store.WriteL1Origin(blockId, origin); + L1Origin? retrieved = _store.ReadL1Origin(blockId); + + retrieved.Should().NotBeNull(); + retrieved!.L1BlockHeight.Should().Be(0); + retrieved.IsPreconfBlock.Should().BeTrue(); + } + + [TestCase(0)] + [TestCase(L1OriginDecoder.SignatureLength - 1)] + [TestCase(L1OriginDecoder.SignatureLength + 1)] + [TestCase(L1OriginDecoder.SignatureLength * 2)] + public void Fails_for_invalid_length_signature(int signatureLength) + { + int[] signature = Enumerable.Range(0, signatureLength).ToArray(); + L1Origin origin = new(1, Hash256.Zero, 456, Hash256.Zero, null) { Signature = signature }; + + Action act = () => _decoder.Encode(origin); + act.Should().Throw().WithMessage($"*Signature*{L1OriginDecoder.SignatureLength}*"); + } +} + diff --git a/src/Nethermind/Nethermind.Taiko.Test/TaikoExtendedEthModuleTests.cs b/src/Nethermind/Nethermind.Taiko.Test/TaikoExtendedEthModuleTests.cs index 291276de31d..3f393b33589 100644 --- a/src/Nethermind/Nethermind.Taiko.Test/TaikoExtendedEthModuleTests.cs +++ b/src/Nethermind/Nethermind.Taiko.Test/TaikoExtendedEthModuleTests.cs @@ -3,6 +3,7 @@ using Autofac; using FluentAssertions; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Synchronization; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -22,6 +23,7 @@ public void TestCanResolve() { using IContainer container = new ContainerBuilder() .AddModule(new TestNethermindModule()) + .AddSingleton(Substitute.For()) .AddModule(new TaikoModule()) .Build(); @@ -36,7 +38,7 @@ public void TestSyncMode(bool snapEnabled, string result) TaikoExtendedEthModule rpc = new TaikoExtendedEthModule(new SyncConfig() { SnapSync = snapEnabled - }, Substitute.For()); + }, Substitute.For(), Substitute.For()); rpc.taiko_getSyncMode().Result.Data.Should().Be(result); } @@ -45,7 +47,7 @@ public void TestSyncMode(bool snapEnabled, string result) public void TestHeadL1Origin() { IL1OriginStore originStore = Substitute.For(); - TaikoExtendedEthModule rpc = new TaikoExtendedEthModule(new SyncConfig(), originStore); + TaikoExtendedEthModule rpc = new TaikoExtendedEthModule(new SyncConfig(), originStore, Substitute.For()); L1Origin origin = new L1Origin(0, TestItem.KeccakA, 1, Hash256.Zero, null); originStore.ReadHeadL1Origin().Returns((UInt256)1); @@ -58,7 +60,7 @@ public void TestHeadL1Origin() public void TestL1OriginById() { IL1OriginStore originStore = Substitute.For(); - TaikoExtendedEthModule rpc = new TaikoExtendedEthModule(new SyncConfig(), originStore); + TaikoExtendedEthModule rpc = new TaikoExtendedEthModule(new SyncConfig(), originStore, Substitute.For()); L1Origin origin = new L1Origin(0, TestItem.KeccakA, 1, Hash256.Zero, null); originStore.ReadL1Origin((UInt256)0).Returns(origin); @@ -70,7 +72,7 @@ public void TestL1OriginById() public void TestL1OriginById_WithBuildPayloadArgsId() { IL1OriginStore originStore = Substitute.For(); - TaikoExtendedEthModule rpc = new TaikoExtendedEthModule(new SyncConfig(), originStore); + TaikoExtendedEthModule rpc = new TaikoExtendedEthModule(new SyncConfig(), originStore, Substitute.For()); var buildPayloadArgsId = new int[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; L1Origin origin = new L1Origin(0, TestItem.KeccakA, 1, Hash256.Zero, buildPayloadArgsId); @@ -83,7 +85,7 @@ public void TestL1OriginById_WithBuildPayloadArgsId() public void TestL1OriginById_ValueHash256_EvenLengthHex() { IL1OriginStore originStore = Substitute.For(); - TaikoExtendedEthModule rpc = new TaikoExtendedEthModule(new SyncConfig(), originStore); + TaikoExtendedEthModule rpc = new TaikoExtendedEthModule(new SyncConfig(), originStore, Substitute.For()); int expectedLengthInChars = ValueHash256.Length * 2 + 2; // Create odd length hash values diff --git a/src/Nethermind/Nethermind.Taiko/BlockMetadata.cs b/src/Nethermind/Nethermind.Taiko/BlockMetadata.cs index 30bb9d95baf..aa0e44fe736 100644 --- a/src/Nethermind/Nethermind.Taiko/BlockMetadata.cs +++ b/src/Nethermind/Nethermind.Taiko/BlockMetadata.cs @@ -4,6 +4,7 @@ using System.Text.Json.Serialization; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Int256; using Nethermind.Serialization.Json; namespace Nethermind.Taiko; @@ -17,6 +18,8 @@ public class BlockMetadata public required Hash256 MixHash { get; set; } + public UInt256? BatchID { get; set; } + public required byte[] TxList { get; set; } [JsonConverter(typeof(Base64Converter))] diff --git a/src/Nethermind/Nethermind.Taiko/IL1OriginStore.cs b/src/Nethermind/Nethermind.Taiko/IL1OriginStore.cs index 63a3f0b0c07..b847f650e07 100644 --- a/src/Nethermind/Nethermind.Taiko/IL1OriginStore.cs +++ b/src/Nethermind/Nethermind.Taiko/IL1OriginStore.cs @@ -12,4 +12,7 @@ public interface IL1OriginStore UInt256? ReadHeadL1Origin(); void WriteHeadL1Origin(UInt256 blockId); + + UInt256? ReadBatchToLastBlockID(UInt256 batchId); + void WriteBatchToLastBlockID(UInt256 batchId, UInt256 blockId); } diff --git a/src/Nethermind/Nethermind.Taiko/L1Origin.cs b/src/Nethermind/Nethermind.Taiko/L1Origin.cs index 4f9a64aba20..ac0d048e3a9 100644 --- a/src/Nethermind/Nethermind.Taiko/L1Origin.cs +++ b/src/Nethermind/Nethermind.Taiko/L1Origin.cs @@ -6,18 +6,26 @@ namespace Nethermind.Taiko; -public class L1Origin(UInt256 blockId, ValueHash256? l2BlockHash, long l1BlockHeight, ValueHash256 l1BlockHash, int[]? buildPayloadArgsId) +public class L1Origin(UInt256 blockId, + ValueHash256? l2BlockHash, + long? l1BlockHeight, + ValueHash256 l1BlockHash, + int[]? buildPayloadArgsId, + bool isForcedInclusion = false, + int[]? signature = null) { public UInt256 BlockId { get; set; } = blockId; public ValueHash256? L2BlockHash { get; set; } = l2BlockHash; - public long L1BlockHeight { get; set; } = l1BlockHeight; + public long? L1BlockHeight { get; set; } = l1BlockHeight; public ValueHash256 L1BlockHash { get; set; } = l1BlockHash; - // Taiko uses int-like serializer + // Taiko uses int-like serializer (Go's default encoding for byte arrays) public int[]? BuildPayloadArgsId { get; set; } = buildPayloadArgsId; + public bool IsForcedInclusion { get; set; } = isForcedInclusion; + public int[]? Signature { get; set; } = signature; /// /// IsPreconfBlock returns true if the L1Origin is for a preconfirmation block. /// - public bool IsPreconfBlock => L1BlockHeight == 0; + public bool IsPreconfBlock => L1BlockHeight == 0 || L1BlockHeight == null; } diff --git a/src/Nethermind/Nethermind.Taiko/L1OriginDecoder.cs b/src/Nethermind/Nethermind.Taiko/L1OriginDecoder.cs index 4d5fb87948a..9e57c56f940 100644 --- a/src/Nethermind/Nethermind.Taiko/L1OriginDecoder.cs +++ b/src/Nethermind/Nethermind.Taiko/L1OriginDecoder.cs @@ -11,6 +11,7 @@ namespace Nethermind.Taiko; public sealed class L1OriginDecoder : RlpStreamDecoder { const int BuildPayloadArgsIdLength = 8; + internal const int SignatureLength = 65; protected override L1Origin DecodeInternal(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { @@ -19,11 +20,21 @@ protected override L1Origin DecodeInternal(RlpStream rlpStream, RlpBehaviors rlp UInt256 blockId = rlpStream.DecodeUInt256(); Hash256? l2BlockHash = rlpStream.DecodeKeccak(); - var l1BlockHeight = rlpStream.DecodeLong(); + long? l1BlockHeight = rlpStream.DecodeLong(); Hash256 l1BlockHash = rlpStream.DecodeKeccak() ?? throw new RlpException("L1BlockHash is null"); - int[]? buildPayloadArgsId = itemsCount == 4 ? null : Array.ConvertAll(rlpStream.DecodeByteArray(), Convert.ToInt32); - return new(blockId, l2BlockHash, l1BlockHeight, l1BlockHash, buildPayloadArgsId); + int[]? buildPayloadArgsId = null; + + if (itemsCount >= 5) + { + byte[] buildPayloadBytes = rlpStream.DecodeByteArray(); + buildPayloadArgsId = buildPayloadBytes.Length > 0 ? Array.ConvertAll(buildPayloadBytes, Convert.ToInt32) : null; + } + + bool isForcedInclusion = itemsCount >= 6 && rlpStream.DecodeBool(); + int[]? signature = itemsCount >= 7 ? Array.ConvertAll(rlpStream.DecodeByteArray(), Convert.ToInt32) : null; + + return new(blockId, l2BlockHash, l1BlockHeight, l1BlockHash, buildPayloadArgsId, isForcedInclusion, signature); } public Rlp Encode(L1Origin? item, RlpBehaviors rlpBehaviors = RlpBehaviors.None) @@ -42,27 +53,68 @@ public override void Encode(RlpStream stream, L1Origin item, RlpBehaviors rlpBeh stream.Encode(item.BlockId); stream.Encode(item.L2BlockHash); - stream.Encode(item.L1BlockHeight); + stream.Encode(item.L1BlockHeight ?? 0); stream.Encode(item.L1BlockHash); + + // If all optional remaining fields are missing, nothing to encode + if (item.BuildPayloadArgsId is null && !item.IsForcedInclusion && item.Signature is null) + return; + + // Encode buildPayloadArgsId, even if empty, to maintain field order if (item.BuildPayloadArgsId is not null) { if (item.BuildPayloadArgsId.Length is not BuildPayloadArgsIdLength) { throw new RlpException($"{nameof(item.BuildPayloadArgsId)} should be exactly {BuildPayloadArgsIdLength}"); } - stream.Encode(Array.ConvertAll(item.BuildPayloadArgsId, Convert.ToByte)); } + else + { + stream.Encode(Array.Empty()); + } + + // If neither IsForcedInclusion nor Signature are present, return + if (!item.IsForcedInclusion && item.Signature is null) + return; + + stream.Encode(item.IsForcedInclusion); + + if (item.Signature is not null) + { + if (item.Signature.Length != SignatureLength) + { + throw new RlpException($"{nameof(item.Signature)} should be exactly {SignatureLength}"); + } + + stream.Encode(Array.ConvertAll(item.Signature, Convert.ToByte)); + } } public override int GetLength(L1Origin item, RlpBehaviors rlpBehaviors) { + int buildPayloadLength = 0; + if (item.BuildPayloadArgsId is not null || item.IsForcedInclusion || item.Signature is not null) + { + buildPayloadLength = item.BuildPayloadArgsId is null + ? Rlp.LengthOf(Array.Empty()) + : Rlp.LengthOfByteString(BuildPayloadArgsIdLength, 0); + } + + int isForcedInclusionLength = 0; + if (item.IsForcedInclusion || item.Signature is not null) + { + isForcedInclusionLength = Rlp.LengthOf(item.IsForcedInclusion); + } + return Rlp.LengthOfSequence( Rlp.LengthOf(item.BlockId) + Rlp.LengthOf(item.L2BlockHash) - + Rlp.LengthOf(item.L1BlockHeight) + + Rlp.LengthOf(item.L1BlockHeight ?? 0) + Rlp.LengthOf(item.L1BlockHash) - + (item.BuildPayloadArgsId is null ? 0 : Rlp.LengthOfByteString(BuildPayloadArgsIdLength, 0)) + + buildPayloadLength + + isForcedInclusionLength + + (item.Signature is null ? 0 : Rlp.LengthOfByteString(SignatureLength, 0)) ); } } diff --git a/src/Nethermind/Nethermind.Taiko/L1OriginStore.cs b/src/Nethermind/Nethermind.Taiko/L1OriginStore.cs index 2ab8778f43f..f468c057853 100644 --- a/src/Nethermind/Nethermind.Taiko/L1OriginStore.cs +++ b/src/Nethermind/Nethermind.Taiko/L1OriginStore.cs @@ -16,20 +16,37 @@ public class L1OriginStore([KeyFilter(L1OriginStore.L1OriginDbName)] IDb db, IRl { public const string L1OriginDbName = "L1Origin"; private const int UInt256BytesLength = 32; - private static readonly byte[] L1OriginHeadKey = UInt256.MaxValue.ToBigEndian(); + private const int KeyBytesLength = UInt256BytesLength + 1; + private const byte L1OriginPrefix = 0x00; + private const byte BatchToBlockPrefix = 0x01; + private const byte L1OriginHeadPrefix = 0xFF; + private static readonly byte[] L1OriginHeadKey = [L1OriginHeadPrefix]; + + private static void CreateL1OriginKey(UInt256 blockId, Span keyBytes) + { + keyBytes[0] = L1OriginPrefix; + blockId.ToBigEndian(keyBytes[1..]); + } + + private static void CreateBatchToBlockKey(UInt256 batchId, Span keyBytes) + { + keyBytes[0] = BatchToBlockPrefix; + batchId.ToBigEndian(keyBytes[1..]); + } public L1Origin? ReadL1Origin(UInt256 blockId) { - Span keyBytes = stackalloc byte[UInt256BytesLength]; - blockId.ToBigEndian(keyBytes); + Span keyBytes = stackalloc byte[KeyBytesLength]; + CreateL1OriginKey(blockId, keyBytes); - return db.Get(new ValueHash256(keyBytes), decoder); + byte[]? data = db.Get(keyBytes); + return data is null ? null : decoder.Decode(new RlpStream(data)); } public void WriteL1Origin(UInt256 blockId, L1Origin l1Origin) { - Span key = stackalloc byte[UInt256BytesLength]; - blockId.ToBigEndian(key); + Span key = stackalloc byte[KeyBytesLength]; + CreateL1OriginKey(blockId, key); int encodedL1OriginLength = decoder.GetLength(l1Origin, RlpBehaviors.None); byte[] buffer = ArrayPool.Shared.Rent(encodedL1OriginLength); @@ -38,7 +55,7 @@ public void WriteL1Origin(UInt256 blockId, L1Origin l1Origin) { RlpStream stream = new(buffer); decoder.Encode(stream, l1Origin); - db.Set(new ValueHash256(key), buffer.AsSpan(0, encodedL1OriginLength)); + db.PutSpan(key, buffer.AsSpan(0, encodedL1OriginLength)); } finally { @@ -60,6 +77,29 @@ public void WriteHeadL1Origin(UInt256 blockId) Span blockIdBytes = stackalloc byte[UInt256BytesLength]; blockId.ToBigEndian(blockIdBytes); - db.Set(new(L1OriginHeadKey.AsSpan()), blockIdBytes); + db.PutSpan(L1OriginHeadKey, blockIdBytes); + } + + public UInt256? ReadBatchToLastBlockID(UInt256 batchId) + { + Span keyBytes = stackalloc byte[KeyBytesLength]; + CreateBatchToBlockKey(batchId, keyBytes); + + return db.Get(keyBytes) switch + { + null => null, + byte[] bytes => new UInt256(bytes, isBigEndian: true) + }; + } + + public void WriteBatchToLastBlockID(UInt256 batchId, UInt256 blockId) + { + Span key = stackalloc byte[KeyBytesLength]; + CreateBatchToBlockKey(batchId, key); + + Span blockIdBytes = stackalloc byte[UInt256BytesLength]; + blockId.ToBigEndian(blockIdBytes); + + db.PutSpan(key, blockIdBytes); } } diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoEngineRpcModule.cs b/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoEngineRpcModule.cs index 9bb243d5810..45973303f5d 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoEngineRpcModule.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoEngineRpcModule.cs @@ -77,4 +77,16 @@ Task> engine_newPayloadV3(TaikoExecutionPayloadV3 IsSharable = true, IsImplemented = true)] ResultWrapper taikoAuth_updateL1Origin(L1Origin l1Origin); + + [JsonRpcMethod( + Description = "Sets the mapping from batch ID to the last block ID in this batch.", + IsSharable = true, + IsImplemented = true)] + ResultWrapper taikoAuth_setBatchToLastBlock(UInt256 batchId, UInt256 blockId); + + [JsonRpcMethod( + Description = "Sets the L1 origin signature for the given block ID.", + IsSharable = true, + IsImplemented = true)] + ResultWrapper taikoAuth_setL1OriginSignature(UInt256 blockId, int[] signature); } diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoExtendedEthRpcModule.cs b/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoExtendedEthRpcModule.cs index 77d856d2d10..1c02cf2645e 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoExtendedEthRpcModule.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoExtendedEthRpcModule.cs @@ -28,4 +28,16 @@ public interface ITaikoExtendedEthRpcModule : IRpcModule IsSharable = true, IsImplemented = true)] Task> taiko_getSyncMode(); + + [JsonRpcMethod( + Description = "Returns the L1 origin of the last block for the given batch.", + IsSharable = true, + IsImplemented = true)] + Task> taiko_lastL1OriginByBatchID(UInt256 batchId); + + [JsonRpcMethod( + Description = "Returns the ID of the last block for the given batch.", + IsSharable = true, + IsImplemented = true)] + Task> taiko_lastBlockIDByBatchID(UInt256 batchId); } diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs index 9863c81ab54..dfa8fb64474 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs @@ -346,4 +346,24 @@ public ResultWrapper taikoAuth_updateL1Origin(L1Origin l1Origin) l1OriginStore.WriteL1Origin(l1Origin.BlockId, l1Origin); return ResultWrapper.Success(l1Origin); } + + public ResultWrapper taikoAuth_setBatchToLastBlock(UInt256 batchId, UInt256 blockId) + { + l1OriginStore.WriteBatchToLastBlockID(batchId, blockId); + return ResultWrapper.Success(batchId); + } + + public ResultWrapper taikoAuth_setL1OriginSignature(UInt256 blockId, int[] signature) + { + L1Origin? l1Origin = l1OriginStore.ReadL1Origin(blockId); + if (l1Origin is null) + { + return ResultWrapper.Fail($"L1 origin not found for block ID {blockId}"); + } + + l1Origin.Signature = signature; + l1OriginStore.WriteL1Origin(blockId, l1Origin); + + return ResultWrapper.Success(l1Origin); + } } diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoExtendedEthModule.cs b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoExtendedEthModule.cs index d1348b4a265..8ab244b3f56 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoExtendedEthModule.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoExtendedEthModule.cs @@ -1,18 +1,24 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Threading.Tasks; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Synchronization; +using Nethermind.Core; using Nethermind.Int256; using Nethermind.JsonRpc; +using static Nethermind.Taiko.TaikoBlockValidator; namespace Nethermind.Taiko.Rpc; public class TaikoExtendedEthModule( ISyncConfig syncConfig, - IL1OriginStore l1OriginStore) : ITaikoExtendedEthRpcModule + IL1OriginStore l1OriginStore, + IBlockFinder blockFinder) : ITaikoExtendedEthRpcModule { - private static readonly ResultWrapper NotFound = ResultWrapper.Fail("not found"); + private static readonly ResultWrapper L1OriginNotFound = ResultWrapper.Fail("not found"); + private static readonly ResultWrapper BlockIdNotFound = ResultWrapper.Fail("not found"); public Task> taiko_getSyncMode() => ResultWrapper.Success(syncConfig switch { @@ -25,18 +31,116 @@ public class TaikoExtendedEthModule( UInt256? head = l1OriginStore.ReadHeadL1Origin(); if (head is null) { - return NotFound; + return L1OriginNotFound; } L1Origin? origin = l1OriginStore.ReadL1Origin(head.Value); - return origin is null ? NotFound : ResultWrapper.Success(origin); + return origin is null ? L1OriginNotFound : ResultWrapper.Success(origin); } public Task> taiko_l1OriginByID(UInt256 blockId) { L1Origin? origin = l1OriginStore.ReadL1Origin(blockId); - return origin is null ? NotFound : ResultWrapper.Success(origin); + return origin is null ? L1OriginNotFound : ResultWrapper.Success(origin); + } + + public Task> taiko_lastL1OriginByBatchID(UInt256 batchId) + { + UInt256? blockId = l1OriginStore.ReadBatchToLastBlockID(batchId); + if (blockId is null) + { + blockId = GetLastBlockByBatchId(batchId); + if (blockId is null) + { + return L1OriginNotFound; + } + } + + L1Origin? origin = l1OriginStore.ReadL1Origin(blockId.Value); + + return origin is null ? L1OriginNotFound : ResultWrapper.Success(origin); + } + + public Task> taiko_lastBlockIDByBatchID(UInt256 batchId) + { + UInt256? blockId = l1OriginStore.ReadBatchToLastBlockID(batchId); + if (blockId is null) + { + blockId = GetLastBlockByBatchId(batchId); + if (blockId is null) + { + return BlockIdNotFound; + } + } + + return ResultWrapper.Success(blockId); + } + + /// + /// Traverses the blockchain backwards to find the last Shasta block of the given Shasta batch ID. + /// + /// The batch ID. + /// The last block ID. + private UInt256? GetLastBlockByBatchId(UInt256 batchId) + { + Block? currentBlock = blockFinder.Head; + + while (currentBlock is not null && + currentBlock.Transactions.Length > 0 && + HasAnchorV4Prefix(currentBlock.Transactions[0].Data)) + { + if (currentBlock.Number == 0) + { + break; + } + + UInt256? proposalId = ExtractAnchorV4ProposalId(currentBlock.Transactions[0].Data); + + if (proposalId is null) + { + return null; + } + + if (proposalId.Value == batchId) + { + return (UInt256)currentBlock.Number; + } + + currentBlock = blockFinder.FindBlock(currentBlock.Number - 1); + } + + return null; + } + + private static bool HasAnchorV4Prefix(ReadOnlyMemory data) + { + return data.Length >= 4 && AnchorV4Selector.AsSpan().SequenceEqual(data.Span[..4]); + } + + private static UInt256? ExtractAnchorV4ProposalId(ReadOnlyMemory data) + { + // Calldata layout: 4-byte selector + ABI-encoded arguments. + // The first 32 bytes hold the offset (relative to args start) where the proposal id is stored. + const int selectorLength = 4; + const int dataLength = 32; + + if (data.Length <= selectorLength + dataLength) + { + return null; + } + + ReadOnlySpan args = data.Span[selectorLength..]; + var offset = new UInt256(args[..dataLength], true); + + // Check if the offset is invalid + if (offset > int.MaxValue || offset + dataLength > args.Length) + { + return null; + } + + ReadOnlySpan proposalIdBytes = args.Slice((int)offset, dataLength); + return new UInt256(proposalIdBytes, true); } } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs b/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs index 25f5670247e..47e0ee2d8d7 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs @@ -24,11 +24,12 @@ public class TaikoBlockValidator( private static readonly byte[] AnchorSelector = Keccak.Compute("anchor(bytes32,bytes32,uint64,uint32)").Bytes[..4].ToArray(); private static readonly byte[] AnchorV2Selector = Keccak.Compute("anchorV2(uint64,bytes32,uint32,(uint8,uint8,uint32,uint64,uint32))").Bytes[..4].ToArray(); private static readonly byte[] AnchorV3Selector = Keccak.Compute("anchorV3(uint64,bytes32,uint32,(uint8,uint8,uint32,uint64,uint32),bytes32[])").Bytes[..4].ToArray(); + public static readonly byte[] AnchorV4Selector = Keccak.Compute("anchorV4((uint48,address,bytes,bytes32,(uint48,uint8,address,address)[]),(uint48,bytes32,bytes32))").Bytes[..4].ToArray(); public static readonly Address GoldenTouchAccount = new("0x0000777735367b36bC9B61C50022d9D0700dB4Ec"); private const long AnchorGasLimit = 250_000; - private const long AnchorV3GasLimit = 1_000_000; + private const long AnchorV3V4GasLimit = 1_000_000; protected override bool ValidateEip4844Fields(Block block, IReleaseSpec spec, ref string? error) => true; // No blob transactions are expected, covered by ValidateTransactions also @@ -65,7 +66,8 @@ private bool ValidateAnchorTransaction(Transaction tx, Block block, ITaikoReleas if (tx.Data.Length == 0 || (!AnchorSelector.AsSpan().SequenceEqual(tx.Data.Span[..4]) && !AnchorV2Selector.AsSpan().SequenceEqual(tx.Data.Span[..4]) - && !AnchorV3Selector.AsSpan().SequenceEqual(tx.Data.Span[..4]))) + && !AnchorV3Selector.AsSpan().SequenceEqual(tx.Data.Span[..4]) + && !AnchorV4Selector.AsSpan().SequenceEqual(tx.Data.Span[..4]))) { errorMessage = "Anchor transaction must have valid selector"; return false; @@ -77,7 +79,7 @@ private bool ValidateAnchorTransaction(Transaction tx, Block block, ITaikoReleas return false; } - if (tx.GasLimit != (spec.IsPacayaEnabled ? AnchorV3GasLimit : AnchorGasLimit)) + if (tx.GasLimit != (spec.IsPacayaEnabled || spec.IsShastaEnabled ? AnchorV3V4GasLimit : AnchorGasLimit)) { errorMessage = "Anchor transaction must have correct gas limit"; return false; diff --git a/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs b/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs index 76801ec8841..7afbdbeeb35 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs @@ -9,4 +9,10 @@ namespace Nethermind.Taiko; internal static class TaikoHeaderHelper { public static byte? DecodeOntakeExtraData(this BlockHeader header) => header.ExtraData is { Length: >= 32 } ? Math.Min(header.ExtraData[31], (byte)100) : null; + + // Two bytes encoded in the extra data for Shasta + // - First byte: basefeeSharingPctg + // - Second byte: isLowBondProposal (lowest bit) + // Returns only the basefeeSharingPctg + public static byte? DecodeShastaExtraData(this BlockHeader header) => header.ExtraData is not { Length: >= 2 } ? null : header.ExtraData[0]; } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs b/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs index 0236e250e18..0b0cbdab48d 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs @@ -1,13 +1,16 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Blockchain; using Nethermind.Consensus; using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Messages; using Nethermind.Core.Specs; +using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Taiko.TaikoSpec; namespace Nethermind.Taiko; @@ -15,13 +18,124 @@ public class TaikoHeaderValidator( IBlockTree? blockTree, ISealValidator? sealValidator, ISpecProvider? specProvider, - ILogManager? logManager) : HeaderValidator(blockTree, sealValidator, specProvider, logManager) + ILogManager? logManager) + : HeaderValidator(blockTree, sealValidator, specProvider, logManager) { + // EIP-4396 calculation parameters. + private const ulong BlockTimeTarget = 2; + private const ulong MaxGasTargetPercentage = 95; + + private static readonly UInt256 ShastaInitialBaseFee = 25_000_000; + private static readonly UInt256 MinBaseFeeShasta = 5_000_000; + private static readonly UInt256 MaxBaseFeeShasta = 1_000_000_000; + protected override bool ValidateGasLimitRange(BlockHeader header, BlockHeader parent, IReleaseSpec spec, ref string? error) => true; protected override bool Validate1559(BlockHeader header, BlockHeader parent, IReleaseSpec spec, ref string? error) { - return !header.BaseFeePerGas.IsZero; + if (header.BaseFeePerGas.IsZero) + { + error = "BaseFee cannot be zero"; + return false; + } + + var taikoSpec = (ITaikoReleaseSpec)spec; + if (taikoSpec.IsShastaEnabled) + { + return ValidateEip4396Header(header, parent, spec, ref error); + } + + return true; + } + + private bool ValidateEip4396Header(BlockHeader header, BlockHeader parent, IReleaseSpec spec, ref string? error) + { + // Get parent block time (time difference between parent and grandparent) + ulong parentBlockTime = 0; + if (header.Number > 1) + { + BlockHeader? grandParent = _blockTree?.FindHeader(parent.ParentHash!, BlockTreeLookupOptions.None); + if (grandParent is null) + { + error = $"Ancestor block not found for parent {parent.ParentHash}"; + if (_logger.IsWarn) _logger.Warn($"Invalid block header ({header.Hash}) - {error}"); + return false; + } + parentBlockTime = parent.Timestamp - grandParent.Timestamp; + } + + // Calculate expected base fee using EIP-4396 + UInt256 expectedBaseFee = CalculateEip4396BaseFee(parent, parentBlockTime, spec); + + if (header.BaseFeePerGas != expectedBaseFee) + { + error = $"Invalid baseFee: have {header.BaseFeePerGas}, want {expectedBaseFee}, " + + $"parentBaseFee {parent.BaseFeePerGas}, parentGasUsed {parent.GasUsed}, parentBlockTime {parentBlockTime}"; + if (_logger.IsWarn) _logger.Warn($"Invalid block header ({header.Hash}) - {error}"); + return false; + } + + return true; + } + + private static UInt256 CalculateEip4396BaseFee(BlockHeader parent, ulong parentBlockTime, IReleaseSpec spec) + { + // If the parent is genesis, use the initial base fee for the first post-genesis block + if (parent.Number == 0) + { + return ShastaInitialBaseFee; + } + + IEip1559Spec eip1559Spec = spec; + ulong parentGasTarget = (ulong)(parent.GasLimit / eip1559Spec.ElasticityMultiplier); + ulong parentAdjustedGasTarget = Math.Min(parentGasTarget * parentBlockTime / BlockTimeTarget, + (ulong)parent.GasLimit * MaxGasTargetPercentage / 100); + + // If the parent gasUsed is the same as the adjusted target, the baseFee remains unchanged + if ((ulong)parent.GasUsed == parentAdjustedGasTarget) + { + return parent.BaseFeePerGas; + } + + UInt256 baseFee; + UInt256 baseFeeChangeDenominator = eip1559Spec.BaseFeeMaxChangeDenominator; + + if ((ulong)parent.GasUsed > parentAdjustedGasTarget) + { + // If the parent block used more gas than its target, the baseFee should increase + // max(1, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator) + UInt256 gasUsedDelta = (ulong)parent.GasUsed - parentAdjustedGasTarget; + UInt256 feeDelta = parent.BaseFeePerGas * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator; + + if (feeDelta < 1) + { + feeDelta = 1; + } + + baseFee = parent.BaseFeePerGas + feeDelta; + } + else + { + // Otherwise if the parent block used less gas than its target, the baseFee should decrease + // max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator) + UInt256 gasUsedDelta = parentAdjustedGasTarget - (ulong)parent.GasUsed; + UInt256 feeDelta = parent.BaseFeePerGas * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator; + + baseFee = parent.BaseFeePerGas > feeDelta ? parent.BaseFeePerGas - feeDelta : UInt256.Zero; + } + + // Clamp the base fee to be within min and max limits for Shasta blocks + return ClampEip4396BaseFeeShasta(baseFee); + } + + private static UInt256 ClampEip4396BaseFeeShasta(UInt256 baseFee) + { + if (baseFee < MinBaseFeeShasta) + { + return MinBaseFeeShasta; + } + + return baseFee > MaxBaseFeeShasta ? MaxBaseFeeShasta : baseFee; } protected override bool ValidateTimestamp(BlockHeader header, BlockHeader parent, ref string? error) diff --git a/src/Nethermind/Nethermind.Taiko/TaikoPayloadPreparationService.cs b/src/Nethermind/Nethermind.Taiko/TaikoPayloadPreparationService.cs index 583156ab26e..15fbe045831 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoPayloadPreparationService.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoPayloadPreparationService.cs @@ -59,6 +59,12 @@ public class TaikoPayloadPreparationService( if (!l1Origin.IsPreconfBlock) { l1OriginStore.WriteHeadL1Origin(l1Origin.BlockId); + + // Write the batch to block mapping if the batch ID is given. + if (attrs.BlockMetadata?.BatchID is not null) + { + l1OriginStore.WriteBatchToLastBlockID(attrs.BlockMetadata.BatchID.Value, l1Origin.BlockId); + } } // ignore TryAdd failure (it can only happen if payloadId is already in the dictionary) diff --git a/src/Nethermind/Nethermind.Taiko/TaikoSpec/ITaikoReleaseSpec.cs b/src/Nethermind/Nethermind.Taiko/TaikoSpec/ITaikoReleaseSpec.cs index e82cb75209f..14ce81ac0a9 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoSpec/ITaikoReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoSpec/ITaikoReleaseSpec.cs @@ -10,6 +10,7 @@ public interface ITaikoReleaseSpec : IReleaseSpec { public bool IsOntakeEnabled { get; } public bool IsPacayaEnabled { get; } + public bool IsShastaEnabled { get; } public bool UseSurgeGasPriceOracle { get; } public Address TaikoL2Address { get; } } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoCancunReleaseSpec.cs b/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoCancunReleaseSpec.cs index 47ed268fd4b..240e17776a1 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoCancunReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoCancunReleaseSpec.cs @@ -8,26 +8,21 @@ namespace Nethermind.Taiko.TaikoSpec; public class TaikoOntakeReleaseSpec : Cancun, ITaikoReleaseSpec { - - public TaikoOntakeReleaseSpec() - { - IsOntakeEnabled = true; - IsPacayaEnabled = false; - } + public TaikoOntakeReleaseSpec() => IsOntakeEnabled = true; public bool IsOntakeEnabled { get; set; } public bool IsPacayaEnabled { get; set; } + public bool IsShastaEnabled { get; set; } public bool UseSurgeGasPriceOracle { get; set; } public Address TaikoL2Address { get; set; } = new("0x1670000000000000000000000000000000010001"); } -public class TaikoPacayaReleaseSpec : TaikoOntakeReleaseSpec, ITaikoReleaseSpec +public class TaikoPacayaReleaseSpec : TaikoOntakeReleaseSpec { + public TaikoPacayaReleaseSpec() => IsPacayaEnabled = true; +} - public TaikoPacayaReleaseSpec() - { - IsOntakeEnabled = true; - IsPacayaEnabled = true; - } - +public class TaikoShastaReleaseSpec : TaikoPacayaReleaseSpec +{ + public TaikoShastaReleaseSpec() => IsShastaEnabled = true; } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoChainSpecBasedSpecProvider.cs b/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoChainSpecBasedSpecProvider.cs index 56d5e791c49..6e426f06200 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoChainSpecBasedSpecProvider.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoChainSpecBasedSpecProvider.cs @@ -24,6 +24,7 @@ protected override ReleaseSpec CreateReleaseSpec(ChainSpec chainSpec, long relea releaseSpec.IsOntakeEnabled = (chainSpecEngineParameters.OntakeTransition ?? long.MaxValue) <= releaseStartBlock; releaseSpec.IsPacayaEnabled = (chainSpecEngineParameters.PacayaTransition ?? long.MaxValue) <= releaseStartBlock; + releaseSpec.IsShastaEnabled = (chainSpecEngineParameters.ShastaTimestamp ?? ulong.MaxValue) <= releaseStartTimestamp; releaseSpec.UseSurgeGasPriceOracle = chainSpecEngineParameters.UseSurgeGasPriceOracle ?? false; releaseSpec.TaikoL2Address = chainSpecEngineParameters.TaikoL2Address; diff --git a/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoChainSpecEngineParameters.cs b/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoChainSpecEngineParameters.cs index 127e790b9f0..408b7b48ed4 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoChainSpecEngineParameters.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoChainSpecEngineParameters.cs @@ -13,6 +13,7 @@ public class TaikoChainSpecEngineParameters : IChainSpecEngineParameters public string SealEngineType => Core.SealEngineType.Taiko; public long? OntakeTransition { get; set; } public long? PacayaTransition { get; set; } + public ulong? ShastaTimestamp { get; set; } public bool? UseSurgeGasPriceOracle { get; set; } public Address TaikoL2Address { get; set; } = new("0x1670000000000000000000000000000000010001"); @@ -28,5 +29,10 @@ public void AddTransitions(SortedSet blockNumbers, SortedSet timest { blockNumbers.Add(PacayaTransition.Value); } + + if (ShastaTimestamp is not null) + { + timestamps.Add(ShastaTimestamp.Value); + } } } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoReleaseSpec.cs b/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoReleaseSpec.cs index 7cbd49af327..db9b697f23e 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoSpec/TaikoReleaseSpec.cs @@ -10,6 +10,7 @@ public class TaikoReleaseSpec : ReleaseSpec, ITaikoReleaseSpec { public bool IsOntakeEnabled { get; set; } public bool IsPacayaEnabled { get; set; } + public bool IsShastaEnabled { get; set; } public bool UseSurgeGasPriceOracle { get; set; } public required Address TaikoL2Address { get; set; } } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs b/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs index 51806561bc3..1803ccf25fc 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs @@ -59,9 +59,10 @@ protected override void PayFees(Transaction tx, BlockHeader header, IReleaseSpec if (!tx.IsAnchorTx && !baseFees.IsZero && spec.FeeCollector is not null) { - if (((ITaikoReleaseSpec)spec).IsOntakeEnabled) + var taikoSpec = (ITaikoReleaseSpec)spec; + if (taikoSpec.IsOntakeEnabled || taikoSpec.IsShastaEnabled) { - byte basefeeSharingPct = header.DecodeOntakeExtraData() ?? 0; + byte basefeeSharingPct = (taikoSpec.IsShastaEnabled ? header.DecodeShastaExtraData() : header.DecodeOntakeExtraData()) ?? 0; UInt256 feeCoinbase = baseFees * basefeeSharingPct / 100; From 66986e575ebbe23afe7f3c68720562572523cb82 Mon Sep 17 00:00:00 2001 From: bigbear <155267841+aso20455@users.noreply.github.com> Date: Thu, 4 Dec 2025 14:03:13 +0200 Subject: [PATCH 054/255] fix: invert post-merge difficulty validation logic in T8n tool (#9880) --- tools/Evm/T8n/T8nValidator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/Evm/T8n/T8nValidator.cs b/tools/Evm/T8n/T8nValidator.cs index 4f0b18f5016..b66d85fe9a2 100644 --- a/tools/Evm/T8n/T8nValidator.cs +++ b/tools/Evm/T8n/T8nValidator.cs @@ -68,7 +68,7 @@ private static void ApplyMergeChecks(EnvJson env, ISpecProvider specProvider) if (env.CurrentRandom is null) throw new T8nException("post-merge requires currentRandom to be defined in env", T8nErrorCodes.ErrorConfig); - if (env.CurrentDifficulty?.IsZero ?? false) + if (env.CurrentDifficulty is not null && !env.CurrentDifficulty.Value.IsZero) throw new T8nException("post-merge difficulty must be zero (or omitted) in env", T8nErrorCodes.ErrorConfig); return; From 6a64fd977dd995ff738c7aa98d5e70ea3ee3dbe6 Mon Sep 17 00:00:00 2001 From: Roheemah <60899500+AbolareRoheemah@users.noreply.github.com> Date: Thu, 4 Dec 2025 14:23:55 +0100 Subject: [PATCH 055/255] Changed default PublicKey serialization to use hash format (#9696) * Changed default PublicKey serialization to use hash format * Added tests for PublicKey serialization format changes * removed comments, parsed JSON properly, fixed naming convention * Added regression tests for PublicKey serialization changes * removed previous combined test file * updated regression tests to verify byte content produced by each converter * removed linq skip and take * removed tests that validate unsupported inputs * ran dotnet format --------- Co-authored-by: Stavros Vlachakis <89769224+svlachakis@users.noreply.github.com> --- .../Nethermind.Core/Crypto/PublicKey.cs | 2 +- .../BidTraceSerializationTests.cs | 47 +++++++++++++++++++ .../Nethermind.Flashbots/Data/BidTrace.cs | 3 ++ .../Modules/AdminModuleTests.cs | 27 +++++++++++ .../Modules/ParityRpcModuleTests.cs | 24 ++++++++++ .../Modules/Admin/PeerInfo.cs | 1 - .../Modules/Parity/ParityTransaction.cs | 2 + .../Modules/Subscribe/PeerAddDropResponse.cs | 1 - .../Modules/Subscribe/PeerEventResponse.cs | 1 - .../EthereumJsonSerializer.cs | 2 +- 10 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 src/Nethermind/Nethermind.Flashbots.Test/BidTraceSerializationTests.cs diff --git a/src/Nethermind/Nethermind.Core/Crypto/PublicKey.cs b/src/Nethermind/Nethermind.Core/Crypto/PublicKey.cs index c76225ffdc8..b176616eb2b 100644 --- a/src/Nethermind/Nethermind.Core/Crypto/PublicKey.cs +++ b/src/Nethermind/Nethermind.Core/Crypto/PublicKey.cs @@ -10,7 +10,7 @@ namespace Nethermind.Core.Crypto { - [JsonConverter(typeof(PublicKeyConverter))] + [JsonConverter(typeof(PublicKeyHashedConverter))] public class PublicKey : IEquatable { public const int PrefixedLengthInBytes = 65; diff --git a/src/Nethermind/Nethermind.Flashbots.Test/BidTraceSerializationTests.cs b/src/Nethermind/Nethermind.Flashbots.Test/BidTraceSerializationTests.cs new file mode 100644 index 00000000000..1f3bc928097 --- /dev/null +++ b/src/Nethermind/Nethermind.Flashbots.Test/BidTraceSerializationTests.cs @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Text.Json; +using FluentAssertions; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; +using Nethermind.Flashbots.Data; +using Nethermind.Serialization.Json; +using NUnit.Framework; + +namespace Nethermind.Flashbots.Test +{ + [TestFixture] + public class BidTraceSerializationTests + { + private readonly EthereumJsonSerializer _serializer = new(); + + [Test] + public void BidTrace_WithFullPublicKeysJson_DeserializesSuccessfully() + { + const string builderKey = "a49ac7010c2e0a444dfeeabadbafa4856ba4a2d732acb86d20c577b3b365f52e5a8728693008d97ae83d51194f273455acf1a30e6f3926aefaede484c07d8ec3"; + const string proposerKey = "b49ac7010c2e0a444dfeeabadbafa4856ba4a2d732acb86d20c577b3b365f52e5a8728693008d97ae83d51194f273455acf1a30e6f3926aefaede484c07d8ec4"; + byte[] builderKeyBytes = Bytes.FromHexString(builderKey); + byte[] proposerKeyBytes = Bytes.FromHexString(proposerKey); + + string fullKeyJson = $$""" + { + "slot": 12345, + "builder_public_key": "0x{{builderKey}}", + "proposer_public_key": "0x{{proposerKey}}", + "value": "1000000000000000000" + } + """; + + BidTrace trace = _serializer.Deserialize(fullKeyJson); + + trace.BuilderPublicKey.Should().NotBeNull(); + trace.ProposerPublicKey.Should().NotBeNull(); + trace.BuilderPublicKey.Bytes.Length.Should().Be(64); + trace.ProposerPublicKey.Bytes.Length.Should().Be(64); + trace.BuilderPublicKey.Bytes.Should().BeEquivalentTo(builderKeyBytes); + trace.ProposerPublicKey.Bytes.Should().BeEquivalentTo(proposerKeyBytes); + } + } +} diff --git a/src/Nethermind/Nethermind.Flashbots/Data/BidTrace.cs b/src/Nethermind/Nethermind.Flashbots/Data/BidTrace.cs index e27ca437a8a..2af6ac9c37d 100644 --- a/src/Nethermind/Nethermind.Flashbots/Data/BidTrace.cs +++ b/src/Nethermind/Nethermind.Flashbots/Data/BidTrace.cs @@ -4,6 +4,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; +using Nethermind.Serialization.Json; namespace Nethermind.Flashbots.Data; @@ -21,9 +22,11 @@ public class BidTrace public Hash256 BlockHash { get; set; } [JsonPropertyName("builder_public_key")] + [JsonConverter(typeof(PublicKeyConverter))] public PublicKey BuilderPublicKey { get; set; } [JsonPropertyName("proposer_public_key")] + [JsonConverter(typeof(PublicKeyConverter))] public PublicKey ProposerPublicKey { get; set; } [JsonPropertyName("proposer_fee_recipient")] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs index cb64343d7e7..7ae6ebfb56b 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs @@ -13,6 +13,7 @@ using Nethermind.Config; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.JsonRpc.Modules; using Nethermind.JsonRpc.Modules.Admin; @@ -743,4 +744,30 @@ public void Admin_peers_supports_legacy_eth_versions() peerInfo.Protocols.Should().NotContainKey("snap"); // Old versions don't support snap } + [Test] + public void PeerInfo_WithHashedPublicKeyJson_DeserializesSuccessfully() + { + const string fullKeyHex = "a49ac7010c2e0a444dfeeabadbafa4856ba4a2d732acb86d20c577b3b365f52e5a8728693008d97ae83d51194f273455acf1a30e6f3926aefaede484c07d8ec3"; + byte[] fullPublicKeyBytes = Bytes.FromHexString(fullKeyHex); + byte[] expectedHashBytes = Keccak.Compute(fullPublicKeyBytes).Bytes.ToArray(); + string expectedHashHex = Convert.ToHexString(expectedHashBytes).ToLower(); + + string json = $$""" + { + "id": "0x{{expectedHashHex}}", + "name": "test-peer", + "enode": "enode://{{fullKeyHex}}@127.0.0.1:30303", + "caps": [], + "network": { "localAddress": "127.0.0.1", "remoteAddress": "127.0.0.1:30303" }, + "protocols": { "eth": { "version": 0 } } + } + """; + + EthereumJsonSerializer serializer = new(); + PeerInfo peerInfo = serializer.Deserialize(json); + + peerInfo.Id.Should().NotBeNull(); + peerInfo.Id.Bytes.Length.Should().Be(64); + peerInfo.Id.Bytes.AsSpan(32, 32).ToArray().Should().BeEquivalentTo(expectedHashBytes); + } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs index 54aa2244d4f..54da5ec75d8 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs @@ -5,6 +5,7 @@ using System.IO; using System.Net; using System.Threading.Tasks; +using System.Text.Json; using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; @@ -15,6 +16,7 @@ using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Test; using Nethermind.Specs; using Nethermind.Core.Test.Builders; @@ -36,6 +38,7 @@ using System; using Nethermind.Core.Test.Db; using Nethermind.State; +using Nethermind.Serialization.Json; namespace Nethermind.JsonRpc.Test.Modules { @@ -375,5 +378,26 @@ public async Task parity_netPeers_null_ActivePeers() string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":{\"active\":0,\"connected\":0,\"max\":0,\"peers\":[]},\"id\":67}"; Assert.That(serialized, Is.EqualTo(expectedResult)); } + + [Test] + public void ParityTransaction_WithFullPublicKeyJson_DeserializesSuccessfully() + { + const string fullKeyHex = "a49ac7010c2e0a444dfeeabadbafa4856ba4a2d732acb86d20c577b3b365f52e5a8728693008d97ae83d51194f273455acf1a30e6f3926aefaede484c07d8ec3"; + byte[] fullPublicKeyBytes = Bytes.FromHexString(fullKeyHex); + + string json = $$""" + { + "publicKey": "0x{{fullKeyHex}}", + "hash": "0xd4720d1b81c70ed4478553a213a83bd2bf6988291677f5d05c6aae0b287f947e" + } + """; + + EthereumJsonSerializer serializer = new(); + ParityTransaction tx = serializer.Deserialize(json); + + tx.PublicKey.Should().NotBeNull(); + tx.PublicKey.Bytes.Length.Should().Be(64); + tx.PublicKey.Bytes.Should().BeEquivalentTo(fullPublicKeyBytes); + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/PeerInfo.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/PeerInfo.cs index 230767bb7dc..58998ca48f5 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/PeerInfo.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/PeerInfo.cs @@ -19,7 +19,6 @@ public class PeerInfo public string Enode { get; set; } = string.Empty; - [JsonConverter(typeof(PublicKeyHashedConverter))] public PublicKey Id { get; set; } = null!; public string? Name { get; set; } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/ParityTransaction.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/ParityTransaction.cs index 5aeb8b1d20a..5d31454d193 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/ParityTransaction.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/ParityTransaction.cs @@ -8,6 +8,7 @@ using Nethermind.Core.Extensions; using Nethermind.Int256; using Nethermind.Evm; +using Nethermind.Serialization.Json; namespace Nethermind.JsonRpc.Modules.Parity { @@ -31,6 +32,7 @@ public class ParityTransaction public byte[] Raw { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public Address Creates { get; set; } + [JsonConverter(typeof(PublicKeyConverter))] public PublicKey PublicKey { get; set; } public ulong? ChainId { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.Never)] diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerAddDropResponse.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerAddDropResponse.cs index 0a86ec1810d..fe66e540eea 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerAddDropResponse.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerAddDropResponse.cs @@ -19,7 +19,6 @@ public PeerAddDropResponse(PeerInfo peerInfo, string subscriptionType, string? e [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string Type { get; set; } - [JsonConverter(typeof(PublicKeyHashedConverter))] public PublicKey Peer { get; set; } public string Local { get; set; } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerEventResponse.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerEventResponse.cs index 1147d50ff00..6083a13d1d4 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerEventResponse.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerEventResponse.cs @@ -14,7 +14,6 @@ public class PeerEventResponse { [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? Type { get; set; } - [JsonConverter(typeof(PublicKeyHashedConverter))] public PublicKey? Peer { get; set; } public string? Protocol { get; set; } public int? MsgPacketType { get; set; } diff --git a/src/Nethermind/Nethermind.Serialization.Json/EthereumJsonSerializer.cs b/src/Nethermind/Nethermind.Serialization.Json/EthereumJsonSerializer.cs index 787c0ad40c3..3f3e5ea4eea 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/EthereumJsonSerializer.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/EthereumJsonSerializer.cs @@ -94,8 +94,8 @@ private static JsonSerializerOptions CreateOptions(bool indented, IEnumerable Date: Thu, 4 Dec 2025 16:28:43 +0100 Subject: [PATCH 056/255] Fix Jovian fork id (#9877) * Fix Jovian fork id * Add test * Fix Base Mainnet test * Formatting --------- Co-authored-by: Lautaro Emanuel --- .../Nethermind.Network.Test/ForkInfoTests.cs | 6 +++--- src/Nethermind/Nethermind.Network/ForkId.cs | 12 +++--------- .../Nethermind.Optimism.Test/ForkInfoTests.cs | 19 +++++++++++++++++++ .../Nethermind.Optimism.Test.csproj | 1 + .../OptimismChainSpecEngineParameters.cs | 14 ++++++++++++++ 5 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 src/Nethermind/Nethermind.Optimism.Test/ForkInfoTests.cs diff --git a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs index a8f77e3b9e9..6095b4a9224 100644 --- a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs @@ -370,13 +370,13 @@ public void Chain_id_and_network_id_have_proper_default_values(ulong? specNetwor provider.NetworkId.Should().Be(expectedNetworkId); } - private static void Test(long head, ulong headTimestamp, Hash256 genesisHash, string forkHashHex, ulong next, string description, ISpecProvider specProvider, string chainSpec, string path = "../../../../Chains") + public static void Test(long head, ulong headTimestamp, Hash256 genesisHash, string forkHashHex, ulong next, string description, ISpecProvider specProvider, string chainSpec, string path = "../../../../Chains") { Test(head, headTimestamp, genesisHash, forkHashHex, next, description, specProvider); Test(head, headTimestamp, genesisHash, forkHashHex, next, description, chainSpec, path); } - private static void Test(long head, ulong headTimestamp, Hash256 genesisHash, string forkHashHex, ulong next, string description, string chainSpec, string path = "../../../../Chains") + public static void Test(long head, ulong headTimestamp, Hash256 genesisHash, string forkHashHex, ulong next, string description, string chainSpec, string path = "../../../../Chains") { var loader = new ChainSpecFileLoader(new EthereumJsonSerializer(), LimboTraceLogger.Instance); ChainSpec spec = loader.LoadEmbeddedOrFromFile(Path.Combine(path, chainSpec)); @@ -386,7 +386,7 @@ private static void Test(long head, ulong headTimestamp, Hash256 genesisHash, st private static void Test(long head, ulong headTimestamp, Hash256 genesisHash, string forkHashHex, ulong next, string description, ISpecProvider specProvider) { - uint expectedForkHash = Bytes.ReadEthUInt32(Bytes.FromHexString(forkHashHex)); + uint expectedForkHash = Bytes.FromHexString(forkHashHex).ReadEthUInt32(); ISyncServer syncServer = Substitute.For(); syncServer.Genesis.Returns(Build.A.BlockHeader.WithHash(genesisHash).TestObject); diff --git a/src/Nethermind/Nethermind.Network/ForkId.cs b/src/Nethermind/Nethermind.Network/ForkId.cs index e1481984bcc..2f740229ab9 100644 --- a/src/Nethermind/Nethermind.Network/ForkId.cs +++ b/src/Nethermind/Nethermind.Network/ForkId.cs @@ -7,17 +7,11 @@ namespace Nethermind.Network { - public readonly struct ForkId : IEquatable + public readonly struct ForkId(uint forkHash, ulong next) : IEquatable { - public ForkId(uint forkHash, ulong next) - { - ForkHash = forkHash; - Next = next; - } - - public uint ForkHash { get; } + public uint ForkHash { get; } = forkHash; - public ulong Next { get; } + public ulong Next { get; } = next; public byte[] HashBytes { diff --git a/src/Nethermind/Nethermind.Optimism.Test/ForkInfoTests.cs b/src/Nethermind/Nethermind.Optimism.Test/ForkInfoTests.cs new file mode 100644 index 00000000000..4daa3d1c09e --- /dev/null +++ b/src/Nethermind/Nethermind.Optimism.Test/ForkInfoTests.cs @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core.Crypto; +using NUnit.Framework; + +namespace Nethermind.Optimism.Test; + +public class ForkInfoTests +{ + private static readonly Hash256 BaseMainnetGenesis = new("0xf712aa9241cc24369b143cf6dce85f0902a9731e70d66818a3a5845b296c73dd"); + + [TestCase(38_950_927, 1_764_691_201ul, "0x1cfeafc9", 0ul, "Base Mainnet - Jovian")] + public void Fork_id_and_hash_as_expected(long head, ulong headTimestamp, string forkHashHex, ulong next, string description) + { + Network.Test.ForkInfoTests.Test(head, headTimestamp, BaseMainnetGenesis, forkHashHex, next, description, "base-mainnet.json.zst"); + } + +} diff --git a/src/Nethermind/Nethermind.Optimism.Test/Nethermind.Optimism.Test.csproj b/src/Nethermind/Nethermind.Optimism.Test/Nethermind.Optimism.Test.csproj index 4cdd5dc0f59..97b69e3b902 100644 --- a/src/Nethermind/Nethermind.Optimism.Test/Nethermind.Optimism.Test.csproj +++ b/src/Nethermind/Nethermind.Optimism.Test/Nethermind.Optimism.Test.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Nethermind/Nethermind.Optimism/OptimismChainSpecEngineParameters.cs b/src/Nethermind/Nethermind.Optimism/OptimismChainSpecEngineParameters.cs index 25d9701e25f..7ae4fe2f594 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismChainSpecEngineParameters.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismChainSpecEngineParameters.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Int256; using Nethermind.Specs; @@ -54,4 +55,17 @@ public void ApplyToReleaseSpec(ReleaseSpec spec, long startBlock, ulong? startTi spec.BaseFeeCalculator = new OptimismBaseFeeCalculator(HoloceneTimestamp, JovianTimestamp, new DefaultBaseFeeCalculator()); } + + public void AddTransitions(SortedSet blockNumbers, SortedSet timestamps) + { + AddIfNotNull(timestamps, JovianTimestamp); + } + + private void AddIfNotNull(SortedSet timestamps, ulong? timestamp) + { + if (timestamp is not null) + { + timestamps.Add(timestamp.Value); + } + } } From 7b9226589c473c51b329b298e3067a995c713daf Mon Sep 17 00:00:00 2001 From: Fibonacci747 Date: Thu, 4 Dec 2025 22:00:48 +0100 Subject: [PATCH 057/255] fix: tie readonly DB provider to env lifetime and clear per-scope buffers (#9883) --- .../Simulate/SimulateReadOnlyBlocksProcessingEnv.cs | 2 +- .../Simulate/SimulateReadOnlyBlocksProcessingEnvFactory.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs index e779fa4dd8d..73a52a531f5 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs @@ -62,6 +62,6 @@ IDisposable overridableWorldStateCloser public void Dispose() { overridableWorldStateCloser.Dispose(); - readOnlyDbProvider.Dispose(); // For blocktree. The read only db has a buffer that need to be cleared. + readOnlyDbProvider.ClearTempChanges(); // For blocktree. The read only db has a buffer that need to be cleared. } } diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnvFactory.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnvFactory.cs index d32e992a084..74a6a426cb1 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnvFactory.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnvFactory.cs @@ -44,6 +44,7 @@ public ISimulateReadOnlyBlocksProcessingEnv Create() ILifetimeScope envLifetimeScope = rootLifetimeScope.BeginLifetimeScope((builder) => builder .AddModule(overridableEnv) // worldstate related override here + .AddSingleton(editableDbProvider) .AddSingleton(overrideBlockTree) .AddSingleton(overrideBlockTree) .AddSingleton(tmpHeaderStore) @@ -60,6 +61,7 @@ public ISimulateReadOnlyBlocksProcessingEnv Create() .AddScoped() .AddScoped()); + envLifetimeScope.Disposer.AddInstanceForDisposal(editableDbProvider); rootLifetimeScope.Disposer.AddInstanceForAsyncDisposal(envLifetimeScope); return envLifetimeScope.Resolve(); } From d7ad74e88e13cd18a8fe2aec2ba6f05d897087a3 Mon Sep 17 00:00:00 2001 From: Merkel Tranjes <140164174+rnkrtt@users.noreply.github.com> Date: Fri, 5 Dec 2025 13:24:00 +0100 Subject: [PATCH 058/255] fix: remove duplicate EIP-7702 transaction counting in TxPool (#9885) --- src/Nethermind/Nethermind.TxPool/TxPool.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index 727ee2cf41a..98b8fd4da1e 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -404,11 +404,6 @@ private void RemoveProcessedTransactions(Block block) } } - if (blockTx.Type == TxType.SetCode) - { - eip7702Txs++; - } - bool isKnown = IsKnown(txHash); if (!isKnown) { From c43523691f158c7af7a6bfc4446230202497dc94 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Fri, 5 Dec 2025 14:37:39 +0100 Subject: [PATCH 059/255] fix: prevent EVM memory size overflow crash for extreme memory requests (#9887) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: prevent EVM memory size overflow crash for large memory requests The memory validation in CheckMemoryAccessViolation was checking against long.MaxValue, but .NET arrays are limited to int.MaxValue. When memory requests exceeded int.MaxValue but were less than long.MaxValue, the word-aligned size calculation would overflow when cast to int, causing ArrayPool.Rent() to allocate an incorrectly sized array and subsequent Array.Copy operations to crash. This fix changes the limit from long.MaxValue to (int.MaxValue - WordSize + 1) to ensure that after word alignment, the resulting size still fits in int. Root cause: - Memory size validation checked: totalSize > long.MaxValue - But .NET arrays require: (int)Size to be valid - Word alignment adds up to 31 bytes: Size = totalSize + (32 - totalSize % 32) - When totalSize > int.MaxValue - 31, (int)Size overflows Example crash scenario: 1. Contract requests 4GB (0xffffffff) memory via DELEGATECALL 2. Validation passes (4GB < long.MaxValue) 3. Word-aligned Size = 0x100000000 (exceeds int.MaxValue) 4. (int)Size = 0 (overflow) 5. ArrayPool.Rent(0) returns tiny array 6. Array.Copy crashes with "Destination array was not long enough" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude --- .../EvmPooledMemoryTests.cs | 47 ++++++++++++++++++- .../Nethermind.Evm/EvmPooledMemory.cs | 9 +++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs b/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs index 684d35b124c..a9b4d90e875 100644 --- a/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs @@ -54,7 +54,8 @@ public void Div32Ceiling(int input, int expectedResult) [TestCase(100 * MaxCodeSize, MaxCodeSize)] [TestCase(1000 * MaxCodeSize, MaxCodeSize)] [TestCase(0, 1024 * 1024)] - [TestCase(0, Int32.MaxValue)] + // Note: Int32.MaxValue was removed as a test case because after word alignment + // it exceeds the maximum allowed memory size and correctly returns out-of-gas. public void MemoryCost(int destination, int memoryAllocation) { EvmPooledMemory memory = new(); @@ -114,6 +115,50 @@ public void CalculateMemoryCost_TotalSizeExceedsLongMax_ShouldReturnOutOfGas() Assert.That(result, Is.EqualTo(0L)); } + [Test] + public void CalculateMemoryCost_TotalSizeExceedsIntMaxAfterWordAlignment_ShouldReturnOutOfGas() + { + // Test that memory requests that would overflow int.MaxValue after word alignment + // are properly rejected. This prevents crashes in .NET array operations. + // The limit is int.MaxValue - WordSize + 1 to ensure word-aligned size fits in int. + EvmPooledMemory memory = new(); + + // Request exactly at the limit should succeed + UInt256 maxAllowedSize = (UInt256)(int.MaxValue - EvmPooledMemory.WordSize + 1); + long result = memory.CalculateMemoryCost(0, in maxAllowedSize, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(false), "Size at limit should be allowed"); + + // Request one byte over the limit should fail + UInt256 overLimitSize = maxAllowedSize + 1; + result = memory.CalculateMemoryCost(0, in overLimitSize, out outOfGas); + Assert.That(outOfGas, Is.EqualTo(true), "Size over limit should return out of gas"); + Assert.That(result, Is.EqualTo(0L)); + } + + [Test] + public void CalculateMemoryCost_4GBMemoryRequest_ShouldReturnOutOfGas() + { + // Regression test: 4GB memory request (0xffffffff) should return out-of-gas + // instead of causing integer overflow crash in array operations. + EvmPooledMemory memory = new(); + UInt256 size4GB = 0xffffffffUL; + long result = memory.CalculateMemoryCost(0, in size4GB, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(true), "4GB memory request should return out of gas"); + Assert.That(result, Is.EqualTo(0L)); + } + + [Test] + public void CalculateMemoryCost_LargeOffsetPlusLength_ShouldReturnOutOfGas() + { + // Test that location + length exceeding int.MaxValue - WordSize + 1 returns out-of-gas + EvmPooledMemory memory = new(); + UInt256 location = (UInt256)(int.MaxValue / 2); + UInt256 length = (UInt256)(int.MaxValue / 2 + 100); // Sum exceeds limit + long result = memory.CalculateMemoryCost(in location, in length, out bool outOfGas); + Assert.That(outOfGas, Is.EqualTo(true), "Location + length exceeding limit should return out of gas"); + Assert.That(result, Is.EqualTo(0L)); + } + [Test] public void Save_LocationExceedsULong_ShouldReturnOutOfGas() { diff --git a/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs b/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs index 6ac9a8d93d6..81e8e985680 100644 --- a/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs +++ b/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs @@ -84,7 +84,12 @@ private static void CheckMemoryAccessViolation(in UInt256 location, in UInt256 l private static void CheckMemoryAccessViolation(in UInt256 location, ulong length, out ulong newLength, out bool outOfGas) { - if (location.IsLargerThanULong() || length > long.MaxValue) + // Check for overflow and ensure the word-aligned size fits in int. + // Word alignment can add up to 31 bytes, so we use (int.MaxValue - WordSize + 1) as the limit. + // This ensures that after word alignment, the size still fits in int for .NET array operations. + const ulong MaxMemorySize = int.MaxValue - WordSize + 1; + + if (location.IsLargerThanULong() || length > MaxMemorySize) { outOfGas = true; newLength = 0; @@ -92,7 +97,7 @@ private static void CheckMemoryAccessViolation(in UInt256 location, ulong length } ulong totalSize = location.u0 + length; - if (totalSize < location.u0 || totalSize > long.MaxValue) + if (totalSize < location.u0 || totalSize > MaxMemorySize) { outOfGas = true; newLength = 0; From df5690f1ce548ca0788e3de950a2a9edde4f647c Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Sun, 7 Dec 2025 12:18:20 +0100 Subject: [PATCH 060/255] Auto-update fast sync settings (#9893) Co-authored-by: rubo --- src/Nethermind/Nethermind.Runner/configs/base-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/base-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/chiado.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/gnosis.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/joc-testnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sepolia.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-mainnet.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-sepolia.json | 4 ++-- 14 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index e5d9a12deee..9bab05134e1 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 38820000, - "PivotHash": "0xd646e691ac5ea46f05d469d8adc96f654e1904ff8b889bf36379161da9dc02e9" + "PivotNumber": 39130000, + "PivotHash": "0x5e1f71fc2fa3b2e2a004d01a6a1066fcf9f828f71f69401d725eb5bce05249fe" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index be34c860f07..88c56c3faef 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 34330000, - "PivotHash": "0x5b33d1dd55fdf3c9a6fca658dd2cf7aa9a878010bfb86e24fd90a880639f0f63" + "PivotNumber": 34640000, + "PivotHash": "0x1822ac708bf06e8a7e214ea797e8a99eb442cceea06312a9a36762d651458833" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.json b/src/Nethermind/Nethermind.Runner/configs/chiado.json index 62d995d565a..d94a76a99b4 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.json +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.json @@ -18,8 +18,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 19000000, - "PivotHash": "0x72069a43422affcdb22db49db2e0eb898568b1e8b82c59318a9e4b8137f43476", + "PivotNumber": 19110000, + "PivotHash": "0x1a2b7e4f26fb3f6bc8701d5b4f3321a25dcf0fea271df67c2bd8003eb200d16c", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": 10000000000, "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.json b/src/Nethermind/Nethermind.Runner/configs/gnosis.json index b08ef56e8e0..e538528d724 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.json +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.json @@ -14,8 +14,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 43390000, - "PivotHash": "0x775967263553a1bc18f7da358e9859ffeee1df31c856da56a23b2716789b047a", + "PivotNumber": 43510000, + "PivotHash": "0xb0c231db103bc1c2c28810210cb1f5ac7c616961ddcd819f261c45d8226d3ede", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000, diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json index b2a50e6313e..dee58f28777 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 20960000, - "PivotHash": "0x5989b4e69e1451575bc72c0061df585f4bfaf95e9e589132086f3b995eedde7a", - "PivotTotalDifficulty": "37942677" + "PivotNumber": 21080000, + "PivotHash": "0xfaaf1341b252eda3a70d64139e2edd1b641ef504afff90310754f2cb9661c6f6", + "PivotTotalDifficulty": "38120722" }, "Metrics": { "NodeName": "JOC-Mainnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json index b028c906d13..f23c07463ee 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 14560000, - "PivotHash": "0x263ac3329ed5026ef50f19c8441d53b0a90749c2dc0afc7f0238efedbf8a7109", - "PivotTotalDifficulty": "24285335" + "PivotNumber": 14690000, + "PivotHash": "0x06781f796eec24970262644da990616ce0f9f0e449e32df4e2cc982303b42bb9", + "PivotTotalDifficulty": "24493309" }, "Metrics": { "NodeName": "JOC-Testnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json index 756fb530922..7d58e8611b9 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 26160000, - "PivotHash": "0x84f64864c83be7cc01902ca7148f505a31dd1c7329995392edfadd232bae790d", + "PivotNumber": 26400000, + "PivotHash": "0x9cbdfb4d6b40b5ca8517df5fb100f6711e0c43af6be981727faafb72282ed866", "PivotTotalDifficulty": "0", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json index 012fe3ab716..7cd20b04b50 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 21380000, - "PivotHash": "0x030d6393c66a0c209b0a00eb7ed02c22331466c4636d915c4d47cb25bdbaa627", + "PivotNumber": 21680000, + "PivotHash": "0xc14a4e4e9fd62815e6abbda005130819da527f4dc275ea2de6b30a424b656577", "PivotTotalDifficulty": "37331807", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index 8adaa804f4c..e9048e20466 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -10,8 +10,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 23906000, - "PivotHash": "0x9b144715d2cb04ed968418c7432b131a9a6592834bc7b4fe3a8073e2ef46e9a1", + "PivotNumber": 23956000, + "PivotHash": "0x6ddc4344e36743b3b11796c1e13cdf6ec1ce3a641213a2a0aa7edbde9d3f9e63", "PivotTotalDifficulty": "58750003716598352816469", "FastSyncCatchUpHeightDelta": "10000000000", "AncientReceiptsBarrier": 15537394, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index 9c852560784..ab48ee25c3d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -15,8 +15,8 @@ "FastSyncCatchUpHeightDelta": "10000000000", "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, - "PivotNumber": 144420000, - "PivotHash": "0xefbea42290af475ab67e48d84f0d7a25b7ce6a1a7f82fdc9800dd6a99c50f502" + "PivotNumber": 144720000, + "PivotHash": "0xe287883dee7b3da078899167050d8cfe83510fd93c9a724c5bd1a71e72c3e39f" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index 60decde1508..9aec40a1439 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 36320000, - "PivotHash": "0x0ff5d1fb43adf5c47335f2378ee9dc8cc9c3c0cb5e3111d260cc5000da0c3eea" + "PivotNumber": 36620000, + "PivotHash": "0xa26b5e8265d105fede699b2d57b61a3002376f999d04a0107485258311f2f65f" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index 8db46fe746a..d8db446f4ca 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -17,8 +17,8 @@ "FastSync": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 9733000, - "PivotHash": "0x2ee122331c383d2efa6d427802a10bfb9afbbb4c913e4bb7056b56ee02d09cf7", + "PivotNumber": 9784000, + "PivotHash": "0x725e962b74cb04b27676159b5ed082831530eb6d2655473b6b0af58b1a75a6f3", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 1450409, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index 666e9ae74e2..68bfb4ace4d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 22550000, - "PivotHash": "0x00eda4a81030e7858a2b147067e5da68e9435f79bdb9566086d069a8c49084f3" + "PivotNumber": 22850000, + "PivotHash": "0xb7e7b846b1855020a04783e2b39c591f867d26cb6f47241598266c38409698f2" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index b6c7d6b7a0f..9d8e1e82cdf 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 21940000, - "PivotHash": "0x116346ef68ad36a4bf58abb5824464767616c92ed89c6997b9e4aa4d6662ec57" + "PivotNumber": 22250000, + "PivotHash": "0xe329fa3d71109b1a73bc8c53e1318a2f62816c4ddab9088b8138cdd42d3fe171" }, "Discovery": { "DiscoveryVersion": "V5" From 959d261e8a5a2a2f6360d802b55c7e594f27c6fc Mon Sep 17 00:00:00 2001 From: Snezhkko Date: Sun, 7 Dec 2025 13:18:32 +0200 Subject: [PATCH 061/255] fix: map InvalidBlockRangeUpdate to BreachOfProtocol (#9891) --- .../Nethermind.Network.Stats/Model/DisconnectReason.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs b/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs index 10b773a3b29..c14265ea159 100644 --- a/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs +++ b/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs @@ -92,7 +92,7 @@ public static EthDisconnectReason ToEthDisconnectReason(this DisconnectReason di DisconnectReason.ForwardSyncFailed => EthDisconnectReason.DisconnectRequested, DisconnectReason.GossipingInPoS => EthDisconnectReason.BreachOfProtocol, DisconnectReason.AppClosing => EthDisconnectReason.ClientQuitting, - DisconnectReason.InvalidTxOrUncle or DisconnectReason.HeaderResponseTooLong or DisconnectReason.InconsistentHeaderBatch or DisconnectReason.UnexpectedHeaderHash or DisconnectReason.HeaderBatchOnDifferentBranch or DisconnectReason.UnexpectedParentHeader or DisconnectReason.InvalidHeader or DisconnectReason.InvalidReceiptRoot or DisconnectReason.EthSyncException => EthDisconnectReason.BreachOfProtocol, + DisconnectReason.InvalidTxOrUncle or DisconnectReason.HeaderResponseTooLong or DisconnectReason.InconsistentHeaderBatch or DisconnectReason.UnexpectedHeaderHash or DisconnectReason.HeaderBatchOnDifferentBranch or DisconnectReason.UnexpectedParentHeader or DisconnectReason.InvalidHeader or DisconnectReason.InvalidReceiptRoot or DisconnectReason.EthSyncException or DisconnectReason.InvalidBlockRangeUpdate => EthDisconnectReason.BreachOfProtocol, DisconnectReason.EthDisconnectRequested => EthDisconnectReason.DisconnectRequested, DisconnectReason.TcpSubSystemError => EthDisconnectReason.TcpSubSystemError, DisconnectReason.BreachOfProtocol => EthDisconnectReason.BreachOfProtocol, From c2f1fa47a9beec195800a12fdf1f11d56115cdd0 Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Sun, 7 Dec 2025 12:39:12 +0100 Subject: [PATCH 062/255] Update OP Superchain chains (#9892) Co-authored-by: emlautarom1 From 3915b5e6ee1c05edd1036fb7f07ce843c430a9aa Mon Sep 17 00:00:00 2001 From: Marcos Antonio Maceo <35319980+stdevMac@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:25:37 +0400 Subject: [PATCH 063/255] Run taiko nodes on latest version (#9899) feat: run taiko nodes on latest version --- .github/workflows/sync-supported-chains.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/sync-supported-chains.yml b/.github/workflows/sync-supported-chains.yml index f2531992615..7517b5416bf 100644 --- a/.github/workflows/sync-supported-chains.yml +++ b/.github/workflows/sync-supported-chains.yml @@ -249,16 +249,15 @@ jobs: $extra_param elif [[ "$network" == taiko-* ]]; then + taiko_client_version="latest" if [[ "$network" == *alethia* ]]; then CONSENSUS_URL="${{ secrets.MAINNET_CONSENSUS_URL }}" EXECUTION_URL="${{ secrets.MAINNET_EXECUTION_URL }}" stripped_network="mainnet" - taiko_client_version="taiko-alethia-client-v0.43.2" elif [[ "$network" == *hoodi* ]]; then CONSENSUS_URL="${{ secrets.HOODI_CONSENSUS_URL }}" EXECUTION_URL="${{ secrets.HOODI_EXECUTION_URL }}" stripped_network="hoodi" - taiko_client_version="latest" else echo "Unknown network" exit 1 From 4ee9f7d3d1ed3d06414b49a567051ec91c5ce87a Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 07:03:40 +0400 Subject: [PATCH 064/255] Update Dockerfiles (#9909) Co-authored-by: rubo --- Dockerfile | 4 ++-- Dockerfile.chiseled | 4 ++-- scripts/build/Dockerfile | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 31536b41068..d7c9b37d270 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited # SPDX-License-Identifier: LGPL-3.0-only -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0.100-noble@sha256:c7445f141c04f1a6b454181bd098dcfa606c61ba0bd213d0a702489e5bd4cd71 AS build +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0.101-noble@sha256:d1823fecac3689a2eb959e02ee3bfe1c2142392808240039097ad70644566190 AS build ARG BUILD_CONFIG=release ARG CI=true @@ -25,7 +25,7 @@ RUN arch=$([ "$TARGETARCH" = "amd64" ] && echo "x64" || echo "$TARGETARCH") && \ # A temporary symlink to support the old executable name RUN ln -sr /publish/nethermind /publish/Nethermind.Runner -FROM mcr.microsoft.com/dotnet/aspnet:10.0.0-noble@sha256:7c4246c1c384319346d45b3e24a10a21d5b6fc9b36a04790e1588148ff8055b0 +FROM mcr.microsoft.com/dotnet/aspnet:10.0.1-noble@sha256:eaa79205c3ade4792a7f7bf310a3aac51fe0e1d91c44e40f70b7c6423d475fe0 WORKDIR /nethermind diff --git a/Dockerfile.chiseled b/Dockerfile.chiseled index 3031ccce3bd..b8f8c568e14 100644 --- a/Dockerfile.chiseled +++ b/Dockerfile.chiseled @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited # SPDX-License-Identifier: LGPL-3.0-only -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0.100-noble@sha256:c7445f141c04f1a6b454181bd098dcfa606c61ba0bd213d0a702489e5bd4cd71 AS build +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0.101-noble@sha256:d1823fecac3689a2eb959e02ee3bfe1c2142392808240039097ad70644566190 AS build ARG BUILD_CONFIG=release ARG CI=true @@ -28,7 +28,7 @@ RUN cd /publish && \ mkdir logs && \ mkdir nethermind_db -FROM mcr.microsoft.com/dotnet/aspnet:10.0.0-noble-chiseled@sha256:5730fa91fab5ec91f69661b86897249ad6a01c8da6da557695e9da4c6bc83621 +FROM mcr.microsoft.com/dotnet/aspnet:10.0.1-noble-chiseled@sha256:ba111738d21b4898f433fd8724ba1ed2e450adcb295c58f31d4137751922c83c WORKDIR /nethermind diff --git a/scripts/build/Dockerfile b/scripts/build/Dockerfile index f21cb787fff..67a11fcd07d 100644 --- a/scripts/build/Dockerfile +++ b/scripts/build/Dockerfile @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited # SPDX-License-Identifier: LGPL-3.0-only -FROM mcr.microsoft.com/dotnet/sdk:10.0.100-noble@sha256:c7445f141c04f1a6b454181bd098dcfa606c61ba0bd213d0a702489e5bd4cd71 +FROM mcr.microsoft.com/dotnet/sdk:10.0.101-noble@sha256:d1823fecac3689a2eb959e02ee3bfe1c2142392808240039097ad70644566190 ARG COMMIT_HASH ARG SOURCE_DATE_EPOCH From f34433881d95068a63f1de3f159140d4a19b5d18 Mon Sep 17 00:00:00 2001 From: Marcos Antonio Maceo <35319980+stdevMac@users.noreply.github.com> Date: Wed, 10 Dec 2025 15:33:04 +0400 Subject: [PATCH 065/255] Disable publishing to Downloads (#9910) * chore: remove from release the upload to the downloads page * Delete publish-downloads.sh --------- Co-authored-by: Ruben Buniatyan --- .github/workflows/release.yml | 30 ------------------------------ scripts/build/publish-downloads.sh | 30 ------------------------------ 2 files changed, 60 deletions(-) delete mode 100755 scripts/build/publish-downloads.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6c258785763..3743330f3e0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -139,36 +139,6 @@ jobs: rm -rf $GITHUB_WORKSPACE/$PACKAGE_DIR/*/ $SCRIPTS_PATH/publish-github.sh - publish-downloads: - name: Publish to Downloads page - runs-on: ubuntu-latest - needs: [approval, build] - if: needs.build.outputs.prerelease == 'false' - steps: - - name: Check out Nethermind repository - uses: actions/checkout@v6 - - - name: Download artifacts - uses: actions/download-artifact@v4 - with: - path: ${{ github.workspace }}/${{ env.PACKAGE_DIR }} - - - name: Configure GPG Key - run: | - mkdir -p ~/.gnupg/ - printf "${{ secrets.GPG_SIGNING_KEY }}" | base64 --decode > ~/.gnupg/private.key - gpg --import --no-tty --batch --yes ~/.gnupg/private.key - - - name: Publish packages to Downloads page - env: - DOWNLOADS_PAGE: ${{ secrets.DOWNLOADS_API_KEY }} - PACKAGE_PREFIX: ${{ needs.build.outputs.package-prefix }} - PASS: ${{ secrets.GPG_PASSWORD }} - run: | - cp $GITHUB_WORKSPACE/$PACKAGE_DIR/**/*.zip $GITHUB_WORKSPACE/$PACKAGE_DIR - rm -rf $GITHUB_WORKSPACE/$PACKAGE_DIR/*/ - $SCRIPTS_PATH/publish-downloads.sh - publish-docker: name: Publish to Docker Hub runs-on: ubuntu-latest diff --git a/scripts/build/publish-downloads.sh b/scripts/build/publish-downloads.sh deleted file mode 100755 index 8983f6daa8d..00000000000 --- a/scripts/build/publish-downloads.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -# SPDX-License-Identifier: LGPL-3.0-only - -set -e - -export GPG_TTY=$(tty) - -echo "Publishing packages to Downloads page" - -cd $GITHUB_WORKSPACE/$PACKAGE_DIR - -for rid in "linux-arm64" "linux-x64" "macos-arm64" "macos-x64" "windows-x64"; do - file_name=$(basename *$rid*) - - echo "Signing $file_name" - - gpg --batch --detach-sign --passphrase=$PASS --pinentry-mode loopback --armor $file_name - - echo "Uploading $file_name" - - curl https://downloads.nethermind.io/files?apikey=$DOWNLOADS_PAGE \ - -X POST \ - --fail-with-body \ - -# \ - -F "files=@$PWD/$file_name" \ - -F "files=@$PWD/$file_name.asc" -done - -echo "Publishing completed" From f8ce8d95237a6915937140ba824d0373cb7ed877 Mon Sep 17 00:00:00 2001 From: Nikita Mescheryakov Date: Wed, 10 Dec 2025 10:21:03 -0300 Subject: [PATCH 066/255] Fix hive getLogs (#9889) * try fix * Fix tests * Try fix * Fix * Fix from & to * Fix block in the future * Fix build * Fix range in the future * Fix block range * to * Fix tests * Fix json rpc tests * Fix formatting * Fix blockchain tests * Fix suggestions * Fix tags * Remove address from AddressFilter * Fix tests * Fix address filter * Fix suggestions --- .../Builders/FilterBuilder.cs | 2 +- .../Filters/AddressFilterTests.cs | 36 +++--- .../Filters/FilterStoreTests.cs | 24 ++-- .../Nethermind.Facade/BlockchainBridge.cs | 18 +-- .../Filters/AddressFilter.cs | 78 +++++-------- .../Nethermind.Facade/Filters/FilterStore.cs | 48 +++----- .../Nethermind.Facade/IBlockchainBridge.cs | 6 +- .../Modules/Eth/EthRpcModuleTests.cs | 18 +-- .../Modules/Eth/FilterTests.cs | 38 +++---- .../Modules/SubscribeModuleTests.cs | 44 ++++--- .../Modules/Eth/EthRpcModule.cs | 70 ++++-------- .../Nethermind.JsonRpc/Modules/Eth/Filter.cs | 107 ++++++++++++------ 12 files changed, 236 insertions(+), 253 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs b/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs index 86c7706fe3f..ee7cc539f26 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs @@ -125,7 +125,7 @@ public FilterBuilder WithAddress(Address address) public FilterBuilder WithAddresses(params Address[] addresses) { - _address = new AddressFilter(addresses.Select(static a => new AddressAsKey(a)).ToHashSet()); + _address = new AddressFilter(addresses.Select(static a => new AddressAsKey(a))); return this; } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs index cbedcef98a5..69d73ec8c18 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs @@ -73,7 +73,7 @@ public void Accepts_any_address_by_ref() [Test] public void Accepts_any_address_when_set_is_empty() { - HashSet addresses = new(); + AddressAsKey[] addresses = []; AddressFilter filter = new AddressFilter(addresses); filter.Accepts(TestItem.AddressA).Should().BeTrue(); @@ -84,7 +84,7 @@ public void Accepts_any_address_when_set_is_empty() [Test] public void Accepts_any_address_when_set_is_empty_by_ref() { - HashSet addresses = new(); + AddressAsKey[] addresses = []; AddressFilter filter = new AddressFilter(addresses); AddressStructRef addressARef = TestItem.AddressA.ToStructRef(); @@ -98,10 +98,10 @@ public void Accepts_any_address_when_set_is_empty_by_ref() [Test] public void Accepts_only_addresses_in_a_set() { - HashSet addresses = new() - { + AddressAsKey[] addresses = + [ TestItem.AddressA, TestItem.AddressC - }; + ]; AddressFilter filter = new AddressFilter(addresses); filter.Accepts(TestItem.AddressA).Should().BeTrue(); @@ -112,10 +112,10 @@ public void Accepts_only_addresses_in_a_set() [Test] public void Accepts_only_addresses_in_a_set_by_ref() { - HashSet addresses = new() - { + AddressAsKey[] addresses = + [ TestItem.AddressA, TestItem.AddressC - }; + ]; AddressFilter filter = new AddressFilter(addresses); AddressStructRef addressARef = TestItem.AddressA.ToStructRef(); @@ -187,7 +187,7 @@ public void Matches_bloom_using_any_address_by_ref() [Test] public void Matches_any_bloom_when_set_is_empty() { - HashSet addresses = new(); + AddressAsKey[] addresses = []; AddressFilter filter = new AddressFilter(addresses); filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); @@ -198,7 +198,7 @@ public void Matches_any_bloom_when_set_is_empty() [Test] public void Matches_any_bloom_when_set_is_empty_by_ref() { - HashSet addresses = new(); + AddressAsKey[] addresses = []; AddressFilter filter = new AddressFilter(addresses); BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); @@ -212,7 +212,7 @@ public void Matches_any_bloom_when_set_is_empty_by_ref() [Test] public void Matches_any_bloom_when_set_is_forced_null() { - AddressFilter filter = new AddressFilter(addresses: null!); + AddressFilter filter = new AddressFilter([]); filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeTrue(); @@ -222,7 +222,7 @@ public void Matches_any_bloom_when_set_is_forced_null() [Test] public void Matches_any_bloom_when_set_is_forced_null_by_ref() { - AddressFilter filter = new AddressFilter(addresses: null!); + AddressFilter filter = new AddressFilter([]); BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); BloomStructRef bloomBRef = BloomFromAddress(TestItem.AddressB).ToStructRef(); @@ -235,10 +235,10 @@ public void Matches_any_bloom_when_set_is_forced_null_by_ref() [Test] public void Matches_any_bloom_using_addresses_set() { - HashSet addresses = new() - { + AddressAsKey[] addresses = + [ TestItem.AddressA, TestItem.AddressC - }; + ]; AddressFilter filter = new AddressFilter(addresses); filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); @@ -249,10 +249,10 @@ public void Matches_any_bloom_using_addresses_set() [Test] public void Matches_any_bloom_using_addresses_set_by_ref() { - HashSet addresses = new() - { + AddressAsKey[] addresses = + [ TestItem.AddressA, TestItem.AddressC - }; + ]; AddressFilter filter = new AddressFilter(addresses); BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs index 20d90ed8c3f..51e67845edd 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs @@ -11,6 +11,7 @@ using Nethermind.Blockchain.Filters.Topics; using Nethermind.Blockchain.Find; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Core.Timers; using NSubstitute; @@ -102,14 +103,14 @@ public static IEnumerable CorrectlyCreatesAddressFilterTestCases get { yield return new TestCaseData(null, AddressFilter.AnyAddress); - yield return new TestCaseData(TestItem.AddressA.ToString(), new AddressFilter(TestItem.AddressA)); - yield return new TestCaseData(new[] { TestItem.AddressA.ToString(), TestItem.AddressB.ToString() }, - new AddressFilter(new HashSet() { TestItem.AddressA, TestItem.AddressB })); + yield return new TestCaseData(new[] { new AddressAsKey(TestItem.AddressA) }, new AddressFilter(TestItem.AddressA)); + yield return new TestCaseData(new[] { new AddressAsKey(TestItem.AddressA), new AddressAsKey(TestItem.AddressB) }, + new AddressFilter([TestItem.AddressA, TestItem.AddressB])); } } [TestCaseSource(nameof(CorrectlyCreatesAddressFilterTestCases))] - public void Correctly_creates_address_filter(object address, AddressFilter expected) + public void Correctly_creates_address_filter(AddressAsKey[] address, AddressFilter expected) { BlockParameter from = new(100); BlockParameter to = new(BlockParameterType.Latest); @@ -124,22 +125,25 @@ public static IEnumerable CorrectlyCreatesTopicsFilterTestCases { yield return new TestCaseData(null, SequenceTopicsFilter.AnyTopic); - yield return new TestCaseData(new[] { TestItem.KeccakA.ToString() }, + yield return new TestCaseData(new[] { new[] { TestItem.KeccakA } }, new SequenceTopicsFilter(new SpecificTopic(TestItem.KeccakA))); - yield return new TestCaseData(new[] { TestItem.KeccakA.ToString(), TestItem.KeccakB.ToString() }, + yield return new TestCaseData(new[] { new[] { TestItem.KeccakA }, new[] { TestItem.KeccakB } }, new SequenceTopicsFilter(new SpecificTopic(TestItem.KeccakA), new SpecificTopic(TestItem.KeccakB))); - yield return new TestCaseData(new[] { null, TestItem.KeccakB.ToString() }, + yield return new TestCaseData(new[] { null, new[] { TestItem.KeccakB } }, new SequenceTopicsFilter(AnyTopic.Instance, new SpecificTopic(TestItem.KeccakB))); - yield return new TestCaseData(new object[] { new[] { TestItem.KeccakA.ToString(), TestItem.KeccakB.ToString(), TestItem.KeccakC.ToString() }, TestItem.KeccakD.ToString() }, - new SequenceTopicsFilter(new OrExpression(new SpecificTopic(TestItem.KeccakA), new SpecificTopic(TestItem.KeccakB), new SpecificTopic(TestItem.KeccakC)), new SpecificTopic(TestItem.KeccakD))); + yield return new TestCaseData( + new[] { new[] { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }, new[] { TestItem.KeccakD } }, + new SequenceTopicsFilter( + new OrExpression(new SpecificTopic(TestItem.KeccakA), new SpecificTopic(TestItem.KeccakB), + new SpecificTopic(TestItem.KeccakC)), new SpecificTopic(TestItem.KeccakD))); } } [TestCaseSource(nameof(CorrectlyCreatesTopicsFilterTestCases))] - public void Correctly_creates_topics_filter(IEnumerable topics, TopicsFilter expected) + public void Correctly_creates_topics_filter(Hash256[]?[]? topics, TopicsFilter expected) { BlockParameter from = new(100); BlockParameter to = new(BlockParameterType.Latest); diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 430ab4cb28b..80305a26023 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -289,21 +289,21 @@ public ulong GetChainId() public IEnumerable GetLogs( BlockParameter fromBlock, BlockParameter toBlock, - object? address = null, - IEnumerable? topics = null, + AddressAsKey[]? addresses = null, + IEnumerable? topics = null, CancellationToken cancellationToken = default) { - LogFilter filter = GetFilter(fromBlock, toBlock, address, topics); + LogFilter filter = GetFilter(fromBlock, toBlock, addresses, topics); return logFinder.FindLogs(filter, cancellationToken); } public LogFilter GetFilter( BlockParameter fromBlock, BlockParameter toBlock, - object? address = null, - IEnumerable? topics = null) + AddressAsKey[]? addresses = null, + IEnumerable? topics = null) { - return filterStore.CreateLogFilter(fromBlock, toBlock, address, topics, false); + return filterStore.CreateLogFilter(fromBlock, toBlock, addresses, topics, false); } public IEnumerable GetLogs( @@ -325,10 +325,10 @@ public bool TryGetLogs(int filterId, out IEnumerable filterLogs, Canc return filter is not null; } - public int NewFilter(BlockParameter? fromBlock, BlockParameter? toBlock, - object? address = null, IEnumerable? topics = null) + public int NewFilter(BlockParameter fromBlock, BlockParameter toBlock, + AddressAsKey[]? address = null, IEnumerable? topics = null) { - LogFilter filter = filterStore.CreateLogFilter(fromBlock ?? BlockParameter.Latest, toBlock ?? BlockParameter.Latest, address, topics); + LogFilter filter = filterStore.CreateLogFilter(fromBlock, toBlock, address, topics); filterStore.SaveFilter(filter); return filter.Id; } diff --git a/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs b/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs index 4e71a417b8e..ccdcd9e4672 100644 --- a/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs +++ b/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs @@ -9,39 +9,27 @@ namespace Nethermind.Blockchain.Filters { public class AddressFilter { - public static readonly AddressFilter AnyAddress = new(addresses: new HashSet()); + public static readonly AddressFilter AnyAddress = new([]); private Bloom.BloomExtract[]? _addressesBloomIndexes; - private Bloom.BloomExtract? _addressBloomExtract; - public AddressFilter(Address address) + public AddressFilter(Address address) : this([address]) { - Address = address; } - public AddressFilter(HashSet addresses) + public AddressFilter(IEnumerable addresses) { - Addresses = addresses; + Addresses = addresses.ToHashSet(); } - public Address? Address { get; } - public HashSet? Addresses { get; } + public HashSet Addresses { get; } private Bloom.BloomExtract[] AddressesBloomExtracts => _addressesBloomIndexes ??= CalculateBloomExtracts(); - private Bloom.BloomExtract AddressBloomExtract => _addressBloomExtract ??= Bloom.GetExtract(Address); - public bool Accepts(Address address) - { - if (Addresses?.Count > 0) - { - return Addresses.Contains(address); - } - - return Address is null || Address == address; - } + public bool Accepts(Address address) => Addresses.Count == 0 || Addresses.Contains(address); public bool Accepts(ref AddressStructRef address) { - if (Addresses?.Count > 0) + if (Addresses.Count > 0) { foreach (var a in Addresses) { @@ -51,55 +39,41 @@ public bool Accepts(ref AddressStructRef address) return false; } - return Address is null || Address == address; + return true; } public bool Matches(Bloom bloom) { - if (Addresses is not null) + if (AddressesBloomExtracts.Length == 0) { - bool result = true; - var indexes = AddressesBloomExtracts; - for (var i = 0; i < indexes.Length; i++) - { - result = bloom.Matches(indexes[i]); - if (result) - { - break; - } - } - - return result; + return true; } - if (Address is null) + foreach (Bloom.BloomExtract index in AddressesBloomExtracts) { - return true; + if (bloom.Matches(index)) + { + return true; + } } - return bloom.Matches(AddressBloomExtract); + + return false; } public bool Matches(ref BloomStructRef bloom) { - if (Addresses is not null) + if (AddressesBloomExtracts.Length == 0) { - bool result = true; - var indexes = AddressesBloomExtracts; - for (var i = 0; i < indexes.Length; i++) - { - result = bloom.Matches(indexes[i]); - if (result) - { - break; - } - } - - return result; + return true; } - if (Address is null) + foreach (Bloom.BloomExtract index in AddressesBloomExtracts) { - return true; + if (bloom.Matches(index)) + { + return true; + } } - return bloom.Matches(AddressBloomExtract); + + return false; } private Bloom.BloomExtract[] CalculateBloomExtracts() => Addresses.Select(static a => Bloom.GetExtract(a)).ToArray(); diff --git a/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs b/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs index f7b192cb42c..6976dad25e9 100644 --- a/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs +++ b/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs @@ -124,11 +124,11 @@ public PendingTransactionFilter CreatePendingTransactionFilter(bool setId = true new(GetFilterId(setId)); public LogFilter CreateLogFilter(BlockParameter fromBlock, BlockParameter toBlock, - object? address = null, IEnumerable? topics = null, bool setId = true) => + AddressAsKey[]? addresses = null, IEnumerable? topics = null, bool setId = true) => new(GetFilterId(setId), fromBlock, toBlock, - GetAddress(address), + GetAddress(addresses), GetTopicsFilter(topics)); public void RemoveFilter(int filterId) @@ -165,7 +165,7 @@ private int GetFilterId(bool generateId) return 0; } - private static TopicsFilter GetTopicsFilter(IEnumerable? topics = null) + private static TopicsFilter GetTopicsFilter(IEnumerable? topics = null) { if (topics is null) { @@ -202,48 +202,32 @@ private static TopicExpression GetTopicExpression(FilterTopic? filterTopic) return AnyTopic.Instance; } - private static AddressFilter GetAddress(object? address) => - address switch - { - null => AddressFilter.AnyAddress, - string s => new AddressFilter(new Address(s)), - IEnumerable e => new AddressFilter(e.Select(static a => new AddressAsKey(new Address(a))).ToHashSet()), - _ => throw new InvalidDataException("Invalid address filter format") - }; + private static AddressFilter GetAddress(AddressAsKey[]? addresses) => addresses is null ? AddressFilter.AnyAddress : new AddressFilter(addresses); - private static FilterTopic?[]? GetFilterTopics(IEnumerable? topics) => topics?.Select(GetTopic).ToArray(); + private static FilterTopic?[]? GetFilterTopics(IEnumerable? topics) => topics?.Select(GetTopic).ToArray(); - private static FilterTopic? GetTopic(object? obj) + private static FilterTopic? GetTopic(Hash256[]? topics) { - switch (obj) + if (topics?.Length == 1) { - case null: - return null; - case string topic: - return new FilterTopic - { - Topic = new Hash256(topic) - }; - case Hash256 keccak: - return new FilterTopic - { - Topic = keccak - }; + return new FilterTopic + { + Topic = topics[0] + }; } - - return obj is not IEnumerable topics - ? null - : new FilterTopic + else + { + return new FilterTopic() { - Topics = topics.Select(static t => new Hash256(t)).ToArray() + Topics = topics }; + } } private class FilterTopic { public Hash256? Topic { get; init; } public Hash256[]? Topics { get; init; } - } public void Dispose() diff --git a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs index d2f41be173a..21e95dcc502 100644 --- a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs @@ -36,16 +36,16 @@ public interface IBlockchainBridge : ILogFinder int NewBlockFilter(); int NewPendingTransactionFilter(); - int NewFilter(BlockParameter? fromBlock, BlockParameter? toBlock, object? address = null, IEnumerable? topics = null); + int NewFilter(BlockParameter fromBlock, BlockParameter toBlock, AddressAsKey[]? address = null, IEnumerable? topics = null); void UninstallFilter(int filterId); bool FilterExists(int filterId); Hash256[] GetBlockFilterChanges(int filterId); Hash256[] GetPendingTransactionFilterChanges(int filterId); FilterLog[] GetLogFilterChanges(int filterId); FilterType GetFilterType(int filterId); - LogFilter GetFilter(BlockParameter fromBlock, BlockParameter toBlock, object? address = null, IEnumerable? topics = null); + LogFilter GetFilter(BlockParameter fromBlock, BlockParameter toBlock, AddressAsKey[]? addresses = null, IEnumerable? topics = null); IEnumerable GetLogs(LogFilter filter, BlockHeader fromBlock, BlockHeader toBlock, CancellationToken cancellationToken = default); - IEnumerable GetLogs(BlockParameter fromBlock, BlockParameter toBlock, object? address = null, IEnumerable? topics = null, CancellationToken cancellationToken = default); + IEnumerable GetLogs(BlockParameter fromBlock, BlockParameter toBlock, AddressAsKey[]? addresses = null, IEnumerable? topics = null, CancellationToken cancellationToken = default); bool TryGetLogs(int filterId, out IEnumerable filterLogs, CancellationToken cancellationToken = default); void RunTreeVisitor(ITreeVisitor treeVisitor, Hash256 stateRoot) where TCtx : struct, INodeContext; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index 0e6b8f73d9c..98d795f7cb7 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -579,9 +579,9 @@ void HandleNewBlock(object? sender, BlockReplacementEventArgs e) await test.AddBlock(createCodeTx); - string getLogsSerialized = await test.TestEthRpc("eth_getLogs", $"{{\"fromBlock\":\"{blockHash}\"}}"); + string getLogsSerialized = await test.TestEthRpc("eth_getLogs", $"{{\"blockHash\":\"{blockHash}\"}}"); - using JsonRpcResponse? newFilterResp = await RpcTest.TestRequest(test.EthRpcModule, "eth_newFilter", new { fromBlock = blockHash }); + using JsonRpcResponse? newFilterResp = await RpcTest.TestRequest(test.EthRpcModule, "eth_newFilter", new { blockHash = blockHash }); Assert.That(newFilterResp is not null && newFilterResp is JsonRpcSuccessResponse, Is.True); @@ -591,13 +591,13 @@ void HandleNewBlock(object? sender, BlockReplacementEventArgs e) } [TestCase("{}", """{"jsonrpc":"2.0","result":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","blockHash":"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760","blockNumber":"0x1","blockTimestamp":"0x1","data":"0x010203","logIndex":"0x1","removed":false,"topics":["0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72","0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2"],"transactionHash":"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111","transactionIndex":"0x1"}],"id":67}""")] - [TestCase("""{"fromBlock":"0x2","toBlock":"latest","address":"0x00000000000000000001","topics":["0x00000000000000000000000000000001"]}""", """{"jsonrpc":"2.0","result":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","blockHash":"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760","blockNumber":"0x1","blockTimestamp":"0x1","data":"0x010203","logIndex":"0x1","removed":false,"topics":["0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72","0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2"],"transactionHash":"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111","transactionIndex":"0x1"}],"id":67}""")] - [TestCase("""{"fromBlock":"earliest","toBlock":"pending","address":["0x00000000000000000001", "0x00000000000000000001"],"topics":["0x00000000000000000000000000000001", "0x00000000000000000000000000000002"]}""", """{"jsonrpc":"2.0","result":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","blockHash":"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760","blockNumber":"0x1","blockTimestamp":"0x1","data":"0x010203","logIndex":"0x1","removed":false,"topics":["0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72","0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2"],"transactionHash":"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111","transactionIndex":"0x1"}],"id":67}""")] - [TestCase("""{"topics":[null, ["0x00000000000000000000000000000001", "0x00000000000000000000000000000002"]]}""", """{"jsonrpc":"2.0","result":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","blockHash":"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760","blockNumber":"0x1","blockTimestamp":"0x1","data":"0x010203","logIndex":"0x1","removed":false,"topics":["0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72","0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2"],"transactionHash":"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111","transactionIndex":"0x1"}],"id":67}""")] - [TestCase("""{"fromBlock":"0x10","toBlock":"latest","address":"0x00000000000000000001","topics":["0x00000000000000000000000000000001"]}""", """{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid block range params"},"id":67}""")] - [TestCase("""{"fromBlock":"0x2","toBlock":"0x11","address":"0x00000000000000000001","topics":["0x00000000000000000000000000000001"]}""", """{"jsonrpc":"2.0","result":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","blockHash":"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760","blockNumber":"0x1","blockTimestamp":"0x1","data":"0x010203","logIndex":"0x1","removed":false,"topics":["0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72","0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2"],"transactionHash":"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111","transactionIndex":"0x1"}],"id":67}""")] - [TestCase("""{"fromBlock":"0x2","toBlock":"0x1","address":"0x00000000000000000001","topics":["0x00000000000000000000000000000001"]}""", """{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid block range params"},"id":67}""")] - [TestCase("""{"fromBlock":"0x11","toBlock":"0x12","address":"0x00000000000000000001","topics":["0x00000000000000000000000000000001"]}""", """{"jsonrpc":"2.0","result":[],"id":67}""")] + [TestCase("""{"fromBlock":"0x2","toBlock":"latest","address":"0x0000000000000000000000000000000000000001","topics":["0x0000000000000000000000000000000000000001"]}""", """{"jsonrpc":"2.0","result":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","blockHash":"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760","blockNumber":"0x1","blockTimestamp":"0x1","data":"0x010203","logIndex":"0x1","removed":false,"topics":["0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72","0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2"],"transactionHash":"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111","transactionIndex":"0x1"}],"id":67}""")] + [TestCase("""{"fromBlock":"earliest","toBlock":"pending","address":["0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000001"],"topics":["0x0000000000000000000000000000000000000001", "0x00000000000000000000000000000002"]}""", """{"jsonrpc":"2.0","result":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","blockHash":"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760","blockNumber":"0x1","blockTimestamp":"0x1","data":"0x010203","logIndex":"0x1","removed":false,"topics":["0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72","0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2"],"transactionHash":"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111","transactionIndex":"0x1"}],"id":67}""")] + [TestCase("""{"topics":[null, ["0x0000000000000000000000000000000000000001", "0x00000000000000000000000000000002"]]}""", """{"jsonrpc":"2.0","result":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","blockHash":"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760","blockNumber":"0x1","blockTimestamp":"0x1","data":"0x010203","logIndex":"0x1","removed":false,"topics":["0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72","0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2"],"transactionHash":"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111","transactionIndex":"0x1"}],"id":67}""")] + [TestCase("""{"fromBlock":"0x10","toBlock":"latest","address":"0x0000000000000000000000000000000000000001","topics":["0x0000000000000000000000000000000000000001"]}""", """{"jsonrpc":"2.0","error":{"code":-32602,"message":"requested block range is in the future"},"id":67}""")] + [TestCase("""{"fromBlock":"0x2","toBlock":"0x3","address":"0x0000000000000000000000000000000000000001","topics":["0x0000000000000000000000000000000000000001"]}""", """{"jsonrpc":"2.0","result":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","blockHash":"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760","blockNumber":"0x1","blockTimestamp":"0x1","data":"0x010203","logIndex":"0x1","removed":false,"topics":["0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72","0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2"],"transactionHash":"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111","transactionIndex":"0x1"}],"id":67}""")] + [TestCase("""{"fromBlock":"0x2","toBlock":"0x1","address":"0x0000000000000000000000000000000000000001","topics":["0x0000000000000000000000000000000000000001"]}""", """{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid block range params"},"id":67}""")] + [TestCase("""{"fromBlock":"0x11","toBlock":"0x12","address":"0x0000000000000000000000000000000000000001","topics":["0x0000000000000000000000000000000000000001"]}""", """{"jsonrpc":"2.0","error":{"code":-32602,"message":"requested block range is in the future"},"id":67}""")] public async Task Eth_get_logs(string parameter, string expected) { using Context ctx = await Context.Create(); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/FilterTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/FilterTests.cs index 2ab35c9ae37..af06485f1bd 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/FilterTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/FilterTests.cs @@ -6,6 +6,8 @@ using FluentAssertions; using Nethermind.Blockchain.Find; +using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.JsonRpc.Data; using Nethermind.JsonRpc.Modules.Eth; using Nethermind.Serialization.Json; @@ -23,7 +25,7 @@ public static IEnumerable JsonTests yield return new TestCaseData("{}", new Filter { - FromBlock = BlockParameter.Latest, + FromBlock = BlockParameter.Earliest, ToBlock = BlockParameter.Latest, }); @@ -31,8 +33,6 @@ public static IEnumerable JsonTests JsonSerializer.Serialize( new { - fromBlock = "earliest", - toBlock = "pending", topics = new object?[] { null, @@ -47,17 +47,16 @@ public static IEnumerable JsonTests new Filter { FromBlock = BlockParameter.Earliest, - ToBlock = BlockParameter.Pending, - Topics = new object?[] - { + ToBlock = BlockParameter.Latest, + Topics = + [ null, - "0xe194ef610f9150a2db4110b3db5116fd623175dca3528d7ae7046a1042f84fe7", - new[] - { - "0x000500002bd87daa34d8ff0daf3465c96044d8f6667614850000000000000001", - "0xe194ef610f9150a2db4110b3db5116fd623175dca3528d7ae7046a1042f84fe7" - } - } + [new("0xe194ef610f9150a2db4110b3db5116fd623175dca3528d7ae7046a1042f84fe7")], + [ + new Hash256("0x000500002bd87daa34d8ff0daf3465c96044d8f6667614850000000000000001"), + new Hash256("0xe194ef610f9150a2db4110b3db5116fd623175dca3528d7ae7046a1042f84fe7") + ] + ] }); yield return new TestCaseData( @@ -66,7 +65,6 @@ public static IEnumerable JsonTests { address = "0xc2d77d118326c33bbe36ebeabf4f7ed6bc2dda5c", fromBlock = "0x1143ade", - toBlock = "latest", topics = new object?[] { "0xe194ef610f9150a2db4110b3db5116fd623175dca3528d7ae7046a1042f84fe7", @@ -77,16 +75,16 @@ public static IEnumerable JsonTests }), new Filter { - Address = "0xc2d77d118326c33bbe36ebeabf4f7ed6bc2dda5c", + Address = [new Address("0xc2d77d118326c33bbe36ebeabf4f7ed6bc2dda5c")], FromBlock = new BlockParameter(0x1143ade), ToBlock = BlockParameter.Latest, - Topics = new object?[] - { - "0xe194ef610f9150a2db4110b3db5116fd623175dca3528d7ae7046a1042f84fe7", + Topics = + [ + [new("0xe194ef610f9150a2db4110b3db5116fd623175dca3528d7ae7046a1042f84fe7")], null, null, - "0x000500002bd87daa34d8ff0daf3465c96044d8f6667614850000000000000001" - } + [new("0x000500002bd87daa34d8ff0daf3465c96044d8f6667614850000000000000001")] + ] }); var blockHash = "0x892a8b3ccc78359e059e67ec44c83bfed496721d48c2d1dd929d6e4cd6559d35"; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs index edf0f8bbfa5..4a988139e3b 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs @@ -603,8 +603,8 @@ public void LogsSubscription_on_NewHeadBlock_event_with_few_TxReceipts_with_few_ { FromBlock = BlockParameter.Latest, ToBlock = BlockParameter.Latest, - Address = "0xb7705ae4c6f81b66cdb323c65f4e8133690fc099", - Topics = new[] { TestItem.KeccakA } + Address = [new Address("0xb7705ae4c6f81b66cdb323c65f4e8133690fc099")], + Topics = [[TestItem.KeccakA]] }; LogEntry logEntryA = Build.A.LogEntry.WithAddress(TestItem.AddressA).WithTopics(TestItem.KeccakA).WithData(TestItem.RandomDataA).TestObject; @@ -651,8 +651,8 @@ public void LogsSubscription_on_NewHeadBlock_event_with_few_TxReceipts_with_few_ { FromBlock = BlockParameter.Latest, ToBlock = BlockParameter.Latest, - Address = "0xb7705ae4c6f81b66cdb323c65f4e8133690fc099", - Topics = new[] { TestItem.KeccakA } + Address = [new Address("0xb7705ae4c6f81b66cdb323c65f4e8133690fc099")], + Topics = [[TestItem.KeccakA]] }; LogEntry logEntryA = Build.A.LogEntry.WithAddress(TestItem.AddressA).WithTopics(TestItem.KeccakA).WithData(TestItem.RandomDataA).TestObject; @@ -699,8 +699,12 @@ public void LogsSubscription_on_NewHeadBlock_event_with_few_TxReceipts_with_few_ { FromBlock = BlockParameter.Latest, ToBlock = BlockParameter.Latest, - Address = new[] { "0xb7705ae4c6f81b66cdb323c65f4e8133690fc099", "0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358" }, - Topics = new[] { TestItem.KeccakA, TestItem.KeccakD } + Address = + [ + new Address("0xb7705ae4c6f81b66cdb323c65f4e8133690fc099"), + new Address("0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358") + ], + Topics = [[TestItem.KeccakA, TestItem.KeccakD]] }; LogEntry logEntryA = Build.A.LogEntry.WithAddress(TestItem.AddressA).WithTopics(TestItem.KeccakA, TestItem.KeccakD).WithData(TestItem.RandomDataA).TestObject; @@ -922,12 +926,14 @@ public async Task MultipleSubscriptions_concurrent_fast_messages(int messages) Task subA = Task.Run(() => { ITxPool txPool = Substitute.For(); - using NewPendingTransactionsSubscription subscription = new( - // ReSharper disable once AccessToDisposedClosure - jsonRpcDuplexClient: client, - txPool: txPool, - specProvider: _specProvider, - logManager: LimboLogs.Instance); + using NewPendingTransactionsSubscription subscription = + new( + // ReSharper disable once AccessToDisposedClosure + jsonRpcDuplexClient: client, + txPool: txPool, + specProvider: _specProvider, + logManager: LimboLogs.Instance + ); for (int i = 0; i < messages; i++) { @@ -938,12 +944,14 @@ public async Task MultipleSubscriptions_concurrent_fast_messages(int messages) Task subB = Task.Run(() => { IBlockTree blockTree = Substitute.For(); - using NewHeadSubscription subscription = new( - // ReSharper disable once AccessToDisposedClosure - jsonRpcDuplexClient: client, - blockTree: blockTree, - specProvider: new TestSpecProvider(new ReleaseSpec()), - logManager: LimboLogs.Instance); + using NewHeadSubscription subscription = + new( + // ReSharper disable once AccessToDisposedClosure + jsonRpcDuplexClient: client, + blockTree: blockTree, + specProvider: new TestSpecProvider(new ReleaseSpec()), + logManager: LimboLogs.Instance + ); for (int i = 0; i < messages; i++) { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index 6adb304f637..2dffcfa9733 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -584,47 +584,49 @@ public ResultWrapper> eth_getFilterLogs(UInt256 filterId) public ResultWrapper> eth_getLogs(Filter filter) { - BlockParameter fromBlock = filter.FromBlock; - BlockParameter toBlock = filter.ToBlock; + BlockParameter fromBlock = filter.FromBlock!; + BlockParameter toBlock = filter.ToBlock!; // because of lazy evaluation of enumerable, we need to do the validation here first using CancellationTokenSource timeout = BuildTimeoutCancellationTokenSource(); CancellationToken cancellationToken = timeout.Token; - if (!TryFindBlockHeaderOrUseLatest(_blockFinder, ref toBlock, out SearchResult toBlockResult, out long? sourceToBlockNumber)) + long? headNumber = _blockFinder.Head?.Number; + if (headNumber < fromBlock.BlockNumber || headNumber < toBlock.BlockNumber) { - return FailWithNoHeadersSyncedYet(toBlockResult); + return ResultWrapper>.Fail("requested block range is in the future", ErrorCodes.InvalidParams); } - - cancellationToken.ThrowIfCancellationRequested(); - - SearchResult fromBlockResult; - long? sourceFromBlockNumber; - - if (fromBlock == toBlock) + if (fromBlock.BlockNumber > toBlock.BlockNumber) { - fromBlockResult = toBlockResult; - sourceFromBlockNumber = sourceToBlockNumber; + return ResultWrapper>.Fail("invalid block range params", ErrorCodes.InvalidParams); } - else if (!TryFindBlockHeaderOrUseLatest(_blockFinder, ref fromBlock, out fromBlockResult, out sourceFromBlockNumber)) + + SearchResult fromResult = blockFinder.SearchForHeader(fromBlock); + if (fromResult.IsError) { - return FailWithNoHeadersSyncedYet(fromBlockResult); + return FailWithNoHeadersSyncedYet(fromResult); } - if (sourceFromBlockNumber > sourceToBlockNumber) + cancellationToken.ThrowIfCancellationRequested(); + + SearchResult toResult; + if (fromBlock == toBlock) { - return ResultWrapper>.Fail("invalid block range params", ErrorCodes.InvalidParams); + toResult = fromResult; } - - if (_blockFinder.Head?.Number is not null && sourceFromBlockNumber > _blockFinder.Head.Number) + else { - return ResultWrapper>.Success([]); + toResult = blockFinder.SearchForHeader(toBlock); + if (toResult.IsError) + { + return FailWithNoHeadersSyncedYet(toResult); + } } cancellationToken.ThrowIfCancellationRequested(); - BlockHeader fromBlockHeader = fromBlockResult.Object; - BlockHeader toBlockHeader = toBlockResult.Object; + BlockHeader fromBlockHeader = fromResult.Object!; + BlockHeader toBlockHeader = toResult.Object!; try { @@ -655,30 +657,6 @@ public ResultWrapper> eth_getLogs(Filter filter) ResultWrapper> FailWithNoHeadersSyncedYet(SearchResult blockResult) => GetFailureResult, BlockHeader>(blockResult, _ethSyncingInfo.SyncMode.HaveNotSyncedHeadersYet()); - - // If there is an error, we check if we seach by number and it's after the head, then try to use head instead - static bool TryFindBlockHeaderOrUseLatest(IBlockFinder blockFinder, ref BlockParameter blockParameter, out SearchResult blockResult, out long? sourceBlockNumber) - { - blockResult = blockFinder.SearchForHeader(blockParameter); - - if (blockResult.IsError) - { - if (blockParameter.Type is BlockParameterType.BlockNumber && - blockFinder.Head?.Number < blockParameter.BlockNumber) - { - blockResult = new SearchResult(blockFinder.Head.Header); - - sourceBlockNumber = blockParameter.BlockNumber.Value; - return true; - } - - sourceBlockNumber = null; - return false; - } - - sourceBlockNumber = blockResult.Object.Number; - return true; - } } // https://github.com/ethereum/EIPs/issues/1186 diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/Filter.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/Filter.cs index 0b3a0284bdb..0343cbf9445 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/Filter.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/Filter.cs @@ -1,28 +1,29 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Text.Json; - using Nethermind.Blockchain.Find; +using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.JsonRpc.Data; namespace Nethermind.JsonRpc.Modules.Eth; public class Filter : IJsonRpcParam { - public object? Address { get; set; } + public AddressAsKey[]? Address { get; set; } - public BlockParameter? FromBlock { get; set; } + public BlockParameter FromBlock { get; set; } - public BlockParameter? ToBlock { get; set; } + public BlockParameter ToBlock { get; set; } - public IEnumerable? Topics { get; set; } + public IEnumerable? Topics { get; set; } public void ReadJson(JsonElement filter, JsonSerializerOptions options) { JsonDocument doc = null; - string blockHash = null; try { if (filter.ValueKind == JsonValueKind.String) @@ -31,34 +32,39 @@ public void ReadJson(JsonElement filter, JsonSerializerOptions options) filter = doc.RootElement; } - if (filter.TryGetProperty("blockHash"u8, out JsonElement blockHashElement)) - { - blockHash = blockHashElement.GetString(); - } + bool hasBlockHash = filter.TryGetProperty("blockHash"u8, out JsonElement blockHashElement); + bool hasFromBlock = filter.TryGetProperty("fromBlock"u8, out JsonElement fromBlockElement); + bool hasToBlock = filter.TryGetProperty("toBlock"u8, out JsonElement toBlockElement); - if (blockHash is null) + if (hasBlockHash && blockHashElement.ValueKind != JsonValueKind.Null) { - filter.TryGetProperty("fromBlock"u8, out JsonElement fromBlockElement); - FromBlock = BlockParameterConverter.GetBlockParameter(fromBlockElement.ToString()); - filter.TryGetProperty("toBlock"u8, out JsonElement toBlockElement); - ToBlock = BlockParameterConverter.GetBlockParameter(toBlockElement.ToString()); + if (hasFromBlock || hasToBlock) + { + throw new ArgumentException("cannot specify both BlockHash and FromBlock/ToBlock, choose one or the other"); + } + + FromBlock = new(new Hash256(blockHashElement.ToString())); + ToBlock = FromBlock; } else { - FromBlock = ToBlock = BlockParameterConverter.GetBlockParameter(blockHash); + FromBlock = hasFromBlock && fromBlockElement.ValueKind != JsonValueKind.Null + ? BlockParameterConverter.GetBlockParameter(fromBlockElement.ToString()) + : BlockParameter.Earliest; + ToBlock = hasToBlock && toBlockElement.ValueKind != JsonValueKind.Null + ? BlockParameterConverter.GetBlockParameter(toBlockElement.ToString()) + : BlockParameter.Latest; } - filter.TryGetProperty("address"u8, out JsonElement addressElement); - Address = GetAddress(addressElement, options); + if (filter.TryGetProperty("address"u8, out JsonElement addressElement)) + { + Address = GetAddress(addressElement, options); + } if (filter.TryGetProperty("topics"u8, out JsonElement topicsElement) && topicsElement.ValueKind == JsonValueKind.Array) { Topics = GetTopics(topicsElement, options); } - else - { - Topics = null; - } } finally { @@ -66,9 +72,29 @@ public void ReadJson(JsonElement filter, JsonSerializerOptions options) } } - private static object? GetAddress(JsonElement? token, JsonSerializerOptions options) => GetSingleOrMany(token, options); + private static AddressAsKey[]? GetAddress(JsonElement token, JsonSerializerOptions options) + { + switch (token.ValueKind) + { + case JsonValueKind.Undefined or JsonValueKind.Null: + return null; + case JsonValueKind.String: + return [new AddressAsKey(new Address(token.ToString()))]; + case JsonValueKind.Array: + var enumerator = token.EnumerateArray(); + List result = new(); + while (enumerator.MoveNext()) + { + result.Add(new(new Address(enumerator.Current.ToString()))); + } + + return result.ToArray(); + default: + throw new ArgumentException("invalid address field"); + } + } - private static IEnumerable GetTopics(JsonElement? array, JsonSerializerOptions options) + private static IEnumerable? GetTopics(JsonElement? array, JsonSerializerOptions options) { if (array is null) { @@ -77,16 +103,27 @@ public void ReadJson(JsonElement filter, JsonSerializerOptions options) foreach (var token in array.GetValueOrDefault().EnumerateArray()) { - yield return GetSingleOrMany(token, options); + switch (token.ValueKind) + { + case JsonValueKind.Undefined or JsonValueKind.Null: + yield return null; + break; + case JsonValueKind.String: + yield return [new Hash256(token.GetString()!)]; + break; + case JsonValueKind.Array: + JsonElement.ArrayEnumerator enumerator = token.EnumerateArray(); + List result = new(); + while (enumerator.MoveNext()) + { + result.Add(new(enumerator.Current.ToString())); + } + + yield return result.ToArray(); + break; + default: + throw new ArgumentException("invalid topics field"); + } } } - - private static object? GetSingleOrMany(JsonElement? token, JsonSerializerOptions options) => token switch - { - null => null, - { ValueKind: JsonValueKind.Undefined } _ => null, - { ValueKind: JsonValueKind.Null } _ => null, - { ValueKind: JsonValueKind.Array } _ => token.GetValueOrDefault().Deserialize(options), - _ => token.GetValueOrDefault().GetString(), - }; } From a3e3ba57f351f824501a4eedab121f76e6d0ad3f Mon Sep 17 00:00:00 2001 From: VolodymyrBg Date: Thu, 11 Dec 2025 23:39:09 +0200 Subject: [PATCH 067/255] fix: remove duplicate gRPC host validation in GrpcClient (#9922) --- src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs b/src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs index 2855a1a2e0f..5ba7a4b1bc5 100644 --- a/src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs +++ b/src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs @@ -38,9 +38,7 @@ public GrpcClient(string host, int port, int reconnectionInterval, ILogManager l nameof(reconnectionInterval)); } - _address = string.IsNullOrWhiteSpace(host) - ? throw new ArgumentException("Missing gRPC host", nameof(host)) - : $"{host}:{port}"; + _address = $"{host}:{port}"; _reconnectionInterval = reconnectionInterval; _logger = logManager.GetClassLogger(); } From de6b7b8231e11a2656b2343c249bd21392f6eebb Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Thu, 11 Dec 2025 22:46:00 +0100 Subject: [PATCH 068/255] Move ExecutionEnvironment to Rentable sealed class (#9916) * Move ExecutionEnvironment to Rentable sealed class * fixes * convert to properties * fix * better * fix Benchmarks * comment * Update src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/Nethermind/Nethermind.Evm/EvmState.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Apply suggestion from @alexb5dh Co-authored-by: Alex * Refactor Disposing * fixes * Add Dispose guard --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Alex --- .../Nethermind.Evm.Benchmark/EvmBenchmarks.cs | 10 +- .../MultipleUnsignedOperations.cs | 10 +- .../StaticCallBenchmarks.cs | 10 +- .../Nethermind.Evm.Test/EvmStateTests.cs | 7 +- src/Nethermind/Nethermind.Evm/EvmState.cs | 30 +++--- .../Nethermind.Evm/ExecutionEnvironment.cs | 99 +++++++++++++++---- .../ExecutionEnvironmentExtensions.cs | 2 +- .../Instructions/EvmInstructions.Call.cs | 6 +- .../EvmInstructions.ControlFlow.cs | 10 +- .../Instructions/EvmInstructions.Create.cs | 6 +- .../Instructions/EvmInstructions.Eof.cs | 12 +-- .../Instructions/EvmInstructions.Stack.cs | 2 +- .../Nethermind.Evm/TransactionExtensions.cs | 4 +- .../TransactionProcessor.cs | 74 +++++++------- .../Nethermind.Evm/VirtualMachine.Warmup.cs | 20 ++-- .../Nethermind.Evm/VirtualMachine.cs | 4 +- 16 files changed, 194 insertions(+), 112 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs index 20496ca0c67..9295fc1f5db 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs @@ -49,8 +49,7 @@ public void GlobalSetup() _virtualMachine.SetBlockExecutionContext(new BlockExecutionContext(_header, _spec)); _virtualMachine.SetTxExecutionContext(new TxExecutionContext(Address.Zero, codeInfoRepository, null, 0)); - _environment = new ExecutionEnvironment - ( + _environment = ExecutionEnvironment.Rent( executingAccount: Address.Zero, codeSource: Address.Zero, caller: Address.Zero, @@ -64,6 +63,13 @@ public void GlobalSetup() _evmState = EvmState.RentTopLevel(long.MaxValue, ExecutionType.TRANSACTION, _environment, new StackAccessTracker(), _stateProvider.TakeSnapshot()); } + [GlobalCleanup] + public void GlobalCleanup() + { + _evmState.Dispose(); + _environment.Dispose(); + } + [Benchmark] public void ExecuteCode() { diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs index 336da145475..a627a5e4691 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs @@ -81,8 +81,7 @@ public void GlobalSetup() _virtualMachine.SetBlockExecutionContext(new BlockExecutionContext(_header, _spec)); _virtualMachine.SetTxExecutionContext(new TxExecutionContext(Address.Zero, codeInfoRepository, null, 0)); - _environment = new ExecutionEnvironment - ( + _environment = ExecutionEnvironment.Rent( executingAccount: Address.Zero, codeSource: Address.Zero, caller: Address.Zero, @@ -96,6 +95,13 @@ public void GlobalSetup() _evmState = EvmState.RentTopLevel(100_000_000L, ExecutionType.TRANSACTION, _environment, new StackAccessTracker(), _stateProvider.TakeSnapshot()); } + [GlobalCleanup] + public void GlobalCleanup() + { + _evmState.Dispose(); + _environment.Dispose(); + } + [Benchmark] public void ExecuteCode() { diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs index 93916272630..3f5d0c4ca16 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs @@ -91,8 +91,7 @@ public void GlobalSetup() _virtualMachine = new VirtualMachine(_blockhashProvider, MainnetSpecProvider.Instance, new OneLoggerLogManager(NullLogger.Instance)); _virtualMachine.SetBlockExecutionContext(new BlockExecutionContext(_header, _spec)); _virtualMachine.SetTxExecutionContext(new TxExecutionContext(Address.Zero, codeInfoRepository, null, 0)); - _environment = new ExecutionEnvironment - ( + _environment = ExecutionEnvironment.Rent( executingAccount: Address.Zero, codeSource: Address.Zero, caller: Address.Zero, @@ -106,6 +105,13 @@ public void GlobalSetup() _evmState = EvmState.RentTopLevel(100_000_000L, ExecutionType.TRANSACTION, _environment, new StackAccessTracker(), _stateProvider.TakeSnapshot()); } + [GlobalCleanup] + public void GlobalCleanup() + { + _evmState.Dispose(); + _environment.Dispose(); + } + [Benchmark(Baseline = true)] public void ExecuteCode() { diff --git a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs b/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs index f46d0d83437..ec3060c5cd9 100644 --- a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs @@ -224,7 +224,7 @@ private static EvmState CreateEvmState(EvmState parentEvmState = null, bool isCo parentEvmState is null ? EvmState.RentTopLevel(10000, ExecutionType.CALL, - new ExecutionEnvironment(), + RentExecutionEnvironment(), new StackAccessTracker(), Snapshot.Empty) : EvmState.RentFrame(10000, @@ -233,10 +233,11 @@ parentEvmState is null ExecutionType.CALL, false, false, - new ExecutionEnvironment(), + RentExecutionEnvironment(), parentEvmState.AccessTracker, Snapshot.Empty); - public class Context { } + private static ExecutionEnvironment RentExecutionEnvironment() => + ExecutionEnvironment.Rent(null, null, null, null, 0, default, default, default); } } diff --git a/src/Nethermind/Nethermind.Evm/EvmState.cs b/src/Nethermind/Nethermind.Evm/EvmState.cs index 872db9b4ea8..b3459da4540 100644 --- a/src/Nethermind/Nethermind.Evm/EvmState.cs +++ b/src/Nethermind/Nethermind.Evm/EvmState.cs @@ -22,7 +22,7 @@ public sealed class EvmState : IDisposable // TODO: rename to CallState /* Type layout for 'EvmState' - Size: 264 bytes. Paddings: 9 bytes (%3 of empty space) + Size: 176 bytes. Paddings: 5 bytes (%3 of empty space) |=======================================================================| | Object Header (8 bytes) | |-----------------------------------------------------------------------| @@ -66,13 +66,13 @@ public sealed class EvmState : IDisposable // TODO: rename to CallState |-----------------------------------------------------------------------| | 72-103: EvmPooledMemory _memory (32 bytes) | |-----------------------------------------------------------------------| - | 104-223: ExecutionEnvironment _env (120 bytes) | + | 104-111: ExecutionEnvironment _env (8 bytes) | |-----------------------------------------------------------------------| - | 224-247: StackAccessTracker _accessTracker (24 bytes) | + | 112-143: StackAccessTracker _accessTracker (32 bytes) | |-----------------------------------------------------------------------| - | 248-259: Snapshot _snapshot (12 bytes) | + | 144-155: Snapshot _snapshot (12 bytes) | |-----------------------------------------------------------------------| - | 260-263: padding (4 bytes) | + | 156-159: padding (4 bytes) | |=======================================================================| */ @@ -96,21 +96,17 @@ public sealed class EvmState : IDisposable // TODO: rename to CallState private bool _isDisposed = true; private EvmPooledMemory _memory; - private ExecutionEnvironment _env; + private ExecutionEnvironment? _env; private StackAccessTracker _accessTracker; private Snapshot _snapshot; -#if DEBUG - private StackTrace? _creationStackTrace; -#endif - /// /// Rent a top level . /// public static EvmState RentTopLevel( long gasAvailable, ExecutionType executionType, - in ExecutionEnvironment env, + ExecutionEnvironment env, in StackAccessTracker accessedItems, in Snapshot snapshot) { @@ -139,7 +135,7 @@ public static EvmState RentFrame( ExecutionType executionType, bool isStatic, bool isCreateOnPreExistingAccount, - in ExecutionEnvironment env, + ExecutionEnvironment env, in StackAccessTracker stateForAccessLists, in Snapshot snapshot, bool isTopLevel = false) @@ -171,7 +167,7 @@ private void Initialize( bool isTopLevel, bool isStatic, bool isCreateOnPreExistingAccount, - in ExecutionEnvironment env, + ExecutionEnvironment env, in StackAccessTracker stateForAccessLists, in Snapshot snapshot) { @@ -226,7 +222,7 @@ ExecutionType.STATICCALL or ExecutionType.CALL or ExecutionType.CALLCODE or Exec public bool IsPrecompile => Env.CodeInfo?.IsPrecompile ?? false; public ref readonly StackAccessTracker AccessTracker => ref _accessTracker; - public ref readonly ExecutionEnvironment Env => ref _env; + public ExecutionEnvironment Env => _env!; public ref EvmPooledMemory Memory => ref _memory; // TODO: move to CallEnv public ref readonly Snapshot Snapshot => ref _snapshot; // TODO: move to CallEnv @@ -255,7 +251,8 @@ public void Dispose() _memory.Dispose(); _memory = default; _accessTracker = default; - _env = default; + if (!IsTopLevel) _env?.Dispose(); + _env = null; _snapshot = default; _statePool.Enqueue(this); @@ -266,6 +263,9 @@ public void Dispose() } #if DEBUG + + private StackTrace? _creationStackTrace; + ~EvmState() { if (!_isDisposed) diff --git a/src/Nethermind/Nethermind.Evm/ExecutionEnvironment.cs b/src/Nethermind/Nethermind.Evm/ExecutionEnvironment.cs index a186862e72f..0f396d82bd4 100644 --- a/src/Nethermind/Nethermind.Evm/ExecutionEnvironment.cs +++ b/src/Nethermind/Nethermind.Evm/ExecutionEnvironment.cs @@ -2,60 +2,123 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Concurrent; +using System.Diagnostics; using Nethermind.Core; using Nethermind.Evm.CodeAnalysis; using Nethermind.Int256; namespace Nethermind.Evm { - public readonly struct ExecutionEnvironment( - ICodeInfo codeInfo, - Address executingAccount, - Address caller, - Address? codeSource, - int callDepth, - in UInt256 transferValue, - in UInt256 value, - in ReadOnlyMemory inputData) + /// + /// Execution environment for EVM calls. Pooled to avoid allocation and GC write barrier overhead. + /// + public sealed class ExecutionEnvironment : IDisposable { + private static readonly ConcurrentQueue _pool = new(); + private UInt256 _value; + private UInt256 _transferValue; + /// /// Parsed bytecode for the current call. /// - public readonly ICodeInfo CodeInfo = codeInfo; + public ICodeInfo CodeInfo { get; private set; } = null!; /// /// Currently executing account (in DELEGATECALL this will be equal to caller). /// - public readonly Address ExecutingAccount = executingAccount; + public Address ExecutingAccount { get; private set; } = null!; /// /// Caller /// - public readonly Address Caller = caller; + public Address Caller { get; private set; } = null!; /// /// Bytecode source (account address). /// - public readonly Address? CodeSource = codeSource; + public Address? CodeSource { get; private set; } /// If we call TX -> DELEGATECALL -> CALL -> STATICCALL then the call depth would be 3. - public readonly int CallDepth = callDepth; + public int CallDepth { get; private set; } /// /// ETH value transferred in this call. /// - public readonly UInt256 TransferValue = transferValue; + public ref readonly UInt256 TransferValue => ref _transferValue; /// /// Value information passed (it is different from transfer value in DELEGATECALL. - /// DELEGATECALL behaves like a library call and it uses the value information from the caller even + /// DELEGATECALL behaves like a library call, and it uses the value information from the caller even /// as no transfer happens. /// - public readonly UInt256 Value = value; + public ref readonly UInt256 Value => ref _value; /// /// Parameters / arguments of the current call. /// - public readonly ReadOnlyMemory InputData = inputData; + public ReadOnlyMemory InputData { get; private set; } + + private ExecutionEnvironment() { } + + /// + /// Rents an ExecutionEnvironment from the pool and initializes it with the provided values. + /// + public static ExecutionEnvironment Rent( + ICodeInfo codeInfo, + Address executingAccount, + Address caller, + Address? codeSource, + int callDepth, + in UInt256 transferValue, + in UInt256 value, + in ReadOnlyMemory inputData) + { + ExecutionEnvironment env = _pool.TryDequeue(out ExecutionEnvironment pooled) ? pooled : new ExecutionEnvironment(); + env.CodeInfo = codeInfo; + env.ExecutingAccount = executingAccount; + env.Caller = caller; + env.CodeSource = codeSource; + env.CallDepth = callDepth; + env._transferValue = transferValue; + env._value = value; + env.InputData = inputData; + return env; + } + + /// + /// Returns the ExecutionEnvironment to the pool for reuse. + /// + public void Dispose() + { + if (ExecutingAccount is not null) + { + CodeInfo = null!; + ExecutingAccount = null!; + Caller = null!; + CodeSource = null; + CallDepth = 0; + _transferValue = default; + _value = default; + InputData = default; + _pool.Enqueue(this); + } +#if DEBUG + GC.SuppressFinalize(this); +#endif + } + +#if DEBUG + + private readonly StackTrace _creationStackTrace = new(); + + ~ExecutionEnvironment() + { + if (ExecutingAccount is null) + { + Console.Error.WriteLine($"Warning: {nameof(ExecutionEnvironment)} was not disposed. Created at: {_creationStackTrace}"); + } + } +#endif } } diff --git a/src/Nethermind/Nethermind.Evm/ExecutionEnvironmentExtensions.cs b/src/Nethermind/Nethermind.Evm/ExecutionEnvironmentExtensions.cs index 03f48b11ffb..68c6e5f97f2 100644 --- a/src/Nethermind/Nethermind.Evm/ExecutionEnvironmentExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/ExecutionEnvironmentExtensions.cs @@ -5,5 +5,5 @@ namespace Nethermind.Evm; public static class ExecutionEnvironmentExtensions { - public static int GetGethTraceDepth(in this ExecutionEnvironment env) => env.CallDepth + 1; + public static int GetGethTraceDepth(this ExecutionEnvironment env) => env.CallDepth + 1; } diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs index cf20f33a69d..a739311a24c 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs @@ -109,7 +109,7 @@ public static EvmExceptionType InstructionCall( Address codeSource = stack.PopAddress(); if (codeSource is null) goto StackUnderflow; - ref readonly ExecutionEnvironment env = ref vm.EvmState.Env; + ExecutionEnvironment env = vm.EvmState.Env; // Determine the call value based on the call type. UInt256 callValue; if (typeof(TOpCall) == typeof(OpStaticCall)) @@ -255,7 +255,7 @@ public static EvmExceptionType InstructionCall( if (!vm.EvmState.Memory.TryLoad(in dataOffset, dataLength, out ReadOnlyMemory callData)) goto OutOfGas; // Construct the execution environment for the call. - ExecutionEnvironment callEnv = new( + ExecutionEnvironment callEnv = ExecutionEnvironment.Rent( codeInfo: codeInfo, executingAccount: target, caller: caller, @@ -280,7 +280,7 @@ public static EvmExceptionType InstructionCall( executionType: TOpCall.ExecutionType, isStatic: TOpCall.IsStatic || vm.EvmState.IsStatic, isCreateOnPreExistingAccount: false, - env: in callEnv, + env: callEnv, stateForAccessLists: in vm.EvmState.AccessTracker, snapshot: in snapshot); diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs index c9ff58328c6..d0b99f8e889 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs @@ -78,7 +78,7 @@ public static EvmExceptionType InstructionJump(VirtualMachine vm, ref EvmStack s // Pop the jump destination from the stack. if (!stack.PopUInt256(out UInt256 result)) goto StackUnderflow; // Validate the jump destination and update the program counter if valid. - if (!Jump(result, ref programCounter, in vm.EvmState.Env)) goto InvalidJumpDestination; + if (!Jump(result, ref programCounter, vm.EvmState.Env)) goto InvalidJumpDestination; return EvmExceptionType.None; // Jump forward to be unpredicted by the branch predictor. @@ -114,7 +114,7 @@ public static EvmExceptionType InstructionJumpIf(VirtualMachine vm, ref EvmStack if (isOverflow) goto StackUnderflow; if (shouldJump) { - if (!Jump(result, ref programCounter, in vm.EvmState.Env)) goto InvalidJumpDestination; + if (!Jump(result, ref programCounter, vm.EvmState.Env)) goto InvalidJumpDestination; } return EvmExceptionType.None; @@ -303,7 +303,7 @@ public static EvmExceptionType InstructionBadInstruction(VirtualMachine _, ref E /// true if the destination is valid and the program counter is updated; otherwise, false. /// [SkipLocalsInit] - private static bool Jump(in UInt256 jumpDestination, ref int programCounter, in ExecutionEnvironment env) + private static bool Jump(in UInt256 jumpDestination, ref int programCounter, ExecutionEnvironment env) { // Check if the jump destination exceeds the maximum allowed integer value. if (jumpDestination > int.MaxValue) @@ -312,10 +312,10 @@ private static bool Jump(in UInt256 jumpDestination, ref int programCounter, in } // Extract the jump destination from the lowest limb of the UInt256. - return Jump((int)jumpDestination.u0, ref programCounter, in env); + return Jump((int)jumpDestination.u0, ref programCounter, env); } - private static bool Jump(int jumpDestination, ref int programCounter, in ExecutionEnvironment env) + private static bool Jump(int jumpDestination, ref int programCounter, ExecutionEnvironment env) { // Validate that the jump destination corresponds to a valid jump marker in the code. if (!env.CodeInfo.ValidateJump(jumpDestination)) diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs index 802d2d67a66..77cf13c8743 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs @@ -85,7 +85,7 @@ public static EvmExceptionType InstructionCreate( // Reset the return data buffer as contract creation does not use previous return data. vm.ReturnData = null; - ref readonly ExecutionEnvironment env = ref vm.EvmState.Env; + ExecutionEnvironment env = vm.EvmState.Env; IWorldState state = vm.WorldState; // Pop parameters off the stack: value to transfer, memory position for the initialization code, @@ -222,7 +222,7 @@ public static EvmExceptionType InstructionCreate( // Construct a new execution environment for the contract creation call. // This environment sets up the call frame for executing the contract's initialization code. - ExecutionEnvironment callEnv = new( + ExecutionEnvironment callEnv = ExecutionEnvironment.Rent( codeInfo: codeInfo, executingAccount: contractAddress, caller: env.ExecutingAccount, @@ -240,7 +240,7 @@ public static EvmExceptionType InstructionCreate( executionType: TOpCreate.ExecutionType, isStatic: vm.EvmState.IsStatic, isCreateOnPreExistingAccount: accountExists, - env: in callEnv, + env: callEnv, stateForAccessLists: in vm.EvmState.AccessTracker, snapshot: in snapshot); None: diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs index f83c470b19f..73dbe12a592 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs @@ -615,7 +615,7 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine vm.ReturnData = null; IReleaseSpec spec = vm.Spec; - ref readonly ExecutionEnvironment env = ref vm.EvmState.Env; + ExecutionEnvironment env = vm.EvmState.Env; if (env.CodeInfo.Version == 0) goto BadInstruction; @@ -730,7 +730,7 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine goto OutOfGas; // Set up the execution environment for the new contract. - ExecutionEnvironment callEnv = new( + ExecutionEnvironment callEnv = ExecutionEnvironment.Rent( codeInfo: codeInfo, executingAccount: contractAddress, caller: env.ExecutingAccount, @@ -747,7 +747,7 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine executionType: currentContext, isStatic: vm.EvmState.IsStatic, isCreateOnPreExistingAccount: accountExists, - env: in callEnv, + env: callEnv, stateForAccessLists: in vm.EvmState.AccessTracker, snapshot: in snapshot); @@ -864,7 +864,7 @@ public static EvmExceptionType InstructionEofCall(Virt IReleaseSpec spec = vm.Spec; vm.ReturnData = null; - ref readonly ExecutionEnvironment env = ref vm.EvmState.Env; + ExecutionEnvironment env = vm.EvmState.Env; IWorldState state = vm.WorldState; // This instruction is only available for EOF-enabled contracts. @@ -987,7 +987,7 @@ public static EvmExceptionType InstructionEofCall(Virt state.SubtractFromBalance(caller, transferValue, spec); // Set up the new execution environment for the call. - ExecutionEnvironment callEnv = new( + ExecutionEnvironment callEnv = ExecutionEnvironment.Rent( codeInfo: targetCodeInfo, executingAccount: target, caller: caller, @@ -1004,7 +1004,7 @@ public static EvmExceptionType InstructionEofCall(Virt executionType: TOpEofCall.ExecutionType, isStatic: TOpEofCall.IsStatic || vm.EvmState.IsStatic, isCreateOnPreExistingAccount: false, - env: in callEnv, + env: callEnv, stateForAccessLists: in vm.EvmState.AccessTracker, snapshot: in snapshot); diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs index 354b8bb798b..9ac15c682f9 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs @@ -159,7 +159,7 @@ public static EvmExceptionType InstructionPush2(VirtualMachine vm, } // Validate the jump destination and update the program counter if valid. - if (!Jump((int)destination, ref programCounter, in vm.EvmState.Env)) + if (!Jump((int)destination, ref programCounter, vm.EvmState.Env)) goto InvalidJumpDestination; goto Success; diff --git a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs index 8ab7cb6ace8..811d29510f6 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs @@ -10,9 +10,9 @@ namespace Nethermind.Evm { public static class TransactionExtensions { - public static Address? GetRecipient(this Transaction tx, in UInt256 nonce) => + public static Address GetRecipient(this Transaction tx, in UInt256 nonce) => tx.To ?? (tx.IsSystem() - ? tx.SenderAddress + ? tx.SenderAddress! : ContractAddress.From(tx.SenderAddress, nonce > 0 ? nonce - 1 : nonce)); public static TxGasInfo GetGasInfo(this Transaction tx, IReleaseSpec spec, BlockHeader header) diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index b2c3a7f5fec..903247ad5d4 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -199,7 +199,8 @@ protected virtual TransactionResult Execute(Transaction tx, ITxTracer tracer, Ex int delegationRefunds = (!spec.IsEip7702Enabled || !tx.HasAuthorizationList) ? 0 : ProcessDelegations(tx, spec, accessTracker); if (!(result = CalculateAvailableGas(tx, intrinsicGas, out long gasAvailable))) return result; - if (!(result = BuildExecutionEnvironment(tx, spec, _codeInfoRepository, accessTracker, out ExecutionEnvironment env))) return result; + if (!(result = BuildExecutionEnvironment(tx, spec, _codeInfoRepository, accessTracker, out ExecutionEnvironment e))) return result; + using ExecutionEnvironment env = e; int statusCode = !tracer.IsTracingInstructions ? ExecuteEvmCall(tx, header, spec, tracer, opts, delegationRefunds, intrinsicGas, accessTracker, gasAvailable, env, out TransactionSubstate substate, out GasConsumed spentGas) : @@ -590,7 +591,6 @@ private TransactionResult BuildExecutionEnvironment( { Address recipient = tx.GetRecipient(tx.IsContractCreation ? WorldState.GetNonce(tx.SenderAddress!) : 0); if (recipient is null) ThrowInvalidDataException("Recipient has not been resolved properly before tx execution"); - ICodeInfo? codeInfo; ReadOnlyMemory inputData = tx.IsMessageCall ? tx.Data : default; if (tx.IsContractCreation) @@ -621,7 +621,7 @@ private TransactionResult BuildExecutionEnvironment( accessTracker.WarmUp(tx.SenderAddress!); } - env = new ExecutionEnvironment( + env = ExecutionEnvironment.Rent( codeInfo: codeInfo, executingAccount: recipient, caller: tx.SenderAddress!, @@ -646,7 +646,7 @@ private int ExecuteEvmCall( IntrinsicGas gas, in StackAccessTracker accessedItems, long gasAvailable, - in ExecutionEnvironment env, + ExecutionEnvironment env, out TransactionSubstate substate, out GasConsumed gasConsumed) where TTracingInst : struct, IFlag @@ -683,56 +683,56 @@ private int ExecuteEvmCall( ExecutionType executionType = tx.IsContractCreation ? ((spec.IsEofEnabled && tx.IsEofContractCreation) ? ExecutionType.TXCREATE : ExecutionType.CREATE) : ExecutionType.TRANSACTION; - using (EvmState state = EvmState.RentTopLevel(gasAvailable, executionType, in env, in accessedItems, in snapshot)) + using (EvmState state = EvmState.RentTopLevel(gasAvailable, executionType, env, in accessedItems, in snapshot)) { substate = VirtualMachine.ExecuteTransaction(state, WorldState, tracer); Metrics.IncrementOpCodes(VirtualMachine.OpCodeCount); gasAvailable = state.GasAvailable; - } - if (tracer.IsTracingAccess) - { - tracer.ReportAccess(accessedItems.AccessedAddresses, accessedItems.AccessedStorageCells); - } + if (tracer.IsTracingAccess) + { + tracer.ReportAccess(accessedItems.AccessedAddresses, accessedItems.AccessedStorageCells); + } - if (substate.ShouldRevert || substate.IsError) - { - if (Logger.IsTrace) Logger.Trace("Restoring state from before transaction"); - WorldState.Restore(snapshot); - } - else - { - if (tx.IsContractCreation) + if (substate.ShouldRevert || substate.IsError) { - if (!spec.IsEofEnabled || tx.IsLegacyContractCreation) + if (Logger.IsTrace) Logger.Trace("Restoring state from before transaction"); + WorldState.Restore(snapshot); + } + else + { + if (tx.IsContractCreation) { - if (!DeployLegacyContract(spec, env.ExecutingAccount, in substate, in accessedItems, ref gasAvailable)) + if (!spec.IsEofEnabled || tx.IsLegacyContractCreation) { - goto FailContractCreate; + if (!DeployLegacyContract(spec, env.ExecutingAccount, in substate, in accessedItems, ref gasAvailable)) + { + goto FailContractCreate; + } } - } - else - { - if (!DeployEofContract(spec, env.ExecutingAccount, in substate, in accessedItems, ref gasAvailable)) + else { - goto FailContractCreate; + if (!DeployEofContract(spec, env.ExecutingAccount, in substate, in accessedItems, ref gasAvailable)) + { + goto FailContractCreate; + } } } - } - foreach (Address toBeDestroyed in substate.DestroyList) - { - if (Logger.IsTrace) - Logger.Trace($"Destroying account {toBeDestroyed}"); + foreach (Address toBeDestroyed in substate.DestroyList) + { + if (Logger.IsTrace) + Logger.Trace($"Destroying account {toBeDestroyed}"); - WorldState.ClearStorage(toBeDestroyed); - WorldState.DeleteAccount(toBeDestroyed); + WorldState.ClearStorage(toBeDestroyed); + WorldState.DeleteAccount(toBeDestroyed); - if (tracer.IsTracingRefunds) - tracer.ReportRefund(RefundOf.Destroy(spec.IsEip3529Enabled)); - } + if (tracer.IsTracingRefunds) + tracer.ReportRefund(RefundOf.Destroy(spec.IsEip3529Enabled)); + } - statusCode = StatusCode.Success; + statusCode = StatusCode.Success; + } } gasConsumed = Refund(tx, header, spec, opts, in substate, gasAvailable, diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.Warmup.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.Warmup.cs index c332d8fc63e..c86f1b39aa8 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.Warmup.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.Warmup.cs @@ -39,22 +39,22 @@ public static void WarmUpEvmInstructions(IWorldState state, ICodeInfoRepository state.CreateAccount(addressOne, 1000.Ether()); state.Commit(spec); - BlockHeader _header = new(Keccak.Zero, Keccak.Zero, addressOne, UInt256.One, MainnetSpecProvider.PragueActivation.BlockNumber, Int64.MaxValue, 1UL, Bytes.Empty, 0, 0); + BlockHeader header = new(Keccak.Zero, Keccak.Zero, addressOne, UInt256.One, MainnetSpecProvider.PragueActivation.BlockNumber, Int64.MaxValue, 1UL, Bytes.Empty, 0, 0); - vm.SetBlockExecutionContext(new BlockExecutionContext(_header, spec)); + vm.SetBlockExecutionContext(new BlockExecutionContext(header, spec)); vm.SetTxExecutionContext(new TxExecutionContext(addressOne, codeInfoRepository, null, 0)); - ExecutionEnvironment env = new( + using ExecutionEnvironment env = ExecutionEnvironment.Rent( + codeInfo: new CodeInfo(bytecode), executingAccount: addressOne, - codeSource: addressOne, caller: addressOne, - codeInfo: new CodeInfo(bytecode), - value: 0, + codeSource: addressOne, + callDepth: 0, transferValue: 0, - inputData: default, - callDepth: 0); + value: 0, + inputData: default); - using (var evmState = EvmState.RentTopLevel(long.MaxValue, ExecutionType.TRANSACTION, in env, new StackAccessTracker(), state.TakeSnapshot())) + using (EvmState evmState = EvmState.RentTopLevel(long.MaxValue, ExecutionType.TRANSACTION, env, new StackAccessTracker(), state.TakeSnapshot())) { vm.EvmState = evmState; vm._worldState = state; @@ -66,7 +66,7 @@ public static void WarmUpEvmInstructions(IWorldState state, ICodeInfoRepository } TransactionProcessor processor = new(BlobBaseFeeCalculator.Instance, MainnetSpecProvider.Instance, state, vm, codeInfoRepository, lm); - processor.SetBlockExecutionContext(new BlockExecutionContext(_header, spec)); + processor.SetBlockExecutionContext(new BlockExecutionContext(header, spec)); RunTransactions(processor, state, spec); } diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index 98366b35ef5..ceef34f926c 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -978,7 +978,7 @@ protected static bool UpdateGas(long gasCost, ref long gasAvailable) private CallResult RunPrecompile(EvmState state) { ReadOnlyMemory callData = state.Env.InputData; - UInt256 transferValue = state.Env.TransferValue; + ref readonly UInt256 transferValue = ref state.Env.TransferValue; long gasAvailable = state.GasAvailable; IPrecompile precompile = state.Env.CodeInfo.Precompile!; @@ -1092,7 +1092,7 @@ protected CallResult ExecuteCall( { EvmState vmState = _currentState; // Obtain a reference to the execution environment for convenience. - ref readonly ExecutionEnvironment env = ref vmState.Env; + ExecutionEnvironment env = vmState.Env; // If this is the first call frame (not a continuation), adjust account balances and nonces. if (!vmState.IsContinuation) From a86e5e60bb6321b6d9ed5ca45a5bb57533fc640f Mon Sep 17 00:00:00 2001 From: bigbear <155267841+aso20455@users.noreply.github.com> Date: Fri, 12 Dec 2025 13:37:29 +0200 Subject: [PATCH 069/255] fix: align BlockHashes dictionary to use nullable Hash256 (#9900) fix: make T8nBlockHashProvider accept non-nullable Hash256 --- tools/Evm/T8n/T8nBlockHashProvider.cs | 12 +++++++----- tools/Evm/T8n/T8nExecutor.cs | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/Evm/T8n/T8nBlockHashProvider.cs b/tools/Evm/T8n/T8nBlockHashProvider.cs index f8f2e80d7dc..41befa0d10b 100644 --- a/tools/Evm/T8n/T8nBlockHashProvider.cs +++ b/tools/Evm/T8n/T8nBlockHashProvider.cs @@ -10,15 +10,17 @@ namespace Evm.T8n; -public class T8nBlockHashProvider(Dictionary blockHashes) : IBlockhashProvider +public class T8nBlockHashProvider(Dictionary blockHashes) : IBlockhashProvider { public Hash256? GetBlockhash(BlockHeader currentBlock, long number, IReleaseSpec? spec) { long current = currentBlock.Number; - return number >= current || number < current - Math.Min(current, BlockhashProvider.MaxDepth) - ? null - : blockHashes.GetValueOrDefault(number, null) ?? - throw new T8nException($"BlockHash for block {number} not provided", + if (number >= current || number < current - Math.Min(current, BlockhashProvider.MaxDepth)) + return null; + + return blockHashes.TryGetValue(number, out Hash256? hash) + ? hash + : throw new T8nException($"BlockHash for block {number} not provided", T8nErrorCodes.ErrorMissingBlockhash); } diff --git a/tools/Evm/T8n/T8nExecutor.cs b/tools/Evm/T8n/T8nExecutor.cs index 140c962a31a..7298e7149f5 100644 --- a/tools/Evm/T8n/T8nExecutor.cs +++ b/tools/Evm/T8n/T8nExecutor.cs @@ -136,7 +136,7 @@ public static T8nExecutionResult Execute(T8nCommandArguments arguments) } private static IBlockhashProvider ConstructBlockHashProvider(T8nTest test) => - new T8nBlockHashProvider(test.BlockHashes.ToDictionary, long, Hash256?>(kvp => long.Parse(kvp.Key), kvp => kvp.Value)); + new T8nBlockHashProvider(test.BlockHashes.ToDictionary(kvp => long.Parse(kvp.Key), kvp => kvp.Value)); private static void ApplyRewards(Block block, IWorldState stateProvider, IReleaseSpec spec, ISpecProvider specProvider) { From ae852f436d655930e084809f9652831e2ceee66e Mon Sep 17 00:00:00 2001 From: Tanishq Jasoria Date: Fri, 12 Dec 2025 14:49:20 -0800 Subject: [PATCH 070/255] Only pool pure Transaction objects, not subclasses (#9884) check: --- src/Nethermind/Nethermind.Core/Transaction.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Nethermind/Nethermind.Core/Transaction.cs b/src/Nethermind/Nethermind.Core/Transaction.cs index 50062b9a524..e33c976cbc0 100644 --- a/src/Nethermind/Nethermind.Core/Transaction.cs +++ b/src/Nethermind/Nethermind.Core/Transaction.cs @@ -277,6 +277,12 @@ public Transaction Create() public bool Return(Transaction obj) { + + // Only pool pure Transaction objects, not subclasses + // This prevents other subclasses from contaminating the pool + if (obj.GetType() != typeof(Transaction)) + return false; + obj.ClearPreHash(); obj.Hash = default; obj.ChainId = default; From 39f6398c0307f109e9e50e9c3a920f251fbb911c Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Sun, 14 Dec 2025 09:14:41 +0100 Subject: [PATCH 071/255] Auto-update fast sync settings (#9933) Co-authored-by: rubo --- src/Nethermind/Nethermind.Runner/configs/base-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/base-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/chiado.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/gnosis.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/joc-testnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sepolia.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-mainnet.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-sepolia.json | 4 ++-- 14 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index 9bab05134e1..8a663659b58 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 39130000, - "PivotHash": "0x5e1f71fc2fa3b2e2a004d01a6a1066fcf9f828f71f69401d725eb5bce05249fe" + "PivotNumber": 39430000, + "PivotHash": "0xd8a2be662628c294991c74aac8c3b329dddde2d59d36d40e35a2efe282c0213e" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index 88c56c3faef..1fff2474ded 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 34640000, - "PivotHash": "0x1822ac708bf06e8a7e214ea797e8a99eb442cceea06312a9a36762d651458833" + "PivotNumber": 34940000, + "PivotHash": "0x2a7dc9daa709a6d3764ebbcb7e8c6c76d5c4d85682bdcd68f70079695558449c" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.json b/src/Nethermind/Nethermind.Runner/configs/chiado.json index d94a76a99b4..243bee7e36d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.json +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.json @@ -18,8 +18,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 19110000, - "PivotHash": "0x1a2b7e4f26fb3f6bc8701d5b4f3321a25dcf0fea271df67c2bd8003eb200d16c", + "PivotNumber": 19220000, + "PivotHash": "0xb50db9ad75826fda6a46c1c638867f9ff33d1569439fc69bdfe80daded1e003b", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": 10000000000, "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.json b/src/Nethermind/Nethermind.Runner/configs/gnosis.json index e538528d724..d2d51b23b36 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.json +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.json @@ -14,8 +14,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 43510000, - "PivotHash": "0xb0c231db103bc1c2c28810210cb1f5ac7c616961ddcd819f261c45d8226d3ede", + "PivotNumber": 43620000, + "PivotHash": "0x231c912a780bd0e68440db9b97fb01f5cd98d8efcac983fe1ba0c9b21a890f5e", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000, diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json index dee58f28777..2ce10b1cbb5 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 21080000, - "PivotHash": "0xfaaf1341b252eda3a70d64139e2edd1b641ef504afff90310754f2cb9661c6f6", - "PivotTotalDifficulty": "38120722" + "PivotNumber": 21200000, + "PivotHash": "0x9d93c2f009f93a4d42ee60fa2ba6ca417262d9c48b1dc8a1fa024a3c2abd407b", + "PivotTotalDifficulty": "38299258" }, "Metrics": { "NodeName": "JOC-Mainnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json index f23c07463ee..ef4fc753a69 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 14690000, - "PivotHash": "0x06781f796eec24970262644da990616ce0f9f0e449e32df4e2cc982303b42bb9", - "PivotTotalDifficulty": "24493309" + "PivotNumber": 14810000, + "PivotHash": "0x60d753d8e2a77906e13afeb59724e46baed553b41d4f68b7cb08769843929783", + "PivotTotalDifficulty": "24684265" }, "Metrics": { "NodeName": "JOC-Testnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json index 7d58e8611b9..f2d85dd3c12 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 26400000, - "PivotHash": "0x9cbdfb4d6b40b5ca8517df5fb100f6711e0c43af6be981727faafb72282ed866", + "PivotNumber": 26640000, + "PivotHash": "0x1488cbc5d34bec7d0bf5b6c45e8f9b459432085df6394e584364ba56d9e0c35a", "PivotTotalDifficulty": "0", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json index 7cd20b04b50..a6c1c20c6ce 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 21680000, - "PivotHash": "0xc14a4e4e9fd62815e6abbda005130819da527f4dc275ea2de6b30a424b656577", + "PivotNumber": 21980000, + "PivotHash": "0xd659545fc933b0b0f9c380b17aee455745d2c07d2e58ba90e64a29cbfd5a74f6", "PivotTotalDifficulty": "37331807", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index e9048e20466..3e60d205321 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -10,8 +10,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 23956000, - "PivotHash": "0x6ddc4344e36743b3b11796c1e13cdf6ec1ce3a641213a2a0aa7edbde9d3f9e63", + "PivotNumber": 24006000, + "PivotHash": "0x85fcf18757692f28b86ecbe9f53b2585d34e1e5628cb8d931095ddde297b57b3", "PivotTotalDifficulty": "58750003716598352816469", "FastSyncCatchUpHeightDelta": "10000000000", "AncientReceiptsBarrier": 15537394, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index ab48ee25c3d..28bdd097e74 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -15,8 +15,8 @@ "FastSyncCatchUpHeightDelta": "10000000000", "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, - "PivotNumber": 144720000, - "PivotHash": "0xe287883dee7b3da078899167050d8cfe83510fd93c9a724c5bd1a71e72c3e39f" + "PivotNumber": 145020000, + "PivotHash": "0x4a0fe1c9d2d524e86bfe1616776eccef51dc0ae4f52ccc75be6d78250ea69fb1" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index 9aec40a1439..730e6cd78f5 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 36620000, - "PivotHash": "0xa26b5e8265d105fede699b2d57b61a3002376f999d04a0107485258311f2f65f" + "PivotNumber": 36920000, + "PivotHash": "0xaaeb3d1d61a6c15e2ec8e47d0ce484d7f63ff3c3ee1bbc7bdfe6f002e8e9691c" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index d8db446f4ca..16012549209 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -17,8 +17,8 @@ "FastSync": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 9784000, - "PivotHash": "0x725e962b74cb04b27676159b5ed082831530eb6d2655473b6b0af58b1a75a6f3", + "PivotNumber": 9834000, + "PivotHash": "0xfa68a96d9a0535ee4bd8bd5296eaf18e7cde94837a9f7666d64fc51dadcfcc47", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 1450409, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index 68bfb4ace4d..3fef418af9c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 22850000, - "PivotHash": "0xb7e7b846b1855020a04783e2b39c591f867d26cb6f47241598266c38409698f2" + "PivotNumber": 23160000, + "PivotHash": "0xd142112c202e111d34d1fa01a3e2ce669e372fb463960fcac81e48060f2734a7" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index 9d8e1e82cdf..01f0118da44 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 22250000, - "PivotHash": "0xe329fa3d71109b1a73bc8c53e1318a2f62816c4ddab9088b8138cdd42d3fe171" + "PivotNumber": 22550000, + "PivotHash": "0xc6cb3a21f360071de9a7450f933c33a146e5cb1dffb152a45da3f00bf9ebc673" }, "Discovery": { "DiscoveryVersion": "V5" From 47238786c63894fc1febd970ddf05b56c29d981f Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Sun, 14 Dec 2025 09:14:58 +0100 Subject: [PATCH 072/255] Update OP Superchain chains (#9932) Co-authored-by: emlautarom1 --- .../Chains/arena-z-mainnet.json.zst | Bin 86789 -> 86216 bytes .../Chains/arena-z-sepolia.json.zst | Bin 82732 -> 82744 bytes .../Chains/automata-mainnet.json.zst | Bin 78333 -> 78345 bytes src/Nethermind/Chains/base-mainnet.json.zst | Bin 36336 -> 37232 bytes src/Nethermind/Chains/base-sepolia.json.zst | Bin 44662 -> 45456 bytes src/Nethermind/Chains/bob-mainnet.json.zst | Bin 68865 -> 69168 bytes src/Nethermind/Chains/boba-mainnet.json.zst | Bin 1083 -> 1502 bytes src/Nethermind/Chains/boba-sepolia.json.zst | Bin 1068 -> 1500 bytes src/Nethermind/Chains/camp-sepolia.json.zst | Bin 74451 -> 73911 bytes .../Chains/celo-sep-sepolia.json.zst | Bin 0 -> 86242 bytes src/Nethermind/Chains/cyber-mainnet.json.zst | Bin 72568 -> 72235 bytes src/Nethermind/Chains/cyber-sepolia.json.zst | Bin 72528 -> 72241 bytes src/Nethermind/Chains/dictionary | Bin 65536 -> 65536 bytes .../Chains/ethernity-mainnet.json.zst | Bin 70721 -> 70753 bytes .../Chains/ethernity-sepolia.json.zst | Bin 74522 -> 74028 bytes .../Chains/fraxtal-mainnet.json.zst | Bin 142764 -> 143082 bytes src/Nethermind/Chains/funki-mainnet.json.zst | Bin 78364 -> 78345 bytes src/Nethermind/Chains/funki-sepolia.json.zst | Bin 72562 -> 72257 bytes .../Chains/hashkeychain-mainnet.json.zst | Bin 81914 -> 81902 bytes src/Nethermind/Chains/ink-mainnet.json.zst | Bin 86760 -> 86144 bytes src/Nethermind/Chains/ink-sepolia.json.zst | Bin 86677 -> 86245 bytes src/Nethermind/Chains/lisk-mainnet.json.zst | Bin 68805 -> 69115 bytes src/Nethermind/Chains/lisk-sepolia.json.zst | Bin 70357 -> 70141 bytes src/Nethermind/Chains/lyra-mainnet.json.zst | Bin 36247 -> 36671 bytes src/Nethermind/Chains/metal-mainnet.json.zst | Bin 68868 -> 69180 bytes src/Nethermind/Chains/metal-sepolia.json.zst | Bin 36273 -> 36972 bytes src/Nethermind/Chains/mint-mainnet.json.zst | Bin 68854 -> 69143 bytes src/Nethermind/Chains/mode-mainnet.json.zst | Bin 36318 -> 37229 bytes src/Nethermind/Chains/mode-sepolia.json.zst | Bin 40768 -> 41330 bytes src/Nethermind/Chains/op-mainnet.json.zst | Bin 1197 -> 1587 bytes src/Nethermind/Chains/op-sepolia.json.zst | Bin 48555 -> 48781 bytes .../Chains/orderly-mainnet.json.zst | Bin 36291 -> 37213 bytes src/Nethermind/Chains/ozean-sepolia.json.zst | Bin 70663 -> 70705 bytes .../Chains/pivotal-sepolia.json.zst | Bin 74434 -> 73882 bytes .../Chains/polynomial-mainnet.json.zst | Bin 68843 -> 69011 bytes src/Nethermind/Chains/race-mainnet.json.zst | Bin 70602 -> 70604 bytes src/Nethermind/Chains/race-sepolia.json.zst | Bin 70647 -> 70667 bytes .../Chains/redstone-mainnet.json.zst | Bin 68728 -> 69018 bytes .../Chains/settlus-mainnet-mainnet.json.zst | Bin 82811 -> 82794 bytes .../Chains/settlus-sepolia-sepolia.json.zst | Bin 86632 -> 86117 bytes src/Nethermind/Chains/shape-mainnet.json.zst | Bin 68702 -> 69036 bytes src/Nethermind/Chains/shape-sepolia.json.zst | Bin 72605 -> 72315 bytes .../Chains/soneium-mainnet.json.zst | Bin 86803 -> 86239 bytes .../Chains/soneium-minato-sepolia.json.zst | Bin 78465 -> 78497 bytes src/Nethermind/Chains/sseed-mainnet.json.zst | Bin 70725 -> 70707 bytes src/Nethermind/Chains/swan-mainnet.json.zst | Bin 67554 -> 67884 bytes src/Nethermind/Chains/swell-mainnet.json.zst | Bin 82910 -> 82890 bytes src/Nethermind/Chains/tbn-mainnet.json.zst | Bin 82315 -> 81789 bytes src/Nethermind/Chains/tbn-sepolia.json.zst | Bin 74492 -> 73978 bytes .../Chains/unichain-mainnet.json.zst | Bin 116353 -> 116381 bytes .../Chains/unichain-sepolia.json.zst | Bin 101480 -> 101586 bytes .../Chains/worldchain-mainnet.json.zst | Bin 72631 -> 72303 bytes .../Chains/worldchain-sepolia.json.zst | Bin 72688 -> 72376 bytes .../Chains/xterio-eth-mainnet.json.zst | Bin 72607 -> 72282 bytes src/Nethermind/Chains/zora-mainnet.json.zst | Bin 40811 -> 41317 bytes src/Nethermind/Chains/zora-sepolia.json.zst | Bin 36276 -> 37098 bytes .../configs/celo-sep-sepolia.json | 37 ++++++++++++++++++ 57 files changed, 37 insertions(+) create mode 100644 src/Nethermind/Chains/celo-sep-sepolia.json.zst create mode 100644 src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json diff --git a/src/Nethermind/Chains/arena-z-mainnet.json.zst b/src/Nethermind/Chains/arena-z-mainnet.json.zst index 0de98135facb039b74e59347eab1b85b355859f4..fef9920bc9192b35e375e370fb7cac36df95bb39 100644 GIT binary patch delta 18203 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 delta 14746 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 diff --git a/src/Nethermind/Chains/automata-mainnet.json.zst b/src/Nethermind/Chains/automata-mainnet.json.zst index 2596a2a70f43fcf17ea8994749799479c4b46a1d..4c2ad397e9624fa4a90581f6a9ba83cec5a8e6d9 100644 GIT binary patch delta 14620 zcmY+~LtrjU(+23+wr$(CZQJ&Vp4hf+J14g7$xlHHi>WQJ?4XgtPV?&BEyW zaM%Cvvi?tV)&J0t{7+Hle*phie*a(21avfJ!9#85&o}ebYd_~S}Mr#TcxPVsH;@1#-gHQE10?t zV11Q~B*C4Dhq6T@c$#b)qe*mfDrdu}v-l;pSXc3kg|UPN0K5WSSB*GgY;_{=HU0GL zqO5#PMISs|k?SRcL2&!4%6?jU64+_WJTzMVO^rx&iGwjk#?hN!1Fka!ot$VSa{-~q zA@?+Xti|xmt(UWC3TNw|1P}%=qRG6$V?vYIQaqr4K(_SrN3cZ0xuBz38!21Bmp#cOKuD!ru zm=K60ht0}Faj*Ze_+Z92@`t-DbxEgfRY$ZLBv6UJ0TDRDzEtf5Cl1+ zi1$4(96q8*Pmi=rEi=Hs1uz`ArJD4_#5{_5qXh6_5T5}1JtGi!0@ej z?mppufKecboD;kfYEYIr6N39kNjng1GLBGDBUn*fp!PWkxcg$XkZZ6-l&}*xEEZ8e zxHu1%oH#tFz(rz#r9xipYZVyVEKy)k=W!!=&^_$5RgM(cQa?C26qem0ot6_cQcROU zYMii=$wCl23Dql6f-PcjQIU!hcyI|23|xT`0F@3DWiJ3?Ucd<06*!6Y?rU#EIfR%$ z41DQ0%XHx4hIy-_C2c#BhC$e^s3h?^gP^pK7#pW@B3bT3T#QkS`7hW3tr9AckPtN; zIxZHWymvKQKT%+0f|SO2W88=;UunIKux3%pV~uf%6BSHZ;J_r%fGQG|6@DQE64gT^ zK##*RsG#2^km)f?|))?KThc?ZP8;3F+U*`MQ7i_u_@b15tiOj!@L^4fw0+x*3n`?apmDYt9zSQWw zuZyIb9QsI#gQFd|jHv;4evHOrHw_mUJl2;ak&y9D9+|<{Y6T~sCNaYA$QuQ;r3gJmK(tVO*A6GCDJ z&5#vH>&7CUz>q_f1Rg41{KXy@cYNz0n&~whVj<#8%^Ci%D79t<+RUoU5(K8r}Kva$-q_L)<;)aZ@qlsj9(6qs<+ZU{c-7k?K zS5;+Yp&|4|`KsneVXQ19o$QO;v#v#WvfsC7RY2(I@D@i_g9SrxVd7@bO0YhiN^ zMp;h-`QfOkgTwA}iil-0cENs>8wtbPeCn${v4Xw6G6`{(Y4v4sHsR!Kc~O3XeU#A* zas<1VVB=@#K<|p*R&0HmEVCke$uL2efT4ly^+L!ZhI>2uG)g{aRvA3WkqosE`v)6a zTuOR{KI2VI>zGyPxiZ`hkdZky+jyrmN0+&DU!kb7y{fXGzKF70wymiVyMO(VXQ*Jb z#C+PR8eLq-s*cG*FZNvWk%1}xl^{p^PAeq=E!86k<(ZyV=23j;S0Mv);m4#)`=w*1AYcQHi6fN>o0& zv+r*exmX1EDBV@f+_8Be;&n*S1ra`=74gZz$@AQj39@yYXe5P2C(uq!4*z!%vYF>0 zCat3~Zi>xQ?TTNiyAwPuQ;{R3sa;f`4QMiHhO9fJ)g~nYL5d6fAT`U)z|Im(sD4=b z9D~%U`L>6qZOo7w=}Pd2J1bGvaw^!5%%j`uUu@SDj~P1DiyVs_n7PKH6n0krBv!=~ zo3 zi^REvvtMO^J5-2db2$p>5;ddDbZY}v#^&GH>7 zEecc2)a}C*HKY6c@;VmtZrJMaAJ)D@>_1T=jkd)v@Wj9|Wiae=Z9x@R7o;kp)3T^SRN)+LFy**b z`y936;on&eYL!EXuH(8=%;r;hHB}mMN%@Dq;^nVatA{MV{Ml@OH@62G^SOb~+o6|y zCEV_F-*y4rK9@}`WRcSgZP>hni6ZnKDQy%$f>lfbiszQe`c945-fDRCC@pfNN@!L2 zd5OA0*)kxtG*AHXjrUaDYT8gWy}eOxnYU*Pg+1ScRi?PO=Y9O^cH);)oR#-PrBT`c zy}n*gO?Hxbg@m!kOyVV}59NZs7xLB$>qpDV@tS|;VNIJ6s} zHm;a}^!=r!IUb9`sdreKAdCTg8@UZ_FTFoKZ)u_S%5)Ulrib!!4E9AIXGO_=OXAC zPzbMTTZO~kO4?2O)PMPOwZN-l!|j)+C`+H%)sgM_Q7y(VlykMo8Wb-KYZWXo|;c zzw5F6Ip5pU+IPguBPf*HZYX;KL$$Xdvjz1_m!77%UHjB_v2jrtpOh_;NJ1g)S{=?& zYY|~@%Fae7H5EBPDwZ@)IR)E!by8TclXSqSj+7kd(o({fhL|(0HiviaZp}*@pwPWS zBB2+|i`BR)gQ|xsvN)JTbaVzR$Nfu5y=_HEJx!@ntICl)<}9YnQo(cKs#M9N#+(kA z8w~)Bq%nfk`znM$)|tL~qh7V^{1ZGgOssAsB~45g$IB%h7J*7f=TLfWJkG;r!u7|} z0*4&gJooFyf|Y8`Y(zVXStQw^2y->^MqNULyjTucGz=ZP%{kZD4%!`nLR>*R2CjhL z#jp+*HZU{_sXIPey)`XHZ%*ZUJXX|1CWu~Hh32+f-~vAo6q=ajB-#N(77{Bt5#?0K zttqKijhzmKQ;XF3Su7Pg2$g!gUeYbjjCyb3R3+*+3e`3~bL`zm_hjuAuFl9^=KGUG zAaW!b#Bd}k2EB!totg-MOvE)NW-F2KXO9}vUYHh-QhhSQ|4f1J!3!!yDzhYF?rHf< zdVQ9VNf|@Z@xfM09Qk);78Tnm|8J5ZP^^wzVtX}=Lt+pCgV}T#F@TA z+-wjF#Jt@{&0G``gT+MbZ$zd}TcQRJhO(@VqFd!1+@xaUMu8$Ab)jIFeZ61~>8Vp$ zcz(<*vte`746jWkrx}}GFBy}wP(ZqQy4?H1tqZIEo`F%KU_vAtp@ihI8|f@5D!Bbm za;g!}`4C)jexU{f^Y>Ls{JAH5$CIde;8PcT(pSaVB4et*Y~?b4Sw#tZ*rFr1q$-uZ z3e~w(DxLn0*vu2a;hmg8ZL(--Mh8|}TP7o^Ov`@XjbF^uPhmhJ&bXp1R@8O6S^Mc? z(MFwcM~^dV(Glxh+ODX~R3a&Fu*nUjQZQsahwC6ecm&&We)i=>;0#RZoKwlI0c_97^Vg_d%YD zo_n^%eU_A}R*zPO-?c+=%c-i0otdIpND5tKxgc(R#+IpKD^4ll{Eu!56@GQ;ya;QW zYvBx$y6y442JKN+rpNj@A@$|!tm$;_hwQk++dr5BJhC)OUljQVr_l-_G%qSnIu#?t zR0`?eafT{j&hgV_5dKe1qub&Wwc107bX83?NyK}q^v&et%x#^hOUSSbynKmL9I}ku zNLi?xI=g1}HLa&hk(gyeF`Otd>-0U@nI*6f#dB;)y2sSijPxumOdjFH@#y&&DPlU^ z$9H!6b}6aH;G+ww0GTH;=La&5zRRg6bfF5pth+p5*{dd2n49=4<7nKSKtnQe`8`%y zIdfLg)n7`Yq^47^{Bi0MYXwFXH*TV0*iiw!GtC_?5()|oD1bW{HGqf+2@Y!5WIsWx zL{She00Lk`7a+iaC}m>Ig@ypm3@6GAH$(&n1Oybsge0Y0QpJG;JYVex^!v#qAhSdZ zb*cn#yc2<;e@MuFuXWSCa-8)E`hR8cWH z{RIzStpx3tX^&zrVEYgc-O8>})IxzZ=LP_{Z;|2B?)0>HDue29`B(1?4|CsC>K6_9 z8|ujAd-Jm(=W-|ud4KoHsnNOV=@rU-nchs-QKlRb!?^#>wM^s%6D;Yzp5+-@d&^A* zzQ6vk&K+cD^P6;v25M~)DY%lyO)2bx%tRR!XC(Fcya{bPljYFOBE2gXToXOPX4&`TtWVkw%!~ZT?1zAO%bn)<1z4X09ymQd3Oef{ zul8`@K8V2@8OqOV6}wH5E>TC0@Tccm1%X-H_)^yIl7Dm55;z?Nz*CeT#aXwzkWX6P zU9Stid;9tJ@+}Cvle#B1?A`%i*(?X;1`yn${!p5l@E|Gznmjd}~%sk*4H8@tIPy z1GTm-H6EJ7tiG$=JPybe)fx(02`($58-y$1k4Pg-_vgqta0 zax}EFvlW9#^JzPXW2q5|++4kBs#@?AquNXR_8-`FW2D@Dm$eFTsYIG%EA% zqvMk8V6=%op{V?#C$4~WzIPdMm)4@#(2hhR%N27OUY{oF`mfT6ld!SD%v%bT%i4nk zHZCu6!eS&SLfLzLe_*`{q(4P^tzgqsGM5PA{VMnku_`4#ohZ)mqwcdYT72T9oIm4~ zmgq)b<+>Jx{fc7sRz_b}!Ee;^^##fWnm9;bVu4US{wG*j@wI?SkE!)+uNU@T!ldXz z-q@Mqu7bL{^_@0MjRCQJ^CHQINW9LdRoGld{)>u*r6UIwPgj&`v&0?KO6R0kw2g;g z=jqqRJUXTl{&j0fQ)}^Dc$8|l@pz`F&YDJ$>)iB)5GH(+vZl;Uh^k`{@;JA^yrYk- zPEA>tw`a}_9&NyfUpEp4(T*Jf`m#mEG|nSt0cBjm-@y?F*;bNZD-vZw_Iij;D10^< zlv;RQ+Z!`6lQ+VE4zueG^%f=|;HIlVACu532UKo^%eoegXSULf|E7=}L6 zFsIJVhQrxG7_!;gFv3k_=4DT@@Y5A7^J(Q9qb*ne3_k$7rHylpJI(&n0xTf-_=nAV zV1tbsu}xX*NJpx#Y^7%UI0xgiVp+ZI7S-EzQ2GLn_hhmY4{eUSa0P#8A-=f})SrTj z4f`PqwA%-I$;KEnIPEPf9SoNBfb-a4Zm#FjH>J(?21M~L@s)STv>5)q!#kwDCa!>J zHz0+e<{9ww+2J-1N#|- zRkxuoZ1Rk?ea?-`5fu=>Gxy)i@Iy@3zf8~>C*59bjCy0|SRaH$S2LP$a|?A4EbBxl zEqHLp(b5$b$-dIRX%qEW+ZYLDo>!(TWW_j0EbL!a~Zs$*=HVeUC{^I8v&)k z#j&A0$v9_^r|WnjGv?*$I8;Z{)Q_`FwA?*4K?7(`~?g&D@abXsCyU^!-x$wj3KzLDL1&{dGH~?*!i1=+vXG?>VGns zl8pR=R^!596>Z$XuxDD}$eREDj!lJs3PqK(v?-Tj%Kf=`3%26f)Y|Q-_f^ISZsjgjsK=>}7SkX?m#`k3z@kbhvJz6^8FF{EDkyIwO(M0eQ|2;o}3QqmU zTzf}s2P!=3pXgX(4DuuUZ@9d69H)eB=t+xCsnf;JD>B5*ZAhsFzV)J2O)OzysswQEjv+|G1^(GF2D*mT^Gg!P{}W9JZMOca+U^c#P)lN-RVEB7M7nSu=4O zXqMw7VhBj>H;_{+IG2xzaPE(g%*%=EVqvss@Z^lR&ejF6e5aBLIjl@8U@`Rz)d%iK ztbyi3XdFV2-%rQ2Z`G(l%ij7bP;Ykmi-iiR$lxs1y^>lJ^)~hCWYiZPYX(3AtoFc< z=*NV=o_&kGL*=UOf9o^Uq)M3ZWip)b-`=*=tv9ebJ$tw`RF7F_%wOnFjBlkx{LYJs z0|7})I^=@Qj)ux`C#ckG+kmeCu-kI+2-cYcmw_xf@OE`;v^CwjHtNYFiGb%$QG(=M zkqossIl((tXzxJW72(u>>rDW4VC9r16|}M$1Fq%sJ-!f_9uI!9!j2wWQW8!zG)cuW z8Un|&6e+pHd>kDeiM_w0xgh_g9wFj{VNe4}Y~+5bQ-iR}9~Z_`&aZevoG6_TfjHzd z2(#_bDsCgA7#toZ7+;%KyO8?#v_@qP^W67m?l(_wlN)c|2a{hRsK0=4A=gj;_z(L; zgVVcL(TN!pmk;n?E#Pry@H178D6|U!pgemMMs>cnl8)fi-OlVH1I?$iB6l>f&n6`< z6gpocb>&u3GQ5?xEsbmd%ThaE`9gvO<}D@1vhnB?}H zJ_HgDkZjzW$q=A4JBL*5oWXGfTk{VJI?97C?vIW$9$$+~^;G5Xi(<#n1gj6WWKb|# zb)t(t@fzZ%4YDN|Ot1Ez1dsQdOp%;8Jp62D^>Rb=e`*_oyr;Ar2tnEesQv=_*{=Jl zlLthjJWUDH9Fj>w`6M-kU6+0vocFwfF~z<--kUB$YQq5BNtugRshm~P4&^~bcUsF- zh0&))xcb#;ZL$`aG40}Eb;UqgPazJ_h>0CwZC?P&HwMC0d%-3&qBnt|xtN&(IMH&< zh1^M`{w&#gn^Wt|g>iztAs3>={XK@f!K&8>&!S}!Mem|!C+{Y3vZ@}Vy?+nZfWPwr z8>iOO@EicuIGn2DM{y^x*bOrTkJV|n#?Ph2arqx-CkLB5X zGAw(HB79Z^$yMc3Cxf>Jp9`?QZ_$y^D^FC5ji_Ddq*!vWJGdB%N6;l-V9Q9&>`A($ zNH>aOcNlHA+ZbOY+C}11Q_YKF#S_$6s+vxns4VH81BZN8DCGnUq@i=VL#fftrQqq6esYeLU;X-U3?Vn0|kjZ?d0f zIx()zYw|>osoi&B{lx9dybX;C&%kAK<5d&*&AL>|l8h}>rZFun`4QWCQd?~{dbBVS zbp`~G2An7rxgF}e?}PxsO<8wSiqN6ZGsxI@lH--wfhzJf#uu~j@n7hUJf?3cL^wmX zTPShoQrqGEJxRxis$C@|YEJR9`y++lUA0Q?O;Tk%gNHRqmhQ{`nJpL3_VtBx1Ei2i z*ZgjgS|riO*(VIIVSz}UU94=4((fxlCjt1RJ3Q?mA1$+IUPilsk2J}UJx*%wLNC(M zA^>SvzG(#QgRMPieR?S9C_31_Bdqch{d)4cu~l@%QJLnf`i}Z;m}qW|0#&gvL8R!h zI*kAFd;?hnmlm0NRbzh!6S+VJZm$bqYxx4txo?^+8rm2#EYb~Kr8QxyAKy~cGywSR ze{9?>A08&&{r)lrM8R74N14H@C8QfvZx`};5mWHHFTcu@++;gxTB#i(!`(GvAbyZ- znz~UYr)^Q(8;gNO65GHGbB2Yts_$WoMtp{R$-_C7&$sKH633RKs>Ismb&sd`s!Usq z57sd-;2aQ~WytNOZzdzv<7~dv908skJ2o!W@@ zQ=H68+Ae%>!9XQf3T_Ae+;|g6Cy#h5+U6_DlU)a@dMmz-%kQgicq9G9nTT$eKi_re z6Y`pf=BqSwRk~WKsp&&Z+ch?o3_N;{f-|FGSVkGs=xC??g!Vt>NnrcEdI0(klY7`` zJ5TZ9A8`kt^ryq4?YNP5wAz|{g~s2gcnIBhyFRQmd7r9ekzP6qT{#uBSn$pNN+NTY zQF7b-b3;i3(R3Oj4ex0T_n|vYoA^>lbSiUZL$Qsp2Nsmwc@Jz&Egwn~a-&;W5?n+m zhVAezZW8U=_7}cZHf2&8vj8v?hs!dUyJb-i&4hHC2eBS*V|OAXaCiWVQDJRO3sT%w z9}^h<@E|p-nVV$l4#e+nSapO8caQ!h4AF-mnF|-|XeL6vZG&tKz^@*rH&j2%K8r%U zp@r;^%q4M2gJ#SQnJWrCHe=(0336qHbDY#LXKi5695_V{xKeyTlK~)^;!qL{cyv(+1?$B7B<1^jgwYN3*-H&x3=M`<}VRPBA*YPjZDL9gh9g-Vl2y!E4bu7jWn zt&CA7k~_8T|Cy5J>K$Yo&YK+B8RXh%X&T~@5bx)CzSejq8UUth&kN?A>jTXd`Y#A+XD0UgfK}4> z5~UfG5ooNVPYIx1GqQP#U(d{TuQTpCtXF!(KlCL~sV*4+P3QBbEEss`WEpp6g2L4Y z+_NUQoU>7OQK$H4LIx6h{7PzVv%s=wImvRi9@>x#ozBc)TCE1+#QCvyO-$<$N0js} zt(7><_#&Z^V0B|2bLF}Od2`Cfg$g5N`b~^`0H|M5$QvNwmGibSYvf}4IRgI5`g*e& zngh;q{|_$c_yjW>AXeB!-uV1IvEo}dvnUu^)3{r9k+<#^eA?>)hhZ*M%P-VoTEn{M z^s7!R5=0VCASsT?k9ht=&UZ1@d$i{m)*Q3F_z+cz8;b`IN2pIV+p^MXTKQwg18%$8 zdMylWN)E6%Ip#7qD9;*wkH-B_eRSd?-FuG+^X%jNnVh<(9iA>F?FlHLAuBcuRW1a+ z&mh&uy4f;87`6o;4Q40T;rQD-fzshr=t%C?a+%V`N{^c-H0lR$A`U*$8yV&f&1Hv- zX+F%j`ExhOH#y9Y@vBTSbzi43!?_7jaOhZr@dzlIM}qxpXU~=3o>_|#+qKs85n?lr zQhPDB9vqloS0;i5L+sd;60J%Ae*|#p-y(LB<;Itr;`VRKOZtZ5YSGBSo^P;fspR-p zWO(re?=qWiqakLMI|p9SFE?Utdh*>);46CjFROhdD~0@&8=!_ z@Ct^^fkd6(nDpIKrsJ3=xv~I8>+OwvcWOl7C{%IXy7GVsL^+(4phOe4K_WyW%n7~! z)cim;^0HS|hf}Q6r|Ej&>2Z+F8yLzEWrSh3#)Koi#(+Qoz9{p9qAP6~eI|it$x2%L#36{mXg4+SGQ| zP$-h2u2`#mH@pt=&K7N-?W68G*3tZq63q^hdsG2na|llZ!!6?zJyH1CMh&s}yf%g4UtZ+4_uu#v8H1|N3NlCk!YhPY7$kCg+%5P9A8w{| zKA&M|3Xq1T4`vv)KY~sTr~Cd_1mtBGbI$-rZ70Ssw`;!}!@%_?rAd#^9rJ732VZu3+l@`D zTbKHbs~1(CG8wfMF&?Z(kQTh~Tu?ne(}OKptjm=1&nnL>=D>|68_22f24`~$#5aod z^#seseWhBbz4^T?85sV{Awi5FM$ce(d>h5Tb6}TEJ(_P(Cba13*2@3l9%ukK#^8jN zkomNG#X#pfjCVTkm}sy=Jz!{7G&h^UAyntsabT$X5KIXQnRY0*io1hMoKxwf9XgNp?!g09Appam(gHMX8i2EOe z76p-tOS}jM@I7UPdTH?$Pf$x)^>@ZIjS0IZzLs7Xb$9BOf%1Qb$y@*#{{hRf58Auh zUrbv%peLHjP73WNh{)aV_5;;6j#ac(EJ;*bnQfXJVc1o_4|s}P#%*yYw5*2q!7g9o ztWl*$TK?qcYYHDP=AT9x^>BFUw_$z>2h(40=xv*zy{tz5M#&9fEWCM1(Q#jHr|i%C z9U_RIC0klMm3mV=Bt*cox%+1Z|9dBPPhj%T;}7##e?;+#Ki%w(%Am%drwWQ`IWuG* zLvR?MFP*%Hy9VWaJn;8IAz-p6c1@-{WX=omp=fAv5Np-7?2lQsl@%+ zz-sb`jjr{}9|Bw{digmjMjX~aTVXgzZDf{lnmvsyYS3Qv^o^nEgO92SN-Z1Q6I;P# zp7g`q!gco;B?<`5yh2)o+}lBgQMcO!M6Yw%&XA2hlnP+j+eNvT+tKf2ZQfWC_61Y! zlImT;>d)I|nRx);L=AP^$;Ueli8tz*^uvZ2CU&Y9$a)vIL!1O{`!hqRYQ#b1lv0!Z zaY-{nr~>gxsD)8nev>ink?XVwGz2JmmA0OKbO3(jyQSxGQL3}7?Tozw7l`;~%r;s@ zaix{#KrUjmWG*D@ba*NGbzR+Fo%L|nmum(9%v{brR~B%bF^$YZ+drfPzDn?p*%-C< zRAC-(Yj(%KsMX3l2K=5?iW5U^E$Mb zgDHIl;u(NSaQf4bA5g|BxzYjWkVHItgM9DfhI72F7DJm;l7h8Th1F)kH|m=tS_#Il z>h+iX63-NAQaOqLX=@$G=qg@eQ~;4my6ze)OSjs!j;?kzMXo!ZEoszCh+ifvZp#IM zn_th^);U=9%Nv)cZ{rPpNtBXKQF~%U`1jISi3mUiJ<`jkt1aR)T`J`|B%V((MxcX*OBdwXkLQ)9`NV6Js%RCo*iN(M&R<$@zw$GJlVmgGO#x!jpo+wqZ{0 zS`BcPs$De?1LyYqv+F3*0if7q9!B7 zNo6LSGBv>0A9M|9!E7 zmsyWk)T%CWQHmML$kmbQ)a+;6L9PzJ^AF1yHeiH? zf1(C#99)Ag4@`TuHceNYcU)rhHa;io)6EEA*B+=JzLGnhI$ITAnc;)N$eDazX4L1I ztY~ywC3!FvzPI`*8Lx*j70sU@I>r|`=jHeNo*W&MOG}@*8Y2*<^hbzWWdSQw?=l?n zt@T&U@>@KOGqaolJaKt?qt+cXWIa$>M@jX`3|aiD;WwJoQ9k@p9P5aWu_~r5LKmR< z86*xgt@O=zhe=ba$x6;iUe`_zRVEgg^3K6UJuKB++xgeX)tK*lX;aktE=7WVwNN?i z3+fPSe)XP#O0@Jg0XfinO#o&6t{K-|utfU6e16N?TGt8&oqXy}C84FF!>ga#xD}?^6*o8X zqH4Qgw-E#)Ehu?0h=hD)zY3ixHRDsE>Iijm;?=lT8tZ`kA?`+S;BGB{2(zDSAJj|w zOQW+gN;$OIF-&SFC%~D~sypq(ae%FoZRtgK`EG;)V-B!OYzR;I+YM-J9%-!^bq@cFT|h1r1N3M zqmYsFIePq-lZXE{cpWSssx;=%Cox?(_jEK@hEqYEkxF;RYac8 zsuDybMi6BM3C5181&Tlo!YL<#ofj~8bZ4nwlm$*u?nUvb)bUJYKQjii;k-EV5WYBH z!4Fb)u^>IO0B{lbXGKe~sOF%iM3|Lv*3`n*I1KIyp1aNsO0xi3H1C&GE`jDQKKow; zXXhbJ)8OMgjwZj+)*_Dva&tFqKF3rzh7>i00sK`2%-KCB3 z3zTHq-NBIAzCP{%wF@gMT=H4@NAb#wVe?8RlltZx z0qce=yOB~SLFJRH;usF8>E~xDHkzB4c(Q-3f0#}aGklkx&R~-2BS^^_)$YX>>h=k@ zU^*`bW{#s!-IJHn#DT}gd)wM>tg+^bPcI@42_PC#;bRZ?Ic_U7AmudG&L4eXB-Dhj zZBf|{8C(|TG&^m4c0OJ5UHsT7_UkfkUsagPABLSH$#q;oZBvZX2kquSSi53~Pj(wG ztvvAw@pWvFGg!L_(m1A(grj=VzUVwq2s+bxwgcc9dp00jAxho{Ix-wSBEXBnuA?HK z03OfGeHqFm-%3maVV6(AK<=Mn(tPeT8;{B>GBNmaT$ zYP;|i_(o+zKU|Sk#+$Hth!?JmXBg9(nT4Lz%je{{wA6m$$}Y3}{r+CaN98C&i6|?| zYy83tivGiP>e@UYkYoI!?93lDT*OWH11#sp5kq11J>_ii=ExhMiQ3_|Zaa^E+TjS@ z92FZgbA^t^;MMO!)Q$MKLK@?YlFBZa0t-h2`;|o0(bfAUq(c13nqIv`=p1xn27$%Q zws70i?RRCbxk0taZ|nyz#n1qu|Cio}>nGqo zilRz~m;%Nr@wh3qw8hH9nO5BAH{a65-di0mV(zsd>~$vBol)}R z9C_z`A;Vs!Y$3|p+kg>ezPHw%1K{5ub#Wyk!~ZdlojOHG0p-aD9qq1}T+d+&!^vXG z=81)J>~7S|^Cj34`0C8d*MEO+iru-&$1}PD8d~S_yy$E*x9h;CRK}3kBP5ztXdUrpvL%_D?(_0;K2H_KM-2M)iIAMv`BtO z6zQ9&8S;m?I}NmhAdeKL1|(r7Ff_NyGMaxj5zF60RWB7k7?eyfkDrcUmA;0~)fIwvFAp{@vu{ z+IVhWpPxB6X7|+I)YPp9t6!a{d1{X^*tt5CuWxJk@Y=Nhb8xKY>AJi&ckkj|!PhXx z+{{_B_Gk?4!P};9+g!Ss{ip7uyIrT?=~=z8?Q!b%-ykN8lJ42`FGlQ^o+CRNtzD{J zOBWvPD;>Ez4sDy80OjrfCefPF)^841U!OU@Y3S6q_ncK|?Ye$(b8By(+0pRS(7YO; z@o=r`sxiTA<8D{Ia;WaXZ`HMLZ&%OVetv0M!3u;vhSbeXp1L-x?#UU3w`*?CeG@9( zAQ5_$Z0e@|I4Cb?>dmNmbKpSxS$JIZ`J_yZo0gB~3BI-lxFCnubuNw?FV>1;ao}tF zFO}k!#w~+jTEPB+1uS=d4p>@adl4Fu$?UjOmKvvXa7hs!`tEv+1&mM(Gd* z=2^1J2plKLx<|-bQ%v}-q_T{3Z8m}Akuhi&qiM057`ton*UZ*aH;TtrEll5z-N&X) z`T->6vcdGg9sST>hAx`7^DbU61`vD%jQ6(Jd38O2g3sqAR@-LkMU~00+oW));NMbj zU98wW(7ts5t1^e}UXjK;DVE3mkFMCpdbJi>W(6ZFSKZI?sfJx>&lf~82y?3b@8iQ5 zR-`lV(*r085SDy+N6^>!tjX*qr=55m#(cmmPNrc`ipW=oA$Fn4yt3lp_}M~zPO%bH zo)8j1N?G@*qSQ7%#F*W;Ozl_rf)t~H2)#Uqql-k2ehk_U_iV_Ty5oWA{o8vP#M7m! zz%|njM|{PVr+{rTIVSXvZ~Xy6qk8cCX7ni3a4q!p=08c`Y`Y(Sd370bq@v!^;^G@Q z$=oPnk|&JIe4_WT+-9}VS2)6Lprbq}4@gcxHzdi<{D6Z<_CPjkVoO)d_DsyAJs2EN zF%*gyhbSv63k$#4p8g77BT~v1?^8H4Z$nEMpCrjnX6n(Et(%*+QwbS&MMfs^8Wvpy z6h+X^D8o&l>H8D)swzjzFAB zV~IBwPJs%sQ;amI#w-ZgrB%UXDr_Yn1Z>cOx0Y0xHH?f^Hj_XGw9E`F&Y7)$GN)gS zMrMrNyDXgutJ_V8sX`4;5>z&Z3}g%nCm?kraJr==i;xD0uuIANP^lT7+A=j32}QDo z0d$vj9*fOvJQUc^$jXRvEF>}n%89S>;hU8?PY5f;2uJFZNJ}&z;LGm~sm~9u8T@*r zK_l82B7{lONyiiycq3@X1w;FKLod}VnShJZ5+DD`obY24a=qEF;Ptf$@y3zxgz!a< z(0e2N=cUl{bAC$T%8}5!4YB7+6!1CU?005P_|lHZzZq`uQYdIrSrI50@eQvi4o@fc iRF3HL|LgnM4FA8rhwoh4=2|WyP>==9<~d%5m;VQ=Y&aAE delta 14631 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 diff --git a/src/Nethermind/Chains/base-mainnet.json.zst b/src/Nethermind/Chains/base-mainnet.json.zst index e901b7add277ba89779e5fca3528db60ba47f2d4..aaaea720746b40fc02e899e2fb65d8354d88fb23 100644 GIT binary patch delta 5580 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 A{{R30 delta 4669 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 P%g_(ra+6@RChUIz1gIq& diff --git a/src/Nethermind/Chains/base-sepolia.json.zst b/src/Nethermind/Chains/base-sepolia.json.zst index 60c557bfa7b864f2e35d82c8b7d19f03684832da..9e2091dc43a2abe91e9025463674f4168a861f2b 100644 GIT binary patch delta 5088 zcmcJRc{G&$`^U`;#=d2j!5}jTV}ESXLOhgx$(CdZ86jJkLbk|qOJv_3iR{^@2!qI) zD6;RAeHY&u(zoZF?;pQ^e&;y%x$o%P#~%MwRZ9w zG>UKr$_fKnNw4w*HGQ|xYd+dfd4rQP$jP4G##j$|-(GSbUBQD$vuq$X!KM=k-e4%N=dJ^G|CigZ~O6E1=Ya z5%?RWIddCwN1atPB3jJ4%y(pLA$A&h;IbQ#YXKYi@tj9FgXnRL*ja6&0I1XDZe@d; zm!SH=mDJ5gKOC0*#psK47yYeE1Z4~rWuL@vD8QFzn{4DU2~?%kSsunlMxBOH4Z$5` zF#&7b(JC&EE@kYhJXTNNu`x5c;%v8`sz+_q6fP$G2sa%mzT0E*hFzWWvBQonDe+eo zZG@RMHCaK5Vs(zpBgB}9CWneI2`x>y?=eLW*jT^@E} z$pxIf^BR8&(qyS>kcmT)>~(4~601?&9np55RHAjPB2(%;)jW?qch$dK` znjI#GJ-dz3Up7JWK4se!FOkvJb5|j43TOy?52s&E_iEAN%q-WqVl5?nWkSs$W(UGZ zONxL|Xe-dAdm#i3__%GQ&YbbwWDJwxyP>Ja2lI}ip^j{049mTVU?qzP3WS%q*gsSz zc|xo%3=f7tSVBWcyrCh`$48{9d`&13kwX60O?jBF?vl=ztxYvG?Hwx`lVdu%xnuI= z22`f9_8h*p_}8ib4>xtUCxFUol9lXLjJn>_}sHM(CAE8IIdlOz9B!%?#iVP zzi#@bQ#Qu>o60iTPH)E7uKBDuOqldIc?&3dNv#&xm)8NXx))v;LrIenby^E81tE6f z)03Z_o_u)$-Sucr>1(X2<*Qk+wpLh{o7veci8F}ySPW6xa>#Wc0$ z`YhF2vRka8-0QsHZq&MVQl$oJx7Oo%6Cs=*mzsukz0kI4YCkrwLc?}0d#kebF7tII z6y`0ixOWyfgokPnD(m;F>)PPG6; zS-t41Y|OeHWFb#J^wJ<5|F)?y36{k1ST#6n3YfNPAvmt>2xn9?)$ik`p)p?FK=JPOVi;Fj!^OdGM5pohbwqID_!bS_TZxI9tTh)R)=7qI>* zitdFc>*qKM<=K`NOB5}H8l{-4dwzd^LsC+&<~E!)(D~r#OD>iBdmLOmuh4n7yoBb= ziqV28c$5B~e-B3AcvVW7bK&`LEE$xoR68v*EW+*iR=P}&Nt%E|nX=fUwZl*UY%iFo z*Fyjn_PGl2ZPsda%1vEEL6+Y9i2l&t3@#!mbICj39gXGOl_6V(r3{a(jblkaOGqcA zjH}n{*QdV7os8mBb@qCu)qjh;tzdV8bjm{{zarLx=`0*$97Fo{K3DnxJ2=Qkr(LPr zntG1>?!I!7AO3GFo?(~-p5Q}=^_@4E=5b$Q@rdp;H(tHZpfYf+hPzGa;!{RgX!aT0 zyczG*oD)KX>ipHQk5&d>s3r4*^+q|Z_-GFw*0i>^_vx%nI=0?@=oD#`mozPrWBhV( z?UuHHh+GsVf8wLR3hB^%Mf>c=+)Fs}FwFUCcW(av?w;GjrWp*`E=>^9Lt}hr+v!T( zh#OY(8i>3#*Ew@maL=7QHV?cdd(gVc#`IQXhvMaScj=5^*E+qJpTR(YShQ^n*MGUI>h6B0u|gj z4G$~KFj3;{z4k<813Y={t>r@Ht&>Dm(`C;al1Y`aZ7C~)wdyP*rV3`Jtpx=B)`8;; zi{fpj2D>Vx`iLA>_^#aT9$|m-o+{P2A0BnPJBk z8hxbpxu6ZZ4Wv^z*LG#aP>H{p{}oP8;DNXcHAaI5eRKU<>kQFaPBCAA@YhD)Ax-;w zNro2S=Zw=MgW@;WZzKhUg}-DXQ+)RKi*tyff@~|s?Bw-9@$M{oQ3SN&em5-omOgx` zy}wLgF-!`wykFWky3~&&vUxtrQdLg;an8&D{ETs@drx!c?fH@QTK!31@VdL|zCmuT zHVMW$r8aE7vGK>M``vn>1yksP1Ooc{MPzW4Z`G8(>t{@hc}Yq^gR;J8Tc0eNlm5(> zADYwi5GM**;lO}Erl_n?qwmS`f_#oT>Z#c6JYph~tg18nM9SBoWwrLqaBWSIb^G%EnoRr~bc$T6>%QMlKjy4!pm3)G@5Eqd*ry>I8&Lee-N z^h+6bm#vJFdwz6g{LV!Bj&|;hX(DNjH`hW&1cOReF)?*0OozKeL&Ys3gX^`!xOg9Z z^;xHy+W0i6U3j=}Zq_$6ZH>x0P00N~=X8)RM}~f0qou}DHm|hF;+0^4zZ|J+oVx1i4JQjyquXtJ3e>C%M=bY zp3VwS>S+5V4O{{xewSJ(Q|?{4xBHS`!~I}KU^H{F=WU6*W=X;J{#qq>(&~NtSS__Q z4B7+Z`B~W<_qLXd zi+8WqZG;#l$3D-pD)eTOVO^{WUb}#dGZO7cL3L9WYNcSgP+zaMj_Wv;v%FWGJ7CRZ z*0j5Rt4;x2H^E$s&8eH;ImRYLCbGv-6N(4~f|LNSV?DsdtPquUA{{b6>}nL_81W@C~ZY7(b=*uMu?a?2F=Y?pjX z+wrg~G0W((GSiNS?sLRD>6sP}$yy4BsQ0~Z>H;=0sdmFy{|Vh(K{mwE6=d06mB4)Z z2V0>BdzHG_b9WFy6`nx>pk{^CJzXpqwM#PS6tZf*;wmI)y|u+?#a8wTin>@8MpAVI zp9~ST`whM7oJ#3x&Ep8I0*yGQ7jukFc~JUs+*9H@Px(Z#@$pM<6>9SVuKBa?)54n* zA=Hvxt%d<4k2&?mU^l79k47vWxpiZ>_E(rbpWV!;X^z<5bH`bR})7PBtdDkoG@(X#+Y3>wcW{)2ac~i`q?tniE2vv5enN$ zk zK?u?5GXk^? zDD$flXTCiQ0u*Wg1!-kUfGolX{|ia{=&zq3fSV41=i@xsJmF$E;+FXO6=tz?tpj-!})2YoMGu1m@}g!qf3Gn1YFpfQJmo6EHCQ zJ755g{KGqP9kUagtN?9Z-apXD@5!CK5C^(APW=-?oe)YNdwSwutuz*>V?6b5h!G2j zFd;xEB#YCBKspl&Ptwa|ioc35qwpX%nTm07p3QA5`Qhi_;Vdoq~e$Idt>DHOV_tl zmbb=nTNwiT>7M&8*8AOnUw5rvRf*qRm|u6}o=f8%{(3sun<})6jnolE{?ho-g#BwY zRTNJea#9>gyEMM_Kst-S$=Z-T`Rmwc8Q`Y?@A2-ak+K{|05sxcN~=$df3k?5Ms6h7 z_;<08@x}{)B@Y6$MOYS~lSiKMe^gciaKq1Y;sH1RM>P%L0!y+Wzz+T|WRwyfc@Taw zFIPc(fClerHy+4g0W9xnHnTy1v+}F5^21;MaC7fpMz<-=eN!49RNA=xf9)4(V6i_Bz;sT`tndG;$7%l3 zK*qUWyF~s(?qrk20TtTQFQKD676=wN_2>y37TCc*4dA~_YT)HVzyW~-%l)vDPvPM}dYs6TKj4&kbNw_0L`b4{3NN!7(v6U=i ziHH(eB9X{Q7@^E>ko$L@bDlq*=N$ih&zaBnn(O;{zuwn!a~wt+f{|p(m43tR;*{+L z-7O*2ZhAZt%6^0T?3FDWSi2(;yJdHJ-E_~XZqQM*=2e8pmUI3$aUEq z_9#CyezUrpGL2FZZPw1swrGd+QhRH#VuO{`7jV$?9z)6xS@{&ol<`maj=-zuSq8Hg7aLOA5 z?QbS3kOL;>12$O5fv5*_6}0XAb1eo#8$#207egcQ;O-epf9V z7Q+$~q8!IE8F`nt){w7jx<^9y@x^%Q)Z`rFzswf|EuNNsHe9=Q%9FY1shiTYp|DF$ z5=AIhkL`#k2`~Y{$>anlRXQtpt?q=x?GBShhVwAC`OcDz2R_-}% zPdbajo>vSxTd()Y-;uUb42f4D^74DT<>zzqy%lJNZvvBpppPj}?)Zk= z`tCpd!9&_v%Il<;>z8}e=jKX@wze%^BApET+@k9Lrs8LvY^w@SZZaezPztOo{9%vOL%7oR!o!x=2s=hh6Hv(6OC_MZhc{lzj6$}bb|~Um)u_p@&hn24IhdU5Di)1h;hN3yGcz!L zvzqq4Qg`|xty;LmqEP)x`!D)fE~jb(1?O)4XzyxSq@MHxxnNT0&9E=yF&&bh@9I9` z4yIem6dXT8{g_*0L{X2WLB`+Mw-EA=DR^RIf9E4YmpZ~`!?n+ z@9A>0{AyGpkdGrk8I2U0$bZWfT*l3wBl=Z%ywbvc36G^Zu>X@nb?P@~cb=sxO zS)z(~5~bvDuqDa3&RLSjLax=~J+AD|sUy+PNcvV7HC}^`F4BF)2LgiHnlY`{lvDJ) z4NuC>F|!psy70U}QT--9f&9(9Wr$D|sMZ$^M+P<-+Nx1gYLLMlhOaL)%~H=%tS}<| zh?dhq$>Zm%Um;qY2+|23!3{4HG(Kg@seP(oglBVfQey|HA$6lgscocS~;IvhBC#8iEfq-8kLvg3CE^f%v88pcziD(F|!ScDs8U#^|b{F!h!+x~@n z!nF$u|9GGJ$b!Dm=o$Ucynf*7qo}}Ne!7LvZ&Wi=mR2xUrk`XN?z+qtNm=h}F-$&E z&l}gO*y9WtB88cE*7|3ewWl?~6NTOS{rOBYpH1E~=_Ov7tsA0294}XdcsaBCp7Xv$ zzx9uqlxyr0qg$EL0qEAnzX%!GSHJ(W+R&ppveH$Omb9zoeJ4|d6tBI!T`Y6)6jLgK zuXx|f`GGk~F2_%{gkU-Q0hQ*|s>QHFHW3BVXFsmnuu7BO3=WUWx(+P;e^?!nckF*6Tw@#Xy;HO;cB-w>?3i!7N@ zDsr=pHzN8kp%-HnJ-K|zF+dT zb9UsQ*>7GGylz&cbNlWpy%*Na&Z1^l^GWDK4xE||3OQX>-8NPH(AzT;vX{r#5Bo_n zLBKMXBn(OiNNz`_7igw%5YCM`TD6=}$rH9l7`!^7Gd0`jhYnjyujHwWn3|0m(HWxs zUtem^u7`s;Zj4#Y&g8QgS_iH?GSC4KfH7uMSc8YdAwS(fJqE>sc7j4$2RF`HG>99= zKuZ+8c{(`^O8AZ7m#{=Y=GDX~HjJ^Zb~mo3UtJped$k+CmX28?)I>~`M0A4)^03Zg zzs^*fPA&K)ie+(*YjvrG0aFAHDhI+54op>c2g5-P$3Fs!MT?^Pvek$&OAdlQ6 zxb%?`YYda5gH?WY1_@OGM_7G3ND{zqabOdsuWuk%zJ-!FzC)#>K;2B~3NCX?>{R(^ z53hr1!9O_Qaw==UNeH_I0`90u1YJTh3F(RCjh!NpvqeA|SnifMx5D#J z%2PMUs$IczXyEF|Y!qtn>Vt0vb2RI4C(s98`53HO`vPwiTJkLjao#2l-PE=SB?l08Nara#>>$GR1yp8|5qv7*fZQ_ zhcjk^1oS6k_(k&nFDgrbjerE`La=}p-hC_{&=DoZJ|Ri%n3Kql>tJ4Ld!7}jZOt?M z#*Fwg&os3+%~Jz&f`9ykAC)Hp6U>ITjm}n}gK7*G*7mP7_?t2uP?nL|RAmIxWcH)0 zN^};Bb*5Y+$gUBLCu3O<8dtjwA{fhp03xPR zv_`A;9-Pq*$UvygLI7x+nBU-ahRSLYeU4!wn4=*y6gGoYSfVD#vlT>^OU;UX_3ipb zlD^wBL^3#Pa%`1L=>7;W`mh&pu5jjX4rgMvciv&a3HAeg^o$Zpsl)5ktfLVK&c(fZ zny17;6kl)%v6^NH%jg2RqM#T|CK8f^90gTA5LtG4yWa$C`ap`iumortT%wuM{NtUk zomHs;35VYKv*gZ);u`$=-PBDl1nyCS=_@>{&j)O7kvnZj_qYL{(t;#0=+s1$!bFZx z8e>GTU?dohXnr!BXqSMX!~NO)lo7a)74Z%2NekoQRG?Zv4z+K>!FL*u!Ax&l4i&%W z^UapYhl7+@0$|bJa1eXqz+Z;~76M}vO=>|;FJ<8_g)1Tw5Q-!Nx1*v_G!n}G=a0V( z3@qXrEE-eX3TO+u=pbjFhm6-BO{3SryyWp z1+lPjkYE?odh}%K>gvva*};gPk1NwX$zrK>G=$AhIzDu97i`QOzVxc)u}++7>!Zm6 zF@Xc-0k!Q~!Jvg@RZ?2VPoy4a!?%VB9w3kyJv!%_)=zmU&7h#bpSYo@8mNc^a*#%x ze$n`hpU!4h=64A5h#3ds1Vr^@Ve~2mEJ#KU1O(`BDEPugd18S^G0pId$jGLyv3c_A zT+DfO2rd4L-NEl~~hFT^9L~dLbLJVzhUoO4CH(o+o=P5r69|t{1nm~Dk`y-2Uu#)gp zJV2MT#Iw07#VY5Ziad68cI#$kZ=yuj)vZd`{Hc`rUttYMha_=uJBqZeN`0bVGt_8- z71MoD#!95UZ9Jpa9DjklfW80<>>t=veUB`L94rKQK1`!g-%xWYFh5A{BXLpqix!}? zfH<9q^z`@=&~8XB_@i9pvxIZ0uObK4Ag(Htnw5D1IhqDj&3=Scc&TL(S_2042xwg| zuXFII_1Kdmlr-24j`CV#blgP?*@*=}gs1Fod9>WSLikd(tCo7Gmi$R=#MZ23mV72| zxKoQQzPE$|wLDl>L;qSKXR^s6eIq$5dm^*oF~j7WpSq&WND1=AqQ(csCQx{sK*H^3 zdM1IYYzR4H4uccz?vGGib$Pwu%UwHZw@@ABV69cQrTr#(u;M?RX)vD?r5zGrq=kRP zxw}_#8#HYGNGbVsj@piU8Ho+6uHbz=l027@RQ08hk&%;gi1fZt36jPmt@fc&vxLSq z-E#$<8V(Uhe^(;vW?O7TLujyhh$()4$g?QUyM?DFXERyp*iD9(j+Bnn22zDtl{3F- zovgA@l=+?MGPbpu@N(##ZIiSmaUQ-K_M)LwEX@o zk-;&zu*gDORVo*Rfa!Elj;>Z;bST5E>GrGr(9^8&aHU^H!%DSkI{752CytCk>%&Zh zP|^PY`adv`!NRWyw~)+L{l7rY1VxVgH3&2m#M1sBYABe&pAQYK>w@{7SySv$@%D8`9HJf|Ach^)1amEvhJ*wQ3^=34Sh!V zD*6ZI{Acee3JB(vwAuWfU{fp1Gd_RpViP$)hiE)_C(q9d+fEH3`L?F3P&@C0*y7aC3=Z&X+x zstYuHjK}MOu9-woM{8XYiPhZcBq+(oJ{GDeGE{e-DXP*XF+>(X!ubEF$zs!J*E&}1 z-1OoX?hmD0p+}bMw$p$0Bk@hPI6=>+5pE+k?UopELwYKtF0V}*(E4T6wf53BnG2~byo)^g& zgoJam)2KZeu{5>MT;}SNVIwA76B4DPICFcom4fLkMhwAT@~VL?8>Gha1rc*o3pUWK zzAx7Mz&`p#LW52MFPmi?NNH#tUtAc}7Gf2G6AgZp@eJc>Z^DknE1D(tJzpHQG=)5` zyl~8^?X04^#mA8?q9qn~9j^J-0Bzy<>Dp&yJ3Z->JY$Rj4b3&Lno0Zih?qmO$O zD@CDZ712I8Rm`?ggGl08Dr&=bTZT07@~f}vGFVIIbr}V+YdE^3R4eJDg2hs8+q9`W zZXGfw_|UJJN?wS#*usUAnNP8_gu3MnHoF|)%BAY4`NDsj#)8uODy$xr-zX)xLu^m- z#l4v2;y&x-)$p0f+Ox%_y~}e0YnS4zY{~5L)Gvch$7wZt zRzGQKW~(;dX_U#haqCsM@wpd{EbkYW-wb~X=I-ENeaRQpt&SHDO#=(vQ13FZpL1?% zDva@u_>?WD@8z5u>0T>Rmo#ygrkxdq+Vx4Rsvq zLA!6=GA0cQGBv1+KwYMOaU|gfVm3>0^sU{cL!#;x5*zoH2(#pQ{AjmdQi`Y}AxKx& zu0FH&QFN0PtewBlr6NbwJhZrDzi*PhmfQD)%&pou#%pGPr=)ikS0|?v>N+?rDEYv2 zkJa^sgj5Yrli{P`tn}=()jurKEq|9dKHdf6g&XnQMA~Q!1DXbLlOzX(gH8FS4L&Hy z*U6PQkn0B&)GlX6#y0gY+`DU0ae-s5&+l8b>?J?>g|#moN5>U;J7!8nJ2rjn{s?(# zjwer0a)@K+(D0dQDKWixfqCVUql+pg9ds9eNk~_vXP)WK9YoWfwque-@(BDTofr5h zIr2f0#7{+58Ti_8Ov{c)xdR{it+dd*GtUe?IV>zpCIQNOi`UCSi-#F1@i{<+N?Jkq zLvO$Y&9y26C^Q~>Py{820tKEGJ&*z=kOF;x0^78gMlk_?LIIs3bzOwK+CfBq)yJ)2 z+*}&r3^kkH#?$>^F;4K)ek*ZQEYgysx$9cYnC*v;NkCEyXo?2+Lw>;K%WV5sasOI0 z|I45gn)=i00{tr@dtz0Km;tvLar!8{X+8LLoZD$yY=cg>5 zo0TYx9adVBAf5g^(GoHLxDiWhvRILXf0b8@pY$gnHkaB5Ve4<`aTqtq+)}eg*D@?m z+x~bcMSz;wdd>F+0Y|1j?Dw1uB`+2fA&tj;7Yr07>dUS6u&}QH7+1*2rLzq`DaSW- zGQ)k$XE95TVGU+;J*Oh)?`L96N}!yhsnYm)ij3d(##XH<_<(K+6q7P^+~ z0=MpZ_fe(^+f{1jDrJA^Yr73?P+pw*XeOVbl>)qng9fP~PHWgOP>WetYA#x()c|QF zjm+`Gmt}B~! zZq*U)(^ehdBKVFV=j#$aw*$-P(~>E9Qz3_LY?VD$@59V2b*3Mgl|o{lovW;*th{7Z zyaDF%)N1~_gB{$UuIR&|n&JHxtX3JCj?=3LQEO?f6xV{2>@^~R$MWsbfa?sHH4)S) z0o_Q<=dzqm`r)JP_g%qb;5N30lG+Fj)H&MN+abyZfpA4;TBeTVFsI1|O> z-y9aZP@V-*{r}aH_4zG!89F5IezT4@2mZkr;mV&6S#Z!|;2vhmbqT#SI^nPBk3CWr zxlr9XIuX`H5FFRfx}0gjQaX{wHwm5xrlcl+K{Ho*zf>%yU`=b-_9IWuDNReeaAZG9 ztPvuiU?ZDy?K)5iwK@y7OzQXn?N&UPIuKQFYj=E&_H*ZUt?i2W^Rw6w>?$i}0uYn6 zUC2vwtCZ`DiBfa4#ye3zzufixQ`#m}FIvIZx7LnTsJK(WzCWE;oizAs8uxo?)XKZm zFjth)56PWXAb>pn`w3%t=}?X~dj;*0MCCC{I zVf|FuTpJ$dPmBdrp9EuzK*XI)05GI5=mp={k4#$30?0D8EZ=Xv`(P8_3}9IK$pXa? zv`Sw+HXz1WBR)D;KTn)&IFY(6JS`MJ*@to=-G$OZ@Fu2Rp8lSrJX^NcsXyJ&t;Y5M z@Xa>OS+Fx5o%3`ZDwikp)@FAE10xk}k0d0F-E`j`tr5$WvfCf&cq7ymNJh)fQ;iBi zQV6BRM(&y-floF0(H68M5)JDzTdaWYN^JJ627B6_Fo65_=LdxLXRfv^0!MR1G3B?2aJr2CGe9_;9 znAKGn*=c1L<=X?8h_lrZfL?)Q{|!m2NSYBpf8Nbe!IskN)>@7!n7tP$-o#ZO7WTPO z_wpaM2HI-b5Au#@e7L?ef6Pi%&ewl{&@gb4_U#`nlq`-{=MX3KE67@3k3604MSdKt zbl5WT{)+YtUVQ1K<6+o9Ycl?=z1YG!+w4TZJ3xNKw|L`R47VfU0=#3cE#~TB1do~A zbS{TF&HM@5X5~c7op(W{gs~yPzC`+f>>7dRldYOa%vtkz4n>kElZjrt{EVz2 zvu=&O*r__G@l#mWJ@A9q+*j#yti$`wkq0kXtCknq{&E%m$NhF@iN1qEwhW+FiXuki zpMuzCtpd#a$MsU}hU%HJ3QaVj94!+G0bJEkgeh*Aj_bX`MF1 zV=60|L$8|&zHZOAwNx&ERN)3 zKHy-}_2WeE7-0-q3iADY^U^LC=PyOjaiKwxdLy~plBVjVs$3~ji8vmlk*VQknN1Bj zBoWoA`mT1KNl3-PtL^32UX!h%!&j|vgGdVhoi~E;LLleJhDvAJm&~G?n6YYWRO+(HD^?X8YbKk)oJ9=yFrj1nMvkRW=Nq*>~Am!^rBu-$$mAR z)MSNZ6n07ckCpwG}imhPL(*_`)-e@*dOIbtSfqU$w~57@HfT4Ntzoduq5gip)wp9D8Bv zOSw)|#Ms&RE0(4BBFQ!2%bh86(ejTJw{z7)oV}Bc(7rP}oVttWIW+1F2uJmTVd)h~ zUg^Y(L>Eehqs=F`K;K0MJ--5dZX`YWbCYv=KcKzuFN-aC*x!cO8jG1t#`vnqOZqoI z`AF-7+TfV+v$4lV0eI!_s>n}d|2^yDbrl%gRGV~ zKsc_fdX69$IUjPqdu4*E2Ap@AF9fmCx&jM35~7tpPTrDE95_ZslZ8#^jHAXc$Eg`= z-V?WjWVV$|h=|9uMRv8u#^`6|DaY6kGh6=&XFOx08QuBL`oL>Vul9KJVrUo)XD2uoMLGe7+`f!p(WS7 zU#gD>vsTK^=0xwWg{;*SSH)(E%QZ*F3|So5;ge9>6-1QVao6QdQVtVhI$iu3cJ=!I zey31Bks;-YX+;-Rp`-KTrZR%aK9nifI=j-3Nynv}??l9Q66%M=`B&=cO0lv7GJc&% zrH(yiivb8DqgTc*{O_zjtHGvM9`h{$?y@#agPuiUgZWeHU*3kn)7#hQDzGw&CxnU( zc;O8n4LJIP{$!Qp-;I`B?4L{>X06J_8rrweinB(&88`H-@N!M24SS)Q_K(`H8|)~_ z0*w7{DGcIvtQY}dMCtuJYmrq(`!(_2IOTUnc&$GkyG`a3KO4=$UnID)$O0dn{keGi&CDkId+k zFo9e6)PTmRTj)0?=C~9L70e=t$mmyXCyVG}qsHqqZ4B-ka;>uBLqk@8gvwDeE$;74 zn3nO&C=b*&gh}opEnWQ}*7*J9XwU z3*_yJUt7?jdhG8H zx;Ha(I*XRb1=0VOQeM9nzkYvtFR^%skODC>Pq)>T8Bf1=r751bXubk1GL3D9g4jad z)q+#bos&6A?;nLrYYlEvw__A&k-OZHOs>nG%$j)n$B2p-Y+ldEN&5M_4@Io`*Q^q| zGisogs_!d;1a

pT1*MWCn}X8cr$^v`;%9ejTBqnQ!A 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 B3-15` diff --git a/src/Nethermind/Chains/boba-sepolia.json.zst b/src/Nethermind/Chains/boba-sepolia.json.zst index fe7db661c33caee8b2c8ffb935dd1fe1d34e1b07..ab72b76af1ac5dec523626667186ba38b4e4844a 100644 GIT binary patch literal 1500 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%0D5E2eUKnmL=^& z_j5sF{xvgbxqPKs_G}@(=EEE?TK<5%r0(^=ftwiGRH1SxbTCecEvB~~#YBNdk%jsB zk8f)DR{#@BEcfHLXcf9fdszm`y!v~eO4r1B=t{mDYMS^mhj1ESv?UsE23ovyCB>%m zIX7=-97e8dLq*%6pTs4&v*!ju`yY2AK4F&2df}wjUs{ex$TvJ6%}^gRI~v^MHz$=Li9@;V!IE?(}o%c zgeDcXxTo@PA3ZsJ)QjAD(OIn)5yO^!6NZRlt;VgTW{M^U>*mN1sRO_-KJc+(!L4+>K2phtO0r}KP|A5A-=^E! zM0bkB$s=js6;kIlz3lDbycjf7D$c?;hx}q?na-vuv}ksn_++Zy4oa(YBDEV@-dQPY zaV_z`L;OGMoD!`Vzg7X>+VCK-Nt8hcmmgEo)3l12CE*B_d2LS^Q21Ph@iC&g;SN#p za-E(dF)#3mHH&(-HKt$B&47pN!LGa{Ah)Wpm;_lOQN<-gV>uiMCkPGJKlp8SNv~Hl zpqg27j%wt_B1^ScI*2w<8!Zas`cW`%8P>@RHeC=9h~c2HF#$~A5U`YW!#v2IY=Cfo zeEDoWvC(g+zwUb3oYvUDq0d_0w%H>dw{}ged~q)%$)<|gYzcYfTa^10@dAh4Ky>5m z^9LmCNRq3$5s4PZ*0>?kF+k#LxmP6L3D^DQZA_upMkq zV7jFAv<7Xo2@rhRRHTF)`f)2vF*USo3A?li@C645dGdNC3>A*E2P5Mxaz!(g_7fYn zv9D37YEYp%Do^#wy-T~F4)(b^Qo)coM2p|qI#|c&PllA&m=?btRi7uiW}M5tSKa=? zsNr*55}2!*60I=HeJ}PwS;;SR`o-BgwhQ&6IKcZ|0{|JBoWrZ(RL&Hj0K-QfyX%75SH(Tbiwj)P*zv0-D>&C0Do>VW7>l$#3_Zz64a5{G(uJ;iJ2kKZp=Icqup3=*ZYr%ZdIxLxHkoXxwM)N*3JpOMlsh(y%*hi( zrJ;+NIi@z@@|B)2ihU#&#o1gt8rc4ku0o)L|A4Dk;e1{*vHUl{@+hK=r}$h{ z0JvVGZ1okV%8M}?QsrMw#Wk`MzE#a}w-dCAv5Ool6wTEm-OngKT2#Vb@$uF`ZH-Nd zm7Rn1#W3fUOy0wWwS! zh(0694u6&HPpJsuSZ$LkKhAu^Yv}fC|HON7$R?u)fu%2av?<|gpX=Go7haUOr}G^u90 zv;Qb1)pzq;XS_$N;D00p$o+k z!oX|7x*lW8{GKK1@I%r_I4Zi)1~Sg*B}{z!bvIcZ$5rd^|&0}b>nT~c)hX6{*nwTwI0qWIYr8bw$RceTW!N!&2YB3)9SDEN#qMT zDy#7q49fkXMF`%GV{XEPU%k+3xM)ZX3e{SW@3BT;zZb%vk^XoW2g)twWF6rYZY6T`~0wV3;1+0K_V&8hZN><+_no6AqW`rQ^3fof;SI zKs05WA1`DaY&@LVW)>6NO{{*G3V5m$=61&IdUOq6R=5s5Xu{`epK92U@Ns560XZ(WcMmn>h@D7n4t!pa}{GOLNNq~*MGAWe>RwUWL*X7iKjm5VHlPnw%?8t zmIzF;4`YV5H-xoWg0vP9ea{}$nRFjqdAc6W(Eq}xgBU%x%yobTT=)%7$U?za*gI$+ zH>E$r4^bgqBhXyae0$kz@8ehqGri*r3KsR%B)6K5$FJwf?5709x!2#b<~^U4oO;f? zzw98~Be)T{i|@aPjT|$p8{XHkk{QV@{mL2EEOC%V(%9#Q;Rq2oM7g9!=SnM!)K;m- zAWGLK6YyA~mT8>@-Y?%d#w*3?&L|Tj+306WG<|Un<#K`t@IMK9B}PJ?zH~@B?@fG|C12Df@YD-@Iz&mT&+O2X%@^_ zC4mFcK=E?_zsAGEWAWLHhxzw4>)!v_iaV@TZ?>u5Sw`@#9#fli`#t7R00LIYffbqzWaXw$&_qx delta 11346 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 diff --git a/src/Nethermind/Chains/cyber-sepolia.json.zst b/src/Nethermind/Chains/cyber-sepolia.json.zst index dcd39dd4c308f58f8812f853fead3be6cd23d97e..8cd41d3686636f2a06d7b94de3980de541730e72 100644 GIT binary patch delta 11526 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 DlS8Z4 delta 11870 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 GXa5hR*INt# diff --git a/src/Nethermind/Chains/dictionary b/src/Nethermind/Chains/dictionary index fac0accb6ebabc0521c9c14cfb849396ee8d994b..3bb35bbf9d5552c79f1b3906976fef2c89f3f123 100644 GIT binary patch delta 16955 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 Vx_5l@Gjr$u{7)9UA3t>N{|7`m-5>w} delta 16712 zcmb8036!2!dEXh$XuQdmgsjDqERDR#t48m>$Y36KX%j4f3o6{t42o0E?so`LtotR=xxEe#p54dKX&KT z2R?A-6N}#U&yU`=YSH-i2ZJSxPG9(iVA0!Obo#&Ex@hdCC7;=G^MVBX0kS2PQ1yN8WL70X`RHQ-Z{?qamGi6*hQCKBKRkU>%S7j9?K~jZnl0mpj z+PLhqw20fRYqB~{^DxPRq$!K6ErKw}iY$$cXcV)X%uf*U85A*7@l*vxH20(yZ6qwT zf*iiBh!`X%X}-Z)lCRSE$?G!vNmhv^Wf!un>hRPE6jo6X8LucNR}nYb?MxF|&+YO|_Kss<8C)Q4SM z^z}&Y!poMqXYU?!ANu&h*=qV_CpOk;$ld$yIeao@4nN|Iw6@nDc++&X|Ktv3*mh;%e)`CE*Du?+ zY)U=%hTHZYXx=c@wuidIhu!OzMXzfPb=8qB+R+`{d*IF8p}{M^!7#3a9Ywmm*;dqj zksQ1SJOpS}m860HL8lN|L^wbNkX`lVcOYFWku%Ay z`ot)Kel&T}6zFzTX%)zKl17s4vV=!d-&^HA_WgA$&|e0nodjK=sv0+ZX5nG+>N)a31KS`xpLARM<+t^(Ce3p4`D095SXQ69D|c?#&H~Dm z^X9iKTQsn2bG*-f1@F@`^1LrY_rZr&?$Vaokn|izc+EBgk>&kK|Cq)YmTUC`gAsL6 zmY2!<)@{LDtUuE@Xyn`nckgnaJafr{FmrGG+OipptSm#A+fk%2%MJxQf!Rr`s&Bfk z4x7Ac(*i3{Bt==&ZP&$l6GTnWH%ZpzZIpBwHoC)FmPu0f*qkISvG7PGuaZ2i8#arLv<>Gex{(G9 zzj`LD$`oy2jDMB4dX@KK-*>1@UDj1qR6$v$QQqch)OLAOhhb3{QIa=#)W%)ihfT%$ zo2t+XVQCh2@WX2ad@alr7j+&tag&vGjX{pvG>p1trb!x%blEg{8R2#E8iv+E-&akA zTguZmjiNecS3z&C%sh~VZWQ|DpOYW3BP9I(72q%wR~6L(P%hjG-f3wDb_RtZaBJzW7?%O-`FULu2q{pKRW}_cxb6{qQTs;gH6JK?GniozfmT zKI|rTHL@McyK*)%I(Z+nXP{8$j(+1px8&XxZqcztQ;f$fVSxkilJ?Fzqh?6EEDcj> z7O)7t!hWt-oEz?OOBb$m7vH;PB$=JM_Z=gPno2@L->fOzbN6MJCRI{qQG|r`*yx}t zf;O(OMpf6Ky?NUKCaOHi+_BY@?zM0J%H_ZAfH+36wypJ>*Wzl<1H^^M*aGq(cb|C6 z^co!mZ+rQoEU^s*hzDoVy72yqUw?rdvir#WTSj7c?EbA29!5$S8NmJ9GQ$9jzg{>Zd=1tU%2_oHO!R7 z!&YDvCQx%pM`fa>eqGLKSb=5XlM|O02=YXzc=oQBy?en-*KCcG$t;~jGbh6$-4Y`n zsc=BIAJ4yK^X3){g+c3jNJMoP)_s*%X%{D5gx^PNum)+&^6Qr4=ux>Y$ZPsE_+%Pt zkOCTB#(j>9%Q>+=X{#WrF|g4L7`d;TB=4%c>43u+@EEI$QwOJ{n4ByhE-=U^gHx9W z>8L2-c9rLKRz)Z-h7;48wS61pRn_)M8fQt{c12ZVUc$CXy1oSv)=f53Ct1qk0yH;l zG4%iqmIv0v_F?3^GR9V658E)Wld{2(XBg5pjPe4fQ@h4y6}vdB&hD74ZJMyI+oYa-_}Z&R-NVZcE}1@9>W^jxgN`+Hac@!-uZ*!Bo3#d$BDm zvz={S?+RO;>MO#Vk5v2H>QKAw&~$rOxBJk6``+w9Vv^(KitT7rUhIf;m^9#Fr`kLY zc5IJ##+a5cj78?ggGZ+KO&{L3`@o?i?!4;kOWL$+h#`u2Ti%xGww>Y5XsQ8lL>T{e z=gu(NUgJtLcYU??(hT2`=Xt*)=uoKbJJVtps$Au}@?ck&guBwI3RoFTxksxFmj+ph zJ4^F2%R`I`xUj~RcUIBP?P*uJzpU0T=mPhP>UlR?pSv&%ZaGxV-n8LW z;};n+#Z6(q&F%Yu2t|;o<2T_^<~EF<>;A{s$|ek3+TzfVT!5|*`r&=hR&TlqK{a+@ zlm}Gs!vmvA!04S32bT=T@TgHpRN&rv?BWUHt`o-d$MEk8+mN`C=FkRI)}98^|Yt76u;gE4toh9k)gTEd%=g%=l2m@}*xQScxuIJMZ5wpwi-Cdk=g2tnAumj`yW2Xt$FC2D>+8+t(Ipo ziNXOx5eat8w-2}71n$;{CdQJk4cwa_`p7v+ACh~pEdue}riV9%#?Eu#jM>;!56I!x|=vflEA@tQD!G zIq7lEMWOaC>)dm1KTm4&?Auo^6k7}T!sT#9q8`b4g%W~DiH4DQ`0Q|YbS6rk3BDLKHU;r@@AZH%gqxGPw zOLzM-6AKu*bmisllbaX1C!aa85_n%QGz7Z@h@sesG80$c`#Se`d$!EzB|g z0gaU!mnY*)2RTs2M)%NtOJq>eK@<#C#R;KIkcw_MH+ zLfH>a90e(QQxhe=@{?36bdTP+>Rju{@rk~~4cax3=XE4re!8c;u3_z%oGdoZ<wFn*YZ17wsMZ(9q(?&j9$>+S$ApvQYo-IW-i%6g&!MbAsGW*j# z#S9`P#;_s@4Wa?)p3g>Fz1UO|Jwma7zKEk2FO8WmX#8zL1Ad}!*7El};leLS{ODnV zr?*Qu4Lc{3R<=6(x!-v8=v9bFy)~XBbvQ|e2SDNxj)8z7LL@-$h|RMSpx@L)VuV%5zXE{HS?k%nLSk^%%x0a$Aqw;O_dXRqn#8RxN0I z_tL8_b_YLk(I{5Oz5f#zk0xR1{?#YeEKNvr>R|ZfcU;zP<#+GDD#?|dq&4SM)v9Av zQptiNOI|3HR2ov|UMR*6om{Q^x8J?!^1&<8tTHq>+SL4ud<;L5v%&w&-8gc|W_m@P zL4Rqw)D7aq(s7Sec()4f@rePN-LwB}jEab{{ltOSaZ}KyTb3pz4x;#PRqRnxFrjhqb*C_UwroL)d~gmzaqU5 zkSN0tD3}bJ&OQG}8{Nx3z0f`Wk+WxC^4Z@R-)wIZi7@Ujw!i2)_mAKtfsfvV!btb| ziD*U?hXJNJQzd7}R4XylhCqE#e4C_13TfB&!1gwYTg9McW)h%s)wdNaiE2)+C7n@{ z*Jv6LciPuwSVdtbtIp|FjS}~AqfD((I<1KyPt$?IVfTw~Htw^RoUJ6k%*>o=fjuD_ zpxiWZn3+w?F|9Hza2Bii_@A#`jJcH6j8nh`;z0)d`nCSqPEuJ1S$zCCpGg$C2RBbj zvg(3_1H%kU$$03%%}@DQjvkm;lQ_M>!x4}^y*qSgtvU1Dp`jSQ(av1;Orp%!bta_X z6n%!Z_%1g0u{J+%t=K{|R=~6HnF*dqc!^c9kK1Rjo?JM#Mpy?q#>!Qkqj@loNw6}v zJg{Sor*Y+ex@P~lIFcmp(zpG_%)pkbC{bE90Wttc z)kMHE%5GUm%wJvVSHoD3th8w|3ot|@VzahsphPl%lRsdcc&nt((K^oy^ba1CxNRXo z)luA!-qx;#9T??-Ob|Zm02R&xk4pFG>Q$GLT_G9kAr8e1p5j7U$_jBX2ITvQB%AyC z+I!A2etUr8KJ#@GYvfehLJIG6h}pcLw(3XYpcd0Htty&_&i2Rnz1+wo{A`Tr*yk#R*w^hwj`^M zJ$WS{v^p2~&%!&DQ#VvPSSF_%6_q>%4pFH&5jId?02j@Edo_k| zOD;%)hUg>(#Up`LEf*oml>i6a|MlCp&!hunX~}ScRfxcjnA8NKDT*l|N=wueDJ#F& zff%ucIf)4T>0+o)K3&EQVm~1~hwOdrg%A|*oIe|Y-H^np`qJ}hTg z6ly7C(P{gE{YMT}&5;x8I(bjpJMLm^4^c7t0Y8BkMIBX5Mtqu;U5gf3VaT95_<#-7($w)6G45j|_tU;DWaj*5B3b?+#BNHs5o&tM=MMcjWHwPqVhGg)WWNJxA_7aEL0^rprTZpWMNT<+nJ)LL_>1 zusYQ3KQbVB%?vHwee8Qjb);f`YIOB-U78gf^4_!T50j`;UsQ#P?Lr`6Tr zZdcds?haj3X-|xfk;kT@cBi!}!KLc165JtoBj z#JCoc<6%J#Nx6LDP9mVFBEX{(G=)_3I1D+E3$vluLvRYl&$D(g`S zCQJaGwsqKNS++GSz*_tdipebBvQ^o*6R=hkVb@8e$5q|rSw%XvD_aV1cn-`DiRP5a zKzvwRimJ_Qebr0H+*2=HK#cy}3pdU__uhAp&!Chih0x?Cj>Fe9k#odmk%E)$s@q|v zV%S36&tw{n1G13$l3B>fvvDLO+meu^ui#4OF|B}$@Ft%*i1o5Cr+A_WfRO|RCfF^sh2IJQFV#02uU+UFvU~B$i8i zHghEeip!z&Rf?$lubWOA#S{sPyYD``>czJB)|Nj267J|4W>jla&Kg4<_9Q9Ionj+S8st+JvWISI zviS^_{m1^Nt*|8D| ztl3;?&AVSkmbOm7_i$b$3)e-NMjjWCWpmqVPo29_{)k?b8Xi1t^UScghB)~44#nVo z+)iz#{SmaZ%o0T1xm zaFa5)8n)p^Nlsb{LM#b8!yhnsaCrI@Sqo3B2gzj}UPj?i&H`nv&plT|i{8#_n5 zmt-Y5b6|2o3b9dIL+%eSOgXSmYKxdi9>(s@+c)l!fJx}^!E+ZDDyp!p{=&Ay0YV8@ zM5zU&(t_yJstC|p$p>-IAfmjX)+|Y9zxu}yju$89PdK;`gUf>LhXWiunU%y`TT%fL z>yP=_GG0A%jB_&bSeQJs; zU4_cnDiIHmX-l-wQod+9>idczTKOQ(Fy~o)4JhGA~+AOAyaZoslioA0hZnP78`lPh^2(lp25`1Veq;o;-g2*dP-VXl~*igj)GE&%qO@9!?<~J3bHhdsBFCX zNN)-Tf2k5#kWR!j03XatqUucJJ!M+B&wn&>?|Jee7yR7~v$y^Jvty&^y{m4&X!gc` z@ye0YAU4g-& z4=&T_Es+-bI(Tw7{NYuvwP$lmq_yo$nV4h|hFV;^7XKKaB-WuBJc>4Yw1sBBXA_upBw#-1{tJ=a_1jjWC0{HFiBZX+9lxfG_5 z0J|l`9_&hxwrb&>_UC@*@$(m@jkLf9H*U`#FXKjoA7|FE)M4q^;$DVH)|?jI5KveY zOBjb!bBl052lr<5{M`qie!wG$rxD!3B4bw&DJTvXj#zt(SX^SuGXfd4BAf`_*@k_R z1NWpe^z*j0ZuR5qEAoSbq4P#^c!Nc7t&oGYV-Y2Gg`?p}{0zt`YNV8ar|Wyqg_3ef zv3u9!>vi|w)L9g+vMo;0kMW-P1F?U4;xNfSCl8H51%;D-SR{@nzfC4 z=Mx)7Gi3PVPh2-jmD~N#C(_Y8YFzN4P3Ps@QSq0( zHYg1%E?JF?y2W36x%A7iBN&E0e#`jtaJY;m|z^^CD+6P2M==c-{(oZJOMI`rF~zLm<>qc3b){{OlTv~D!XW4Gzp>Ip;zY(vRi zPD9%xg<>41m0G?^<11$<5)IpwpbdgX*+}0%jfd}|(vLKcsa}+pU^!3R-L>&%7l-~& zESBsHaIn1_$}57Zit&Jt?vZZuV)P@Nw=K8td$-L9iRp^5;Gz;xoQR&lfBaU&!3ioH zQ*D{&xS5NNFstSrB~}`*We6%0{@O?r9`18XIR%+ir6h#yD|S8i&n;RvsVmTX6nmPl zh1zkt{%QU-XgRwSfMAtOsgJ3ZKr{Z>Y^FAuC#qv!&Z$4WdlhNoOYyqe8`mT^eCCQh z0_LRuv`zr}5U6X_m@1emX~t<7>!nuk$PNL_C#M1*NUrKQ;E~C%8~NzuHN-RAm>~$G zEYWfCngnQHktycxa6{a1YDBMk6mX3+6B@1Po=iJMybt{O1tX>I<-50h^V*k@ms2@H zc-7K%npVC}c1J<1-S78rbPT*Tzvv+g=y1t*w%-D4a5M60Vo~g^B{ooh$tKBT>S;J$ z*EYN}Cxqe-kb+D^fm5?+#_PWd*bBcGgo_9qGEJ5%?-`cf5{+hguJv3%&y*n>P;z>yX=BuBqYtd2~AVp z-kT*^M&pE857QLOs++J5+n8$5k0)6fRpqTkmnrnO@XxRhPu8XxSP(nb3_OXG2;+=z zvSBpITlg;C{3;_Q)UCz%JZNv3z=)>*;{9xO)A1xfWS(A{7MqSKPn z$vv)X-ypmk$T;)G2$6zL zEkAArPPGbhFP6Y2Nl5x$i5zxmh*?MC#gpscriCg;L=h=F{!*zze!11!&U zGk>yV0^2o@h+Y4cZEG+T4C)j2`+qWdEur$fPNLFK&}BWsFZ?y!m)x>(hPGCD7?UOm zwt8h;-u+U!pa|S+zI5?2(){cfPI-(hxa}VM(z}+?+crD!`C;B+jGtTPZoh5WDAvHe z=F2%&?y)a#x}MtsC$5T+9!rI}_?4^TwzOXr+!O}0RoR)i-9KCHZus)q6WG;xRErQk zvNnk%pJK?GuUv6s=?f!hi1EJQ-WfL%{lejijp4gT!!b4kSxM=Zc;??z%O28v_gAjF zkb24dnVF6Bt*VIyrcNsj%h{iO<(iT6D@?ZxhjGY4P+ek{VEM0NtZ)x)zTAEAtLHDT zxI8Y~r=EOsNF?*zef_K7TG8kWC1F@`caGnrAsHUP=&vt#&wp+067G(sTogNU0rZbdZ{i4~@T%rfBqi8diVt~_i!GnMtE#zu^&AoNC zQm{O+RWn5j)zp_XQ5>}FTdg*Swenpc?pb-fMQSL`DI3~rNfN{6CN^Tkt41uB6;>+A zT6GyneW}iHeKi@hf|TLMd|JpOsE_-nw%lrvmzrx8t+1NWl`@D8?@`$lAy=e)YZr1K zl$@DOtXk%YQ*Z-`+p)M}y~peMQRKjYm9=k0`Mp`;y?V)E>!@(Fy6EsK14{w%$vl}w z&LF36uLRslQ+Ja)pM8=z0GJd_$V$ol>sc1fr^wZYaZlaf{Fl{Z7@O4nukWlGMaGT69?#r<<)jAGZvDTIYw=*_ z?&gsz4P=uX0!Dd{#2gB1xJ7-u_uS4D(BMO4rRl;c0Ydz4m2sB7vo`YvbGx9@b)1m= z0DW}G=*DnbQ5#GvZ*jsRjb=s-Vuk}gP84Z5p&LZ87W~eUnG-~z=PQ50vvVx^)f`f? z`(&zOxR%;4hLDHC9vZt1?_cKr`$w-_#93-$E|U`nQjggJVh~q_g$?{*)?nED2*6jv zuw*9%mhQ(N4NfyPAw|FS-aBvC-HEx9RiXrmZk+T$J_=l{Raf_PwU2M;=&qHOmINC+ zF3TxlX%_}9{it;2yacD)y%yD)dCb8*LC8Ut8XG`g z(@;gbR4L6RI)me3SjzpAbj!>0z6m92CS2d)LN=v$^EW~0o_@|DC_M4h^knU3yaw#zNml9!I>(0yOTkh(gubUrbE9YL_e(?-Jfh}^rGbv)exB|z$ z9UeLes=OiD`9ak{-(-~;ZgakSLMY|?>VDA)t!6;65WW?S!v%O3!>tlpXCTqRaV{YF zNS}GVop|6A&%FtHevb-fAwUrs{3O z=9)z;0+U)R--*b3zI5k_@l_w+ij(DfX=$z2_rxjYxM#G;1=%QIkS=C&u~0MMaQwpf zejRs)wX&q)Ha_13wv_=@{jew}oGb|N@bwB3fTeQ~Q<`n%4zJk&Y~c>C=ay2y{ozZF zJ$x>?+re-N8(nP0tV@?myoHa!JcB$uXu2m4zy1sz7q_j;iZ7ckbGyHHW&^>7Rp;hElAGDLqpt(LHZaEMs3>Pw5I}n!cF@LB%Z7U zIY$2jimJJRiL`5(_G89YuEWU3sQuI5KYtYH@1FbqRg`j4z6rbeT*JunWb|XH*4Mpp zW|MpC51f6z^sj@p%*Cp82(VO4#do8@`d)e9mjBILPqUFlao zqh>AcEf)sk{tx%$g;y`(J`ij6UklSn`zoK^qQ5`{JQ(HEl8fBO_MxbV!&mo)@7+8b j{PNjB+4JoSX8-UbpIb2d*iU|U%$@estB=FdZ!P>k-mH6* diff --git a/src/Nethermind/Chains/ethernity-mainnet.json.zst b/src/Nethermind/Chains/ethernity-mainnet.json.zst index 2d6461bb5257e5d254d74298b26457224a79e613..278fc5701e55d43799a05b75429d7f9351c7d4b4 100644 GIT binary patch delta 7415 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 delta 7399 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 Z0{{d9b2O7XEFQBL9TWorq_Zp_HT1=^3K{?a diff --git a/src/Nethermind/Chains/ethernity-sepolia.json.zst b/src/Nethermind/Chains/ethernity-sepolia.json.zst index 10e98d7be4bd150a1da4ba397c4db33fe963a9f6..0a365fae323be2b13e81d7ef666e6e26b59c65d2 100644 GIT binary patch delta 10920 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 YQz+-Ym&lEunDb#^Y}^_rS>$j3AE>2l*Z=?k delta 11418 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 delta 6633 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 CR~>Eu delta 14622 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 diff --git a/src/Nethermind/Chains/funki-sepolia.json.zst b/src/Nethermind/Chains/funki-sepolia.json.zst index 908998831d26218366cabbb6b45379ee8dce4116..eb82ebcedc17e21aea50d997e201f89c24e3738d 100644 GIT binary patch delta 11496 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%0An&v fiu>mx{^u%5n&%P&8)IwIX3z!&b!=*4?7RG5O%lD5 delta 11848 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 diff --git a/src/Nethermind/Chains/hashkeychain-mainnet.json.zst b/src/Nethermind/Chains/hashkeychain-mainnet.json.zst index 18753fdf32d95d02cf67d0776928ba25ee1bb489..28dabe61bf0513a4fd977af1557285813af1f2b2 100644 GIT binary patch delta 14664 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

_)v#?6DDz{EL?=Gl#=UsJsA^# zVtoE*Wif_t1q9V@xo(qMJn#(UDasaE^$}KwrB#dtH7VAt z3nz#D-T5s6*UfR`#o^dhNc0<`bRkH+c>PMQXqO|>9qp(;^QgRErtcZJ@Um{Rs($)f zg-ZRc_-7XC_8TA1?9%cl5RL-1a&>^MpFqJ3+AfY7Vrd@*2o z)<~oWRNKdLfTU#~J+QyVm?Ee`HIF?+^%H*zL=X0jgS=`$6<;>mu@EzRk7uBW(C}i z)MO1mN^>BJiuq+k%U9}DQm;!DtdwykK`%<#?G?GG(ljR5xFFNd3=%Z`pyiFEx({cC z%(jYHR`8Lh`Ic}PQ|e%w*Xlc+y&-B#l$%+~dytQ*<&-%{zMe^6XvLKmXuAFrB?5{? zcm(5JWB>WGox=fv=V*}qGf(@Q?;pvnNHgbR?Rz6^`XW!{#n+Zf`tP#~Gt0t=gWT^3 z3Hp%Y8Ww_X^ex8Eing|r1-V40WXO9~dWJy!={PU!TKbk`xbfN}I;T^3 zP?AW2hJw299m?h(Lhk{=1en13ks^_z-2!bxC0mPn9|(7@ZheT@S;3!{5xiF$M7*tC zJO_L3#8jA=Cr`ZfQ4>H<29JN}k>^zdKJxOr9*4R{ZcTVE8)JFrp=QOzZ(U zWYEj*RA|5teq9oL#VkvpiCznnW625+^6@KoB?3kVws%Qq6)(Y}3TNuM+Ml2Sx+mc0 z0S=!O$G`=UX$8-}q!Fdfh}i6#%UZdUcGc;*E3MPq2Y;v{_wV3x8a`ek zvyF-MEENWYW94vGGp|n;VUx2KY@i?Gijx_?ntV{)-7A%<&zc+HA~DS}Xgz>>y1Q|8 zM_-i1=UN85yZCCw43R&Ta&q$W?+(0rX?)i(<2!@vD#vy+o`JtzkTtJ~=2V~locX!K zi2z8Aq`x)|GY-{M*|NJLd%GEgvEQPbkb8NX39!xMng7k|kCi5*gzHo0eb7Zm8c#8N zczG6n(jRvQol)WI13<)(6?dGWX7MN#DwA?k%;~+SW=OlT+7}(z_Z=mz zX9GRR-#Cf`pTgJNF%F;3GV|Ipu`%03ih%Q;26HzM8x(611@j=mU#iTvS2sVWl~JA- zH58}eU*umk84tNk7XR@#Qb(mz+J+l(h1!>7Iuj*;+Mn?eB*&5lXL7Z9({Mg9JpLVg z^tEp`N_^p`revP`;@I7R$*A7uE`(O?ni5V(BJTLW?v8wC!fjDv5?W+Wi+Rt7$p&uK z&y4uh6*w`u2FIauEeA1V1Ev$>0m~P931r1+dDrt;pTS44qJIomAk)Ux7dP(Q5)dQQ zHf!U{P)av2Nw(i=mOs|*JMiHXsG@d@nCkNo8(m)9=P-KXei``LY_`v!5<*`ISUn{- zd>*Z~lQe+|XBde!^BKz2#0jn9Jpdi7%gskE-0LY5-@j@`K^d7--CuovCqT*i*QP~y zAKoLk2tJ`h}|A+U=>|)?At3@vo z%{jizWVXn^)S|t0n)}M+{@K6TXCD?%=c!N5x}VJp_xjlz-l9FAQ)u>YD0aY>1=!mc zOW0ubXhPuvtRyT>gJR1-Y5Y|M;Lde(vE_oA->BWHd8a(NyZ$Ti=NNVW zrWb>A*qLwr%OR7paDF4uEDIRU6tBox+Yh2W6mlhi4ni75U<}Z&o|CNgE|!=XBXDP_ z|1KLi5hbDI7hf4m8QvY+OSanBzHdfJJ;-w{J@#Bdz&VvW#|?hY_L*j;Wzm7T zCevfu-Rar?`r!NZ90LfUGF;?>znMdNKy8+dk7;3*4J!ywDoH;f$L5q&k&x%0Oz%ui zIZ@KvY)nZ((ecXP{=ia-hUgE0Z4_~hrxyMpSs&$7Om4AO@3qIWV79`LkAc^JAUO%Y zt(0K#DV0T5zaH=IP5s4phA%*27UdZ)X38ufbsoelt^d7_E?S zo$v6`8`MWW)GwgEhq*(^p?4=ULcRFw1NVoKFhu3n_~{o;bIhT8_k_`9=U$n_=!I>| z==u@YPH&)wFSA_cTqw6V6R#N7UH74;4}~-_foiv|rpdoB(q4UiwUz0oKFVJBf1yEh z)?XI%W*)A1yi*k=NcXxiYKVOS_XT1S+zi~+hQ<<`OL>4LrmJfj$Sr}08_kn+Szp2@&dj1ZnqD&qZKG;*e?gmk9>><=GjNT zh4=_8^+TYqIL@xdt-T4C+(-=?xGO3+wTICZLDb_I6wN@>eA3;w><>6~AOTe7NB_1h z1ka}Yr-r2sC7$Om6~7x@_Q-6J-VkBjT-~lkP%UFf+eY|U1bq1WE*@*p=&S|LE@y?~ z^fH-Z0oWRR9_<2eJCdTw3f7-amN7kZ3|a>`o`6IFAR$M>9Q2BeQN>JwlyR5ngbSaf zf3LSQ#1QMD5uqJM`0f zE5E&^({e=o7?~gGZScZ*Fkw3Ux~i#UV}?%C)HvfdUrq$S30#{Xc~x6vzZv0%hK+&y zqay86bul}OW{D96%g3n|tV}iyN;CTX0kGFkt8A6{PmEJ^=5WNxaDtw8Xn#QjM%lt; zU( zA&(%>6Locb<1Tc}*3*?(}fS$#QE$ zI31&)k+>#2y2Pud{8L;=HO-R+cj4yHLnoNMc0iFY-4(^^wrZkkDhgio9pFTZ^k>*!`J8bGvRkec1{>js7;h! z2CB?e@3r|WAEWsGrkEFyhX0Upt0*Ds-@Muz{j7M_;E2J`NqBoIu`yUNy|FXn)B1C8 z@WKkku!4SVwcz$*D3i~Cfeh|~;j{&7wx zKtxIStXq6sj}Dpr{#B2*UXU&xv;B4Tsw=r|XtgzSDCUG|D7bj*DvzHQtwI!YhxQ>7 zU~VcZp=7_0KsyU2%dxo1VxOQ(-m62!f^+`zV})SYr{PW=4IuUd+++xJ5^bS&0(DHD zt0DT@q^@&zYFa`GVeaY8WU;zyi64vf>99v~5zwRu38%(T4co1VKVtkv{R;X$GWXBQcfe%W?IHa z_x^8O-d2yaGzmTl*ujcX0@dt`N}*m6(%6;=CD9+SUhN#BiO$xpkAs1o3|@8ejH}-u z*gBFRRoXirh^&&X)PpcEIt+1N6zv+kIJNPnN4*@^E9)ulX2Coz@@*REFDD{|mpJOb zYq#)QXlGAoW#ZVtK_UobrpV|fPlyT-QF~k@1N+kkoUkK-l;=R6WZT&}!Jsvt zW}eP}moAA2(QBK6_5Fd(o2*WU++fPtdO0`i-kT~T9?EbIw!(Xz{dJ@3j~N8AVv0}$ zZLa4;Y}}JU;zc7R95JLdTc+3R=g^Ul{<}dRqa~VHumNV0^1EpA~SQUmN&-a|Hd= zW;$)jv~;!=>bxhR0(F45Phb_KaADWjJy0Wx|0ntv$a+}?NqVgJWb_Vw&Az=-=ZzSM zX&AOU;CAeLU&43K%o$pp3nMELf)d3WmXi|yHtKZg{dHR9%|*xuikAjka2~EO38UaO z6YmQCK1c1DQPuT9P>R#;Nmkj)09G)0IeBDmg(mb-)Nq*+>_BpBfO#^*AXtNn_&(c9 z=hov7Sbj`*1mM7yT>MR36a=EJ{$R(JJxR`+N%i`VN;2!If1;VXo3rQ(x*pN?|5$yE zJ~0JWiLDO~6cGo}HW|WR285`yT%lCeVzx85?uzd$874PNt$8yw%+~HUp z2&IJeK_FHp8A@;9J1R{{)P4gy$8tm)Q_xIds+VUXCO0;u=l> z%<_++v?0>@l=FPQ7%D+HOP%`SbrbbdNbf9G>zeF1+;irSrwmQXlFSU%0d)OC845x zV6?nzk3xHG$XBor-}w<33HGZS|70{Xr%yZJNRspj zPPS{Gh41|Br_MfhXlF-Bo#B~RD7X@>mHQ&rLx9h7nVcak-DYHFiQFj#Xk*a+f(#qv zzh@79o&~Gec#o-`EQ6a*H5`*`BtQB7IXd}4Mbc6ADAyhBwW{+xp9aN~$>ZNrR4fE0 z0|R4nPsz8S3U08(6)`8x(~qE0B{m52 z7fo3bMYyPmdyvEJ_u9n`tUR*TWlZ}Hn(jc0yl7uox^-0&q9h2;`XZx;I$(I*2yv#h zWRPszlE|TNY*FV2bl<*kWqL+)3ook%5SSSnFUyUJT0C-C8D2RTYYt0X&aQk7Mz7p z)q2IkTilxmQ$!>GXk~ApFf4%UaK~lamR{)p_4e(LSV<+(4xo6Xxq=8Fp(()aarL3# z)W!^|r)3*^Y2Obg%2C@mbTg!5nNm@kIg)CAIMH-E)VNl^?r-26R*p7gH@GWV@Ixaxs@9@H0#VVh5#p%fV~FniN`YB@vfOAM^@#01r(!f=>58gDac|qs!(cnwne` z2~os4I%kd4u2;yS6QosZ2=`G}X3$A!k|_B=-UMHA2~gCJXIDJ2FrR<2nQynNq(<4-+GNTvL)kZ~kNNk)tkC{iZr5+ILr! zu(5-Th)r_g)2Hp4>OAXv*Fv>+CJ?t&kODq%L3W4t zG&t*LCA8FpWn|@K`}a3dH`9F-`bk$31#1{9FBo~dWE|s33m3a|*MAxSXIj*+XQ?0*QfQFX$;apT9!3 z0!dWCb&-YlqJcbH>9f8IA|n2mL23^vi^=Sovs*XqF~30B{xYF^1Cq5)kw@{eo15?~ zVX(i(iD#xcysQdOg*J_7>M8IV)&KodDyjrPdxX*8kL%yw?$R@BoHkgN5Dh!r(8zbF zeqEag+2GCe9F112Bms*>N{j^yNJUTs5UOQ{7-ylobmjeV`|-oi8+PL{rg`2VpOtSj zqo$N=Ro<{-`_)9s${uG6mxQjqMv`2aQ6a(a&4O28L&QzdEoum6&Nb8OAVsgd;5YzQ zmzt}2tww}x(}vS0*(5=2oFA9%S)Wj2qY;}k##?L}Q6e>68`f3BHlga|3*16MAw0-@ z{Vk|1P$WD{;=gh%gjI$9z2rhyk;M=^e|}d=(;CXe)s) zBhW0y>2y^23R^k|LDV1YGj`lOmeQVMSTf0?i4W2ntv)p#v6jiu#Y!9oeljkLw!1^H zD7>71#FJNT@>U^#xG*YY<@2Dmw^9sc{BXJIrlC#N&x|kDZcImOovQMIP!mHO-*ktfYsMbyaUpAV>H(u$b zZa&r|z6%Rm?r*z6mbURbJiQB^*{ds-%0Sfi*%-mI&G~pRBclZbFkV75X!d+`I}J9B zm0w^^)w`c{?6xp>4G{0n)Zf64hXex3tS>bk^N9puBQR>z0wRH4#^z>-_@4F>*_+e&77gg@y`u2X*?Vo&peeJ zYNy|DMfp;%9NKJa(br!(3K#1lyeL>tcdyiQ=!vsxNdFxnO$*^i7@2@~tvJ#0*~T)Z zs4HE7ah`!^uaRzzk>>Jx%9-@hGfTSm*y+*A%%?mEB)4<>-KP7AyGXlU(q`S({G#^O zn`cG#0-)isGNeDk>1>BHm_$*wAV$TEv^I+{OaL&N<@s=ag8*FVXU z7#1vkE0v@iVpzL=l;g8o8Ak3?S?#}UPeILs%nb%_tT9yLOOv@M?*CNt-hVREtXw$&WJF?AHpatcRzC%>036rF;z=+FS3hZ=x+v)pUQv+~Hc{^kYI zvcLe4k0sZBglNc(bwj4FwS%_6XwGkAvKo_I>|M{))qOr(4P|A1b+T>L@WpF4&;?1N zz6WzvTYuhq^$QanZq61tvb1>(dP@29pqF7rGv?G4Z6r?q;4+9R80(2yqN&|CX;aBc zKIX?p$AGk~m>0nPh-JgMjs?TlD9VkXcDlqm=^VvW%-|NW@p^`Dbbt4vwQ%_kL$#2*^r9V$9gW_Q#Fiy zkNcQv=spo0bY2x`F$~rp5Dmgn+GdG;%QAN+k^3xA`+aCv3w0NiVm+;`0V3NpGxD?z!#QLqqDRzcq&_pwF|{!aS;nrj*1;w5S70+dF-T zk&_+^M+bm21Dno&vuzJF=cIh(xRxGsiTH)-w2^_Qt8>n^MuXvloiDoZ({bOkJ>tP ztntcz>yYQFCCqB)5r2*#rPE_1@^>i>5OLz0Q|W+Nj-d5N^y&T@Ym9=b{Nb0FshgzC z9(H-|c&Pyj6sCMOS!IcMQgR+4jR}qlEp+S{;TfSNfXDIAL zQ)!KUpbs5%501p98l7m4E<@-iH5O`%-L;_=uV_dJ;mW^5ou!A;ZqbNfPEJBgN?sjpWvnXp!KENWJG2-AY{=PJ=vB*R0WNKD9D)< zN}M6%&LRyI<}3K_$T&wK4UZqLST@WLHaAXjXDX9%^*&?!CeQ!|+W0x6yJ*{y)AEGm z*UILOcmHsz4guaxD2^*SGm>a4ah8SYtT=GMG9mbit;32nK}s&>BWHJ*A#I+sZbxHS z>k{>)G6=)aXH=$VpMB@fkYPyuS!AwNY+iq3CuaDmU&ZIkysk`vHv@? zprNVaI^_edt!+#8igz;?OV-Y)nCwpQp<%mHkudzkK_Aah+VmZ1l~WsaBJpf)?;S{c zPFz+`KHirnB8!ryO`B~qraL*^{7P20m}ak+{z0^;bgXT|FTOkd(D3sL8?DP~nUxMa zjGvSKZd%nQBy){hU;lI1(17fDbIVD;95Jry4rCUWKa2q5KmB<+`ezQ*Qi}GEnX>MW zsI6jtXfGu|CC#uL#5+vB^IQ&xGxAv4E z)C7G~2l`ulty-Ch^rVA`pCUkI-$F~< zIIPi=LB{vF`2nIKqLt$u5vb91ye3qrx5g8zV&~8;oGu<|rE00Tv_+Lfx?5#byl8_n zh{cuCI_^gPB4TRl*9pTfVI89>8cr$IR8{U+! zo8qAJ#yB2x%%y~wMCk^Qq|-%194lTkVKv1Xh&{vL6{4^jKS%;`qQ!AOKHBHWbECeN z-ZMhj7bjE01^PMf2~;$m(fI`F*g|dc{=Uwi={y1W{YM(GUIgLLHKl3+xf@_ZC?*Y) z{OIR29`iT>#=_cMm%#k`Np0`%IC z_>Bd^s9gQ~oDp6j{1ID&8f&a|CQt+Z3h+-D15=Q+e??>YiGVA$r_zXLD)10$wBTTp zM<~PY2Y1m-FKVuN;iL?&1eH7a8%Oi%@=l(?K&Hr*Cc8(Z+U@Al-+oDm8wj&X! zn0T&4@PkIiSpfu;H2n7jDB_&W`#K3Sbut$ju7!zi_MuWub5+-d*j>$S4ZB)Rz5#a^ z>&rd!s>e!alPHpoh-AU}{G=ql`8-V?KG)(`&|5HOYLT@+4l2FK7v@&%z3q&S*cC3} zqgPhG<1UfAjjeh}M^9}!%Vu*!nD%-zOu0u2F`JOv_&|#IrDIMjf2RJAW{()&82dFx z)^4{cE1i}4HV=k~?cJv}Hl&G6f`XC{t|Yj%wt z&D~~-SiicLb9c==e$D>kpJ8&)MTB;*sjIVew)X7hWVGV0aBh>ls%DHkL+Ngx%|`l* z)u#I&8(@g@f9UYF;xagT>J$9`*~n{a4HtX3+ga=GT(@~DL~PD-t$C=l+sSh>9$gwX zmycc!{a-dQZCW8A-Md)!O_9yrR##ZfG5?E=?ey5sN<#++MrhCOt2$d&YuC6|Mmz1i zC54!cUWa(#jHSEr|I#V0Sv7I)<{!;sF!S6d=pMc_`(M4;YQp<({o4A|M;@L&)_OCJ zT>OwokGqUo0qD3B(;XagPrXcB*UjrxXi>Jk#WLJKhe<|4)t3sHM;_1$h5R#lu<%FK zla~5r>zhfJzb}C!VS810P*jo>6(BB$UP6A0zi2%}SJ?K@KBizvE)u+L4UxK6W|K}Y zGflEeddjI(`i6_6LpX>A`+DXM*Du%@$?r9W7<^DWSUKZA$H@x;b!Pus!E1W(eW4!fD3(Kjn z=@s%+pX4$&ge7W()Pjp4BYbiBLs-q&J8|KxlTtzQ&iXXAM4rp3?p@YASkS_-n#9hx z5d{@mOcV(fWhzc{oFesX0G?ehe^T@OVe16~Y8D|N;<9U#b@(T{@}~$p!pC;~s}D$) zGNp^_ma8h5n{xJ--$J_AqLdx{2fZ(1`XPS*G^|yOQtxEgfd>JHL6w!(kdV;$&kd#h zcnmpf5rue|-Q`Pll(&h%$xnH>5WV0sZ*os6*;YtH=x!QP8?8VD571doMMwF|182IApR{1(rv!(=sr$PO`4&DB)pHHDS9aKI8=38gIOk@Ok#nN$P= zrUI1EEJnd5Ff|_@Xjp-aSLINVQ(QoCvwY*0;olbYdpnSVjX6)^SeRn`iJ$;pz5^kX zZYx5Y0k4`4ZRVJ_hAPV*u3`3zRS*YJp%b29*fuaVWI&@b1Bpp1%jln&!&#+>DkX0y zR5*?!48gH&VG#y2TL{r zEw)*pDRMlt*7#fZmc(z{&>PMEh0o7T$nE|9nZO3S|LOlkBl54rnco}x{ZBWA9-5Fp zuf*q{iZc8+_JtmP5c_OKd_5Ie9~IX^t!Y0f5dVJ?PMwJVR|513u_{Sr<^6Mg^A-;Y SI9QNw$OnJ>2S4aP@c##X)aC8 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 delta 18774 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

rl5S0ws1V*-Ty&sTB_oG@S}v< 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 diff --git a/src/Nethermind/Chains/lisk-mainnet.json.zst b/src/Nethermind/Chains/lisk-mainnet.json.zst index d0a426c5aa4b5dbaea35332009e3d8bcae485914..598598dfa3be25257d7e54795fd950f1a5c9a438 100644 GIT binary patch delta 7992 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 M>?ySh(GH#dA8*@}SpWb4 diff --git a/src/Nethermind/Chains/lisk-sepolia.json.zst b/src/Nethermind/Chains/lisk-sepolia.json.zst index b32ff1196e4baa1463770d72d254d341ce827927..88a36f768fde1fcb8d452e85e63a42a190b83339 100644 GIT binary patch delta 10587 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 delta 10737 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 O@?41VvuIQV+z4i$VdLun delta 30266 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 diff --git a/src/Nethermind/Chains/metal-mainnet.json.zst b/src/Nethermind/Chains/metal-mainnet.json.zst index f698bc9f00303d99a94be03e67735c71df6cdfd4..c0d9dc63466d8d721e5042a7db1db42a9080988c 100644 GIT binary patch delta 8110 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

oDw5hzVxZ?c0*jp0pJ z(_Y!9g69xvCw^xjbFBJnRP|Buoz(l8XTe@}f5$YfuRoo$VH(nznQBGT(vLq1(r1nr zV9CDl-bQ0rC5&;(<3Iv-jT+U24ZU*yd^T$;SrP>-w@EMDTUcS!FZxG(n#s_oQiKKC zyt@bak6V1k5M1)gugj@TI<=z3b{@xBKeAQZ%w>I-BcdP3vMgm)rCwtE%s_kXx-YC!6|#Ro{==d>+v?iq}_io%Iyd*^7>H6v79Pgp5HX zO;{Q6LZ0$;p8S;HibX58?!Oq{E#H^Xq8LJsscTD=40r#&VafMw@2 z5L%Lv1dqwwiUnD}O}$b_Ijk|+S~-YaLM5qud%x{S^8F zSAE|I#X{-vBWqV6^zV~FRyC!p-R|4>C`lsp&p%}2nD1SqXv5-}Kcr zBbkM6hmLGUp)#_ zJxS2+O&$C0-!g97=bR?nH5%av0bn|<*<>cgASkh;_iJd{Zmtx|D@+ru2#d7ifKCBZ14gAGW8FFeqOw<{^lAK?YMB#*s_J zZMMqMJU+~?AaUj&g4Sa2dF`0mF;2Wfz5(=PH6q|V_AV0xIXsQ}f9`5r{*N`cup%TM=}9fwlO^ zW`Do!z^yz>p-!G#ZOok5md<|nGuTA>qY4LQRp9zH_KHzFj9YI(f}CoFtG=@J1#=}+ z%UxT-OUR@1>&T}+lK{SQ^3C@;L)hD5D=+^P!qdRn+?Cq0tc>DoRPvSZ{&Hu#RxXwE zwLxrmD~_Or2V$FU_HPdy4#VAfI)%03weaN|nLjwAVjM5{L&Z1fJ`J|D+Qpgf03?uLI{ZYp_%zE!&RH#_3XL z36vR#whb0E^(ILiL3A^De3n|wTJAFtgEVz66`jI zVH22QyT`PfXnJk_N`_2|pRn5odI#X_0PEf1+^tW%d~*ypNte6Xef?7sbl6rY9}gT( zElsRMEg9$h2HyUlT0g92GZ`T<6zADwIl1SQl!Z;w)M-NC*t2o~YUu&J)OlFh(;%Ty zMOq$9a7>Doo67M2M{iseoSex2f;x(iav2oInqvMmD5ZJv+U^J!TlHBn*SsbDzf;WF znQ#E<|D3S{osuOWo0IgZbuf1a1!=^f#NyISCl; z5>Ih_YnlTp@O7L3GBE;Oc7(Re^HprBa&}QtHA*lZS*+Ry1v`;y3~9G)8R=cps<7Ybi$Gk>A#!8{`FMObBK7)=1Q)B>*3?sL zi&=M^3WO!~EiDQxr`j}+OLL=g@x=Qv*O^m!hHbfhlv4M_`XSf|AHS%#*TgYT^0*~_ z;_#2o=z;8%=QDK3IE5wp7#<|_XJhzYSp89d8rG|NMAXlyhEr2+3(g}*6Q`3&oR8rz zz%kXS2vXNlOnKHeMDfBRFT?kEBKn6X7GGejbJo(Q^@JB5@mHSt7v;vhW$yI$?Ne(G zh2QH?*pYZxe)Gi92*<+hx0bT$I8T>eJl6 zSz8keqQ3`arZ8E)o_(uyS>N0zh-Ze2^+y&A221|0a%)8xT2t8YaB;rrwPtbFAN@b5 CF|hIg diff --git a/src/Nethermind/Chains/metal-sepolia.json.zst b/src/Nethermind/Chains/metal-sepolia.json.zst index 788fcc71cf2a33736d3b9e5def87ad67b8355ab0..2806a8338b5d72e33cb5774deb02a0977952f83e 100644 GIT binary patch delta 5044 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 delta 4341 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 diff --git a/src/Nethermind/Chains/mint-mainnet.json.zst b/src/Nethermind/Chains/mint-mainnet.json.zst index ce65ff50447f0cca095f74e7dff3d5283942ec09..827516e59bd92cb38361a35d7ec6a0a04ec3e136 100644 GIT binary patch delta 8006 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 delta 7745 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 E05k}g9{>OV diff --git a/src/Nethermind/Chains/mode-mainnet.json.zst b/src/Nethermind/Chains/mode-mainnet.json.zst index 7d35396f98b9e5c68cbfde8e0068170ca84546d9..fda25cd5316b51a2ca8b5f64b3c69368388b8453 100644 GIT binary patch delta 5572 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 diff --git a/src/Nethermind/Chains/op-mainnet.json.zst b/src/Nethermind/Chains/op-mainnet.json.zst index f8127f7c97d4492b9b16f4d817f3d6ab4eeb2959..6664eeb91e507bdd202c628aae7f2db9b2cdf8f8 100644 GIT binary patch literal 1587 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℞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 LQ@3ybGJH+~5p$(a literal 48555 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 HFZ1Cfd1Xzl diff --git a/src/Nethermind/Chains/orderly-mainnet.json.zst b/src/Nethermind/Chains/orderly-mainnet.json.zst index 939e60d40fac1f07400d84e4431ab5249c84e247..88a56c6cc9ab0ef9cc5553b2d9cb8ed4e41a8b0d 100644 GIT binary patch delta 5550 zcmaKu2{@GP_s3^r?E7vE!`LEb82gZ=LMc=vLbkCpmdYqimW)z~CsMK{T4YP1G9^<= zugutql!&QBm{dyrpW$u!{eQpreeUa;`?{a|y3c*i_k7NIhEV`}egQ_+x~abm_jq`v zmgl$^HTYK$`@K;9WT`zQ(U{XVYCMI$&4+UU+A_z<9Ca5@+ zkZ>d4en(u!)(O+PN0k$Ch+4_5pV@Kh(hBTBDGl)~FOM+`-l;$q8M*>4@tmY@J8D zmX5KM1tpf5Zvwj(T+DngDlR!b>jwT(^4@u?wkhx0WLR9oSxl7^6%#6b`3_cYQ@3r( zMI)&oRAH^a-Jmwo;z`FW&h6@V`7_77Mr$Lxd~PZ@7OposXlMs}kHrcMc-XnG^h&IVYaR3!8sga?09nJUDN$z$$LZWT8r6@_R*q#JZ;~yTw{k zq5Npm_09GuG1K_d71UYP(Rm_YUlKpG9SBt~%5n2`*?VjEHbuuNWkViy8Cud zA3K3gb9e4M?Nh!xq;0}HRX&jHm5R51pvKym?^5i2tJR`;=P3yFFi&choY-P{1=&Va z7bV2Q5Bb0+B`9P1IfJ@qPGnrsw3bY^mMYhhLAAZIfzs|<*Qvac6_9|G?2$sbHR8`l zw>CV-c1_kIx37Ji;ektV(3KKKtBl5Mr)gDf>+%o|-+__xg*<>m#YExOM5$a`Eme|{ zq~!jODpJu7H}a{xr3n+3<^+O9s!Q_*oVXBt+Zd$O!_*Y_^1iK&R3`7+kvVM_Tw7~4G$lr zHIOVi`7fbfO#MQy89U%-py?hnVZO2;2co((@`UYT8GE>X~kYFA;0kTfUr zS`Qe0CC1j+-|leRR1bClu&2z%M-f1KW5DsZZ0{V_y9jKo2!*_!^+FZQ~v!%DGHXBx| zDk!XZUC4Rq_GxY_pKPDRSnirmG0ZxdHM=)G&+N9J8g|&;|01_j_s-~e{jRo(Ncr}N zPY!pBJ+V4U<~JnjL&AgEE;EsCK|LaQ8_@;jMt(D(h>vmE95eVGjh}eDin&F zuHFL{yqORnB5R*(n zI6jre^tP)__6$-Di783n1P3n(#V7lvi3lcm9i4&k4|!9~v1xUqFgPjzdzy!3r(FqS zgs97WXpnf0khqS&$2=Qi1+(pHldW%QJpE=XZuoZQMgh5sN!2qaGH9L3@=b3G)ulE* zrDk-?;F8QT?RmU4H6Ztw`7E&O!#m!4rfAyPwCLq~X`JF$(#+bopnRmc)8nP$rjZA> zmZx(wj&O9SUS=}4t2&Z&d+mbs`Q>=k1E3rYZ)p_9<1EizBhis}LUT6sD@kY%QE{u9 zZT`!9N`5%Yi4%*;N$CnB#A^e@gW>3z^5$*H5YjC;dixHvQLXucpKOjRPj7KSCmY;Md>HW*JWfX6?k+$qeeio1UJVGJom z{Q;if3|%v8b6}y(-q5SCd!5~&(}k&qoOs_O^<|s~F;aDB38s#lvNhwdT{v{d`0?>& z-8jy$4>eYb<1XK#zebsS(3zBY{)*F!M3)cpI@$H(eV6W5wPZ4Z^gC^380Tl+5#K(x zoWx8WlJVV^zFSt99i}&MQGDnUaQpyLm%j z^}YJjv*fRT3p%N6NP9-dkMVgeu;;R0N)LrfUeczX{o-m}QEb%_oJWb&Tcn31x9&OF z9-Uzq>(U(YO295xD8#OQjp7Su%Jb>H-BE=e-JZ6XFB=-onuD+1c|S6)dQE6o8c&hi z@>|J{xSTURWqK`Z!tJ`Q>WjF$7mZm8ygO{iUpph&%G5}FhDX&_!?F+0XEN`_96b#@ z@7h8QrPAN;D{s%;ew3zgI6}zb$41}k8=ska;qqI;voZ@_#owN3?=ZS-(R}o&nM#4= z<6PS??Dfkc3w{eF$vrrf@8a3|@@x3MyT-?{*hz>x=3DRD&~uwyFJgtu^86k5CHuDTlI8gk^E9r@2$QsyCn!^3%Ne~WZhGxlFVg- z4>rCWij=ZtV_#@^(Ju~1pI1c}>&uMzM9CLwY?m|MWi{YGs9_muS(Zc&)e(!|cWm-w zA=EpiRy^y{Rz=~zx*^y0e5k(}Go>?ZP}2}ID>=yK%S;F>vnct_k`-2E(*c2Lzb&0< zgF&-J)XPqH%k!1g0=)OR7%D%Uai5D<)jy)#JrkIdLF2rSGTuUZRhEq`oSmzyAFB(N z@UK%ZD`O6O#-oSc&a?zS^7$AjenW1_q}r=~7)LpBp9x=j;7&@8DxxK7m91xK>fVQ4 zuPGlFo`m-oEm~LU6QSi9ZOo z^oBg(J$L5T^ck6(a@0zd&QWyX{a&9DHjr4Y?pRbr)eyXN^F}5MS#EiV1-xN>3~3+q z=jz}__S$n$WldFyNTdEi_mzzB%1e*%pYAcgu20ddgh19T{P)AGSj*F29-5} z0n|qf{uxJ%cuLaKJA=HYC-xjFog8+@inXkLj8E8nrx2p1=N3*1!z7^lTwP4|sPPW- zoH8b-J%=F$!X7&vqPfbVyVd827pCr+`%@LrRKuGO$EvZ4wZ|^KPy6xdb@~Y* ztA=99(V1(1NnbD%T5P|*Cz#P;>?24zb8boLOhn4&Se<0DiFuJ+{|zs=qr^Fdl&>72 z(DrAS-QCtW86C9rJaXb$3HmD0KqKNc1-Y;u+N~&X-|%W>WQ4`SDJ0JV1YW~jS~`Az zocdnA+_O=*HmzapUb&lc^bju!HNIFcU9C=Qc5uURQ$$OF?1>BOhfB!*JLKozImN`d z@ci&7c{S|ZBjd2w>Vw!Kt#Gzd+~XzF^VW;y8?9p{#fxq_`Bhh5))j86b=iKU<&mu` zb$p+EY~_m!A@mJtoyoHkosX*SZqg%KoE@^IuJ;ymx)tMoYRdCTzm9oLu6En=udy$8 zF_JAs?uP6Qrf5~Hm8>kjcfl-HC!;r5WshOLp?;GKIg8iyY0{w(zh}{lnFnf4=S*)< zpWES(CULFG8ykFY)jEC)X&v*27)6yVgp>? zA;k~?fgk7Avw97MeUr$xK}TUlEhlVhC{0G9^huj6N)vwdx+Y6e%ayesIrRuiFX`b9UMLec?R!9?jLA}DF&ROzSxn3;@Ua!lFin|#td1qU1jaqf!++}PuO z$Gj3dr~w%J0&ASY0*E7?T(Riwj4BG-NHp>3Kg{5zkL|K1Y%V>kg8@uI9JT8YP^QKf zSAdxsYa?Rg>6M%-Eun}F!XlJU=0y!L=*!kbWF&UBbEJF$lReU0l~sd zgGeMC2~RR0{Rgce#6RIxovx!!{V@B?ibh90wPRAiY(_EdX1Vi7tKE~+dKE`>nyg=( zqba7c#TzaP3MsCqzv8lL{&#?2l9`NE3Vte*fQ|xaMeT6Q#|+^WCA@IU+YetuKpw!1 zxW&RPqCXyB3?&z=0@lpBN+`1Tzx@FH$)bP?H*G;LI-xl#q9!>sG>Fc`7-=317c7<$ z7jz=Ph1%pXoQ)A3M{|Tf3drV*W`NYL&?fSK|qX_6kw%gBtG+pq2!=`CNFSCTnoxtaY`_J3E-E|hW4ziHuEn52fy(t%kCZJ5U=pbMh`N}&ez2LdIvVV}U@<@LcAG6+5E=rmwZQWMtwOAti1%Q6&j zlrn;L12I^2;Gz^^9s3>(WB?22HcRfn|N8)2?9WFT1rh7ZQ9?s4fMq!a8-G@-+^A~HL%5>4$2{vz2(z@%`%#>uHO!phJy|^%lwoebMF$M zC%Y;E81xcQ3NE+`Y~&Y|r=N#I5HM2!Bc=rCsqn%OKgCex!-P-~U?Sl_mYk{q0sl_} zj3DRJKj%_I5X&uB!pdz^oXJYnz5w<0zUh!IBd69@zqFs7FsK%IgSz><)FEA}q}Or<~Z z<2z&%&8EUFL>q!(@qWUI&k#VUL_W1KPmp9d&F0jutR z)G}K3Z>HzTa7J~pFbdQcW&#@GvcPA^h2cuiFBru9(O^dyY0-Wg3}5Y7MdBzvBO|V- zjohZ=fLslY1c*zZ_)J!~c(~esGS%onq$(Nq`aAGK_0J+f*7R^~k$?zE6n|hK*VgCX z<-+f}XH`Z+U{n&t7ewOj^R5WV^Uh}pejG5z8bfPSs1D>PVWD_nNlr=OmnMvP76bgR@_H=&b*b#lQtI~epN#YY*pOv!e+xI0HwLwuN|OtAWM@B XoBa+zwbnov0bMOmsDC|8ix~8Otd)t? delta 4612 zcmaJ?c|4SR7iVTPBg+_Mn=xa}mfaY-GnFMoDr-o>G?dCxl9}8lxlC@#@>3UsNDCEN zaw%7~tQSLd%kGvek;rlr#rw=m-MsG~?>wK+oX`0!&pGG&{hsp--hef*VNA_({jYG3 zcmq!vS8IX09uneeN{%nYeXrKkZI48t)iE)Bb$*A%VwH!&NP~{69T|x_0?G!c1%VNP zdI3?f6!;B1CjRe8;x!@kwmQFPL97}Q9xa6TEYq-6)GZIG zJCgFj+EQ~{a$o$-^vvHkAeliD2HAmwclNXGKDvJ`s$L<{j3Z|v9NcE!y(S6Ya%yra za2t4EIni?_-rB`m+8UP-r6l0#mRGJ;M+OZ?d!`A~9DpA~So&Y3qGIHX= z1@odx`nkzEyZu$#iEkvlgd2_SsHL69~o0z;H^JPO8}coL7Q_i%82Q?N5S>?-|*roH%-FrhOqJYD>)! zUDDgOiI)1AloE7oLscZ@pp}F3_0Hn%=Zb$`* z>bX=}L~W0M8mpdOIjQ{2sTJ`_d3QyGeSQf|o96jRO_(NKaAgB6@6_1Msn5E5oYY>V zmpqPZ zq+9MZ*+$L^L$x$m7PKB?q>s54P8}x3J(29v+p-@PAA*&Ty9Z zS_raL2Qrf*`Qe}SoL!jlMOuaBA7qEKsWaKfCcV7oddUu_(>vE%CO!Ntsb|VEE_P0K zPJR{<<9Jcsk3RZGlWuC+dOSmK>$xLmHh0h7KBcEHPo=}q&F5KGwGGj%FCI!SkGE$` z2Z%LSKi8(McI?`$8&lKwXJzltPTgDYfx?GR(l2|KCAJgoYuXD^nY)Xg+bx#1=dmP- z`ma6?-VIP0>g_FD)Xp90u+Q4BWsZ-y_hItm-I9-QmS-N1ig;>~^Ae_=HivIGbXu9} zUSWCren+WE>NNX4W^2=;*jfE#G{L6qRsQYfho;L4;U}uPmXF5#vG2x=t`1@j;`{|68(F?Czt{bNB zLfrMV+duO`TBk+x)$Xh3s)Gvl1y;8;;FW9|#=rD1^UU+xpt>*ak9~B?4K=O z-fpH0TG-soT$ZR}=M}tlLYPZ*Mt3~V6gXO+WFJKD$;wmf|4>@Dbem}%XtOLm8&)6S zyx{GTQgklEaWI>RE;$o0HQf9qus8NKQbJSCw=WB6cX?-|sL2ea4CPid%?aHh9}6#? z%W+pXA#!S`wREP`P0H)TL)w>#-7*nXEkS3reA5kWoy}MO@DA+yXxMtobI;MsY0egP zO&Ms*+LXs$dIu7I4)gSi| z3U+R%?q$`>e3hCF8?rec)=HA<>k9Yi8Pt^#dmMY0T}(x5)rQ)+b^nteU_DG;PP(u% zWiE(91&fO~`gd%~+M?ZU6ZmCL(H-E=TWk!o{+Q`dY_J1&Q`Vd#f8}Ct-K<}^daF~( zQ07=&MV|Ac+Rj`ibunGmrujuDob+^C=?)6Vijk_UHzDu)@bPodE@Sel}+6f7Phl&&U7h>ZJO78 zJ?<2&|AN$);~ItJ#A~ts-3hifMOF^1gbdp3;+JR;QbIHj~b zO;L3S&6YdEj6?t2fVH4DAaYl-_wGN?xi?m~ihvRNqj7V|<+|2{8=KFhUFV0D|^i10lm@?&EUjj&xanvGumUaISr0;IpcFV8rT9AL zh4cvu+C5~cNZC}T^44(ztYOKQ^{M|9Od25&4kMZS`BM+m0)UdJs#_I5G`;dFc|i%y z*n%d#&HY54AficQx#L`0F`oO1JQ0QuZiiCoI*Sj^VB!Ca85(`Pd9LdKej$^EorhNW z_7r}>GGPUS0BNEIZhai`fDfLLf}~tyVdvJLNn`cTcR^>l|?)yLqpeUyAI(VHtup7^4jls`{p29OazS;JeA)XHb zGapLDGfdG84Rl3|6=&2!pI%8sSC8`%q>Ni6(km%wzNOhMp zH+9B9R!6*A_Tj66WF!T!uy1oK$P?yhQoB_m4-_bWdKVQR+}YqWpVQ3c3*R2&6Fj$9 zMhIw%8@MmA|HbLRJaiDk3$ovFtD<*ZA`iIZ8Jp3JwuTNm1UrNQ-?sk`7EsVsmd{%Y z{eSG>ph(<+`DmSZc(EZ7@x*i(&w!G>#_AvCiU~@Nm*lY@w%zIhKWQudF)sL0^ocC; zgk$|m0U{G2@B(H=3kWa>FbpsXFg78YlFYv8#?WB>!~E_jz3=`sbMkW!pPXc5^)=Q3 z2&TE5z`4*7@%*n7mi2R?2k5mBe2-X+rvFnW7nhUxU`=#&ON>uzgDy`Cx;?8U9`E4- zCNSdnh}=dp1jFb}9)tk_iP9ysaPBKDu9MFDG!2CQ-% zU@-c?S4sw8JY(Yf91(v8>fc$V+B*9xy;I~IV(jv~UfB9$N}Y*o5UC0d^QX z%8Xm5)sH$+e=V;5!o>mnfl);Iad(|~B@16Vy#nX%7y*4rMI@EGbBJ5Mo!|;+Q}|wd z%$5j1!D_*N`M3Cu$`_fb2!REdVF0MbVgUy$L|9LjAyi7r=l^9(Ro?HckI8DJ`9_mxOR={3GEx`eha(Uh@TtsyIyJ-U$HFGK#3f+&eStqM%{{TG8=3fYx3JcER09LEP6p{v>F!>X2GONky1QFCq>+^P(+$$yT_OzvQcEZuOLup7-}m0R@64I! z)9>qu;|rp0e?=|w_AHz}*&haautHW4HU=qWjoKXtC~JyFk(UCo z#^<^e6i+AjjwA>ohARrE-Gv~D@EO7FR_n&5S48O=_dQD?gJ}yyK`xX3>q|(-weBKS z&%d0@GVat_1FOUR5WZ3TYi%G~=zFKF_Tb0ylJ>Dcf{(@Dv;h$QORM6FDW4I7U!Du8 z23K1CJIlg8M3!%&cG&xvaCn1_Z*QF{-YoC=iECnrspUUUgf9MSE32Te9{C$<%CWmj zJtvnCSY$7=z~q?A`glR*R=5o54LU>%L3YwXWPl5n5w(jXn%3rt89P3Pj~9g_#}`60 z2J1c`P)G-YKmaKm8d5ifuC56@D7S}o;vDlCi*lm7J3yDz96m6Rf{-a7kbsS?d!6Dr z^_k=X6rm?2{qZmiM*r(tyBy?;n3@k!6ud)Ke+HO%UJRB9R=|ijQT4J{6 zpNsP|Gs+)y?}ATuvf!eF>MNejkRHzdyp6V<+gLa(M82XV*o z40QJ=wPUe_1vQ!@grX}z-0P_-bkI%jMy8$SyghuxznFzhI>GJ6? zXk>Ck=1H-VeiHXW+`_qd(uWeYqA~n*S8(W=5+7+wFjO~Dop0XWUX1D|YTpK-SX)?+ zgeW{TNG9KD-5M-S4JP~q<|Exe1|ef~2EyT=%ZQ3W8EtIN(PhDb2w(0&=(zEs2(PFB zB{<4U&UZ)p{hngvY>lS2MrdGyF#xzC= z7kSW?E6+@$c1&x2PUhFb3T@h#J-;DBJ@<`?#f;m@&3Jlrscd7~IheZ6tP!Pwno+^5 z#w^RyKqBQ0WYt#Mz6_TtPnO_fWl;$DBQ4Cg$sg1w`Cal-_coz9%MPJERA0?{mP97T zzQXy0(!sW(g1M%a3`UMfU>OffZ$5PkX5OxubX<4e}8yRc4T^Kb8T)Jas6V*C5nx> zV9(Sc7>|wgLP z{}YRWXhmRHex+sIB|7*ajb<+Zi>fvgkvkwah3AZ#cG*El>lU z6&NUhS|*gpZJDF){?YVWZaL)9jLP%dmYqGDAeZ`)^@Dd~OMLY4G|ZhR zo4-GN>jWR8{@uWsMTar{XId0>{JINO8N;E+B||zy7i43Wi@UY%$)>O+gdAji>Nv_( z2MLJU_tj zo%QMX1iN7P&hQ_w*icSX%b2)N?Rrtg^w^{s(#w;{TkVOfS` z;+xpjwB0{xu$W-Ej9N)yW`UkeR#~YpQ0Z9rsZJit@^oJzgGxmvr{>Zkrn0WFq8B2_ zOt8qFAdVcZx;BpQj*Z7df6A>02>oLSkG=DbI_t_iBM@-iJ+)8?m6y^38E9|o^o_tU zWK^q1&|Nl>A`{XT05O7{sX3=!cGVbdV^<2FIR@iKhCWhr|6==;8F{qCdIACU1f`jg zG08$Yie9UIIoAkq?E1Q?i2a(_hX#c{t|YmXf(*z&`&{ctbQa?{O2 zm$u}4v*p7rpFEk+{&nI_Sc#pw6h9XGE+hjIO~f){P?%p7KztKR@=NJ~FqE_ifX)GaWr5N3jZKJBNZQ=HF|1u=HLs}|Y zDmgWiXi8|OuxG0${C#Y=!#4jSUkOK%|W@B}Ed$MK$~1{Lh4mfl+(8 z@#MZ46qSVRBW4uX=$VIA02(no;&FO&Tw<2f@5~&whyIOuIFhp2pz?H4iqSOZfllcp zRMKUgg`-Q3^CE@nOx#rqceqsNMBJ$CP;n0jPDD(MHe0$1aTcRD*qcZrC1o)!S)5dF z0eGgMfoiw4aHHFenkUgR^?bD6-<6D*E^s(Fbai7%pDGgbWALD!&yY#rR z1^dRmblt?h{))}G*z*rUC=<0O!oXbkWl*>vsKf3`j*@qGm$FYe0dL?nVY*D)juR>Q zSJTZqMFL4IjhfHP0XvN_r1g<*=DA?$62NHDQ^I?E-1(|b8oMipOu|xf(0Zy?!Ym=A zEm)y(O9J{MH;8t@&sDhOY2P<+K>|gnLt(5{mP6i$J6EKqr6%dOBG>ZHrabd4sf3pa zMplB`eNzAO;QwhUuJl5fwOLv(;3i9V$6v5F0XPyd9>C`eCngF?kn=2d80d{}=N%n7g2@m}A_zAzsc?yL z)9Z9Nh&a)ArU=R>4l;5F-flYvZUSBl}XcK%^!!2tG z&}=Wjq!qPg?_9U9(Acl1mZ_6D&-U9>kE1gCNvE?^9yQ&aD|EL{yr0R%?|D7xlq+T| zG_O+;W`(ADBfjDorVKyt^C=>Ly`tZR`@?I(Y0fvZC*ellpew-MOBn9(SJdN*4%M>Y zF{N?-{Nzzia1-fT`t+|>Zt&5%^}acgiFt}XIHs<0W`>yyW0W1{ zh?KU9!`_r0`uthJR*!_>H*sOiS9sKYs-Zk`_*YMeUGyIyWS5MV8MomP89j7`l3{j` zP=jc3$+oZqF%{a)vT#&rEx_v^@VNms0Kqu#h~}#$a2EJn3T? z7u?lBAg%u6mGhl<>lQmY+gSm>w%H=%AXVnIGU=V$;9t4TT#540JXveY-yfEodFY3( zJe8?4py>qsI!Nx>_*#ULWB@0oyYuLU@SohMv5L>Z*dO>*V1Cc!y!KOI;Rz0Et7pJG z&-fxS=!@iOsa|X`K$6Dhj#Y`Fp&CIpA@&Wo7zY>RnUu^{#<#yP^DekE_tk$t-c@3A zvcA3F0=IT5@d)EN$br2FsJz*d6H(6NbLkWK_BZ!Z_In*#7RRN?F}PrVY4 zmtgf9fu$^a0FEZIz$BRpZJRfx`F#TN9@2fe+Wp45**Yt(o=;7W8 zc{%)yHca3M6id)vgql|wv%klo4`qEgUDlB)u*vA0R9YSw_n@8VU#A0f*UHG6V3Y@z zxpPv|qaB-~*2Ge0p77_iOEDZ}bs4$vXaJi+v^jlAMQU30q88HI!!P8HfiE%Qqf}!l z@WnnrSNzq=Le0I3E)xpwT-f*7P&k*yyQPE@|27EuJ*_4Z$D-tH1V3nmSEDLccZcrV zMyLfjs(F}}%+y0*vcFBl4-H$Hgh1j1qb&s#h;5 zimr(f<(K3XXCg2AkY$Q7@|AzEihsK)z&+laKV>7cJ&~pS{tQ)?YX7z zBiXuEjjt8ujaHqA<;%yk$`1#? z$->oiK{TF=6byn+noPATQKDGkez;Ty3Dr<{x!`b@XD46w9hK;(yK0iyFXphi9iw(s z#Wv3PRdyP9QX#zWu$#JBRxHBM%VLsHTFvZh>73Z9^MGI~q3^pC$#Cscgp|sUb9SY| zGYrJ}{`6^8g>VK~MPktN^9jf?#cBb>xX64XD%5ry>%cmr&JU)^)C(gtQfCHR!J&2B zxxX$UsMa_lKREC>$NS9skGM(N&MbA-jeqE!$q;_^A%cTSM#xi9#_R2(YOyiWaF}j_ z?}p8f#F!&C6yif9M^qUX#|QrCN4~+!M^NJmaDdjuxlna-velX-o2G*8KN$h%rQg4x zrThr2$z6OZtD`3y;+9~^I}_ATMoceU71Yd3Qc#p2>Xvl|;aKA*?-Lhh;*6+QFRPPh zMJeZbA>Gz%P_Yl5WNlsll@!2tvX|3sVr>7yaFaG=Ui3ystOQQ_PC!Go;7NWtH?`B^ zOA)->2vdXwaLTdO@BkFG&TWpWTCd4GIcXUS`;*-UU z?4$;9x-ZOKSWl8#&3QQ)iFtHM-fVz0cJ;wrjS{cJVom4a zNQzaq$(=7;wp|>PHLelIk9*j`Cmb@QzWJGsiYTZn6er;KnyT@+5yF_-Fqk@ zKC4NN49I7K;>Ek4VHYgMA!y?)a@paLa%m%Jp@c?-mKkWK6?Cqqgymf}H*ppk>l0br z$Zoxp71iWC%kJS(;76fU`mpaO z(x^`70fSm;+NbQ6uqp`wzHLTs_M!U0#9}&#ZU|h7eUvIEjlGz<@~9_aYPMFNO>KhI zNq@6b_q7>QIn6+g@y!zX)mz7F)mNBdFc!+fw6mv0!F1aEKVXaPg)gE`KK?bw;$Uu7 z(^|2pPIk>n?{T;HnyRJ!|+)D|7E% zaYj(uipr?JQ*czb?&JR28i06pD3Rmm`^yStCPZ;QGM^0 zaA}F)Ibu*24fylxyQ5xzLHdx73ifj2WgODEKZl0<6%NF)T^7l42*i-gschVaIBe#( zWFyH^WIQz`aYO#sNuMliDX>3xj$kZzk6d52Ngl?x1ZQ_R?smfBu>#6f9-LZ8eBGmF-o5)lB_M37ZI5t?E=3aB%+OHPYMv!D2kRY_qQISQ<@ZU(T#ZN+YN=*5V}1KB zi58WEZglsX&IFA}w0%-;{tLy=d8p`PK;;*Z917*Y6?pF?6Xz%UgeyVHb`tR}M$nvH7qDYXBC;ECr22E0U04{2b!7F0S?=|a$ndKtR5rF6@V zsk3fFv|zqy@dmgQNWG1^g$prRxSEo=XJ+}t5x;dPb4i$#V>XWm-xHUSDGmV;LRVk~ z3lk8+j*SEJf)8`8B!e1wX|Eif-D6edtRZ6DR%2VHT%$`7kJeTABi0YJ*J{jZB$)m{ zuYMFxKbtU6uXP2A0D%Y%$<^~l!i5M_RzL3!Z}24*B1Ha%7zKX53nQV9o!M~r9bB?_*Z z*@XU^g~nRb*jF9fDWi&+-99vd_Xu}5b)X-3E+v?^pXj|%w>b8d_S%GyHd>-Q z=tBYO8-B9VL%av|+A}khfdnA=o(5U#%toFre9xEslgC{f@eTIxB!;1W~`rXVr zZiW@gIb7POEUfY!dmb~^S%{^9tpU*9Hq%@l6WYM8V)f17p8sg$aoEolp85Nm>7u-hIgiOwqxKK?2W#OtoDM6EHlFR= zzURYpP6YOCEv8UqgU^1~D^6s@%k@o5psd%I^YiIyB@%}ggK*@o=f_*1N709u?YPly zTBhsi)->otOS41m^ePUG$V;Z}=Ky5&(bvf#3N7ijUX(c0^$z~sDn$;I_y&FXS+#u3?RQV#C4xe$da=pGV zVC=Dg+lY-hE0e8e7}0A_xF>V*@sZe|d4J4EdY9RnLE0zti<&(&cIV>p2EcdKdOrLyau5dD|v0`84#LJWf+}rYhy% z6I=|f)4laiTD!UPs0`OC4xgMOibS~hhh$K)27#`=c6rcCkt2Zu)z3tC3z`Aj!nEAN ze9?C*1H~J_N-xt&oOC`DwMHwmVG~+IR95LM?^)) z%Gz{9TdmIYvV6<=a2RNt?xVnk{-CBW!-;ohe=#lPFxY-t)v74)+m`DLMnwCYQjZ8r zPPx2p2lI)>+yz9JC~Ai8fPzm71>bv;21NwWkpgCXK@>syJr{`i=OWHD9yIeP%P42i zyFdmIYB9VCjY;`jH&jZD#seDF!0o&vNaD{Sok$mN(`;+<*zMOX!iS68%hj!DpAZPD z4ng`vWD73Y3rYrLU_V!03lxd?{QiR74zY^@ne7k;`LJXc(Bj!9x>JUcnW^ASF_e!` z1x5RC(+N_vUvG{1CUUxns-GtQsm;Mdy%>!*ofk?R&5;U$zm#}dHP zM1$YHCC%efc6GpgkZ$Ra5|{2S>F(~7ZX_1z?q=yw0lD6L&+nZ7 z+c#&<`DW&2=3yGjk;2Q7pe!w%F97{Wt`9^E3vd3QL^3dQMK(8M6+>oF^x?^$j0ABd zb}C(!HAmZ=Pr~*mE;hqGID*20Fp%mI@ezp-ZQ2^8Z8;nBEo>;Y#z1~5B5&t}N)u=w zGQD+~+?8pi&-t&bl@HRT!j?bne#jW(4h1$W4K?w^T40cx*G1Y`LGeZjc!rGeXC|8e zgS-E7KmUV?|6t%h==={F|AWf^;O76=;HA^bBuhHbL?t1E@#Evao{_GmjPkAL;b1vB zVsoYABgoR=$)lh^vAIOJ0%!t}M7Tg<;iyQ#p~IqB6jTvreSNh3>B!NxjWykb_>rfw z_fO}RgQgLvBn0O=@=SZb(~la@&ff(0oAZPq(`gJRx>yN+M`tEN^EZpSVq^aWHmuLG zZjo3b4?#}mIF?1U8=x&V*VHhTAwEwcNVgl1njK)+W5FDQGMMcsn*|=S68z+3&0oO_ z;>JADQO9upqMU`u_nzg)ngbL2GJ0!*%Mj(rxt<~tl3@adr5HT}K?ibHy@|YX3v#Jx zApjtQTtI-N6{XLDCMPM$&ccFLq)s-8h=mQrkzoLDZ|`vNsoR>$2M6}Ou?|F&K}_2Y z03d?GQHEKd-T{661Ob5vD5V9GdRf}RaKfHJ^%m*8%RbG!G#eMzzxMD1B*nUj36Kr&0-*#?$87xprQl8 zEavzOBxsER-Dq;yEW+)#q~EyU0!Q^R^O1p0hU5Lr6PSg`t=H%NGk zSOYA5J2d?Ws8}QfL%}SiJ39!25NJwUTo@n;1ew8pL_|5+(YPu*s7On0`+DgRsdCa;IFBIchp&L7gwzEp8+|3p@_n3ls zw~LZ)D}K+gX4Z|vn{&sce3CY#QHJyvAGF8mxA^tXBv{TO)#ple;i>c}f?cHF=CT#| z(AI;^L@$Tsm%?YarRs65cf*6l34B5!B!iKMGNlF=tgG}bMV}v>^!|P`LabTuw#R`t zFKNNypD%vA-F2PlRs`MIk(xKy&(FHMVEriXkRX?_m;PEniE_=tQ9zf&{Po_;&>YH^ z65eZa`?X29#xadMN)9el1Fs7|fee(;&A2w4G-x0Az9rsL+4|Y5z2{9J*hOhq{8eZ) zrEwg)gpEM{E+U;wWH9K%(8(pKEwcwSMlGG9mpR;{Vu##; zodi1#;&+(C{%qIm6m3hn_VJuUYnYGLyN?`FH*NeHg^Ae%-j5wkzCEoXdh9ESw|C}j zp6M%#Gv^*7FcwI=an&SUw=ywl2mQfsV%9{NZAsz%`A3SgF%u5o*GIic+h*w6PpXEd zZ?em&T;vF4yAgJ@y*$$s{fJ1Aj_g=#%__B{>C5dn%$xY^5WY`JQq&I0EqmcI%jYz|243R4M@Og}H%DflX6-zoaMKrd!h`P8D3#xr_Dvo}Zy&BTZwpDg zJwz=g4V8BpKkqWq%B^*F-p?9jnY|rMWBwTxe=#;PHYDlQT%?>KNsrMl;Ec2HHGVy@a* z1SHOtM=aT&K zY7GAS20KkyFWsvi#5n_nW!GK3)5{SfKifCTAT0T*x@Q7Qn?8Sb6l%~Ci%s!)UCM+P z!xnK>em|P|<=UsPx@DGpFK=wRkvICh%4M;4X-moBD7K{EiVvT#WL{|nuJDb8J{Y<2 z?^h+}9PI8ISgtwqB<6(ZhGkm}$E}f#o_}zso0b&4!10;6*Y1X1d9?Y)O;8d_sk4@; zzQbD+W#?6FR)eTX3z7wC)4t{Vq71(ALu85%JPabqN~e9lZvpwg_bsZ#<7Pi1Iqrlh z3^$S{<+EW)Tg`6*vx(>$D%+qh5G+YmO-+%^s;4TNvQl;Tf$U#V$zx4kRu6h@N?VjI zE&KEeevnjVvJR-V3;#L=wKFHXydm{+QNHfNgksqun;=KKn;s;Sex*#2QNTTZ3H9s)cx;Lhi3VUDI$J zYvjcR@_5oW5QBVFZG;AEynaF8AVs89QnqV@&IS7}m`&F&B-`B~?q_BW2PrG$Z8bf$ zLHDWp6og3V-x|d1;5oo0LUd2@-2CiC#IF^9rL3;@?kU^CXv|8!Tq7Y;fv7_gZ>BPW z7GhnED+Wb(8=^rnu}!}pQlvDK`ZYG%HJIMWd}FDHic2+A+!>6DqcX%Y6K+{3C5(#0 zR!S%xLaJSPW%1=0{OOikk#jDoY?+qs$#}9lDwXXh_Pn}UexNdaoF+>lcuYM7^xm{{ z(bDo}bV2#Ih@y!a)Jb=EOp&_#1?!y-yrE{Nkq^4(bfUTykFB+;G<3jLmZL*p{(U)L z?Ojd!sTuM1aJd`Y0v=NXhAe+ zK~NgBU@iiSK1P*HfMJmmYcvW^6SXH+$b2t=pIoNEbg-zhQDMTeB_g+Kd`ZNK8I}-W zc)KC$l!UUF$__E3L#WJZ{$qp4Ogtd22v!AnTu9G4Vj)OTo^GJFU|+A5!CK(M?VLzn zMhxmBOV12!a-gYl!tSU13xD}hvH6NSXaVMc5R6iUC7J=p#keP!jWK4QsoTZRWBy&L z*j}8UqERe93E!V)czZmjfFMU#RwvNlrwQom%0Nvo<$Rv1^*nNzA(>|FVi%4vZ`(A0mW|$@vTJwU5 zr5kTRg(T_Lc^svcamOtV^mleBKBLK-E4KHTT@ecQgfd3fasJ7dcEM$e?hl(`NNQ=( ziL(sO`YY24U^=5VK20Wp$W5J+Llm!(cfY(7k3E@cqSB2|ky@eKr;ZQ2=4-17oC-7B zh16bJ?`dw}gs&|d{W7_ytd%B*z6j&kK+n32(W<*jg0+S)TNx3bzn9RdcNtSpe_S0S zGZ+|)`BGL=;uW}AhN!*gOtTjeS9}|vtBvI~9w^ZKmFuq`PsJ?L4pvrNNB_+-zLZ4~kc&$av)zMD$@VZPjl(XPP2-nKYf+=yz1? zH>%j(d3-mAcDW>cy(z&Y`}rqfSzeg_cdmiC&C@M_CGwU&~w@+4bbQ!$lTwAqG_9KNVTOk!Nf~?B#|!* zA4jW36#sUYte@$3%-&vpy?BPv2N)W2zH#o!PbIqY(p-PyV6OFKCn zcM4!+1<|frn3tuE5z{u{nim-Em#}*rvcL26jh~+;90r*+*ET4I*3c_BGlIT7F*Nd- zeX6-rDU5Llq>r#qeyzB=W}6{6q)(0UHVNuEetVR<=F*GF-P&d6%xgVXmZZKoH?z00 z&A(j$rT5NMkt#5nrTb3am$t0??6i>2Q04Bi(sk^m_ifMG;w3HgcfzygGOUW<;!#lW z+rARjLE(M6p6fvqPHdE)4<2T%>I8kWO=E0n;D-7@6rr=$%f>93HW}M&uPG(g*h{0M z`QI6j3yuN`Z|c*PVh_ZJ`;*`mU%YOReY~v_H1{Gkn=b0WnO<)7(o*faVD(+brFwZ*F`|n|qbt{UKXxY*!PpO^v_Q2@BkP zeDi>709uJWuJdSd$a3SIDs4ir=GXlKn!BIC=j3iY9qGB@Iy2a8__<5jBSX*oP=iwf+^5b*rU)b%S;gy|x z({@QGgN$$=9BF5@?7uuQ&9@vnWx3x2h8Gd`HzYuh-f!3Z{C@6TIbtiMjcWK;NV$ zqAsUL8q1-5tmjecR}8!spdQd z*RMeBi-c5PFH(xie#DLGudFS--f^)|6f z!=s!qF>`gQXaWO2tspK5?52F$uUj5eS=z0I<#`lU$Sa5DXPPGF?+PsYa()yqC9!jN>69JAEil`2e$h-vho z7I2bX+OTulkQ~CgOfsDYbo(Hq@ek>I5CR&{68hl!LO0sto9WDprE=Wcg2RvblV*{l zGxxK7^^vVY3!aKy?P=Yj?zPcG2Xbl#ws;>(U5eUWSiTh>*lhjPd$`!)edGUpc>s!z zW1gtM;Cp&+LeWbdPjq=o`_6H(ImtWf~{5Gtmz=VeBU4D~2#^LmcD^&3;! zq@+~C0B6%txgnNsOVTJmSKvDaG5VI`uG{>~?y~5`U|YvL+KWao>yJAK%+0YU_qCIT z;KXH!yiQ1>dt$53`CPHl#OyBEL%@+NZqGhk$d9IQO?`Tr=MHRZjK}RwKN66f<)4)~ z`r}Y*pAp@@>ggeJC|%6c%tCXxuXz;r}1rgO@pL$7n@krtb9E`Mh4zwHf7nGxZob1BW?o7eGSyhx zd)n(nB_kfUfI4&Dg%B`Gqw~!7oMrZ=z;!L@*3R1mpyy+nKoh)PQmyXlag2|`l2Px{ z{#5apK8`3d$|JLIp(}62Vwt?Mm!Cy;4$}j+o*Mi&QU@qjY0Y>X^&& zNt8abjxQsgty362mw0+gp1jYno-nT`>L3W~&O@64K$rG+QFKZ1EiE-+Z$-D{HaY}u z1z4^|34i>kEcM%87`$GZ=n*LXJEeiFOMRPXo&Nrjru0NEPHoJUCo*e!RPr_9Cw;&E z+X!|mT7NV)I#1?pH+INoYOlTndJuSZXmmy_C|rY2J;mnIKtEb1OhuwL_e$*}Hd?3r zje-E<0<=)Iq_hN$=9Nwy)=5p0<(d-k{WwnONu({oRn|`1Ah_3_VW`gAe<~jyfBXx6 z{acX33ONg+pqh8TfP29906T*m_Fyel%Zi&uvh>bAQtj^nCS~Y!bgRP)2KAR-@^8HY zQx7@i#PsN03*36>1B~N;kGFJ3?W-3%+9aiDLAAmyvsRziD^PuJFPyg=+8N58IK1y! zBq;0b&a|rUVvP1hGcDYM!b`btI~{b=yU7d8 zptYao)`s{>TcSrxH;`y8PZ~&=O2l=?5Hsix_y`rHN(z>E+obwbftUROReg?0F4*T6qiO~?*YV5!bB&u{;W zUaMy;yk-NpyY1>5^Ztsg2+sbO44F@U4z24|X+kp_wQJ)_4(DN(;O0%1eMFcR@3Gp7 zvj%xe9h44i-n)k-)Fc`{8CaZak=M(G`;?$^2RmgF$sw7by*S99E4m>#d+@FE$_ITE20t9q))Q^BNHW(IB)$4 z9yOLgvqtc74lLM`5xq62fH*}g)xud6K9wkw;@#(~#B1t^OZa*F>PU=m%ZN51ZS1g5 zrqHDa!6rE(D1f-xmcOcZF?fi#^@2QtPz8=Ql&?;-!=!F~WA#|%GE7+fsJ566L*&l0qh zE`;?9gL{aC4^8W&RXI8?O(OwNB1oDcGBS0G|&9b;YrJ?r#OrL*~!wc`+{_jq{06%zw=t<-2pV{jUa2KkR(Dct=ew z*cBt%!Uq-6{S!_3G}m;PuNB$7U+7@Q;n86wbLQYJXX&(_bEqL53-gtKu9}J!WbCl+ zE3D4;GDJKqFolHJ#;;J-pkL-2svz;ABDg4Q@JZGUOZ%7h`e>#J0%+GOopoPn$(J+v zs@$_RK<3vbCboJd3pqhrmB}nQmh0(EcdeZzASl~!-cQtf2RI~ZB(sORvmYdADcfhw zR3Qwi;p$hU#L}Es0%q+5x8Uj8+q2*uv-YW3vSuDbwTXk=N)(e2ly`WvRX~U6`~|Ao z03c;3It4bnb>_!vjUL2AWO%QVz0O<1HFq7RKWm=?k%GdeRxi)auEkg7!{1pm{AkvM zHbWI@4G=72te2_`UDJT{36VNsewlg=fQ=~D8fIH@qt)HqQ4_B1a{~JVUtjyJ`@qS> z1JzIW`f~5r`F%5dTA;5MB;cvv`e#z7@Ac2W4J_vQ8-8nY&HC#1I!Z9R)84_Lz09!h9fziEvSzR=@p1D2;u@FC~ytB0Q-TG z)!V-i@~_0^#ayVHak_CfQ8!WLfglAyls}Bt1WUxI@2-GKH@h4`SMHs9syHb$Poi)I ztG!Mrw+d$!^-`K#gGLS@HAM8mHXya`O=%cPX^N4Hl?TZ4lNyHA=?`({5J+jf>t$^x zy`5=FSRZ!)isn~D1|>32wIl268hE+)7dvzGUyl-d$xTkn1K~w zO^Bjv;=FjgMis4W?4-d7%i1XjM<@zKA_Nt2w7g~n&_&B7!@2ipSWK0 z#r=<0#O@k#Uf|L*4`!TCur0AW2WsDy@V^fQHc$26{EwZfeOqz5L0Lg$%PO;5pz`v- ld%~BK;M@%vGz281H@~ctRT-$8Iw+_Bh{se-E7baT{|9H92AKc= diff --git a/src/Nethermind/Chains/pivotal-sepolia.json.zst b/src/Nethermind/Chains/pivotal-sepolia.json.zst index 7da101279859151dd2c0b08347683144fd8fc0f1..7b0a4d2ee1f8400643e4d8ac2717d500e1bbf5af 100644 GIT binary patch delta 10737 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 BM4kWu delta 11289 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

y&U<}*Sd>g&PO9Fq^z@cDy849T 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 ZB~L}TsX}Z_4Ie3x5aEj(IH}uD{|^>q1;GFS delta 7754 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 CaOkT5 diff --git a/src/Nethermind/Chains/race-sepolia.json.zst b/src/Nethermind/Chains/race-sepolia.json.zst index f375ab0a29807a976ef649642102e1e9628b6257..be45c6ea1ddd541e7f0efd523a7be2fd12afb561 100644 GIT binary patch delta 7299 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 AuK)l5 diff --git a/src/Nethermind/Chains/redstone-mainnet.json.zst b/src/Nethermind/Chains/redstone-mainnet.json.zst index 8c2aba2c4cd2f2fa28b0d05b7ad38aed61011736..21bc7200f92c22121f884c53927e7aa97463c8b8 100644 GIT binary patch delta 7915 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 G^nUtdqm{dI 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 REgLjci0}+8&$Pv-{|^-#aN7U? diff --git a/src/Nethermind/Chains/settlus-mainnet-mainnet.json.zst b/src/Nethermind/Chains/settlus-mainnet-mainnet.json.zst index 6e2e6dc20daa6699fff830da3d79fe064c4a64de..d9cc94883dbf4e054b83fe0c887f50aa1e88debd 100644 GIT binary patch delta 14659 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%0A?~i944J(&mvKUu&S}~SZiy+QbHwPGwEbS9 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 diff --git a/src/Nethermind/Chains/settlus-sepolia-sepolia.json.zst b/src/Nethermind/Chains/settlus-sepolia-sepolia.json.zst index 1a9238e73a38f7f1160a9a5294d67193d7ab596a..91748ecb4ed93874ee7543463dd312527bfd2acb 100644 GIT binary patch delta 18155 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 I+DZYA2d1yr9{>OV delta 18674 zcmXuKV~j3b(={@|gHr)kCh3sYRcUXK^u&i}pi9=Te%W;t{MjW`~X47_iLpl=8 zu*Nd=!5Tp;Kwn{b(wIq9*qPysrLsTes0oH%Xh`c2M;TR;kGb#GIstG=BqKz(P@d0u z25*G(4N9^8D+nBCWpUy(n4b3IhWawcy8xN-THsnWs!z`yr8KHR5rW}C6DTq)4^bw9 zM)4UDdN!LB^`_{p>52Y$>-zA`sFgZ_kFUf&gHsMR6a@2)D2-ftNiF^&A#z#nTGHeb zUv!HlvoB_x3H`~%&K~OV?z7v{Ay$Z62SCxc`pcpUnaGn=I=ywF^zDL~D-T)xA)xxA zK=k+>XTQ2g{(Qag;q$gy4s@+VP=+|fu8=t5;zeu=3T0@Rr$U*@M?z;|L#|WT04aP(d4nfZvfALPn3{+8gA%`Kd(m6Xm?NMib$Ems!Mc&Wwrkq}6x^6p0VBh% zf_>8)sc-?DhQNeJBTWh${XvHK9KgIL?0CL>`(4Pt6t*rcSkk||d+qj7)vGTJ^(D(6 za*liaal>FCKAsX^T&J*!B}f>`B&trmTO}Yd0haAzLoZSyEy^Yj&B`1v2(5$Wds-DK zvi?MhYv@|?y}nJAUvI!;QxuI8PhVUMqrq6kqFMf^(3k{+O;RK9STmst1Ni@u=>Jlz z{{y7|1E~K4&0%oJ8u?xtCyOHCP}Pcjv`;;W#6wr8^U-|T6G+DYqAbM;=*%J;K1P~J z=FwTiwET~>lg9t2R{fv4@PF!#|I~p0ECLnMEHY9igJ|j{mA;oDh1Og}&VK4*? zq^H0=ZyD)(z8-8I`0uulOfjSvV0f&RC8wN?!qJBnTyCRS>!VSh$ zf51KSFS&&VW|Wx1L0HCkm;h)<5O8b25OC>CSSUzPWKIhQK^wk7Kuiw>Y?*i3yMOW;w2TCK{cu1thuO-yFnZEX;WHxhX!3{`7Ws=N=aM$$wPKBuHz$Cty^j*7%?hRnriYIn`UECj$)-a1 zKr1LTg1lD8?zxuLcv@Y?^A$a(B|45H6r%AF44d}dkHX79H>~vFO>mu-e}6;Sc!TR^ zSYm~Dj}v;hSkt!{VzU8xJOlxLPsS=UcK;6rk6^7bVmaM)+B}aUsQ?>4nuhT)Hq0R{ zIVnIjgNz-z4q4AChTYDT10Ccjj2RbRtYRVw|EQsY8x)$%h?=b>6}6?bN{c>fzw_)H zLM8s;Jvek5#hQ>?v>Q&FZW0ff>;m`6i$|m9q=Hh@{W`~3Dh+uVCoElxiq|hJSfVoz zRb2*IHz$>*T4W4UYLai1DH?m$!s*G?iU*Ka>{C~BXjAjo)d&3~1xMoHK^j>d<|%^W zJCNcq9EO;%(XbfXg@{6CqDEZ#X=?3ujrbeAwrXD2UBE--`S$K}WiGUGb72aeRw6

iy+_CjdZ& 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 W75>85SVYZ@gy@>qI7^pw{{H|^D;zEW delta 7564 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 Q4F?+PR7wjCL*nWG0p)c)1ONa4 diff --git a/src/Nethermind/Chains/shape-sepolia.json.zst b/src/Nethermind/Chains/shape-sepolia.json.zst index fc3fa6ce2ad0c9528b97e8680694be5f1be10233..9cbb6aed88d88ce057af9e3efd805c6bf3ccdd1e 100644 GIT binary patch delta 11518 zcmai(Q*_?J`|aa5wr!`4)!23#G)ZHlF`I8}r?G7{wvFbEZ8x@a`p56wopt77*36#I zdS=#K&Fr1k4D-?e1JE~qeuLH?EUSgZK7>eT#$cdfwQ4Gap1u(yHTf%~py-NzA*u9h z*yNrJW1Bao{?UguBqRV4bsNeW${cE_v7eV||LeLzkwPEUa3xK zyHQprN6F)tjZbytOva}QLw_}|v7F)(!lFZ;UAW7wa}kKF@`3MBrD5qo>%PeeoHsUa zLCDA7S4etCv)GmXrYw9jKRF8Goy6p<9CEyVh$_~3s}o2$=LgY+#7*gVQWFAcZ4SKp zP(MMtti_g}L?y>0!abHQ&R9tl$J#}hJ{zC)` z4G|974ZYAP94&FnA5v<|52gb$1QyrOkQE<+R0=v44#~sPP=xiBgPQZQKLDDu7Agc5 zKMK@MLl)@~6i_x_-gr@Ht*bRhFM9n%p4uB201JA_SPKNl+)+Sn7U-o-g%OS1&Kz_(5sK{t2$jG^nXvhKEd5}ExrySas$2it-l_YL0j1N zmD3pT0D|tw;P_u*H=8UmOdQQZ)+0(pW5g=fj9k{po_@q#c$ZMzMi3c=XqX;;JsWJk zDi6#6eA}g~haWmQF*;YW?!j;owV{|RO~6AiG{USvauLIj*6uYrUPlTN&WT8@(Fc6r zab^`1Jd}tbOr{?cvk2rM0=ftaeOe$mEj}$62==O*V;YlBUZCrgEJK>IA+7u=%fUW& zH<>;DZVhTCo;rWuwF^NUeKyWQ>){qS)YBW9Oq&Q8!g6)GO=$p zCYIF2n~LGuYua8nq^h%rA0v4_^OStzQugtM|^NfXT z*HUBHII;mkLkYxpAKRQ%P3mDljB;T( z{`!hQr<5S?4qw24gqOti=a-VRgY+KzysvXZc^`OZ})Fgm#!pU+>#^r>b!9l87{HI`%Gv|LxMLamOiQ1;!e z2|k`0#Zg8s6+ugbMl>qmqQ)RD<}HD0U1MJJCZU%JizaYNO0P(=kx{GonnPHRvxYVs zC;Al)Z?YoXLXv7XH1c46pgtetV>{oI>#EXH;`Il(Bi-XG=gj}G08aGff8dvX$s6k( z9dOwD|1t^xskikXkPKiAjlH^k)vm)UKo=w)S&<1o#m5$4=vKo^_B80

rE~>_rM$+s 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 KKm2*&@BaamH2{tP delta 11874 zcmZ9RV{o8L+pS~Uwr$(CZ95Yu^CS~YUTn)wOz6-&e0+ z{iE;qW{8|N2!N)A`4e0xl0_G*c?0AOZHtnMCA^gandWKTUBlm7J3!z5uV}rKHQ&s} z-vE_V3{r=ac?%O06}m1k7BG6S9Wsebj^U+b7Ibmd6bM$hUN=n%(yc;iuGN`@(#k5X zvuFC698OhBMCdeB?UocQ%?$byUgg&WINU-X&fDq}b>Lqm{;y#FSCIcJmO>F0x--4C z9`?k-Y>X5I=-(Vj#X0Jzaxnv%<4H5M(dVLsbjMLsSP)qZhKsT-$o?1`JY~+t) zC_D_gNGBoTE~52QYW`p-w}Zl0Me*VQNA>pgpl~UeHkYl0YxB?90mo47@;FVKm($>3#zmWA_@wQf`kYq>h01WgpzLx z3TZI_W<|0Gf@Cfl3<4*D!6Tvqf+)g6BSHcpBn&$x?E#H3o-R^JnWVki9SRAFJ4^w~eJme7-X?tck88YpwejOhI)7|p zpT?4K))#;{T+L(2_#2*A4M^G)Rx&s4hVc5N<8P(O$gWFtm6aLKR+eua5G~6Oim?_saFxcIX0^qmQIQzdQG4)Jg@@W z*y1DuR#!qqtWwj1j2!k!nvIj0sSBE3O8%VF$u^gA)|?(TEzMEe^D^C2ER<%hZ3HuZ z5{i`a9W~^M60eokcNVqgtrLb5YaQLRQDs?ndh|l(^Gb@G3mR1l*7gZ76Xd$1%`KI- z;nZ0hqy@hxqpu0^GWEoDy>45JI>mvSvN1i&4V|P_RXE&-=u3ja19V$*nKrJz)$*Tt z3D_K5OV|^ZKFQ5n-FoQ11(&1tcSwcwOIn083)x4i7LnGV^P=c4q;nXLSX|@8^9Jto(q9;7}h`>D6leYytY#x)Z znvuT0z^U00J2prdeXEgH*8y+Hor-~U!1ClP18 z2;w}2NPclK09u~2q4Unk!Ht%F?YNLOg8oJ=QZ|WRr}LMK{;o+-NH}Gm{`c%jFFQ?S!LYuZo}7fGQ?@)f5&mx zEv*|U+$G{kj+90=2E^on+3%wn-Y)`*Zxj~X?&d;!!x0CCX0*j@`b_YkWLO7Q(h%NGo{stZj|Aau%ODe55uE8a-LuUi4Of!rkq+y zSPT1AxrSoxf`RVp=hs2X!k;l8#)Q|hKi^8)#ge8u?Z1diu>@Sc;f99K2!|pR6!~!4 zSHz=F?8|EDcm9Y3Fc9s9GKMM`^e1r?!jSkX)^a`r?;YIktiJTwpvII;RLRU6AFvVg zxD+_jI$92hGo;}^)=)I|3B`Sx<&=~LyAoqrD`_uHjsM8)G?H1K+7WZV$ds9~&(XIUas&uk@tgUqh;;R}b@%=EjAM|W_nx!`= z)yj8q&&Z7nXW0gg*rhPl?-DHL%!mWXA#L3bi}|XPf9f zd&RPOM9nF_^V$@Sav%p4Hs3AQH+ng;NBs(+DalU$2 z+`lW;VK

9mW$Y9bGuoA)(662FajKU%k3TDHH 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 WlT<50)bR4z4+dJl;TvPn{r>|K%T+o6 diff --git a/src/Nethermind/Chains/unichain-mainnet.json.zst b/src/Nethermind/Chains/unichain-mainnet.json.zst index a79b8cb1944f33f33cceaaa407e3cb476944917c..0c645ad0e4d6776499cc586c24f238d7dc4ff78b 100644 GIT binary patch delta 44566 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 delta 44578 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 diff --git a/src/Nethermind/Chains/unichain-sepolia.json.zst b/src/Nethermind/Chains/unichain-sepolia.json.zst index 656831081947fb1430014dba527d14b70d6c266c..af355eb5bbac9c2d27146b4bad42e0fef556f028 100644 GIT binary patch delta 27959 zcmV)DK*7K0mOF7KfD!N=mT`A}Y&i9Y@4XY}=!0 zp3bbN7|v&dJBOx2qpGPjoaWV7=jTk2Pih#!!zV>lDbf#U5^ksv@)3J-ASO!4tVL0h z)Rc&|=3Uvk-G8UQqE(-_&c{x-b1;sb2~)G7l^a%!4y_#B8Co4N8=akvrqO2KcvSJ= zd6dhVl{6(avJNrYL5e;_e?G2kBpqR8-%ZCweehVqF#nU5t1iYUJ)d`k{0GS90 ziC-cc34g+5V}&Ail_ay$Q9P)sVZ@4P z!)s%-x<$hH-qs|vv@S9f3}ZB_u#j5o;PEK&@FteZ{oszjx|GJVs;kj)Yd|X%%KjZU zR3%EVkdyZU4}VKm$tt$f(RED9k9bLYHH=F7>_lo;AANpEtK5c0!l4X1(TcO>2&+dF zsAMT5$@ePEq{;YWG?1Iin{srGF)yuod#Uh@LA%?ZXnz$FA$cUnMOLBEq;~djq-e54 zaYP3l8qe3q_o`^q`E@A#zOOP3Sd;!Jg$%NVh8&{X6EtZfNC*$>phm&y8EHXdGr=Oa z=#G-6nrZ?=7z)SRIutEDTAwZTk=E;WJE|}nKc!&e80nM4115jZ&Zpb^Lwh_Oo-Vvj z`XT+D?(|iAyV8v>71hT7$6KGxx!BS1gLE8q)l6-SpW6mGL(EWBO1G+y5i)_MoLY+z zY0?l)Q^HJ)<4=MX#a_88f=;y599{Fj-bRh_%0!KEtkG7zsPuDXpJEp>L|A>|S&^p{ zGDKK?;#rZ06f!16SbgGIk!KV#L|A>|S&>H+GDKK?;#rX=6f#6ued1Y>XA2o3tdo=k zO@A{EB#cfS31Z7BmR+Jt&<&WW0V_991qjv&HbSrvV^|^UB14n9q7(|KH$r(7s?BRr z19Ye>vYzBoickybF-RGKmeO%z$b_P# zYO%Q?huo_u=?G)j(Ft+S5=5-XZEguBfvhh?*Oz154V)liLRzOF5h<5>Ert#ya41>y zVv4XOsOU?S*ucjPyxhQD07NVfgAk%*xJG`F1{Ug+Fk4Qf;1~+yDg*}#0bT65;(sOE z4H`V|oGDn!w3LP(p=+l@+5iJ0k%AfB+s$ zKrGk_gpC~pA9w-}EU*CpfB?n?8dRVH79bXo2|OSUmRt~k3;=)t0g%802Nn^2EPzDhU2fla)wiO8eUuIeaM5_vG7~p{eJg^Qd z1Q;NJ2-HsC0fd1XH(*@A?fMM_@+yU{x9fApE3kU`%a8Ln(fXIU-76=ao1O*NpVBoou z;rWq=oE2U$01G@I6Fj(pH~;|KzySpnkOlx?f(APQ(O`lH1Y>(vu8_mEx4WxIP?yW2 zDel7a$`+qnGV$$$jDN4IPpwd$X(40b3)wHG*Bz{okraK@+;z?>tkPIAtq5}{>L{V> zlu=2jM&;oNxe6J#;7Ry0(3Lc$pZY`Ru6(HmT^(YO(QdvwJ4i;fk~vMyeJ^i(>VycJ z(>W?rx~lrs63#n_gTqF-IIIgQ@e6XgMj20JA-cL`DgJ!N?|=n=xMcT?RPy+HN|sgn>&H>a_Z#VWCJB_mx~ z*(n+IWX!rM4XPUqm5jF%QZ+%gL95V;Od{fL)PfW{B3#$t?-3K)k|$}!ri?-^qV1rP zFC9WAgdoz9QGb6(zw>IJDMwR|JWAxKZX6XEXYxpIT(8^oQaVGUv)}7utMLq>T_;ig z%2#!YAs89e)~HB9Guo)UkVY=8|MEW7F%%i;tY-A4R7%DqGLof9Xy(Jv4ZX(4L>RK2 z-uioJZ6q7M#wkfk$fHPJMhq&Yld>;SY(F8oBP=U-Y=1G~l0)T&NX^hcVrcGG2vIat z=;EdGDyM3FD7Io_*=dd?(n43<;<3dK5C6yMDkP!ElBUO>8WqzX&CA2aKx{poKTqlz znw_C9>Cbek`Ws#miM>>mQBg}%Ny!*C`gbGWZaK6ZcAn<&%&-_^yJ_mDq~?CNgQZI* zg%Dy0oqst}kF6`jl!9VtoMaTn8Kl`OHF$YhhH7eWL<-_DdhBuCV;+;yRR}(!=JAop zh=FMQVL4|lsfC=1D7iLGv6Ct}Y|V4lA6@Kvtj&Z0MHwtPFJu&&J5UP`O%UQ_Ar;C) zBtwEujEg{=GZ~UfP?PKFq*5ot_d2L>h~W@sRDYf9ZArRbJ#BP2`-~B!EM?GY>bX(< z(A`H#Z*C*j^>(Qh-TH#2a-W)%=ydDY`IKm*DV&W%kJ6{)T{ErO8p@F!LX@xKl@Z7S z-D*eKtlNmJA~ebdVkm>$`p$+3MJ+r^TB~ZbOqltn^t01HW~1Fyl*uBE4!2GbvW*Py zqksET5!K^+>izRw{R(T5OhdK{-8PaH(GKD@OO8FZ)%H!j*9lpfv8m^ufA#s9QpP%Z zf{-JZ+mbN_GDcBmc6Vb_ElEm}Xq7!{)rmrcK+Md7L?L%~Q>!4tB7Y4YW4sV!q=I6MJD2uOncKE*5XvJ;ze|m2 znVyB)!`e{6A4CP&#L9SJ6Nrosekh0=XiK-SgB11x%mvT2H%M+{jj`8YNJAYS+ zl7&W%^wwEb&DW&~`RQ;K)s%EUDpXNVORdJ=L@-=GZfXSPz^zF#;?(@&cy;k`R@6P( z42~Jyz3h)cB}?z-lW|UNj2?HZie4Rc-tKSS*p!lz&eBLQQL%E!d}(Bglg}fgxvePg zhPhEC#iC@qhwH;h+>XyGSz~i`Sby|+y5?Ex)gdA6pdlolWROBSq=9fGdNC>Qmd1Cq zp~h&eg^oT2Zzw1kA3W(Q>oMwJ4*J43I<=!&BIB0F>O3+t@I+F0?Lop2xkTI+iQ|@l zq-Y3b%b-v!Y7}$~mfg7*o|L4M!yL11G7)(?@|q;xRaqDrLl8Yr;)W>r9Dj6W> zQ`Vv9eT$5@We+`g`aL|0jxuut61t>m9`z@uL!_mYG?)rWFq6@AKEh~w$>2c?lZlKq ziWGe&Z#R6HoG%QWhl#)O>3?{%@XP3YXu^<@p*0z6D3pC@$U3%raR%B|kg+C%>{zae z${}teSP{t`O8*d3EJ=)qQDT2}V@XoF8_`GgCswGu8=70+6AfE51yKcFo|Xi11xqM3 z)F5!IK*Gb4UM<#{uvMjWSF+eRcNJ%ShR`53xf5ipiJ*kr>-91l7)_&Jv>Y!FIzck}C~6w>S5w$f=bz98kL8XamhxqNy)|}JBe<$--{S+ zOCfrQGH$8y`%Dr#tl5X(j5K)u`^MLfnj!Q4Hm{2kJ2n=o@od^5O%r^9=Aq#>NEzdJ z$PYtQHegw-mVdF8v6a`4N{uK7JG$ouLdIAg&Q46GEPnqSO2%Yd&$}vfSE!73BI6=t zGpOiT3y&Fv1IHen%IF~*<8hrbhKn&h&xjDX&l5q6md7BAUyAZC#aN8PSVOt$kys*O z%Iy9(!rTrYjN)F_&j>Q&gp(bUwcCDX$za)rnX1-F0)Iz1Pvh4@y5ZAtYQN#!q9`7P z6zWH<=VQzVD<+JJ=op2TA|4lmwxQdY48t;58pv46!%#Yr3!|x{sbz4W5*?LD$-zjT zaKjjqvDw56gJcpZZ?p(Zfr427@j>_yDVZ#ARVWXL?MTW1_?z@d|QadCm<=4npq+DO<^n1 ztbq)N-dIq?jb05wU2M_Pi$eb5mh#)M;+W>LmIxgkeVQ&&M99jI->G zn15goQ8MV0e*@0pt!AyVj@roJ6#86qCZ#4Xent~69>+@m`j3hRJ$2Kp@#yQQ>Cvk? z>bU1Lj924=l8$%w)nD*@AupDMEU42AAkK&LXaiI<~t<8K5|qGkxdIW5+56yhe8BW z?jA!>QBE197EzQ$<4?nk=83FWjYq@yqeMkER1QO?kCBz3hZ(gQ4SpE(*whOr42_K$ z&1XnU==qk$sfJ=hXxbu284>Qnu9ooG%)0WCB4-sUhr&=9$(~pIU5g6|O4gqhWrGm+F`=9nHK=Uu+Q!9-G&ULt8ET6csu||W9S&Kz zD&?k}ok!G+)#j>{E0;%T#F8+B=tCaDLx!R*7m{Q$k{E0RA)sIVGIo# z!ZV0$!;zmU*-W)5ildlLAW}Ek+>tVwU6C?c#gQ_RQ8pwdMw3MnAAcng??FV-Esu&Q zogp8ED9<%1edJPSBa}-mh+G*j)xH(Vc&GtG8Li@5#?&yfj6PCxla6i~uVvi2R;kBI zq0`h-BSg!%;iMm0o)0ahF`F&CZ}d*lcW(ttty`h)ZBM*zTKV~DS~=muLPjZOa)~1+ zB z>Z5yfXguhMM~XyXWlO)xfBo2ntZDAQnDPRrFGMcTCGsk$zaCta6)MpZjHnSR) z`oc>}%bMb(GQRArT;)(s4k^oXdztMMYU!*#I@))7I^?fgr+=I^s(dSt7L|+sX7ug% z<1-F2cW3m=+*xfYM)EeEvM3L=#jGXAFx(U~ni&-f$0KG87l?gDlB4NAF%KRYGrEYK zTn#g#@gC!07}46jGuFUiHXCNt8)kg)VAU`W`wly+4c!RBi~`NKyDQ8XerGfkX0n~p z@@c}t>x}yqSbxIAQ4EPX;~*qha0up5K4boZ)%|M0X4Z_Ns2$B98Ee*J#{6Hxn(Z28 zsx@P-8Ea2RHdbFy+dr>nv>J^n8P$*el*p*cZSCf9vu7~u+5gkv(r5k|W)&ef&6q{l zWSY?~SB0e+^Yqe;m1bNUgajG|e-+JWlt+n%rZJaM&40`j&FER;;R+SbNY9McvpXX) z&*x<)5uNQU2w#brS&nr)_(j!q|IUsI&4vlHBQs;&39~CRy39+iELho=*}hbn%Pt>| zOwCyZnUZ0i%;>H4U|J1^lff|dQo>+E+tj7P7)+hF8Hw7AbydIG=DfXz=0Ag`3}a)= z__R%!^M8|LHsj`)iM%eiW;7KvW;87-%ai-v{!*BwjDbQ4Q;JZz7gM3zn0N>oXCz~c z8g(Z&296~*IOQ@}v?Ro-P!)xuT=vjc&qEQJM%+hAXkut-^&(C14|Q}Y>~#zEYu@{< zCQ+NvdN~9wTrFcB39aE#Dx6i#K_aK8KG7+I!ha|@I@G#bGef=PDSLb78lTtus*t7sGsIvUhsF#RlpL&>;M9Th4(>I)SnV+aw# zuIitOcxNVr>%xAO47U)rlB!b$jroMIv$PB z=v#%?vi!%))VAY2Q#EwDeHwkG&X2d?S54Ve8I=Z)*U2BzYpEVwO6~Rdl5{Gg{;2kg z=ZB&?5eb{nG(%NGfMNahjOZD%ZZthiIK%xliu5e4_!$aBzTFp zT(KWP6AdFrq*Ou`QSFC8#>?V3;we%QR7n*(GBQz^*f+z4&+Y1zQV6$*LUuRjB7a{; z`Ha+ZWfENDS*Xee!ZIp^(FZRLJg?%%WH4eJGFmLg;l7MA`9WxCS#*_-e!HYuKKASn zL_?#DP$hLnj&+NEM!fl)V;J zAR2m2*ik40^++hqA93Ac3q@v#q~hwoFjVLn%QXmpJY$y_VF@EKGA6lV#gS6Vg%~A8 z6_HouLZ}oE%au7orIbSEWg_z%RkYQkvW?23q|`hkG8y#NgV2L^v&I%2p?^w)$T6Mh zhxnj58y_BzJ3X6cOhr^UvmvGikN@*hh*7$r<3qvBSf>jz5x*j6ElsP%%jAjkSoht#UQW-3$G>T>a^77yD_XIXb_#6 z_gt?>Gvnx|mW;MlS~Z)=OMh152KJ+q>GF_38prYcUt0~GsJzEOH5komGfqz7WjB#H)yG%v$swe}q z6rDIRq*%Evmwy7>J2d$=Fj}lW6+ZH>u-_!cl>7nGB&|lyM*Hx!Z`$bqGF$U0a-Jv;+XAi-e|88_yTMfSx;bLr2~Fp@OsrdZ2wS zYH)MpstQ)&`Z4$$2l1Mz?MTrlr_<0i`f+@lp@z?u?tl7(VvJ>)?MN*1#Ky{{_zWVg z4DGv~OATY4A@-6qIcA!B>?g@O#diDS_9sKuxt(kzZipp9hFUaG5pxm|91CzI7knCz zj#;r(NjvpAU3*#ZM5-pk4HY1y(Pf>V$IcO@hZWS~a=9b_6=0lk`{ML;ln=5a8P@|) znWkVzjDIx)qz#a7hvACF1J25$EdCmXxGEG*`drKLD+7Shdx@S!&y!nADXK)c-KFg6 zVz}M$Jg>LN5uxrm*V9w{l{)l z2Y(HlC?1-GYA7fO(>CEy{)MbInl0MY{|*iiIL_>y&TK5ce>Wr$Zpa!i59hU$zV}$?~sn7aO1h4UIl6z=e(gxEqW6}i?RL(g$2|dtg57lVJ zaqk6HlII3~g%A7wF2Tv&kaInOgZWgG%YUU6EXzdt5!xhc-8?VPyVDKIY{z(BSXVWC zweJi(5XfdQ>dOifOZyvOE}pEmSbdibOknq|Z2#yYNl<|G8wgZRT8<13CgccF6|1RVLqB_J2v& zPsqaXYcY*pMIAI=bmB@%?}@g2BIFN~1vHKjyH{_9A4H!#PKZ2b%@8%n)R7J@w-R^# z%Gu)0kkv6|H zQ?PnwsJ9O>dq~uw12*naTnj(S|^zN9illC%} z{AT~p-D`gwpS+#tj3G~QrtRMX%^tRNrPqK#U}nsN&NXST<&x-c z7oO_gRlA;Z{WOsXxZVrWoe|!?bg+N8=dR0@`#+G)giPN2W&XFdit$)*CWlP!og8p7 zJ%Dlw)5H)SJfNVjD6>;0&nUX@&fOj9F&H=^no>KAta#u%MEg^s zFnW~UU05-Nih3#ThH(bO#Zl`nUJlfqn**C0I3Rf1wavw%U$Jd?*Z@d+KB2G0R$%lE z1-Lbb&-{d?9|y6#d@e&Z`4>MopRMgzZ~!8xg^H>u^G97psrpJNw!M=*hd7|WY}P24 zn*7PjrbcbCrjZN=yI&w$gqMTfW}U^xG@ zp$J3K#npCl9!~m<9-A17*RDV@!+5$AbV9yR@EnxcaseDm5`yzi2d>T#dFGI#7x2)` zos0_fGlDJ@c7Fr8+iyjxn>y0WmHPd=;vQzlh2yYfCGYc53x83(0U?Q7Bz&=uaqx%N zS{>NC=x1Z&@B!WLp~sbLI$9H`Rn_F1;X}#a zukByYj`{6~5R!!f5!U8M=z=mA>F}Qsb%1sAW=O)FOII(>|3(j`E#9+2+WP|G-5rbl zS`~HJ_xt?yN`LW-zW#EN0*gZMH1Sv7TObVe6E-D$;ruNK~#+q zs+4tzCj;Miur6Jp)qH1ofoSuUmH1yTG3OFj9?Am6L*LlZ4+W1bP}h&m>G*36KQ)&7 zV)^8kr=~hmUI_ny5Q*cLa{vNLqU}HR*sB8NRKzYbi+}ciKCyEL=)ZSc%j3F&J0hSd z=d!v zI)WNkp`f8Z7AElmGte*_ifvK^(=tS#D}Be*v~rKubYGLt7IS9vWKuj1oXLt#uelaG zxmB|No`1hoV>yV#b@@nDeFP5I&Cm{IXl%6T2?)p*4~di2u-=3ujn+CwEaau6if`z~ zpuz?}7weMl`b9)?cez zer-2yt{w9R#rWDTT6QAZUZ&=bJ?Df8yZz#0}fJyS1@)Z6=gqy(P@_&Jr zwfl&c7w|aETm!ddVLAa#c88naxR^ZiJam_>Gjaoo0Uek%TjulqMyb}gp^;H2?Cq^) zUtw^y=Migv$qvS`V#mv=!S;M8RDX9oPbHxcKXG8G>q-)n9K-x~ZwcpyEEv=M>o24G zd?)c$RA(V*8Mkm8#ObUu&r0(CT7NT&gvY=CFM&H>a^&mpuL5aU7-W&cwz^)4I+yh` zik(+)_{3Gnw3vR1B8I!_*&s4&-#ozQfMnmLXweg|(sd6i&#q-_1Thwv+!Rj?${!}( z3~?)~SwO#_%I?J0Tn`m#GYRO+d){R%M%41htAq9OP@nyeM!=l0c51XOfPcnAM9>A# zI8=N21&*s5jiyizp__vYMhXH;&o1B4;2=P*e?mtA>e7H22IOqkrRU_aO@_E%mqOpf zdoKFA43yZAF7ZBT?|PZgVZJA!S*O7FyUeC-4k%HtzJX(xL0eTyeieP?5^GwM(%{>b7@P9LNMHiEtzhWx&ZCqFJQ2BFs6QfLAe>xF zPU-D_!BEBCe!v~Fbcq+aj-WnNt9$o;Ie7`=xd?p%Mu)_9>v?xmTz}(^L+sJb*4YT7 z8aYAF9d`?c^J;2)p@7T_c0*8X6Otpqi{A?aL`megQ$KkP@f4M(B~e7$tX!zD+fQ!h z41TBVUxKzkk3+@OG~#fdlCVIMnxGr=`Cuc4jwQ+$HVIcZnN`9Jq!NNT0A z+Ug$aQ^j6BNy#fi7=Je;dDhBS82QKF|HMept}BMlYYWQ|{7!swucFWXeK<|XMW?+A z;-?Q{$4$ks<(7$g*A~HK`jDHm65)OSU^_J8!(ijME zw4edxJN!b;?z8O8B~QocaI?DaDk#9T6I%|Od46#Q{LIeAQ*UgO2dy!*!C^-PkC&+j zM8xaQqyB+@`zc9->2Wu9x2e=569(d228p_1lXGT8o!)xy4ZYA#KJ-)M^p0b|K2H&O zx<`n}wp33}oPYRwCzz2Rh@yZ+$iD5{Yl@bdvOk0W@$pHj;o=oPrHhmhF*#>BgN`nq zr*SwsQMi0MF0mbolkVe&!5>d~DD?Emu?%$cV17|1f>9Az|H0U@X6W({?{FR~sX0S_ z$F$I;U$3}kz|PU@!;L{FM1F0U`CLr%gS)kX6u;3H^?xv(2*U45!Bv{^|7zz8zhRM` z&yuut03QX&Q%mMYfod!fF6^d7hmf;3-(jHO?H_rMx7#~N*MX1wM<%;{oOj z>`M%Fu~4z~13~zHFmwjKfL;?7eynUT(lrY3oDMDvAgzF02BU49%dEainHENG40wdd z$+0pgZ+{rjay6swfK?Vdhw1C0C^XKocVUW ziUny05|bMKboiy)V|gUd^tnHADR+g%O@JO8mBE`mrpA=G9~r;Fe&xY^1zl}%eY!;a zq!W!jylrY`8xXxD0)fK~DV?+fV1&mlPBDJ%xqp3BaH}jY&DVdv4A>_^&?VioiFA2% zVkxUfnTvx!_y$)cR6BbB`y!#M>5L9I??!AI60SiW&D5BP@AnC8wUgn z9Dk;2J$WC%*AEGGno5~_k8=STzR>B+?8VwA*9mQVNEVoiDi@7p8M_ueXVHxb+6(2I z8qQ~Cfd_{@o?`3kIcSwi25-ABEG{-v@UV&8nad`6fbN{Jb)60j-hn)I#}R~%xy65F zIY&@PC@yRDy?}ce4p=Wyfv@wvtmZUYGk=2(J@xp@%>E-wVu2as?J{NxN|5@feSy9j zqn9vI#2xZIUB|iGUJ++g@nXGO=uFN>2T5c!QGh;2U{H5#lAUg=EqQ=E{VJ&nN;4vUzW#in`EMV)Y$eSai6 zAk+SiogaryPDe)9-VU+Rp4pVgJ9ke7b-`AjCkw181O8Lm_ZMq&U~kWPzDV~L&I4F9#((*DML>17 zg2Yp!0;B_!*~IlLW!~zf;>DzhbsmV>NMZd3H8|)(#w$6Lh$C9=2Uy#PO;Y`E<7lsB z&R<4Y2Os@{>=07cR|;lIS+Ye$bq(H)~$^|){TzTMko3CfI$gv`A-YT z7X^>K==qof9aNNP_1S7e8h>@1Nx)rc@;|T}=+WjGm8OsTu!kZ_Id=@q7*DND*_Iwb z*ppUMJ?iv|pb4pgIhcu=x>lOEMI1(X_98D-f?u1Neh)U{k+PT0cLxTwl4kewp90kU z;i}I=1zz}lW)oVMQS{kmdi;`TsK#VIf{2VcW|nN2vF(NgSF4D3TYpwm9NC~c^A_FW zS2GWlTa`z!X2LN!{&-3io4aaa!Zq#NE%K0Si&`bMU_Ww;qh)v{95}_F-N2R7x%}k7 zISNs;J-a@ArMx=7J=Xy5Y@nQP#U6g(oozHaW-B|Rl!583EmLVhqx-bOEK7U_w2u6I z{rQgR-0qfFrMhlZc7IQi?C*awn+d*7jMERqfjd;#TmICVvDsVdIp$r4DT-(!+cCv| z+0J@0e64|pk<|Bt#98Z4z|QTkeFG|6I?+Hoz3JSY4_6RE;$uPUoPkZ_MG-QPgUq9P zXH*n--wZQ3&J#B}h)CW=BHh0ML8K$lmDr`UsN);}od`(~p?^BuXC)bsEXi`$XoPnvJ6=}nrJ!BbLvDCLIbQhgRMj{w-qbPxP}*J2ObJtUTn*M*C}(ScPagR1d~ z|8hs`vpRL%w7AfpOs7aiWTU^nD`8(T#fSHBoGJ?f)qnUWFJIiibB|7yT!%6LL+q&N z^h)-p(!DOpz&{lu&`IbQ27fu-({FK`tOLACcOz|4#Kq^TVE9qC4&xzLa5pDp7|V&= zy=1+Hxo+TKuE=fLtS{&I{lVQzcZwYIFMb(Cr-phSaz^bxmUbFXQFr~yUV|#=wv=~~ zdmO8Auz#-B-(IX=P=hzH@cdstn+K^qJA7EspH_ti`Xu?Qe%~IAK<5BZ8XtwRRI=`i zqiiy0qt9Oos-&%nuHorD7TJr5$A&FyVulTNoBuyeMyq~gFhnj@>dltTFuOnl>#0Ld zx3mNX_GS2TzoJtCRhL=z*v}*)_mK>HQ3Gf4^na`yv+Bh1RRD8%Pm<3}2LfpAPpXgm z$h0_Swu;8@YOUlOIv@@^6-`(-}ycpR(OhTNik`XjfBfLLlb+u~1J1>ZK%YBUBfZ=;Lb zQNe_0|oKM;(ubX{jL(ZF$t@+NlH3DibE~QVYhl&(3<`C z70F?dcCf`!VISnL6=$|Np$;;SxeJ?aOITm7#v4i@94HBP_ps^SNj(JaT&Zh?Lw}&E zs(is=@vR<&GI3+D>l8wK91TJ=eG~I^13;3Ab*v_8{t}t z8=SbeK<&H|ZhA&Y!V<3qUr1`8q~Ejpa82cr{&BcV{h51~D?tKi)m!lk+@WW^* zdt+{~rK+$!5BQkj)hzsf;(ts`HH01vlOJKoRk6fyP{J8|Ihxn3Jm8P{KT z7usJ2gD<+dJg=^$f^XCmUT)5qdV$TEWsR_G_RpyYN72|hNyzlYqn(gS4Kbg;L-7IM zeM4MoEO{DVVGW>@rGHx$Sc?Na%6@>(zJNoI^vB@4%I&{N7=K48aOb)<=S&Y_LXpxB zzL-WwSp!1U(}CpdC>f!Dpg6yXRek7pakMWZ{(eE!M>#*yKYP0U7q4f>?0nAHX}Igg zL8Q}o=7FC!lZ&10{AErwRXi+(dFE{zI3ZW9CYzXoiyQpMqWSMW%|AstQ$EXi_bzpV z&Z}TRf;q5U!GD4S0g&7BUcJd5^dqrffz@AL1FFqCgv7FwjA=%h@A$K8KtzPWvFkN; z^dKpJ?RVBLI^HB8;{Y2K?+uGxGoF>hSWgmP%fD2EVEz36rrNblVrF(fUSC1|(dTYF zJYgVma=JbYcec;509}{(KXn>(R8kw3k+<8cXf*9@ZGRt2Zsw*?q1*hh`4IqaO&++pq|>XCfjNUcq}*D~5H3Ab;{v(?r{CW{~R zRpEM_R$iUVJgT;p{QHhp!zX_A2}@RRW$)BHQ4qwgF~?zj+NXil2hXMls5)YVASE53 zDc>d}yZjD0 zj5$sY)7>~ivVln4Xp!UYf_VBi^>pl?L)_tUFYpru@>W!%Cf6QFeYp$vYwvj9y)ODZ z##Ef;+}joQrOt2nKGKTvEahoU0NAfuZ?EhKu{n8ickvN;^uJt1p&;_D+JgvPnx)WM zH-FTO`T3`eU*fdSsX$!Or4bkYJmfmbHSeZn?89xY@v#N#8^J4t{Xr@9t_&X1K~%KA zIaLG90pQ|2-@%ZN@+rE9!MDY%BGrDAoq#xHig^4A^$c|$(@-P;Dl4XDj`GdY*hf=?E5SmOn+C;q@xA@o>U-{A|8JS%^T2fr%H<@&Jc%W zrxt~#FM#>|Up%OQrz%nBk>5*#BDB*2)TTr?ah7H_>;7ab8|srgyV53CrmdEASIsiV zXX+^%ZWkTy6uP?XZaCE*vx3E7w{lhJCr|^6E@WtY;VRUPMy3F7-3V%>) z&fg|VX}V93rvP$j6&4)<0GjfYhql>pYgY5Z(W3bsg zaVz4;2px3pA;6o1bG85EAULLcgsB!*m67a3QfwEi5*N1jPWcV&83M6R3#B2VmBas( z*^=({;PDKjtCE@YRljd=SCFct!V@DaUhkKTxdug7=$bKOvVuBVo>&!7!hZotd}~g^ z@{`ml;Ffk-Ue2!DVZKyfuPfHgWeu{Ca$r<6w^0r!!vVIMyPSoKi3u;RRcUBH@s4SJ zX-d#6UT_Kzn?0ABXkQ+;0)JNL7}D=w(q=@#zXs!YXYwBpqj<*_F^AXk8;GM7qe~bA zTTo|x_nw&-19i%dpnCXt;D7e(U>??%ng=(NI2h|BuJP-k@6Lf$w1DorXem;Z9Bj)(I3o28qpXp z#i__XJ~SQK#?bK}=wE$c z*01zY;HtTY`xhRIzBhzz(QXkW8+bY1Qx(gA%T_}SP-2K6~VUcw=`TwWE zbN+E^txtzPP=7Q(XKUQ|So&z!>4GD&IoukAxn$PvUw3cAq07A9HL|~uYc}58K|GgR2Y|kczy2 zqE8x5+qGam8}X0xcJ^U$S;(aT{bg==SBAZO$D&zN~cSdTF}|MBgV z;j7(u=U!i@ow_dR656Y!3$`gz)KfmVOglK93R3;1*wfc)cKpPdv_h z%Q_8%^M61mX6`?&$HR;_Bxt{w*g;vn3L3qg{!WYFa~PzTIxOt2-G+-UeO3ezfg^z}#3(9XiB9)m6fud{*e^U85!$*3Yl~u9xzBke=4$BSs`p78*nqjN@-(M64=*a<+IfP zkFLeeQ|Z1A6=X99)gu4@Rd3L>ZAvesm-(c}2ZBy4R@o3f-VB^X&7z&CnUK;e8uO^$&}_#Ua>t(Uzbf_*OP&Z*d1BBI(PrMy&(F06Oox z;d2cdZN5l`>XcpSbVWDbsez3}Rc1wcOM~>Sdj1SLj#>2|$EmXAN__zwqU#zBdub6C zmCt%VkCPYJ+x4DBt(C)1oREW^Zs@V z=;}>jmc{Hn;#!AqLYmnkFM|S($EHme2MVB)YBY1#Ab40tWc?H6| zCr^?No+iFhMY{u&dre80|3b0n`iOSll3daL2A%wsy&3O0h4xSXqw3!L&#a`83J%K= zz*V@8wlpg;uqG1ns98%?Ab;7}g1|fI>gYJpH?7NItV}JjK*j0sIljDU1jl6jzMtG z5oPwpiK)RI>%5xW*OC2(_x^N)%ky+8-&vXjc`dwL)0XF^9;d}HYJa+lG9U$MPG+7u z!=+lSeOKwjPiVD{A>-qqeZbd(gZiO9CBR?TFl~fgms#R@F9|?6Bfc+pH(|fg*HH@d z$O8W$M;?EMkBBzprFz9BZ6--z8=OQr1<6V;lL0@`|Q~!=RvR-`fpTt^p-@`;hmnjJG0o3bQ;~88~4C zax$pCtp+Nat`P;V2efD10LVexuIMn0pS-rLxA2vK&3d?vQgYqY+CP6}%F^(9@GT|G z2&S7D!U+VkB@dTz)lvQ(e2Ex@aQqBM3FvnDI4&j_pN@|bz}Zia$Yg7fY^YJo$#8$O zRz`(ziEdlFeW>p4wG}E=IJsM{ujz$0BE1oHr#A%nozH}HI#SXW3?O?^AUr{bnF?_o zZ42XYE`g!I`n`6z&k280=z8m`P86%1h^M4T7>cI8Xy-(W--O)vH(xe@52qxZ15S}3 zF8$eqh|1BRv8@@X9Gf>A3CQ{2`q(qKEdY(3F&{F4p4hDtW8DVk} zW52}qQwxNno0W@$j?qoHoTyu^DQ2AtWAL$EmgCHkt5PJ^EysT`578Oo^EChr9hau= zjKa9%=kA2YZmIqs)zEnp#iYn&Sum#rl8dCunwP&^>^mmFXF^#n8{>jP zO;29@DHn+x*uGdajo+g3ZVasn5rrsPUqg7U9Q{6>C*`K(o3%)z;;8pq<_@wKKgR7c z%#Nt`3ZA>KK+7#rvuP*Paq(};jHS31Trxei1!z7YWKVxLHzj{XPWE!=;Bq=lk=(ap z{je^SRLp`hCuFI)4pft!edGv~XkS<2gB?+iB}$pDO)*`|M>z>mytp4-^F0H~2nb>? zOHbZ_HBvESs|g}&YYLE`_@q%YKenUD7ZG{f>&AbmTKlYzs7olZfJr0ywi10ZNS05I z;{4|4_>t?c6J}I0nmgY*JM&=0C^z`7seJwn`EG& z0G0wEa?Snv{nEFkc%2K?4~;f!?dcc)W6}LfEm6!Cv$v-E0Fla)ooj5iQP15_eqr4d zqPl+?ZYiy&0D5KNyhs2%m}K6Tx$G&W}{asf4WC?Ueprf#u~U& zi}rk}??x9I8}G|K8;Kzv7A=}T;;)KK2x-IwP;Xq@rg!>#ZV>1&QqHav+NY)%LkppX zh4u}=dNP`Ib-h4-;wf8F!I#d|dq=YSX7_uN!1@^L#XwtZLFL%9hr4K$S2wO9S6hGN z!ex4s!|$`+JvC=4K%2CzI4C}np%2a{UZD;+yEl}ozkmTI#aXtO5=2#yjC(ZrmrZ&F z*@_j~oV|3nc+|Pf)bvdT*#2pK@^B@S^N*G8b7mR(RRZ$OBz9|hf-KI#V`+CmfXMOn zlvFvnaxX*EfJg^F$*&bs`>;Dp`$~VBo)_y4(va<*1W*i0tg$tz>d-4w{>tu}IoH_F zCDQUJ{5eeR{ti?Vi*p_8ZcH*eW298^ls~Wk+5ML>@k?4 z5vaiSr;CTFFGwrgUu+((7h-?S_u6Vv;`uR}&=d>novrW867 zVpP{tWj~vqH?w?g5Q>L=4z+Pf{-*QRWwTM`23z9kBGCX&dy8Nu*0?S0#Pg7RlyMZJ zU@9KZrfzXBe@fx)v=!E4wks6W0tPtHE566GB=aej66KnaN&3@?q zY<1UQ%S?C%0H=2RK}9oP>bioCYFso`Wj*0*J%W^2SJhRGw}bwF)g@9mOKLR3hpXKb zal$Kd{^^<3zve@UPdzmriT}UrA{5Nhj? zmb6fU8aVZ%fu(ck4{bgCIP40ONu6$2e6q4o-pFFv(dd8AtT%b<-zifPJ`P-X8Cs7a z2;>H1M`%6ZZr2pEsEekQEKcJO4HVy-&okSuER}VB3rZm|3xli`Rn=B5v;M-$eNW@N z?F;62tayuBMd8v>|J}$A@8bK~$v{!-8w)PJAtgjS!?Kw(nI!Hemw^%_ix%WmP@3AtZChr9&~lJ@Ykk6ooJ>7K0xSml$F6_$kBxnssGOr=+_RnJ?gM z>?w#uc=cvTOb}NKe$oZH)0ov^h-JKjU;1VvDH(qre~nfjgvyC228-G^J7ShG9x-&=`!`Iqlo2y%i96e#P=Z(YZ7 zk7F()DCUWuPX7oi1@qXAeJ{5t&(}5J(6)cyYCkPVvBUPU9*%jnq!od;+>i)Ob*5?N zl?6+W$j_=&N`oIHg(kJ3khA`jmlitM810_} zw6E|e3^m(tX-ez~(J*kL|9M1l16F-RTj==XqOpOFe~Ad<3yPr)T2^PEH9^4mNV&YJaa}Djf%byR|P}0rA4Ku<9kLWRf5B-(R z<5%vPGatEV9pW}cSOrMScEo>^>U!bUEXK$lyr{c|-o?ikJ)cDbhl=)_ah6n~2^(;k_1-ZbrCbo>&id?Cb~ZQYiyfKJN;0_h!?6H~#BuF(?ZA zgo5$n##LFDMKz}WKI87dpD6Dk*$=|&balnU&>)-1f@It<_CU?MZvTIWpe+R*O#B30 zkv!$|k)mj=m_MY)am=f>+$YlpcLiFqPF>bV5B{XTZrML`T4EeakcgVUXht&navw6= ztQ8MbidKYjV%J*_0AV=?#cPR3h#M%fe;b?=Qb ze;hfrX#SX%&3ua#`6~45^(}*uX?oXK>~ov4^yTIDM9^c)=IDc!!&7k!pHZnOv?Y5eqMiu|1=o?zP6Bo(wjr? zOL8an5u^8)^KErH5Wd`Lb4Vh(+fapTBWKX^H1-ewUA4FHV35lP#?<5xMcc%u&C)eC zmJ&_u-B&r4WwE23f|45!g=SC!LnmI`R?)Xs~|do+i&VE(|-rMU3h>m!j-wrT;j_kQACd zAx=X$<1F-dh4Nhqh9rt7l%R(p*+_n_3t%n6*-G?pwRxxczp)b`cw2M62YzyXHskGT z7AQIIo-2AGDozDUV8$z(7viR|$JS>o6w8E)lC+!TA1HtAa%jz1V$3YcsX4PgA&8es zYbooFRn3l=vGS9D?w;nhNxTxvFbxjHa{GSP&|oI+`x?p~5#Y8Nz@ZKyT0GO}Tz99! z>ui6?ahYl17-dQ{nv_DePz`UdNAYn6AUAK>pFnyTP7Nq_$cN}g6Jmhm7^&tE%ivn~ zzCzW4o-uz7zUj1mF0-Dla2d^ZlP;_#`{ndIhFf%l z-%oMTPDd^i`}>gw(0?dTHWp;IOm7CDlP7`r1}IlfsGq=fYEj8_QCUO#WNT!f(~g zkRN|NKHYL8f8qH>2naA!V?ukTQ{)XHmOQDkv$YE=}Yz;L!VS#=$j1Cur8uZwXm_X2+RjNzWjEX65V zAjNCfBH{K?2Zw7wnSwA3AH;aL+QB>~7ySG?bsr2_(=j>EC`6LRJO?Dq^Q;INvt@rK zD@)73Va2Byvctro#Z(DOaT_Eb(sL|zs)=cYgQlAaJ19@V70>!RDue6XxS9w2<}+L( zd$?rT>U3}ZJ*hUEs+N&y z;6TP(Z!AZ1ZMJQ7;h^Vw;xeqvRSti%)#Yeeo`I^#!nhS2zVeY`Pe zWPDM?bt|^`JfCe?)dv)q+GZ?rlN!DmheN?@Yz4Ay!K`~&lJjnsblhtyo0uEr^ilF~ zd2cr!%$QPyOy>htQN|k~0EWerAr~q#kF#~~DX&Y7VCG})9-%sk!MlITV?BRJ2m6s( z+WC#6#jWMlP*X8CWADXjA1XIgZKgQ-_f1Npl;aIKo;N;|cU@$J^&=^{9n8Ck;c7&}DJh9BkMhev(F1BvuaLS%a^P1;>IL(R8V0^eByZ@74#X7saoYCcc$JlF zU6G>}+|k-sO>T1!&?y~@gy9&m5UMU8bd2ljux%WUQsjQwe< zC-O1y#a_+F@E=2b`Lp7}&t<7xSf;;TMMu>Y) za&~cy+-S|oiH>Uj{Z-a5Lt3xryn~Ok{n5o(yyx1X>-z{Bo}Yh}xDW;pOM`#cDIfL6 zn$ZR-Tl30=rs|kjcI1yGQYxBt4So|V?lhKcIfTyps)nc2T?IamBDl}lL{hxsr(w3F zuNo(w8U7m{linN#1{FmhhrfB5@y^nPrMpDonJ?XZLZg{VKqh-Ai+!xhnyT|zb)pEi zr>`8P&(X$2EuMep%51pzEai}6ySh5T)|_C@9o@SN!4xg`b+ihnYu3Q>d`DYOanz`o zQB5FnQN;V{GUsZ$T+_mUPCvU)V9MMCOr?=M#uKZ(K zCiX}gFnfQ%4_!N1J)YvIEdqX+6-z}58eQLD8&e8PrOIy762g=l7fyzX(f8Uxlhg*C zJrB$c64}ZG91ag`&%&bmG=L#b>9rCbLor3RS(At|IPv!?8VD6>5o`EWxN$#~e?fk{ zN)vGw{5c#SE8{~!EFDhx3x#TOJj`j|YQLU^*zbQY!mJ}cl7+kwv{3eTC&)36%YIHrsK4G+ zW-5Q-IkKVe?sneD@yk>!TY)z{z>eD_(?gQuM`hc_9YpJ*y*rLP$>6c|QZZNK;&Ujp z6ll~HEFj}S={rZJ^@ynM{QPE|)-1r4;oQzFgMa3Jk?Jp%u_0y~NeQI)FkV4F)t%;e zEyLe}e7@YKd&Q`6UK5K2XgE0~|3ige{|kTlg^wWSa;FoA1X&vh1R0ZDJEpFZG3($e z+8k3}>@A=`d&-_jsA&D{M<3zOFb8arzGr0A9R{zS@?zj`Ow;A;Eplme)a05_jvvg* z%tlq6+6KY;{>%VFia|k^`aBY}-fsBT0=J9^J$vJ^ko zOo;RDY@wbwQhpX_h(xWd7u*bW~|R1Oprj zhfH`oQy7$Cy0Xz1*<%zcvhu$JqvPI?h(lhwR;L%3ttrkXg)cPV40nW=u$3rOoVpj8IL_+# zIKn-YOfSaXpmZ_nPy*S}`}Zfbvt?;k$hUy0ZMvZ(!uAX(D=&8M z7Qt$Kt^m!BUWSRN|J)90^348J-BGY-p}nX1AO?0{=I9_eStp;~_^+do2&UwJj<(#< z_?i?wVQHjBe=A|EZWa8d56ORoR#nUv!;i23v_+$+et&PfV#FaCR3MwI+%~1*mOK?l zB4%>_S-_G%1pFO+C$7Eq0J~x2RigoWj;zTOXm6$%ua9QplE1{l9IcTEP8cqa$3ix( zGY;y(_lBim=-9c(i=tKs;L=j4Du*~#a!jY=RK{jt$)KNWT(!H&#ms*ayZy*;wa({t z=oHBL+!Kz&f$~bw`gr=GlUr0n+Z|W3V7oT`B`qMQaZTPT^jiu3Hs0MHHS>mU@`%r` z5IlWwM5$uubzQ$=5~2r8=RG299Nmqydzc;`pyF;2;O;P5!ZxB%K1r{2%&kr!pI$9r z=o{)tajW92y66A*t`>j255>-JlRMtO`HJ%MT@Pek*nha)k^Qo#&C5=iE57bs9akHy z=*U0Nyh8Q;tG-_h(Z&YtW1Tj=8QdMnkl4ux$pvhD$VGkDDB@GYi0+vviE<`O&9+kCIKt7?8)`f zZNN|8iJK5j!*XT$qCVI^9W`nTB%EbUI5^Tgq*+Jx`jso3Kk%qw=(r^!rJ<)k>{+*= z&@i#H?<4ef5VHtU*x>-=ENpO{O3d4aIr@Y`bll@*`~71@ICTFuWdY+q9=usl7EMaI z&4_QQwkmjY{osG(>)1!H+JJuM_VE+7*gxbL{NWqb6=SHr(5>3f zRZa6T%aW05YVVC6YU#8&InXL&m|u@?no@PrL8iPVOxq;IY`V?)a9I zddmlR413v)Z#Zdh_<+Z<2fO2&O~zY3=&|g|uAl!O3{Dhj=V|+MRE35^wo{$FOI+@eO|`^9CQ{G3&+deACIi!3R8+J?zFeJBc@Z z$YZb;oRdUUtK`IBB=|kjJ!_-S7=3^M((2%=WMw-*OV( z;)5NFz3kSvoP;-g$Ya>UZu^Flc*_TPEcUG5Q$$q8VC(Ta-~q2H1bmbQr9A$QCzOA` zp+_gi%Gb(qQ(uRFYpb0X4Kb=aTKUbn?+&On_p5bXHX`JYZlIN~zvVeI#`oq|&ya~?(bz=#(RF+{Xn?f)}{gh7b=Fvwp7r0|c43?&|6)1L&0 z*njuM!^uN|{c>Ev<^c*2<88hJWFmhCfvNu0!w#+!moIn=#0vQNz0kzl=c@qO-mA*GhN}SdDS9WX7*s|JcndlInOc{@B3uN2OGS`@ z#iL$(qE!cxtNN2&l-^V%3&~po<@UeF3DJF;&8tU}urj;QtmS5?lk&xXL<)}@*Y?g2( z<4O1B+bW)=w=Ip;+^^nmp%=o{|DD$RZM*zYCb*gW-?r=j+!yZg-{RX=zGK$SZOiMF zEH^Pmo%LA@&vq3490G6^WO^i?)`^XG0!uh^( z-OWAPYe_cbl7@JIA=Y2!qJ%~X{%>=M5lU!%0nJ3 z-iCHJ#qj9?Y*zrgOUwzD0H6Sy07Xkio-j<2;EPh93rr;;gu)}7?+O*cVi+_pNWe47 zleqic9esDp=XvltcSe8wC=ol``Ht8KJ0tpM4CRKbg4WE{)@&hf=ijc*_NX(`nu)^P zKfg6^T%E1XXjOugUS@Kw(3#5RWv+sVpmSagx~u02Zyq-I1H~7;_f+`M8O!8hD2+ZA z6J`p&|A;>O;zQ-5`-FS}iD{M}+r~o1jIqX;%&?JbVmoBv9W#HX31f#XHhS@SY6RZdwcqV$#EoD$%V5Ss1 zp%-wDn4u0r7fXMJ$hmT)vZcHX?gnAPz@2gyR98evf#dT3S1%vqRh?qpaEy2Lz3;&L zRo+yYtI%dwTQ=5EBE`kdP&i^G3Ry;&YsRQzCmu=WEankzq#%JDF$pJL(mKBRjxmhR z))2OpJ>NHS`vX{UydZYpMO5*|~`!fwtr;M8mUX+nK z5xoRRN9zIcKs~J^)i+}Z6Q*0!qjDNptCURO7`$j8Z6)CXQ^6}8f(P`cm((+*((&m> zWqyBSBn^0orF{t;qZbXRS!ww|X8J_9z00yeWKw6t>!ovfewEGV{x$kZWdWd_E;J{a zK|=ymr))mhPXkesR0I==A0;&!^v^`NN&!NNd}!e2K44=F0peEt>_fD~Z@(2mdodK! zVw{Z-Y-^b=Y)#)yR*ka$?E}qyplKgyD!qRY!a2TY7fweQIxLTR0^1MiB+Beqdq2)o zH$YUkIqrwkMjQwK|BQ#NFblZc7}_Ym4X{GO1#A-(CT<5p1)Lrjc7h4&y1upg-K{pI zEi9qwhp%4q@t3=wfqkdB9O9-Pl)$y>`T~bty1{D4hJ@g6%f9>eOwnbea?T5#30!S-*9OZ+6ym!;E0L{0TA`u*^Vpjk}G}| ze7(Z8^vgB%f%T)Hdo`mV`H9Dh3>W7jLt>+ROmqBqofW(b{7IpwW(<>U0*!W7{Pb22 z6=FFHW8^Q>ZQ!SF00l+mCAAWdrMbkk#G$N^gHchbySR;GG~>=rw4Q|F-z*Uh~Tcrs=@Lg+u(PE9oAAv&Vm{%Ge9!=LhG~CByirdmYwJlz zV(?cuBV5x54AbN z4f&!a#Ta{1CCuRxvRn=l6%FUB04^zg9@Cg=AzcjozzDI5ju;RmeF`LovClc?TT7ZK zVtkPIMnnVbbnY>5B@};5NU|2J1K?yrMn6XaHCMF`rUVB&5o+`3Lf~TD6K^hz0o3Y| zEFC^jH9xB1k2v=s2}MY9hT;aW1;ff8?mGxcmYagRoBqFQGbs4IWEU+p^A&|6n*HgDba^t`Z8i$VyEhUkjx-JR3_H?1w0t&ukr(<=iR3^+L$CKP>==#tB z&xRT1vibeXceb0g{^tcqn{DuMoptHRwh!n; z_%y(AA2=yJ5j1}ab7%k#Q6Nt8&m1F!*;<*F*%9YRBo`Zwh#%7H16j@L&dK%8N3gGt zS(Jd@icyxi3U~w>9>EjX({JUC3o*JZjoC zNJk9*Hy+hHoFt7u3V$ct7i`@Y-$!(Y=3y3sXSa3ZXuNgBepOTnP3n z^KJ_ti(G5N+w@YCj$l9tcD_krJ~yReqKBDEZz}Pcj;)MI7gwmqH2C%{ zT?|31GUT2U^;BGS>^V>T7O^0~(nQhP5eyZ&Rgy=fnEsFtTFNWaPM#v`){SBgL!T)_ z-aUjv%}#&8_i;T5g@Rj;Hd?$i*JvbzXya#t^hGhChjXrc=O$N#;+*oq%2}+h8gK_F z9qWGUJ|AbtXcqvF9>c$hs`~2{tE^*hrGF^TTKZ~JuffLF;;bmG68NBdrxu}TxN%hvH)1Ef4K1f-<5wFp)n-|Z(=S_T-N*mi$Tm?8vP55 z^GNE5d$E|09Ff1g5O=a;(->8gdYtwGAwJ?J>d4Km1*JAs(PpzT_fw?tcbF~rL3`eC zrbG|K5Fq#XhmS|FpS2Y_vP|Vcz}ysyySd5F&3YbX*97~wCl69x5tHXVXsMu=YZ*bEv2@cm!B@}Xoxo(Avbq-CyZ1{H5$jiDh=0!yo44P{Hb&xikJ%a!ghUm55xv za86+mS#myuuzmMbGVb#HV3XI~qto$-H^P5ZP&mhLBxjej-mHqw2yVTj`6}Bu5Paea z9@@J$O(a??|M|3;G{Up)V#l%a3`ZWMdHLQ7`L1v78pzm>!`wT;6h10iOOrkPJhq#a z4GBlZINPXa2Vf0ZUPRj~Fb52Tu1lEaopX|+HTPJGZGW{ha;EOHW-A_Ye97*u7;aoY zT_H=J9t5{_`4;djgVBInt1gUvrsLsN*Z10(N;elkyh2jP zO_)L_LziA^OWxoDK30#;-Mz2pUffg#0E7ZDWMyVDFfuSQF)}fe&ubiiCm?a>kHW$M z1uEHx{`R3~`_Rii>~9}>whz7RLx20AXZz3#aTL_RLd5>`p=bNh%RcnC4|=u_z3fAO z`_Qv}aJ>)(f&v=oj~GX27f5EFZ}~pi7;6fyafYl3%_I}Fpo-YoNNomug-oLLI_b1oU|K_ z_KWUWH&=G|KGGY4hJp$N$Oa4s9|l9|A7Y9niSaN>?5}PtNlIrOtUs|r<=xQS`krXm zqA7?f@ba`IkSkb1si6jeV+9f(mb7ZI(YMZoEmtYs-B)bVDt|WG5E{hB6J)I9^O@jz zZ55V+;&-ljzk!q^e7+#zwnW-T&d@GH7E3Zm1PS_vJf4mfFFEQF<-$l* zu#3fE<${t@tb&Nja$3g`aTDA2Xjp+t^K@p-Q8G_4*oS5_IQcm=oz77`SJrSf*7-TT z3i3$}BY60vh$;p7Lz8|$lW;?YkdN4}(F{2d6D4HUqJJoPW$Sk9kp7BR)#t4`A3G`f zcK3a1XTsEMXyt|#qeCl4cZOC+%tmL1nns&_bWx0m?jW?$_m9)DvhSwjqH6G1g39`z zv|JZslzvCZw+GkpLxBj5k?7!;$VS4SFxgn4h<&$`WTT^aR3F*KDzLW7qHTjE!?eWQ;*qgDHhVv?#gQQZ9e`GS>1eM5p_hX%?GdC3knm zC{$2Sl&T#S$r(LPIg)uzSV3cIOmOjBz-y_YDfQD-!}3(qpER`u9AtEELqQ$AKy2Z4 zyFb+z9Sw>^#$hclKh<}yFw10#3)2lMZc=t=OZef^)C~5WW z=SYpzMw1xQ5$qf@s*H;u;cf2yf=*?Oh*V7sLl~0gK2wT^u)WHN>qGI2l;n7hyLIj# zL!<~XNISwEeWw@x$1^MxV;{AHjk#%Kk;=tg+woVI(s;Mhace*;70Uh{H&i7`u#m@a zu#^7*41Wua+GLfiqV_WKuVdP)VRj<5tB*cEq_0=G4UL3D8Fr!-XUh>*k0?;dQcmlL zB>7&2nKT)Hj0SR7a&#_l%JHswd#Uh@LA%?ZXn&P`v=oVuJd$NgTKcCQnru#o#4&so z9du|sU*mgKwCVgh6n?*bm1)45^hYUVkS#Ri5I)_WNE<;ycvuHD3P#UJ3mTgV7P&=t zlr+`6QWF@$P&f)(hwy0COMNs&XGi~}Lv}klk1EW@kCt+nIL09@lfD8bf9-s_y+5=^ zy6`&bhxB*4d!0^SwYMt?fq$uI@O)!jpWVf*=y=j`)YT~)Lxj~Qo)vjSAwz`KC!Q5~LLozh z)hC`6dA5)tf|H2@O@Bj#)hC|SjD?LI1joiA%qz`0nxFxh%n2Hh0!;9L024eIfB+_V zK&G6a0R{6!JiPyDb@t#7>-1*3x>DB!4M|k^#BA5)PdSPQdtUN;5<);S%43WAQJ=(f=y-w#ego;fz@CN z0a*sYms9k%iVo;Scwhw9&b|v#%5O;tLl;0W z9Qfi-6ncSeg@3{S%S?lSXjNg2d!T@sv0#h^WQ>JiEFcURECdV~EMYJlkOVk*(4Ydb z$Up!ZsGu~UfB^+WI3N;$07*av_5j5|02*+BctF7*4pbn42jl?_6d(a{;9wi@00kZl z2Mrhi0g`|Q7yy6+!~+Q&AOkpp3Ooo72q5NatWCOX!GFEHFyiD2&K$$2!kKdw)fbK9 zBgzD#s?#^DQ=;uV+Yihgx`6^Jcp!m;2V#i>HUJ?JQ1GCFrGQL;0KGE;2mnC?3;E5Ct%h00ta1*anCO4i@l$b1Xa{*Yx7K|@V(7oJzP z_}mf`+Xoq6SKo$0b*6=kg)c9rnwuW1kdYMWsJZK$g;g3$rWIk*=qc(bq3e`UNvKBU z;R(448CMIQgf9bKNmKf%KPX?SL05+uQ+5YYuRBOaw30bZ8NHV`K4q*SM38Yx=cr8S zs(|HM@4p|H?G%hdMVxr%WS*dTGZn?=kr&- zD#Z|tthSUzZUxO~qw+!;*^0(+3qz6dtY&m(hHgrwNn|8*ng~+nv4(E&H9jW7kbm*? z*55;GBiZmZPDxTi9!2spVo)ialzoX}`w7tr__G=n(@{YW8w2s_yq+iZ z49(6UsnNxf{!FK;zu}EXVlPofMSm?#B_(6n=(~|`w}>+0D5Gzsq$bV(v zXmrM=w2}1YHs)d7zP;3nZhb*hxo=MCq-Y(}4m~A%*Gy}!GGX>p`p0avxv40dJSLxv zO2{@JqI#U_`>1|}g+ym^p?}*}WLm=8lVv={w%TsrDq}oNz1InqGUG6asplWX|C`rR z#yWaGLCCq>mW;``%xvz)rdpCD(JFh^BCQjXaT#ONF~(72bP$s<3>wrOz3gMy{8f8p!8HNcFh?!ZCDCBZYCa>h()JlS|NQ1{1FT@zBpnn)6(d?Xe%G|bf zgHRq(`dw;F%k(VV9@d5m{vayICXOzISya$1CFgz}eC8Dky)<8!HzD=Y;VP;r>3&pb-9#{4KW@&nbn!S@lVqA- z9P9PEcsMKS9*yo^_Q#--rFV1fttU2N+?|@1(vBOWDthX3}2 zNXGGS@*OmU#FLCFG=wA3bTVR6-Yt#qXhV&qb#CrQ#!~wfydfpygNuw1>SK*35#UbEB5djO)jjdrVA>lN)M}ckwW(_`vGmJ1o$)zG}40O}v5L&cW zguM{OO@G+<&j=gG!f4?#C&GnAf;}wGhWoKtu+bL6PAD6Ml3jcA>!%f(wHg1SHkQHi zSf~nA8m}TF%+Mk<*}6~p?M{lvBSX26*Ptj!lJK+HHq57Pv*ggbhW&N+TN$K!X$f^B zIU_@==B-8umUh~%w6T<@lrp0CByOWX`(rT+(SJ-hADP&%gi*RBf+o2lSw3!WilJxB z2pyJ}`-qy@LPyHkXnIFFY8u~x)PFYW<&6%WjW0i&?cZjeI(oI%Caw^noK0-zgA~I+ z?u#WMPFjrA(n{rukmQ&vT+^aCWTGUR*w)~)ThMWojY8Cjs$o*bQ=Pbo%f{PmYHB9r zF@L0tdiu#mQgV{#$Zr2HiWqH6ohaj$8pTuW`%Dr#+}k%J4W9pG8w36~L+1T$eoqliodBTa1aUf)j<>BnaW6C0a{~Suj zWL(d?DtCp-XeTl*LN;RvD?{km6&^DRM}NSvM<=@47?10eF|g#$p`CYN3oCi7_sbFva`d2;&>Ool)G&`WYNSMw~E451#CJkn9+D>=^fYr7RgN z+b~nrI!WLN=V|;}NH=^sPVG0GTNK5kkV5^qTF=Lr4^~VVA<^*&Pboqk7lXE;+kco0 z!!lTOqk)X2T=zt7G<7t!3|fy$q+}&|GKOH>For|MW^;TxB$G&KpCT{`>eYA{A)+Cc zA+jTmhX#$D2~tL}G1L(`D;=$SnJYZHnU6ibr9f&c!bULsmFasssg2}pjED|q7N&?8 zOwzO?4f=(3_EnKyJq*qav$GH>7k^<-$0pCW1gR8dA)?$|)scxD#=< zIP{y6^Ve1t*{TXh2_w}1l0!#MZmF1&WWD?0$}B7|-7u!g&{gXGvwvr6mqkno zq~kP_DC7{)Afd>KZwt}*1SDlrGb`l2DQqR0br9-8L|HM)2en)&nHkBXPFH)8T5(CeCkF8oEscfvsPJ0jSNnq&nBfNFMfBU zXu`#rdqFJv>pvFo?iEKtzla6+3`dM$-W zD4`vw;&}EXr#NN|vW@TxQO}a5de+kn9@_1kMpsquk58f>vb#^-Uwd0B{7`*-M8Z;XNXvhiAx{p%DY^6p2XF%SdCAq^GxL8A)OdhSwIB@f5IzX4#f0 zIdhDc)KEFpBbK};W-|F` z6$=l6*uNsl(e$5~2akW4(dFC8mCGMHrwI$Mvx%b^5=M2#K}fLR5X|K>=5OqEzgnQr zno$(Bqntr9R$s!JN11BPm}|z`+gR-jYWwHaj8>yj{UD?I(Vu@Bkx`Y~+RfwUuy_0I zr@=3M<|lzR%qqfWY7u6fOf%YLy)G=xn5UO!tTf~1AOg)8ysKzNqdZD98gm&^&CC z%&v^eOfJ}#+4g^>%3O9yrsk}IOvx}$hP1UF%o+@~8VrQNhPD}9DvZHq6sFGGj6`il zt*iRgHs|d%H2-H98)L?&jf6R$W5ySb88^plRBp{Us-}X*jHX3u>MKifN7}y>W+`K! zP{Ne*5Gr?1F%|m9RmjIf$T%Yzqek6{je!GAY>+-KgGD<_LY!Jfp{Tp3ef2yPk!gg! zbY^^{L=5kyUZl}Y8e#WaI<{}^{Z^CMgx1R;XyIxZwT5R^bCAfL`KyzU6&HULBw?9% z;~bvaBrLTd9B38qB&!pHW3H3xs4A_FuA)&m=x9)j!Su6SU2fguDP&ZB}2&(Sr#6xl7nd_b*ivWV?H75EG>gdV`r5KnlO_vlVN@Au*#hk zjTq*1Oz)$2reoBhfIp?wx%7Wnu|nS?tc+Ilsn%#wD@!ZWxHzlxg&VpVfBoK9TiMEJ z*1DoI`fe3o%ksC4M{PUaGetD}`R&sv*>!%r1;5HRWmU!+rNQHM@<;Sqst1=+dp*7+ zoyvDewcn#Es*}kkG|f;I-(gVM?kV9Ct_PR#T*f?6m;G^>a?fTaJRpCb>hr{v`2OZP zmaFP%!M4l$yfUuw@F}DDf=qd8KBkOC&il6?-5I5M*&oWOqAe$8MkYoUYfXA@6Fzh$ zWsu+{-g3o$1Wh!I9FbB9RYbKP1{p7lD~Z%H#*3p=HrkI{NLB zX8G8&KM)O#GD4Nq89COWKfx_2ltP(hP!hD4rspIDUnYZ*Yi)|L3`CzmT2*%B{4Bz9 z0u@Y`O>7ZXLEx)@E^Us`|FMH@oKky37?3Qs}G zUW+Oa4ZVa)DJJYFl!1CAl;)4PZn1?TGelBx^igg>4kY&yHd2um1=kuk{? zD~^;>F2pD)s))QI7eb|YSgyK^s#3)_R@gc-uMg&cYITVDY1R2SW z1Q`kB6oG6ZkTsA`g^e+)RBFQrrUw%C#7v_m^C+<>k-dkpU%H@11eUd;N+FPrk4i0B+#8Txl`xY#pX=zAT-=ZTGVC!6Hm z5IdXssDzMB1+rE;XGQ=3006;56JQ`97!C-b3Buuy2RLulrbn#1pR4)#Gj*y#5$Vi_Xy) zR;-+r6OcE6pm%s{8yvY<%UYX~PhsOE#`12>d&bwux-gGlt;?A-sf2Dl-3g%oYXTM!FG zw%F<@m=-t>=-Wm7lg{FOI&*CWi- z$pK^)^`Uh#{=k}rPB+k($K1F#ndd~`u=yPS`cU=B9%R7yy&Out` zK*vNeu}KKxg2Iq8s3`fvvf9RjO!`Z)!T@3WWAA+?dGTG9ZUu@iQ;(Ivy6&^Gtv6AP zabQ*Y`VQSr6?OV~<&ZQqxn6%E0GKMB(d$3!JL0`2`y>&evD;K>K=OlBU203wNgyfU8Zf-hjHTS|YT=@no z%t>q0V!AU6%J!bYO5RlH7GsW{i{G%ea)%XsN-qCaiu&lnOi+_QdDnjxCF;vjz4V|= z7>V$#%9*IGzWXRrMICbZFQU7aI;%;=wwPg@k?2ar*xHcjBL?&d#MlIAAgT=CmK|{= z%{A-7*2O%>Dvge%4z4Y#4Hq#Tf^gg_)DkV-i`Tht zH_R7I<f4)>PyDtc}Y!j7! z2Ip#w@ga?^qa5-*co^T9lZsO&f+z~?&bW4DXfP;>X#Yer6@8HZv;I>jZXTH?0krPT zg5(@v^mx9zx?)m^dMD_Pl?;eXY0R)VEuM8-Ineu%#n`mLn+y0DG}~~k0U-A-mpWOq zpb6Drflz+{gmCnw{JDR_i7qy+uFzrzj9EU{F1x6pjFR1R zVaowyaG#wHU2apQnZwCmV9?A}V^s9d2%k_E`wiUbX|(H`znFucQ@ZEfBn$fZbuGE( z`w?jn5Nig6=C??kW3#;!VMPv_3b^W&_j#XCTMYdNZ^;pG!&Yw)IA@ zU2(!-$Ds&vWPj}w|4UuKueEF(JiM%601dT+ZF^rW!5Ut(QlWQ{1Hii;~rYeJ#tM=5V zq*?5Xk9MxXdkFt=UP9rXRtjwsGb474$6A#orIeWG2*aQQ*p$G{0ahBkP{~eU~ zjbu<|KoE~%M@XsMs$SC0A4z|D^P*r%UTtrQ^OPQ*1XYMJ;SWBd*yw6!A3!$f1j6fd z^cD)r=TUci&U4tkI1FVQLFXp&wDc=U!kdZ)chF1fEl3~DCjY=Fg2{p1OB#0TygthB zos;$CzX}SaNOXAtMZ5bh`7I_oTUWPq$g&NzgTc3?q4X--O6`U*V_JXe;OP-mkk9Ko zaPe*grob-@tql;ZuT?RBZLc@p5=k=U?Qx*oel>slHK+u78VuTeKQE*u0A%oo*dES5%YSR`fyc1St%h8yUb0tWPhM+!k zArWi0N6^HCiLSa4Xv)PQgeS8st03sxrqVZ1T!`)UOXw(QEudnD0hpf$$Ep%C_PVlf zBIQ=#x0SLEst|wMJ=|yRT`38TWt)0}+7->FX&1bJrnx!&61FGZ74f^jw%os3&+r@- z^qQ-0mz!XR*{oVzdsS%bP#t`!8c@GCNehcaTf_PhTjja_C8jKj9 zV1~B##LHmDDn*JzM%^0?c1@a`Zr68gS|%f!3GlT7CE9=Cj8cN0h!V}ZkuKJKFv`#tyCC8tz=-1l}E2TIBF*E!PX#`#m5zjBSFww%PtF(y8IThG>Ya^C!`Mo4eA9xZ7Db zkMG~9?3jON^G8m5rC@E+Xg9hoNvkD^i0z?|Jxw{>vdt^u&XO3P2--{<+WoFj}=(e+9>4FDTQ$hZ}-vbiJ#< z4Psv@Hgni!vzS*9l}wSZfE>09%Q66*sWw-)!}xy=fS2uVY|w_1#NYy;Y=A3|D9l4} zU(pa$RTH8xK0BeMhTc6|=4tQFpwWr`X~ml+hkGL;rg~*9HxB)Dz4b;Mwrv;U1S1goAH)Jh%SS{8#dBZ?$XlR{}d=aQ-?@J4y?vneV#n>)G0#r z9uT+Z3cXBoM3angz9D39-R&*gQqwiFnma9TJP{;%c1%BqQrJ&!&l8)(kwoEVI)Y<6 z7ZxG$`uKR@ncOybj>dVgPte~F$%+v)VU2&MhbH9tLnre6B2Omhc&ykCcm(m%FGgJ3 z*PSC)!wvHjvVLuBc`nLF2d7$G| zSRym2Ar&3Mk0sD}4iszjk>2t4J)d_Scz*wA+6CWduag-MKR}a)UUYv4 zp=037j4Qv;f}0Ao)Pn+e(*YO&s4M?{Fy*Yd&)?y8_)o(W)5iDIU{f9>m41NX>c8wC z*WN*-!p`nk{ql7KIFG3{M}pM)MJ(wrX!gjV1A*m(&&dCW21htT z&!T&oNNs1=>dQu&t9Z_#Pi_7(Ao`$#!~?U==p#vbd+Q^ozUlA3_x5(a<^A-mAv@nI>=6R+5mOS=vvg&)~WFIvtd57=nK?uzjk=Yjo2o3BjE}3b8anDq+VCdk*kB;hfn7)4oVKlkDhKqA`0nH9mmt0xr;8J|s#>hvIxzSqP(EQOHNRYg=H*)9vC8KHV60VdN&Xav-M@b9UT{02GpdZ^)HjITF*DYd37_Nq+0 zll6BVD6W?G;Z>*@CH1g8AKCztXM=psTwO(h1?! z9OfI~=FhKp*v)3};+$Xp_tRE%>{}`*iLV#Ya{wsHIF}~M-sgzKA2yy=P?~Lq&&OQs zZ!Pwy_R(!+qnOBE9^o7*N_CG^K9}n025a;R=x3OOu5d6#Smuv2nW_gR5KVVHG$wo?dnj1;}xnd#v}cMxEU&ZFYKTNQuQqBpyfe+r@U;jKPTiWmOi zs@oeq0DKwkon1J_U)IpNBLB}4Lfy3;_QKsrk6XtKdt|w+aO{h*yXt#)6({y2@!c*T zq~89Dn*NlBHMjJ{P&G}l=vY-40fz(Qe0NiEtV{Xi={b@T+Y`a8(l+baxc*jS4>B-N z#BT+vJn(;L9*rE?@_|Uo9P|qsX-_{U_qNs{;bJvc#Fo)R{-^?iT(WH z3fx=6=;lxGewa-FU3Bzi9-za#M3Eh8ceD}ZH(f=$XU0++1&_*DQKQk4^+tya$ zGeCw6MdronwjflN^kRqbMW|ec%7^<8(UO^_mruPj)4eA9z*%?myvX}&g+RH7MA%o@ zCT%KRZQY2UUc>l&77PuSEq6Td2x8;}T&wKeP@jA?VGkP+?A+@$eTZpKNN;6DmOg)H z;?aIOl~trh_xPedpVChMDFpIgS;ta~{q=Wwaj{AjvG4!7*I0b0h!d&ZzTsBm+{m6W zEU-^kp{D9s;Pv~<>GACdy|%CP?0zT^_N1vQJte}?QoAd4GExg_%Vpmj7cRE z$Aw%fsW)4;VRm7Z=u=j;v@$?I0t0_Nt4P791-}f$UB=h-Jmm2X%rQ2&YrBPZ$^wE;@*0slfs@eTi=S8HZ z{nt-5*_WJ3l(=VW`X5iiXCeG9UXNEP)@|O6w)1{UB(T3hyH0fvbyvrDU>Wjx&-^1N zHF&-i(_GZI)SM<5y@ANls-J&YIwO@=)eilCK${T#7ZV4+R-MCCEf377-Y!fpPzpBa zib(uo#=cx7fmB;gN59f?-|bdE11!tze?=V>sV`zUYV3oYft*?Kyq!;dPduX&U1&Ce za%(^3KrsgY=Xf`s3c9sLxILYBd@5&a-(tYx-Jglw7vY))l?fvL2i||7^7Dxs2{4{i zS1l+Rm&S@&7Q=Lcs9_cAD&AOe2y~|^nR~}F5_NbU^HF~B%bl>&wWasm4(PRCj*vNm!zDnYu(`v9Z#*BB)uP1*VkrVz0yBqtHCf`E=^e=T9lvEj3dBrGj+c8d$IoAq%pUU)-no~W!T0PMjp9}`|bB~Mm>L?#!uvKZHSNMLP@ICmPw@g zCnN+L(Q0*7w2Y?DTk?>mr(twqLgjM>=~!^&4LhHR<9pBJps=%B2kRmu!R2-U zQ?Q?h(dj%=B*eKC&6NyJYa(ifY)>=&(xCdPx4lr0AKmj1FBZwxhP^S<=_Y{Bq|0(1 zxl4Z_?xGUS!QR?>&+;;Cd7Hn=XuM{>c6hb2NBpWlMe7gV4cn&w~g{5An zjUE;B<9=s;s$+lzgfZB(B3luf8`SneLk~_BEyqb}PSHPCd;@;@Nn*Nxcb8X?A%J8w zTC0k4ZxXydhC5rvv0!L%)}J_%bO&O?_K<&yW1}g$(uMEx&)&DB-f}Mg1@_oE)LUK{ z>~!o?+mqARHZ_2b&L~hbed|V!I}!lDYSy0ZR;!kS=*T2dD+xe&RB1ste_DKkxd*$LmfTRgxYMSD%?H7lyVWxpgml5ID#Fd6fpFTLgd5-8ihou=v< zAXz+8uT1N;-0}*r%;U1HhQBXaO-rxQ$?)SGCxXyWM_y3-i)MyL>O^%e$2YVP#Ci=2 zmQCJ$H@MS0g1)15PlJhkIfU(hS^9t7zHK7D7dW8g0%WOz-lsyL0v!!*z&PwjjUrb4 zv+s8(L(C~;(01df?6A50UW+-3F31S3{z?b?Z`0r5giOcDQw|pOacVeoph^Ms5P76(j|yLNcl$ zM43<^js(qrIulzjXI5`q#9{+!t3$I*oA5`I(Qt zBdIlg>k^%Uh^N>MB(=w^JhM@`6m!#GDCN}iB7@fj(0`IkpvS}&Ivr;oW+Glpnne5sS#J+|*$Gy-r; zjJx?b=13A=Oh;fsZyhhvbpxoK+$*gblYH1 zwQ=6>A2IwTLoDK%TbF_x;#bq^Hf$4zPg-zOU5+h(WDM%`cW|DoBf`DX6dZGV?@PZS zn<4u@YLR6Kw4nYe>Jh+yCQ!=>jULEtAy<|P%61Kj&^_ms4pUQ|)>V>lTO zu+`dSEZmju4sl7P*Xvk!45XLtDz7;hw`fh?ozDslws153ADo#&LP~#E9Z?ymv9R4~ z9QT|^1d?YC#pQojdA9_d>-=mIYwIM0P1h-DMAg6J0VCI6c{s~iuQyX;Fvce?Ag>2! z_@SM(oJ7NgdW#wT@a-E1SsCNcZt86(7Pcb|*J@F@b$jh#*vn-d)D%m;GV_;i#U8zU z(<~&-(*M!eRx;#gg(Wgbaet&I4jiyu2P>NSzp7bTzm|WsImO`FMMX#$m%n)np&J4C z<~JOQ6_pMFTSiRqBL7a2{VA?u5Y9b)*p>Cz_9bnjoY8QfOzjo2$X&t{vgJ!U(aNtb zw{umBAfJeiV&?<*5c&3*Y|`{T`4pD%xd|S>9mCw* z!~+fj{Q`gMLR9MTJQj}>LX+Za*%<(ew7i}j(ZGw5Dr3m(R&YiAlfx5B6^n_ehg>rX z`DYGZ;Z79x!O23oJBf=&ifKbVq%8Gh$?(Q!B-3aBz=#*fLj6gq9-kNY&zoZYohqq^ zQ2!t3;qRiGR!K7n1KD5In%LOBW9)v60Xvz)eeiz((94MqH}w#T{DbPzSAf^=T>Stu zJr===ltUz0PRFyKDyPR44>)UTvMNyziB-N~Rz*C!j;0?c^$;q|w5ClVp*>>lnh=#w zSivwpIS5JM>W3)BptIt@>_`jS&RKJh^*4;&-e>WD(6H_hbkYZQJ_l1D`E6U^2Vb}g zX(oSvAXE_I^ZLW;$K!tx89_ecLXQava{O!%&ZZBNF{aCmsj&cB{VmLLx?Y6?zDej zerfQy=nU~OC4D{L47cXk{%+VxuMaPI^Q|VuSzpOE$;cv9(5S%FfHhv6!w`Ql>(id^ zwZe&(K*Uke6)04*0`i~E{b#0t?;`exJHj-$TZHQ_gp zk-leCagRG1L6^#ri4Ja(TX~}$n9YBtlE3vJ-Uuz;-7CHlhXb2*bwZ%CLX$?1yLaa* zrI`F){&nQ;ECu%Lr|g(}u<*EH=NGJ-2G@t*c%xI;CO*AxFFl?|@rgNaZ_p?LA_(z& zC^N)TRMn6i?ow`}bUeeUsBEIB(mUFqXe@ax*Y}JT=K>%LBVG3mz zBbMo0NJ0IBKxNKLKQhy2ikl|vViCHYYVLV-G6pKpn;t;yyZkKosCz4`nYVbsh;==) ze=r+_UIdfPlZ5HG;9rq-o(td%HO%cR#`|#w6;phuuKj#p9+^$U6xXrsIj0Uem~1<3 zgT{{MtAUtD_Hn%2E%~szKks&po%sJ%83xNCW~*qSH;K94#Ce_98)oX+ ziX)!G`~n%2$Cq@Y-8O?u zN%3gMdh7;!o^$!LyqoiOkdGb@_7UslBljp9|6m0b9%M2;_y~U#bGD9&__pxuJze!e z5~iMDVQxw=`r$E%K8%A{a@nHaZcKqvZL@ty{GplFLj{H-QQcX8h@)Z(<9t!FAdaHz z+)cMV+79lJ@#3j_x))vRke-NE)b@29!Grle!~QNzZH(rp)A5H((H0!z60P=VEHJtB z6GXXIB{J4{)>nV_?MW_}{)W;@#kJo7;APR6%%jTP%tz#5{A}x@BaNPuCT(d;WZ-9C zzEQI!KtQ@+O2e1hTcIuS)s+i$MMeT#D31bF1U_1r<=kaP{1M!_+Q2s-qA)b971!KbLM}Z1B&b`4^w|N-FU=F*Ok|`o1y~t2Q5sRJ`GPVuDpN?(!Ib^Eb4VV40?<1_o{M;iRPXVV<)EORqA(f6v za8Xcq_;i2e9uc~|wd(!#d+A8AcUrOX<9;d`9`nY5Zm&rWQ<&^%s4Wv)KWxaTz!*}53Q?W-v788IF*bC zrB!eDU5R&9T1?cpJKMARyD4JFTl3@`qyy*asJ?%oz7(oEsC6*Tw!9Chbc+nIgLYHV zA)@KH1mf^by3oNj+&)|_Osnx9^7Xg|%)kYnN3i0E@jTD+#T*TF8LJ(|2)>FOioE{` z$HQIPd^|BJ@Z&h!0ho@dJK)1ZQ&*e;r3PsTHQPBEhlxv>8AZ3=ZpVE`SmknN_l;BROrMUjcb6hSOBQ0>{P%yN;{?R#u!Lcw$gsPx?C? z_5>|_^!HOU8UC`bQN55$F4`eaY+a&_q(nO_8{YFPW?bWE#F&}K!`&$QUSf>}U5ag! zrAB>lO{!ll*t~yd`AH0rF~@E$0!tNmoRE(x-ikke&)p9kvNXPk`CL+MH|L({7|X?< z4eU)w^g3AoDQ1)kJNPK|vz(?#s#}&C|B&G?kU!XTl%HgFfFlQi;YIdB08crq#z^P! zutElz41`E$Su^?4@nWO~6UZOO0M_rFJXhQsMbyTUV&C7Si`Kw7ZQo053NBI8#5gvPQSU~BmW=E;s}8Fp{(E4BWW}!?_&`;jF~?F zYTdOvtvImg?%OTPyl20ePW`R7D5w`QrJ|~cI6X0f6KGx&7Rn8l@=gwH!9&)@fa2jo zt*?n8g(yZ}<32@9{Vh+|T=SFCtMmKw>iyS$*5|iu_6?%Af%_$ksx-ARhtjE`FeBUj0PRA5 zN@?7oM$39#)A#xVM!Wq{vM5#QL~5AAHuN?rAU&VhqFv~f)-~jcw&;=ki@PRsF`3!k zdEi#b*bz3_$ywFW$3r~qE&VK-fus2t7;O%nrzQ?3)Ywz5oY8j08E-^Vl<;S6R4Es) z#FG-EybpF;@K_o-`Qc0-xaE_DgeWV2PeJcJG#~GVgkFE7nY;yTWRacW;-E5dtL0D{ zKemQ;#BLG&%sn;N0HC){aO)$dY$V?UnC_diOZc1|mHEw2j2~RDw5J||UVaBvpMsUu zTr;L!*U=Eo+3AZQo0r3g{(u`tt$(WG0~crwW(-c6Oa={FO(U1jS)F`I(PGhmfFt2L zJDbk=wvN_0Y(KPIG`}@Kq<4t7G$B)NPsz*02^$&cn17e0I)G>ND#xJBq=8x>wGxcA3vK z9Tcp|f7rAWWr9uF{jj>k*eOBeu=mT=9<_)_VRJK;KRu#8FY57qW69mAjn2Wadu71M z_t0}ewP&PLL~_}_7>;*5ZGL+mcsVyzA#7XJ^oB!o;eRQPY}qY8R$q937Adek?Oel- zeFH^LTTz#i7ob;lRc?&sD$+YWy1NQK1l;dsV*Z%WVlcj8zCZRv_+qmC3U9N;mpg#i zyB4`-7p0KN1ZYC810hSGZm?#LB>uroU^lA}^fzMcLj63dw?G%t7dKHn^y4 zRZBOgcZWG?)bm7h4SjTfq~FlL5z--_BN5aWfhyhc;MFUyl2qQKn;v~?R3idx2&^3c87e0gl+xpBovbGYB7 zx!=daqtlXh1?c}VefmTa)BM=mDNK|OWl3br*DzA;?$kl*$dLIZ#r z-oljpc7Ts#?VK}+Y}xh2rxj|f(DI4QM`E0bMu+DWl0s^;bFk) zP%HPqV^sdv!{eE)U9`76`3d8-C=!=}$vW=?);TQpow8kuYnp zGI2}?*4R#%g}p6jDm;e0v8=^NGJt=O63+U+zJ_`H_1OfY9-k@?ZEWl zs0`fX0UfT8n0lGWtkDj!&-|?jL0ZXX)|cb2!PyUQf&;UMx`S*p6U<#lY|mxmPg~#T zezeoxI%=wO^@I&Uz@4EISklH4=;u*x!#D_?wZa)CXeLIP8?^{NuE=xOef5XvVwk7S zjE84`{@1}~>g+XzV~h*NrAdxEMj24|z!AK*^4)>&z(wr5v>zcR z&72M?o&^{j!Jmp0yFnhW&GfWfT)GN$9%uA$%&^sw>!9g8eU7i@E zw=cXzY(0LQ4y{L<+XZ^qoQ)}Q#Yy`^BW|E5n(CTybECm7a?`ZIU z`q0_QWy$OjkDTd#z6v%SshARGTA{KxD%_*zg_b*hB1izF`Tap$Ad5F<5!F?Ke=r@h z-ieN5CkoMS{8A;RjhsUx*q-hAzeab>+|;7s0-YSar{V#P4@3BmHaNMVV+33QD8?Q0OHogz4J|vJ9XqsU`BNkYwDq&<} zH~Qv!tL=UVzP^QQqAi5ik8oTH-%Qv}!zJ}HwA z)Sbt`Z}c!T&!~ALyCnG+dg!Hp`!A@f{!0(gXnVfoApm~6sIE$7jt)ZJMJFHk=|?Ih z?z@f@rsP{*)9Ko3S+#fCQ^z+^YqaUEPR(uFnCn;8|dB zS8`1R-IVh%d~xkyo#2wYoZ@BEO52h9?)cVfgqKX<$tLgKZ-kf&6GfGFV0)c#K9C!Q z&scOtqIN{8-@5D{uzWDh{TG5q113-3H=~rOuSow=&~ygmRuJ8nxK|b`+ssJk;H1?9ygkI zi8*@=?t-h(hoYK>-x#`^Oyssa^dIo!;@xa-tyfyC699L)(08%GeTP)S^E^&O?7N!W zUaxpi-%*O9z2)4>;zH_~c~7A}my;--Kd;$Nq1@ISY{nl0 z$KaD21LkaY+Ubss_nq|ccF?k`;rt|JqbxD4=Q&Q-I62dJ0p8G!ng?QaG@(cIaKESj zO2XsU`HaqZ=oB7*@vU*$R61bewR4)o3rn)asDZ)1S<;?YiXuL_FcnW>>+OT4(HMq+ zy2W)0))}#zDmje0sCYJFRQ;Td- z&=*+plt~m?*K}9LQQs3Y%~BY`mfoKjCveoJtH}*Rt0xP8ye57>VkP6WdIn)01Y|zM zB)K}6!Mg3EeaiXK3~H_5I3#WNLQ`#tPNo^}DmiJZwX87(D8sx?p3$0GI+q`lHTmOL zCgmSppHaszd(Gqh?hZlBqq=C5eWYho5uRDGKTTn7GNyUxMG{(!j{^S4w+wGr@sMUXs`1bhgD-5@vuyJeoLwz+{LJL0 zCC|fH=X~;9mJdFztPyvDA=XrcKy76zJZ=&IJ1?4|EG8<;bJDdkI%2n zT}AOoEJDK5aP|AJov^?kWmJ?Q#=coC2>ZG8KQKx!SJ@m?h0rGT{j>ju;R|k5wb`IO zkF@{ccNKpx@nh_-Kd53Ri;qbRibY{^b z@7zW8zEl&LvVmAx?1+F#7}LWufV$rFMJ8Nnjo5r7%vJV1fehaFu;zb}gI#Ut=@|JVen{0qA}Xbom9Ch&HsMro~E z`xxn00zAqF`%f_`I32Fzxa<0N!Ag6PRm7OZxXY)BSgZ`Q<`2-=&AWe%opD%}|HjYT zk$k*A#ijBjS_ zkM&66^lL`;!~)n3l9MX5apQDMxec)|js#*A>?*6H_Vby7>;k}2VJua&Tmf}4%9mnkl}aRk5mCJ*3DA-l&hl@si$@=a{hdL%K1zG9jj7CF+i3kc zGV#Ks$HUeN1`K?*v)dp6SfZL%J-2MZzyj2K#>-4nI~nBmr!; zuUd8EJSQ**`Y^2vSZ9hL$sF1e#{+SUDk{|6{&4V|x=q&H$uVxLV4Gvb8}ds67kJ{u?m6ArAPq+W(= zO%5eMFb~z`pDB6+Pm`H(Yd?IV{5dl>LD=j9%cm!)VEQm9M!!o$MrCJ&TZ+Qa&}`pd zt!NO)7|a?DOPVFJ#54KOu^p$Izr(DmWd`3qB?6Qz(04~S*}GkT_!$PPbm|SI`{6?= z{{oI4H_c%3Sd`RoGcUC2R4`xYgY=whl5WA`FA`LYp0W2LJXE2f)xw6V=5fPkzWTw> z)1i;5m&+@FGQFI|?CpR<5p$qf(W@Hw{8+G-kGo zTZ>@DH9C~YZ`vb&$o2@060s5?6s%lb9>;X^M$E!5%JN1FD_LCIY9yz6&kcQdoI{;= zTn~y>O#-FfO-j!`S~erqf2FWsX49^9zU0fj~5j8%oRN z5>A3p`=qE9=Yi3m^&&RpV!ij@@D;0y%oX$m=4nO=oey7T_N4<|Ec?x`wm`h)IY^Wq zrW@6dY-R;}O%G4Z)uTk;!p>@$IVug=ovI>0< zyE*W?FeE1MAIBglcl3D%vUlOV z`|j1+3uV+g5wfE(_fYwbsnhhDE6hcC1jz7XUPHjo#`e_w zjFql`sfr!gCYy#j`gLAl!KtI){LTnndhY_tDIV%OVL72jglZncgAxlNDI6{O>5#@0 z!F`qNhN$&Fl)_ z=mlJU`K$Z;(8W)D}p8 zDhU4IY>m(t7}r$o_uIuu2hJYBp@SDo0|Z8$1#rVWTS{>jx4w=(rraE#ahGqUwDGZG zmxGGhn`qfla3MB*c=kAM&?#4@^4W;>_ADY!Mi3gG4A&KuLli4V#nhDi@iGY9_v!E(>W&@tXF9N&9nsFn@~0l2T!&C}Nv4Men(VkRHTH)QIvzWdDANl;_EROxqDo z^#$%zRT%%KUWMAN^hF{=3b_`_j%OF(%Iv-mvgsQ<{7HId^{-h9od+Ef{;zIY%oK^m zu{_ex93niBtPU|zBNvSAq%w&o>=$-_ff*ZBn*xSf4B~4oZ|8HtN}-{8?mH^CuD^y=jBTI>&|iUWfQImj{<-QA#!fsUOjtOURC4{qox)Uxv`PKV+ ziXXO=qi`w>FZ)chd3~Do5FJ@oiJWId57NyEBOyoY2hO%;vBlyN{jCjDjW9GHQtrM_ zh`^P7_85)8ltcu%s$Cjapf=%?O`&%q2!(1%!9`Nx88*D6%Dyf`T{-d4&mhVQ=!+HE z4^LE11&SM@FYM3{#^Q~Ca|=dnzP&7D4H}M9D_68?gYxVscYasYD1cQzD&#Qd?!lG3 zovuCz7F>lI@*I#>8Kr-GF%c~TnfSAh#R*BX;kX`tzS}DUYv({aYhF4vfV#YW!&dxaQ zG=Sre;9#Pd52FHYnF&H81mwBAHY>hl|IKm4BDwx?6|7}E<4#2dA~#M)V~1yc+1!pX zmPK(CL)EThoRu-dzpD4+;AGj#vpX7blQQ=y+8&=CoH@aP=x}4agM%@olkad#2XEaWVEx(HbJ(~Y| zZq9Xb*NZf-6|}SXnz4%g9?ehAOZqycA3DAgxNH3}7v<0lurHR%EIPk+&x9#OjW{nP z_om8!y32lXPhvjku9&Fg!k-zzVzBpyRwlVsUfdtK?qqy_*S98Tjq*m{yO8a*3_3{Z z0DoWO9#|K(e4$=)q7v*B)1+;@^2<6t+n{=q>~amPw>pz>t@+Ett%2H00#`^um{OP^ z(9)H`$jP3WguBDQ3^{dixQ_j%Ha6Y;;hu3_7LLtz0|JyYat}R-cSBWfX0+Zo{!Wrg zTeIn1s%NTyd*~bj4HdY%{8kK-_n4F+`z_*#fUln(=Rq@A2IxHwq8(hokh?Tx-s-Q* zI_mi0#H=hdyH#Z*1U?uW^RaM5Vq^ZU^|ty@`%#Y({F2C|8X)AUIjCZPlWTHnb7McS z?m9NjN*S_=_m0NzWcIN=6?TQXuKk2skn(@Z6H4oU6G=Ts(RK#_TFOtYA-QxToYEbT zJo-VBEagxDQ2`>0rLmBSphR)71G;NQi|b=8hDp>id&5Op9_bsk_cFlylB94CL_nkxUO1tM8W`Xc6|@x1{}+ zSUb$Nt=xLB0Vj?ui19#xK3(YkVq-VPFeOS2=T2Z&Wk}*=S|@7LjOgLZdQifro1x-e zO>mW29QpqNtH{f_1~2ycL9(ZVFUPY{!B@+F*M{nrq2jL8=>eP$NJGhUd+4~UKMm7H z2~Bx1dVQPls1v;OA$T{&_$)z52mCvTtY$&a2`&xhY{+l*I+rSxPiE9G><=Zpp>l;n zmH~NW0^0O{f(7nWd3xC-qHm?oK7JNgSOpKg7#-S7tQGw0c=W@68w9^NzOyRh8!1nJ zDG%22l51c6ogeRvKaORzMxWQ>mJZSXKDD)Ixl76!XX3Pp6cdkg-X5$YM;i>xi|dvE zw3>lwOFH1n_a0RWOtwF7yIul2QSZAL##*Y%)?hhij@?7qle1nhHe520=#QMv3qZ>t z;!F@|%MH47Kaom*K!}D!u>2lu30+!$NT)?J3jaBD7=-mR+782s#StuaKwTDs`}BfB z?1v;J(Mt1X!>(*mWif9t=Tfovr8&W>fZ5~6RrvFv^B*5?`7(5#Og zg`gi!V;VN%yKSL4gGLk@hi$+gt1X1yI13eGv;9HS5&OV3S^Y7VH zWWQ;C+E*S@KVOTlQe<^`2Esl*_q~@icjP{MTH@-?GS(O5QI%QwNL}U*ncsuh($Beu z2Yc3oSps|eLudI3?|V{fX;XcF>GFN+K^|wJEXhCIz#II;^R3+4`~+9^4BvWS%ds$@ z;4VMrEpK8SE92WP?Q4Cu>ny4`i<*`i#`)mjCB!76r*03|*anj!KDX*~Ew&{a5-a|dnJK3={{i$<#xi`I} zE!n)^I-s8I5RYiDcI;bj;@w{2SvFzIe#Uhk;MqKACAWt^cDA4MjwiRaP4f$v_q_-6 z7z<~~`qPcQ#m_v)%B;H^t*JCQnW1*QH=TkEK<%&+lU7Kl9Ij%{{+46IAzA?APt< zZTF}gN%vaml#}r6_SA_u24wwnV!w03Dvy^xIe}t(M@bjS;l!#z`GerZuZLQcE%^Pz z;5sB^`3L&*ep3Qy5x03h!8D^AdC~)1#O{;W>V$0 zND@Wj0;Yzd`yo?*ndF;O#aBsgwDGKeuv6$z@V5Bk@Kz1Ke**ZVuYDLp^>KR#z;<&?)p zV>~D06W(3c+mB0Ne(E3RfVJJiANRd>i{&rScF%ZjzP0^-w;%dIevVWo2qV`Re6T>4 z9wICDOK_NvaAEM3y(B9dU)$uAQ-f|Rr~-%D%+@h@m8>~8E>?{9Q5CE$))HPV)l;-2 zoQfTZSmc?EjGPlVQ!ectlr#@KTYJ+B%}QVGM%uw#EC(bTE{>oqntc}50<<{)@(z^4 z>RbQ$res}zQ{wkWBIQ4=M;+ICd#kNa8s0j*57$+iR<2{mMbSTy(`7YUpJ`L>^>qpC zR{+~g>UVbYu=fXwFM98(@S!u7$-_|Ip3bP}GZqtOvf%p> zeZKfm`FujYiD`5GnCu*58M0%>SYu3NHhoz;WZ@k%CSgI~SrG~HF|(85Lu%7$2@wTz z5FImr63f^{UEdE8$HQZ2&3asqJY2*>xlnpJ<7bZq-)f;S1N~E~h845?NL?O!vbIll4?8GCgCuod>F9%K3m~esE><}nQ_$m!6dKYX)k(v;t6ca0*5;V4d zvKt!BXCj?2o2Cej8F{em?x9*Q4!f!+yJUnNglLtek!K>_87YCBZ4x4ghX}9y9VtmR zDLCbQ#x*A2gksIh{V(ecdD}XW@RiHLNxHNyjE|^dmmwWglZ1{|8%+1<5KCSw?Oe zQ^gQv?hb=LSHkHYDNCpzt|P_gV=99csB+BKp&3b1MkY{j2Gl%|TSdKj4oJe8OV9D{rs_@azdfMns&z=zW0T$rxJ z!h+}}xu;Ds(C28AThGgN+#q_vL1JzOv6F5enG=NqaTwp5nr9+Ux{qz$1ae3)5 zo7d%jqb&_Up%hi%7<$%#>V|rMlV$@UPF|h`89UJ+(xtj_o6`k6#bS%Cg-Q2;vwi5a58uj61>qcw#Dh`eEa5_4Fcb6uJie8U< zMX#m;gZ}aLabGxN!%qRCHqqp-GnGM}${ZD7YR+~Gs6RZ&i>$siYDy4>n5Z$fX|z{~ z8XS1$N3O=@KgE6czKcRl(4q>MLtRuoUrT(!df7@v(kg_kI*xN);AJKB~(JJ-DlSo>trPj`_6}5jWN!SIi`!5%t2iT!UAml6 zF-Vs{&-zHJ#A_ObS3B zp*1OHoQ)JcB<3xg8_DtH`j#C{eqS(=e-Ssr!r}F-JihiI}^NRSlL0 z@&><~+0l(cifQ?bcU-?`{wRcumJV_JC7RyOCy{1DI4EJ{qL!=^z)M*pnUA{~zjMNf z1=}XPCsA8}E`YQM&0X0NZ-kI?KgSgM?~hOhd@!!|)rS zGTdh+gHURRPR_vTX0u25OS?RO_Et41E@)g4bw^1iYY|-ooJ<$P zW8@^eR8;x4gJx#+3D!%f9morJ9%(I%i>508)Fz6-;<4AEYI-F@?p@>$83{#5((`mX zs?4I0u5omn6@$2Bx~r{Y6p0YoLZ~5^!@9X6dx$AKt3+S4Q!oc`tzX>n>mXj@rx_)I z)APuG5EBxiWLB4ZnhMx|SZBuA^G+7s`7l?!yIYn=g%xp>M^r8?c@K|Wqo|VK$gJlx zvQjx_)l;|Jl63CLw`qonPEL^A6e+3f?m1FLauX<{n0)8?7pJi**_h(A>VU=nr8BAe zAh~I;{~-sYl}^&>!seA^A3nsAXh7ON+@hp^5;TfmXrSsufjAs*a|{s17=S#P(-Wg1 zE|DmIN%e_lk2)Q7sL@P0U(5cA1Rast5yG?rzXM{v-Lz;yL1*po2=!&eqa{TN#e*Eu;)KOs;+6l%2Wd)b^+DkGtnpD z_#j|bX0qht=AC8Vqz3)&>*i)9DjP)jP*Jp!I66gi4_VVG^H1CGc-jljlx1`e5sd|J zv>@Wig}&Di>(=YK7SF;p>g@Pv^t0!GXHyoy!^wWW^^z-9@N+ga05&R)O14+NYQz_y zbCACoa zq~t5jr~HL5R#|sVT7n$z{TZ|1Ksp@E0#s^!Erl}+zAL_hx9=N5LMD4ddp3%HE)Dwy zX7xyE{v=b(3q`a_cvoAyghfb zk2eiBHcK~%bEJQ?C5z8eFmarJ&wCn862K@AeB@(lAThXcN`kiaGw_9+q0~@+k#}=ow7Qk7{^9t`0yZS$-h}hXYuB)0craf&)x~6JVYs~ zu>6+KW7MpS>NqMu+eYbhfP0bU?Xby;$X(9uAY*t!DwGvt)Y~QKpl5{Uzd0qePDeLV2!41a5@}b^=z*RtUTfZ zXlc3Qs0s7l-pR_0UN3#6N7)=c7Prn#Q_dbSUy7otE=Km+;ZKP8IgLVHpEWOV8R6gU+dPA1J7S{p~}~_Mw;i`{5N7 e1OWIkVq;`wW;8Uj>udxA0WgE`Z@2Jo0pc7y0MSnX diff --git a/src/Nethermind/Chains/worldchain-mainnet.json.zst b/src/Nethermind/Chains/worldchain-mainnet.json.zst index 9d73321b4f8d7761d0ca22863a6c9f5ce59a9924..2c243b391bbe9fbc6a347069c6e71d8c1c98cfa6 100644 GIT binary patch delta 12237 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 NhV?%f)iS6n{{yGe-2MOn delta 12353 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 diff --git a/src/Nethermind/Chains/worldchain-sepolia.json.zst b/src/Nethermind/Chains/worldchain-sepolia.json.zst index bae0f9e58fd70f1c029474d0784c678185a261ac..830f302c5d8828376eb952a2c4899a2e9d5d8b57 100644 GIT binary patch delta 11607 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 AkpKVy delta 11958 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 delta 12364 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 aAmW^n7G>j?KF)V_)j}qL&km(rZ2u4Oo6T7O diff --git a/src/Nethermind/Chains/zora-sepolia.json.zst b/src/Nethermind/Chains/zora-sepolia.json.zst index f8c45644e266f9b92379f691eed4ae60eaedfebc..763641aa82e85fa24a249bfe9205b65f519e757d 100644 GIT binary patch delta 5075 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 V^Akv#@>gbW8UTM>pJVDz`Y*=5hg$#u diff --git a/src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json new file mode 100644 index 00000000000..6452392575c --- /dev/null +++ b/src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://raw.githubusercontent.com/NethermindEth/core-scripts/refs/heads/main/schemas/config.json", + "Init": { + "ChainSpecPath": "chainspec/celo-sep-sepolia.json.zst", + "GenesisHash": "0x1b65cd292881564a4ba788e0822ef07f6dd558c76466ee9d1f07b57065b392f4", + "BaseDbPath": "nethermind_db/celo-sep-sepolia", + "LogFileName": "celo-sep-sepolia.log" + }, + "TxPool": { + "BlobsSupport": "Disabled" + }, + "Sync": { + "FastSync": true, + "SnapSync": true, + "FastSyncCatchUpHeightDelta": "10000000000" + }, + "Discovery": { + "DiscoveryVersion": "V5" + }, + "JsonRpc": { + "Enabled": true, + "Port": 8545, + "EnginePort": 8551 + }, + "Pruning": { + "PruningBoundary": 256 + }, + "Blocks": { + "SecondsPerSlot": 1 + }, + "Merge": { + "Enabled": true + }, + "Optimism": { + "SequencerUrl": "https://forno.celo-sepolia.celo-testnet.org" + } +} \ No newline at end of file From b52db8a89102c1e5c13d33a5c9058298c2de53d5 Mon Sep 17 00:00:00 2001 From: anhnhx131 <106639913+anhnhx131@users.noreply.github.com> Date: Mon, 15 Dec 2025 17:42:04 +0700 Subject: [PATCH 073/255] Adjust JOC testnet Bootnodes according to recent changes (#9940) fix: adjust joc testnet bootnodes --- src/Nethermind/Chains/joc-testnet.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Chains/joc-testnet.json b/src/Nethermind/Chains/joc-testnet.json index e11f1a1546d..be486397105 100644 --- a/src/Nethermind/Chains/joc-testnet.json +++ b/src/Nethermind/Chains/joc-testnet.json @@ -61,8 +61,8 @@ "timestamp": "0x5bfbe6b5" }, "nodes": [ - "enode://c801556bf3e2eb2b4dcb1643febe1e7011096997e8cb41230e5f05c737cc0a3f41a76fb73f3262a8fed9742fbb3df6078eed6733dd3c358554207ec8cacfa999@43.207.64.52:30303", - "enode://8aa6f351eff4bee5d3a6a72ca5820fac65274e9dbd63e13d060682a5228000ab960ff8c177d7cf66b0555859b7eabbc866b71625626a11856e3573bf0592bfed@3.112.196.238:30303" + "enode://f964f94067a851758a3f308831602ca05a374a8a5dcba8ec5f78cde5d31dc809fc0115a84a785bbd1c8024a46d16eee732f4b681cc36cf323e8fab933f92849a@54.248.244.225:30303", + "enode://c68340e7daac1eecc3cdfbfc7c68a80ebf91dbc7f63413dae39b75b2738e63965033cefe452f0b50d8f1d2c5df74eba9905e85c223dda9bc0040fb1c06f35dc5@13.158.174.185:30303" ], "accounts": { "0000000000000000000000000000000000000000": { From 9361e1bff634241ca55bc8024709df7d275f7160 Mon Sep 17 00:00:00 2001 From: anim001k <140460766+anim001k@users.noreply.github.com> Date: Mon, 15 Dec 2025 12:07:44 +0100 Subject: [PATCH 074/255] fix: Remove redundant BlockHeader field reassignments in StatelessExecution (#9928) Update SetupCli.cs --- tools/StatelessExecution/SetupCli.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/StatelessExecution/SetupCli.cs b/tools/StatelessExecution/SetupCli.cs index 631fd0f893f..0ac89458954 100644 --- a/tools/StatelessExecution/SetupCli.cs +++ b/tools/StatelessExecution/SetupCli.cs @@ -110,10 +110,6 @@ private static (Witness witness, Block block, BlockHeader parent) ReadData(strin MixHash = suggestedBlockForRpc.MixHash, BaseFeePerGas = suggestedBlockForRpc.BaseFeePerGas!.Value, WithdrawalsRoot = suggestedBlockForRpc.WithdrawalsRoot, - ParentBeaconBlockRoot = suggestedBlockForRpc.ParentBeaconBlockRoot, - RequestsHash = suggestedBlockForRpc.RequestsHash, - BlobGasUsed = suggestedBlockForRpc.BlobGasUsed, - ExcessBlobGas = suggestedBlockForRpc.ExcessBlobGas, Hash = suggestedBlockForRpc.Hash, }; From 85d9e39a418c9b927148f72944ab98e9efb292d3 Mon Sep 17 00:00:00 2001 From: Desant pivo Date: Mon, 15 Dec 2025 12:10:36 +0100 Subject: [PATCH 075/255] test: add Eip2565Transition check for posdao chain spec (#9920) Add missing Eip2565Transition assertion in Can_load_posdao_with_rewriteBytecode test. The test now verifies that Eip2565Transition is null for posdao.json since it uses the old modexp pricing format (divisor: 20) without modexp2565 transition. Resolves TODO comment about modexp 2565. Co-authored-by: Lukasz Rozmej --- src/Nethermind/Nethermind.AuRa.Test/ChainSpecLoaderTest.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.AuRa.Test/ChainSpecLoaderTest.cs b/src/Nethermind/Nethermind.AuRa.Test/ChainSpecLoaderTest.cs index fa61a1c7971..0de9680b784 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/ChainSpecLoaderTest.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/ChainSpecLoaderTest.cs @@ -76,7 +76,6 @@ public void Can_load_chiado() [Test] public void Can_load_posdao_with_rewriteBytecode() { - // TODO: modexp 2565 string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "Specs/posdao.json"); ChainSpec chainSpec = LoadChainSpec(path); IDictionary> expected = new Dictionary> @@ -93,5 +92,9 @@ public void Can_load_posdao_with_rewriteBytecode() var auraParams = chainSpec.EngineChainSpecParametersProvider.GetChainSpecParameters(); auraParams.RewriteBytecode.Should().BeEquivalentTo(expected); + + // posdao.json uses old modexp pricing format (divisor: 20) without modexp2565 transition + // Therefore Eip2565Transition should be null + chainSpec.Parameters.Eip2565Transition.Should().BeNull(); } } From fb402a4bd2a91f508023d3b14f1212069210b0c5 Mon Sep 17 00:00:00 2001 From: igladun Date: Mon, 15 Dec 2025 13:17:28 +0200 Subject: [PATCH 076/255] Fixes #9606: DebugTracerTests thread synchronization issue (#9875) Fix DebugTracerTests thread synchronization issue (#9606) - Add vmThread.Join() calls after while loops to ensure VM threads complete before TearDown disposes the WorldState scope - Add ExecuteSafe helper method to catch ThreadInterruptedException from aborted threads - Add ThreadJoinTimeout constant to prevent tests from hanging This fixes the 'IWorldState must only be used within scope' exception that occurred when VM threads were still running during test cleanup. --- .../Tracing/DebugTracerTests.cs | 60 +++++++++++++++---- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs index cb484f6aadb..134b2736ee8 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only #if DEBUG +using System; using Nethermind.Blockchain.Tracing.GethStyle; using NUnit.Framework; using System.Threading; @@ -14,6 +15,7 @@ namespace Nethermind.Evm.Test; public class DebugTracerTests : VirtualMachineTestsBase { + private static readonly TimeSpan ThreadJoinTimeout = TimeSpan.FromSeconds(5); private GethLikeTxMemoryTracer GethLikeTxTracer => new(Build.A.Transaction.TestObject, GethTraceOptions.Default); [SetUp] @@ -22,6 +24,18 @@ public override void Setup() base.Setup(); } + private void ExecuteSafe(DebugTracer tracer, byte[] bytecode) + { + try + { + Execute(tracer, bytecode); + } + catch (ThreadInterruptedException) + { + // Expected when test aborts the thread + } + } + [TestCase("0x5b601760005600")] public void Debugger_Halts_Execution_On_Breakpoint(string bytecodeHex) { @@ -39,7 +53,7 @@ public void Debugger_Halts_Execution_On_Breakpoint(string bytecodeHex) tracer.SetBreakPoint(JUMP_OPCODE_PTR_BREAK_POINT); // we set the break point to BREAK_POINT - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); // we run the bytecode for iteration and check how many times we stopped at BREAK_POINT @@ -69,6 +83,7 @@ public void Debugger_Halts_Execution_On_Breakpoint(string bytecodeHex) } + vmThread.Join(ThreadJoinTimeout); Assert.That(TestFailed, Is.False); } @@ -91,7 +106,7 @@ public void Debugger_Halts_Execution_On_Breakpoint_If_Condition_Is_True(string b return state.DataStackHead == 23; }); - Thread vmThread = new(() => Execute(tracer, bytecode)); + Thread vmThread = new(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); // we run the bytecode for iteration and check how many times we stopped at BREAK_POINT @@ -121,6 +136,7 @@ public void Debugger_Halts_Execution_On_Breakpoint_If_Condition_Is_True(string b } } + vmThread.Join(ThreadJoinTimeout); Assert.That(TestFailed, Is.False); } @@ -136,7 +152,7 @@ public void Debugger_Halts_Execution_On_Each_Iteration_using_StepByStepMode(stri IsStepByStepModeOn = true, }; - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); int countBreaks = 0; @@ -152,6 +168,7 @@ public void Debugger_Halts_Execution_On_Each_Iteration_using_StepByStepMode(stri } } + vmThread.Join(ThreadJoinTimeout); countBreaks--; //Pre-run break // we check that it matches the number of opcodes in the bytecode @@ -170,7 +187,7 @@ public void Debugger_Skips_Single_Step_Breakpoints_When_MoveNext_Uses_Override(s IsStepByStepModeOn = true, }; - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); int countBreaks = 0; @@ -186,6 +203,8 @@ public void Debugger_Skips_Single_Step_Breakpoints_When_MoveNext_Uses_Override(s } } + vmThread.Join(ThreadJoinTimeout); + // we check that it matches the number of opcodes in the bytecode Assert.That(countBreaks, Is.EqualTo(1)); } @@ -205,7 +224,7 @@ public void Debugger_Switches_To_Single_Steps_After_First_Breakpoint(string byte tracer.SetBreakPoint(BREAKPOINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); int countBreaks = -1; // not counting the post-run stop @@ -221,6 +240,8 @@ public void Debugger_Switches_To_Single_Steps_After_First_Breakpoint(string byte } } + vmThread.Join(ThreadJoinTimeout); + // we check that it matches the number of opcodes in the bytecode Assert.That(countBreaks, Is.EqualTo(bytecode.Length - BREAKPOINT.pc)); } @@ -239,7 +260,7 @@ public void Debugger_Can_Alter_Program_Counter(string bytecodeHex) tracer.SetBreakPoint(JUMP_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); while (vmThread.IsAlive) @@ -251,6 +272,8 @@ public void Debugger_Can_Alter_Program_Counter(string bytecodeHex) } } + vmThread.Join(ThreadJoinTimeout); + // we check if bytecode execution failed var resultTraces = (tracer.InnerTracer as GethLikeTxMemoryTracer).BuildResult(); Assert.That(resultTraces.Failed, Is.False); @@ -270,7 +293,7 @@ public void Debugger_Can_Alter_Data_Stack(string bytecodeHex) tracer.SetBreakPoint(JUMP_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); while (vmThread.IsAlive) @@ -286,6 +309,8 @@ public void Debugger_Can_Alter_Data_Stack(string bytecodeHex) } } + vmThread.Join(ThreadJoinTimeout); + // we check if bytecode execution failed var resultTraces = (tracer.InnerTracer as GethLikeTxMemoryTracer).BuildResult(); Assert.That(resultTraces.Failed, Is.False); @@ -305,7 +330,7 @@ public void Debugger_Can_Alter_Memory(string bytecodeHex) tracer.SetBreakPoint(MSTORE_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); while (vmThread.IsAlive) @@ -319,6 +344,8 @@ public void Debugger_Can_Alter_Memory(string bytecodeHex) } } + vmThread.Join(ThreadJoinTimeout); + // we check if bytecode execution failed var resultTraces = (tracer.InnerTracer as GethLikeTxMemoryTracer).BuildResult(); Assert.That(resultTraces.ReturnValue[31] == 0, Is.True); @@ -344,7 +371,7 @@ public void Use_Debug_Tracer_To_Check_Assertion_Live(string bytecodeHex) tracer.SetBreakPoint(MSTORE_OPCODE_PTR_BREAK_POINT); tracer.SetBreakPoint(POST_MSTORE_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); long? gasAvailable_pre_MSTORE = null; @@ -362,6 +389,8 @@ public void Use_Debug_Tracer_To_Check_Assertion_Live(string bytecodeHex) tracer.MoveNext(); } } + + vmThread.Join(ThreadJoinTimeout); } [TestCase("ef601700")] @@ -375,7 +404,7 @@ public void Use_Debug_Tracer_To_Check_failure_status(string bytecodeHex) IsStepByStepModeOn = true, }; - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); while (vmThread.IsAlive) @@ -386,6 +415,8 @@ public void Use_Debug_Tracer_To_Check_failure_status(string bytecodeHex) } } + vmThread.Join(ThreadJoinTimeout); + // we check if bytecode execution failed var resultTraces = (tracer.InnerTracer as GethLikeTxMemoryTracer).BuildResult(); Assert.That(resultTraces.Failed, Is.True); @@ -403,7 +434,7 @@ public void Debugger_stops_at_correct_breakpoint_depth(string bytecodeHex) tracer.SetBreakPoint(TARGET_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); bool stoppedAtCorrectBreakpoint = false; @@ -423,6 +454,7 @@ public void Debugger_stops_at_correct_breakpoint_depth(string bytecodeHex) } } + vmThread.Join(ThreadJoinTimeout); Assert.That(stoppedAtCorrectBreakpoint, Is.True); } @@ -437,7 +469,7 @@ public void Debugger_Halts_Execution_When_Global_Condition_Is_Met(string bytecod tracer.SetCondition(state => state.DataStackHead == DATA_STACK_HEIGHT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); bool stoppedAtLeastOneTime = false; @@ -451,6 +483,7 @@ public void Debugger_Halts_Execution_When_Global_Condition_Is_Met(string bytecod } } + vmThread.Join(ThreadJoinTimeout); Assert.That(stoppedAtLeastOneTime, Is.True); } @@ -464,7 +497,7 @@ public void Debugger_Wont_Halt_If_Breakpoint_Is_Unreachable(string bytecodeHex) tracer.SetBreakPoint(TARGET_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + Thread vmThread = new Thread(() => ExecuteSafe(tracer, bytecode)); vmThread.Start(); bool stoppedAtCorrectBreakpoint = false; @@ -477,6 +510,7 @@ public void Debugger_Wont_Halt_If_Breakpoint_Is_Unreachable(string bytecodeHex) } } + vmThread.Join(ThreadJoinTimeout); Assert.That(stoppedAtCorrectBreakpoint, Is.False); } } From b807df26a9ddb67b225420530ab9a23b473dedf5 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Mon, 15 Dec 2025 07:34:54 -0500 Subject: [PATCH 077/255] Faster protocol parsing, add Ethrex (#9935) * Improve protocol parsing, add Ethrex * Add comprehensive unit tests for ProtocolParser (#9936) * Initial plan * Add comprehensive unit tests for ProtocolParser Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> * Refactor hex validation tests to reduce code duplication Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> * Optimize RecognizeClientType with zero-allocation likelihood-ordered regex (#9943) * Initial plan * Optimize RecognizeClientType using compiled regex Co-authored-by: LukaszRozmej <12445221+LukaszRozmej@users.noreply.github.com> * Address code review feedback: optimize regex ordering and group iteration Co-authored-by: LukaszRozmej <12445221+LukaszRozmej@users.noreply.github.com> * Generate regex from enum and use FastEnum for better performance Co-authored-by: LukaszRozmej <12445221+LukaszRozmej@users.noreply.github.com> * Add explanatory comments for regex pattern generation Co-authored-by: LukaszRozmej <12445221+LukaszRozmej@users.noreply.github.com> * Use Regex.EnumerateMatches and ReadOnlySpan to eliminate allocations Co-authored-by: LukaszRozmej <12445221+LukaszRozmej@users.noreply.github.com> * Simplify regex pattern by removing unnecessary named groups Co-authored-by: LukaszRozmej <12445221+LukaszRozmej@users.noreply.github.com> * Rename to _clientTypeRegex and optimize regex order by likelihood Co-authored-by: LukaszRozmej <12445221+LukaszRozmej@users.noreply.github.com> * Refactor to use Except for cleaner exclusion logic Co-authored-by: LukaszRozmej <12445221+LukaszRozmej@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: LukaszRozmej <12445221+LukaszRozmej@users.noreply.github.com> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> Co-authored-by: LukaszRozmej <12445221+LukaszRozmej@users.noreply.github.com> --- .../P2P/Protocol.cs | 81 ++--- .../P2P/ProtocolParser.cs | 84 +++++ .../Model/CapabilityConverter.cs | 29 +- .../Nethermind.Network.Stats/Model/Node.cs | 97 +++--- .../Model/NodeClientType.cs | 17 +- .../P2P/ProtocolParserTests.cs | 329 ++++++++++++++++++ .../P2P/Messages/HelloMessageSerializer.cs | 9 +- src/Nethermind/Nethermind.Runner/NLog.config | 2 +- 8 files changed, 542 insertions(+), 106 deletions(-) create mode 100644 src/Nethermind/Nethermind.Network.Contract/P2P/ProtocolParser.cs create mode 100644 src/Nethermind/Nethermind.Network.Test/P2P/ProtocolParserTests.cs diff --git a/src/Nethermind/Nethermind.Network.Contract/P2P/Protocol.cs b/src/Nethermind/Nethermind.Network.Contract/P2P/Protocol.cs index 4175cc638a8..42ed5fd4d50 100644 --- a/src/Nethermind/Nethermind.Network.Contract/P2P/Protocol.cs +++ b/src/Nethermind/Nethermind.Network.Contract/P2P/Protocol.cs @@ -1,45 +1,46 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -namespace Nethermind.Network.Contract.P2P +using System; + +namespace Nethermind.Network.Contract.P2P; + +public static class Protocol { - public static class Protocol - { - ///

- /// devp2p Wire - /// - public const string P2P = "p2p"; - /// - /// Ethereum Wire - /// - public const string Eth = "eth"; - /// - /// Ethereum Snap Sync - /// - public const string Snap = "snap"; - /// - /// Node Data - /// - public const string NodeData = "nodedata"; - /// - /// Whisper - /// - public const string Shh = "shh"; - /// - /// Swarm - /// - public const string Bzz = "bzz"; - /// - /// Parity Warp Sync - /// - public const string Par = "par"; - /// - /// Nethermind Data Marketplace - /// - public const string Ndm = "ndm"; - /// - /// Account Abstraction - /// - public const string AA = "aa"; - } + /// + /// devp2p Wire + /// + public const string P2P = "p2p"; + /// + /// Ethereum Wire + /// + public const string Eth = "eth"; + /// + /// Ethereum Snap Sync + /// + public const string Snap = "snap"; + /// + /// Node Data + /// + public const string NodeData = "nodedata"; + /// + /// Whisper + /// + public const string Shh = "shh"; + /// + /// Swarm + /// + public const string Bzz = "bzz"; + /// + /// Parity Warp Sync + /// + public const string Par = "par"; + /// + /// Nethermind Data Marketplace + /// + public const string Ndm = "ndm"; + /// + /// Account Abstraction + /// + public const string AA = "aa"; } diff --git a/src/Nethermind/Nethermind.Network.Contract/P2P/ProtocolParser.cs b/src/Nethermind/Nethermind.Network.Contract/P2P/ProtocolParser.cs new file mode 100644 index 00000000000..a0f185b8082 --- /dev/null +++ b/src/Nethermind/Nethermind.Network.Contract/P2P/ProtocolParser.cs @@ -0,0 +1,84 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Buffers.Binary; +using System.Diagnostics.CodeAnalysis; + +namespace Nethermind.Network.Contract.P2P; + +public static class ProtocolParser +{ + // Packed little-endian keys (b0 | b1<<8 | b2<<16 ...) + private const ushort AA = 0x6161; // "aa" + + private const uint Eth = 0x687465u; // "eth" + private const uint P2p = 0x703270u; // "p2p" + private const uint Shh = 0x686873u; // "shh" + private const uint Bzz = 0x7A7A62u; // "bzz" + private const uint Par = 0x726170u; // "par" + private const uint Ndm = 0x6D646Eu; // "ndm" + + private const uint Snap = 0x70616E73u; // "snap" + private const ulong Nodedata = 0x6174616465646F6Eul; // "nodedata" + + public static bool TryGetProtocolCode(ReadOnlySpan protocolSpan, [NotNullWhen(true)] out string? protocol) + { + protocol = null; + + // Bucket by size first - removes repeated length checks and helps bounds-check elimination. + switch (protocolSpan.Length) + { + case 3: + // Build a 24-bit key - JIT can eliminate bounds checks because Length == 3. + uint key3 = (uint)protocolSpan[0] + | ((uint)protocolSpan[1] << 8) + | ((uint)protocolSpan[2] << 16); + + // Put likely hits first if you know your traffic profile. + switch (key3) + { + case Eth: + protocol = Protocol.Eth; return true; + case P2p: + protocol = Protocol.P2P; return true; + case Shh: + protocol = Protocol.Shh; return true; + case Bzz: + protocol = Protocol.Bzz; return true; + case Par: + protocol = Protocol.Par; return true; + case Ndm: + protocol = Protocol.Ndm; return true; + } + break; + + case 4: + if (BinaryPrimitives.ReadUInt32LittleEndian(protocolSpan) == Snap) + { + protocol = Protocol.Snap; + return true; + } + break; + + case 8: + if (BinaryPrimitives.ReadUInt64LittleEndian(protocolSpan) == Nodedata) + { + protocol = Protocol.NodeData; + return true; + } + break; + + case 2: + // Manual pack is fine too, but BinaryPrimitives is also OK here. + ushort key2 = (ushort)(protocolSpan[0] | (protocolSpan[1] << 8)); + if (key2 == AA) + { + protocol = Protocol.AA; + return true; + } + break; + } + return false; + } +} diff --git a/src/Nethermind/Nethermind.Network.Stats/Model/CapabilityConverter.cs b/src/Nethermind/Nethermind.Network.Stats/Model/CapabilityConverter.cs index f769b62934f..82eacb4a3eb 100644 --- a/src/Nethermind/Nethermind.Network.Stats/Model/CapabilityConverter.cs +++ b/src/Nethermind/Nethermind.Network.Stats/Model/CapabilityConverter.cs @@ -12,6 +12,8 @@ using System.Text.Json.Serialization; using Nethermind.Network.Contract.P2P; +#nullable enable + namespace Nethermind.Stats.Model { public class CapabilityConverter : JsonConverter @@ -20,7 +22,7 @@ public class CapabilityConverter : JsonConverter private const byte SeparatorByte = (byte)'/'; private const int StackAllocThreshold = 256; - public override Capability Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override Capability? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.Null) { @@ -32,7 +34,7 @@ public override Capability Read(ref Utf8JsonReader reader, Type typeToConvert, J ThrowJsonException(); } - if (!TryParseCapability(ref reader, out Capability capability)) + if (!TryParseCapability(ref reader, out Capability? capability)) { ThrowJsonException(); } @@ -93,7 +95,7 @@ private static void WriteToBuffer(Utf8JsonWriter writer, Capability capability, } } - private static bool TryParseCapability(ref Utf8JsonReader reader, out Capability capability) + private static bool TryParseCapability(ref Utf8JsonReader reader, out Capability? capability) { capability = null; @@ -120,27 +122,14 @@ private static bool TryParseCapability(ref Utf8JsonReader reader, out Capability return false; } - string protocolCode = GetProtocolCode(protocolSpan); + if (!Network.Contract.P2P.ProtocolParser.TryGetProtocolCode(protocolSpan, out string? protocolCode)) + { + protocolCode = Encoding.UTF8.GetString(protocolSpan); + } capability = new Capability(protocolCode, version); return true; } - private static string GetProtocolCode(ReadOnlySpan protocolSpan) - { - if (protocolSpan.SequenceEqual("eth"u8)) return Protocol.Eth; - if (protocolSpan.SequenceEqual("snap"u8)) return Protocol.Snap; - if (protocolSpan.SequenceEqual("p2p"u8)) return Protocol.P2P; - if (protocolSpan.SequenceEqual("nodedata"u8)) return Protocol.NodeData; - if (protocolSpan.SequenceEqual("shh"u8)) return Protocol.Shh; - if (protocolSpan.SequenceEqual("bzz"u8)) return Protocol.Bzz; - if (protocolSpan.SequenceEqual("par"u8)) return Protocol.Par; - if (protocolSpan.SequenceEqual("ndm"u8)) return Protocol.Ndm; - if (protocolSpan.SequenceEqual("aa"u8)) return Protocol.AA; - - // Fallback for unknown protocols - return Encoding.UTF8.GetString(protocolSpan); - } - [DoesNotReturn, StackTraceHidden] private static void ThrowJsonException() => throw new JsonException(); } diff --git a/src/Nethermind/Nethermind.Network.Stats/Model/Node.cs b/src/Nethermind/Nethermind.Network.Stats/Model/Node.cs index ebb4fc91bab..24d057d6961 100644 --- a/src/Nethermind/Nethermind.Network.Stats/Model/Node.cs +++ b/src/Nethermind/Nethermind.Network.Stats/Model/Node.cs @@ -2,7 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Linq; using System.Net; +using System.Text.RegularExpressions; +using FastEnumUtility; using Nethermind.Config; using Nethermind.Core.Crypto; @@ -193,56 +196,66 @@ public bool Equals(Node other) return !(a == b); } + // Dynamically generates regex pattern from NodeClientType enum values (excluding Unknown). + // Pattern structure: (ClientName|OtherClient|...) + // Ordered by likelihood first, with longer names before potential substrings to prevent conflicts. + private static readonly Regex _clientTypeRegex = new( + string.Join("|", + // Most common clients (ordered by likelihood) + new[] + { + nameof(NodeClientType.Geth), + nameof(NodeClientType.Nethermind), + nameof(NodeClientType.Reth), + nameof(NodeClientType.Besu), + nameof(NodeClientType.Erigon), + nameof(NodeClientType.Nimbus), + nameof(NodeClientType.Ethrex), + nameof(NodeClientType.EthereumJS), + nameof(NodeClientType.OpenEthereum), + nameof(NodeClientType.Parity), + } + .Concat( + // Less common clients (ordered by length to prevent substring conflicts) + FastEnum.GetNames() + .Except(new[] + { + nameof(NodeClientType.Unknown), + nameof(NodeClientType.Geth), + nameof(NodeClientType.Nethermind), + nameof(NodeClientType.Reth), + nameof(NodeClientType.Besu), + nameof(NodeClientType.Erigon), + nameof(NodeClientType.Nimbus), + nameof(NodeClientType.Ethrex), + nameof(NodeClientType.EthereumJS), + nameof(NodeClientType.OpenEthereum), + nameof(NodeClientType.Parity), + }) + .OrderByDescending(name => name.Length))), + RegexOptions.Compiled | RegexOptions.IgnoreCase); + public static NodeClientType RecognizeClientType(string clientId) { if (clientId is null) { return NodeClientType.Unknown; } - else if (clientId.Contains(nameof(NodeClientType.Besu), StringComparison.OrdinalIgnoreCase)) - { - return NodeClientType.Besu; - } - else if (clientId.Contains(nameof(NodeClientType.Geth), StringComparison.OrdinalIgnoreCase)) - { - return NodeClientType.Geth; - } - else if (clientId.Contains(nameof(NodeClientType.Nethermind), StringComparison.OrdinalIgnoreCase)) - { - return NodeClientType.Nethermind; - } - else if (clientId.Contains(nameof(NodeClientType.Erigon), StringComparison.OrdinalIgnoreCase)) - { - return NodeClientType.Erigon; - } - else if (clientId.Contains(nameof(NodeClientType.Reth), StringComparison.OrdinalIgnoreCase)) - { - return NodeClientType.Reth; - } - else if (clientId.Contains(nameof(NodeClientType.Nimbus), StringComparison.OrdinalIgnoreCase)) - { - return NodeClientType.Nimbus; - } - else if (clientId.Contains(nameof(NodeClientType.EthereumJS), StringComparison.OrdinalIgnoreCase)) - { - return NodeClientType.EthereumJS; - } - else if (clientId.Contains(nameof(NodeClientType.Parity), StringComparison.OrdinalIgnoreCase)) - { - return NodeClientType.Parity; - } - else if (clientId.Contains(nameof(NodeClientType.OpenEthereum), StringComparison.OrdinalIgnoreCase)) - { - return NodeClientType.OpenEthereum; - } - else if (clientId.Contains(nameof(NodeClientType.Trinity), StringComparison.OrdinalIgnoreCase)) - { - return NodeClientType.Trinity; - } - else + + // Use EnumerateMatches to avoid allocations - it returns ValueMatch structs + foreach (ValueMatch match in _clientTypeRegex.EnumerateMatches(clientId)) { - return NodeClientType.Unknown; + // Get the matched text as a span to avoid allocations + ReadOnlySpan matchedText = clientId.AsSpan(match.Index, match.Length); + + // Try to parse the matched client name + if (FastEnum.TryParse(matchedText, ignoreCase: true, out NodeClientType clientType)) + { + return clientType; + } } + + return NodeClientType.Unknown; } public static class Format diff --git a/src/Nethermind/Nethermind.Network.Stats/Model/NodeClientType.cs b/src/Nethermind/Nethermind.Network.Stats/Model/NodeClientType.cs index 69c6e652049..ab8df133b21 100644 --- a/src/Nethermind/Nethermind.Network.Stats/Model/NodeClientType.cs +++ b/src/Nethermind/Nethermind.Network.Stats/Model/NodeClientType.cs @@ -15,6 +15,21 @@ public enum NodeClientType Erigon, Reth, Nimbus, - EthereumJS + EthereumJS, + Ethrex, + Bor, + Ronin, + Scraper, + Sentinel, + Grails, + Sonic, + Gait, + Diamond, + NodeCrawler, + Energi, + Opera, + Gwat, + Tempo, + Swarm } } diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/ProtocolParserTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/ProtocolParserTests.cs new file mode 100644 index 00000000000..3baecbc75c8 --- /dev/null +++ b/src/Nethermind/Nethermind.Network.Test/P2P/ProtocolParserTests.cs @@ -0,0 +1,329 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Text; +using Nethermind.Network.Contract.P2P; +using NUnit.Framework; + +namespace Nethermind.Network.Test.P2P; + +[Parallelizable(ParallelScope.Self)] +public class ProtocolParserTests +{ + [Test] + public void TryGetProtocolCode_Eth_ReturnsTrue() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("eth"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.Eth)); + } + + [Test] + public void TryGetProtocolCode_P2p_ReturnsTrue() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("p2p"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.P2P)); + } + + [Test] + public void TryGetProtocolCode_Shh_ReturnsTrue() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("shh"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.Shh)); + } + + [Test] + public void TryGetProtocolCode_Bzz_ReturnsTrue() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("bzz"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.Bzz)); + } + + [Test] + public void TryGetProtocolCode_Par_ReturnsTrue() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("par"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.Par)); + } + + [Test] + public void TryGetProtocolCode_Ndm_ReturnsTrue() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("ndm"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.Ndm)); + } + + [Test] + public void TryGetProtocolCode_Snap_ReturnsTrue() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("snap"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.Snap)); + } + + [Test] + public void TryGetProtocolCode_NodeData_ReturnsTrue() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("nodedata"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.NodeData)); + } + + [Test] + public void TryGetProtocolCode_AA_ReturnsTrue() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("aa"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.AA)); + } + + [Test] + public void TryGetProtocolCode_EmptySpan_ReturnsFalse() + { + ReadOnlySpan emptySpan = ReadOnlySpan.Empty; + bool result = ProtocolParser.TryGetProtocolCode(emptySpan, out string? protocol); + + Assert.That(result, Is.False); + Assert.That(protocol, Is.Null); + } + + [Test] + public void TryGetProtocolCode_UnknownProtocol_ReturnsFalse() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("xyz"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.False); + Assert.That(protocol, Is.Null); + } + + [Test] + public void TryGetProtocolCode_IncorrectLength_ReturnsFalse() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("e"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.False); + Assert.That(protocol, Is.Null); + } + + [Test] + public void TryGetProtocolCode_WrongLength_FiveChars_ReturnsFalse() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("ethxx"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.False); + Assert.That(protocol, Is.Null); + } + + [Test] + public void TryGetProtocolCode_UpperCase_ReturnsFalse() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("ETH"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.False); + Assert.That(protocol, Is.Null); + } + + [Test] + public void TryGetProtocolCode_MixedCase_ReturnsFalse() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("Eth"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.False); + Assert.That(protocol, Is.Null); + } + + [Test] + public void TryGetProtocolCode_ValidatesHexConstants_Eth() + { + byte[] ethBytes = Encoding.UTF8.GetBytes("eth"); + uint ethValue = CalculateThreeByteKey(ethBytes); + + Assert.That(ethValue, Is.EqualTo(0x687465u), "Hex constant for 'eth' should match"); + } + + [Test] + public void TryGetProtocolCode_ValidatesHexConstants_P2p() + { + byte[] p2pBytes = Encoding.UTF8.GetBytes("p2p"); + uint p2pValue = CalculateThreeByteKey(p2pBytes); + + Assert.That(p2pValue, Is.EqualTo(0x703270u), "Hex constant for 'p2p' should match"); + } + + [Test] + public void TryGetProtocolCode_ValidatesHexConstants_Shh() + { + byte[] shhBytes = Encoding.UTF8.GetBytes("shh"); + uint shhValue = CalculateThreeByteKey(shhBytes); + + Assert.That(shhValue, Is.EqualTo(0x686873u), "Hex constant for 'shh' should match"); + } + + [Test] + public void TryGetProtocolCode_ValidatesHexConstants_Bzz() + { + byte[] bzzBytes = Encoding.UTF8.GetBytes("bzz"); + uint bzzValue = CalculateThreeByteKey(bzzBytes); + + Assert.That(bzzValue, Is.EqualTo(0x7A7A62u), "Hex constant for 'bzz' should match"); + } + + [Test] + public void TryGetProtocolCode_ValidatesHexConstants_Par() + { + byte[] parBytes = Encoding.UTF8.GetBytes("par"); + uint parValue = CalculateThreeByteKey(parBytes); + + Assert.That(parValue, Is.EqualTo(0x726170u), "Hex constant for 'par' should match"); + } + + [Test] + public void TryGetProtocolCode_ValidatesHexConstants_Ndm() + { + byte[] ndmBytes = Encoding.UTF8.GetBytes("ndm"); + uint ndmValue = CalculateThreeByteKey(ndmBytes); + + Assert.That(ndmValue, Is.EqualTo(0x6D646Eu), "Hex constant for 'ndm' should match"); + } + + [Test] + public void TryGetProtocolCode_ValidatesHexConstants_Snap() + { + byte[] snapBytes = Encoding.UTF8.GetBytes("snap"); + uint snapValue = BitConverter.ToUInt32(snapBytes, 0); + + Assert.That(snapValue, Is.EqualTo(0x70616E73u), "Hex constant for 'snap' should match"); + } + + [Test] + public void TryGetProtocolCode_ValidatesHexConstants_NodeData() + { + byte[] nodedataBytes = Encoding.UTF8.GetBytes("nodedata"); + ulong nodedataValue = BitConverter.ToUInt64(nodedataBytes, 0); + + Assert.That(nodedataValue, Is.EqualTo(0x6174616465646F6Eul), "Hex constant for 'nodedata' should match"); + } + + [Test] + public void TryGetProtocolCode_ValidatesHexConstants_AA() + { + byte[] aaBytes = Encoding.UTF8.GetBytes("aa"); + ushort aaValue = BitConverter.ToUInt16(aaBytes, 0); + + Assert.That(aaValue, Is.EqualTo(0x6161), "Hex constant for 'aa' should match"); + } + + [Test] + public void TryGetProtocolCode_Length6_ReturnsFalse() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("abcdef"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.False); + Assert.That(protocol, Is.Null); + } + + [Test] + public void TryGetProtocolCode_Length7_ReturnsFalse() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("abcdefg"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.False); + Assert.That(protocol, Is.Null); + } + + [Test] + public void TryGetProtocolCode_Length9_ReturnsFalse() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("abcdefghi"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.False); + Assert.That(protocol, Is.Null); + } + + [Test] + public void TryGetProtocolCode_WithSpan_Eth_ReturnsTrue() + { + ReadOnlySpan protocolSpan = "eth"u8; + bool result = ProtocolParser.TryGetProtocolCode(protocolSpan, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.Eth)); + } + + [Test] + public void TryGetProtocolCode_WithSpan_Snap_ReturnsTrue() + { + ReadOnlySpan protocolSpan = "snap"u8; + bool result = ProtocolParser.TryGetProtocolCode(protocolSpan, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.Snap)); + } + + [Test] + public void TryGetProtocolCode_WithSpan_NodeData_ReturnsTrue() + { + ReadOnlySpan protocolSpan = "nodedata"u8; + bool result = ProtocolParser.TryGetProtocolCode(protocolSpan, out string? protocol); + + Assert.That(result, Is.True); + Assert.That(protocol, Is.EqualTo(Protocol.NodeData)); + } + + [Test] + public void TryGetProtocolCode_PartialMatchShouldFail_EthX() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("ethx"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.False); + Assert.That(protocol, Is.Null); + } + + [Test] + public void TryGetProtocolCode_PartialMatchShouldFail_Sna() + { + byte[] protocolBytes = Encoding.UTF8.GetBytes("sna"); + bool result = ProtocolParser.TryGetProtocolCode(protocolBytes, out string? protocol); + + Assert.That(result, Is.False); + Assert.That(protocol, Is.Null); + } + + private static uint CalculateThreeByteKey(byte[] bytes) + { + return (uint)bytes[0] | ((uint)bytes[1] << 8) | ((uint)bytes[2] << 16); + } +} diff --git a/src/Nethermind/Nethermind.Network/P2P/Messages/HelloMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Messages/HelloMessageSerializer.cs index 7ffa7ff586d..9b7db3f894e 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Messages/HelloMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Messages/HelloMessageSerializer.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Text; using DotNetty.Buffers; using Nethermind.Core.Crypto; using Nethermind.Serialization.Rlp; @@ -59,11 +60,15 @@ public HelloMessage Deserialize(IByteBuffer msgBytes) HelloMessage helloMessage = new(); helloMessage.P2PVersion = rlpStream.DecodeByte(); - helloMessage.ClientId = string.Intern(rlpStream.DecodeString()); + helloMessage.ClientId = rlpStream.DecodeString(); helloMessage.Capabilities = rlpStream.DecodeArrayPoolList(static ctx => { ctx.ReadSequenceLength(); - string protocolCode = string.Intern(ctx.DecodeString()); + ReadOnlySpan protocolSpan = ctx.DecodeByteArraySpan(); + if (!Contract.P2P.ProtocolParser.TryGetProtocolCode(protocolSpan, out string? protocolCode)) + { + protocolCode = Encoding.UTF8.GetString(protocolSpan); + } int version = ctx.DecodeByte(); return new Capability(protocolCode, version); }); diff --git a/src/Nethermind/Nethermind.Runner/NLog.config b/src/Nethermind/Nethermind.Runner/NLog.config index 1dd703dcb03..b78b9a6083f 100644 --- a/src/Nethermind/Nethermind.Runner/NLog.config +++ b/src/Nethermind/Nethermind.Runner/NLog.config @@ -59,7 +59,7 @@ - + From a568396414463b3c970d0fe3a14fac14f0e00712 Mon Sep 17 00:00:00 2001 From: Stavros Vlachakis <89769224+svlachakis@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:45:59 +0200 Subject: [PATCH 078/255] Precompiles names fix (#9944) correct names as per https://eips.ethereum.org/EIPS/eip-2537 --- .../Precompiles/PrecompiledAddresses.cs | 16 +- .../Nethermind.Specs/ReleaseSpec.cs | 364 +++++++++--------- 2 files changed, 197 insertions(+), 183 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Precompiles/PrecompiledAddresses.cs b/src/Nethermind/Nethermind.Core/Precompiles/PrecompiledAddresses.cs index 756bd0bfea1..a01fc358a56 100644 --- a/src/Nethermind/Nethermind.Core/Precompiles/PrecompiledAddresses.cs +++ b/src/Nethermind/Nethermind.Core/Precompiles/PrecompiledAddresses.cs @@ -19,12 +19,16 @@ public static class PrecompiledAddresses public static readonly AddressAsKey Blake2F = Address.FromNumber(0x09); public static readonly AddressAsKey PointEvaluation = Address.FromNumber(0x0a); public static readonly AddressAsKey Bls12G1Add = Address.FromNumber(0x0b); - public static readonly AddressAsKey Bls12G1Mul = Address.FromNumber(0x0c); - public static readonly AddressAsKey Bls12G1MultiExp = Address.FromNumber(0x0d); - public static readonly AddressAsKey Bls12G2Add = Address.FromNumber(0x0e); - public static readonly AddressAsKey Bls12G2Mul = Address.FromNumber(0x0f); - public static readonly AddressAsKey Bls12G2MultiExp = Address.FromNumber(0x10); - public static readonly AddressAsKey Bls12Pairing = Address.FromNumber(0x11); + public static readonly AddressAsKey Bls12G1Msm = Address.FromNumber(0x0c); + public static readonly AddressAsKey Bls12G2Add = Address.FromNumber(0x0d); + public static readonly AddressAsKey Bls12G2Msm = Address.FromNumber(0x0e); + public static readonly AddressAsKey Bls12PairingCheck = Address.FromNumber(0x0f); + public static readonly AddressAsKey Bls12MapFpToG1 = Address.FromNumber(0x10); + public static readonly AddressAsKey Bls12MapFp2ToG2 = Address.FromNumber(0x11); + + // P256Verify (RIP-7212) public static readonly AddressAsKey P256Verify = Address.FromNumber(0x0100); + + // Other precompiles public static readonly AddressAsKey L1Sload = Address.FromNumber(0x10001); } diff --git a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs index 5653b5c548c..e0b3ae60a95 100644 --- a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs @@ -9,198 +9,208 @@ using Nethermind.Core.Specs; using Nethermind.Int256; -namespace Nethermind.Specs +namespace Nethermind.Specs; + +public class ReleaseSpec : IReleaseSpec { - public class ReleaseSpec : IReleaseSpec + public string Name { get; set; } = "Custom"; + public long MaximumExtraDataSize { get; set; } + public long MaxCodeSize { get; set; } + public long MinGasLimit { get; set; } + public long MinHistoryRetentionEpochs { get; set; } + public long GasLimitBoundDivisor { get; set; } + public UInt256 BlockReward { get; set; } + public long DifficultyBombDelay { get; set; } + public long DifficultyBoundDivisor { get; set; } + public long? FixedDifficulty { get; set; } + public int MaximumUncleCount { get; set; } + public bool IsTimeAdjustmentPostOlympic { get; set; } + public bool IsEip2Enabled { get; set; } + public bool IsEip7Enabled { get; set; } + public bool IsEip100Enabled { get; set; } + public bool IsEip140Enabled { get; set; } + public bool IsEip150Enabled { get; set; } + public bool IsEip155Enabled { get; set; } + public bool IsEip158Enabled { get; set; } + public bool IsEip160Enabled { get; set; } + public bool IsEip170Enabled { get; set; } + public bool IsEip196Enabled { get; set; } + public bool IsEip197Enabled { get; set; } + public bool IsEip198Enabled { get; set; } + public bool IsEip211Enabled { get; set; } + public bool IsEip214Enabled { get; set; } + public bool IsEip649Enabled { get; set; } + public bool IsEip658Enabled { get; set; } + public bool IsEip145Enabled { get; set; } + public bool IsEip1014Enabled { get; set; } + public bool IsEip1052Enabled { get; set; } + public bool IsEip1283Enabled { get; set; } + public bool IsEip1234Enabled { get; set; } + public bool IsEip1344Enabled { get; set; } + public bool IsEip2028Enabled { get; set; } + public bool IsEip152Enabled { get; set; } + public bool IsEip1108Enabled { get; set; } + public bool IsEip1884Enabled { get; set; } + public bool IsEip2200Enabled { get; set; } + public bool IsEip2537Enabled { get; set; } + public bool IsEip2565Enabled { get; set; } + public bool IsEip2929Enabled { get; set; } + public bool IsEip2930Enabled { get; set; } + + // used only in testing + public ReleaseSpec Clone() => (ReleaseSpec)MemberwiseClone(); + + public bool IsEip1559Enabled { - public string Name { get; set; } = "Custom"; - public long MaximumExtraDataSize { get; set; } - public long MaxCodeSize { get; set; } - public long MinGasLimit { get; set; } - public long MinHistoryRetentionEpochs { get; set; } - public long GasLimitBoundDivisor { get; set; } - public UInt256 BlockReward { get; set; } - public long DifficultyBombDelay { get; set; } - public long DifficultyBoundDivisor { get; set; } - public long? FixedDifficulty { get; set; } - public int MaximumUncleCount { get; set; } - public bool IsTimeAdjustmentPostOlympic { get; set; } - public bool IsEip2Enabled { get; set; } - public bool IsEip7Enabled { get; set; } - public bool IsEip100Enabled { get; set; } - public bool IsEip140Enabled { get; set; } - public bool IsEip150Enabled { get; set; } - public bool IsEip155Enabled { get; set; } - public bool IsEip158Enabled { get; set; } - public bool IsEip160Enabled { get; set; } - public bool IsEip170Enabled { get; set; } - public bool IsEip196Enabled { get; set; } - public bool IsEip197Enabled { get; set; } - public bool IsEip198Enabled { get; set; } - public bool IsEip211Enabled { get; set; } - public bool IsEip214Enabled { get; set; } - public bool IsEip649Enabled { get; set; } - public bool IsEip658Enabled { get; set; } - public bool IsEip145Enabled { get; set; } - public bool IsEip1014Enabled { get; set; } - public bool IsEip1052Enabled { get; set; } - public bool IsEip1283Enabled { get; set; } - public bool IsEip1234Enabled { get; set; } - public bool IsEip1344Enabled { get; set; } - public bool IsEip2028Enabled { get; set; } - public bool IsEip152Enabled { get; set; } - public bool IsEip1108Enabled { get; set; } - public bool IsEip1884Enabled { get; set; } - public bool IsEip2200Enabled { get; set; } - public bool IsEip2537Enabled { get; set; } - public bool IsEip2565Enabled { get; set; } - public bool IsEip2929Enabled { get; set; } - public bool IsEip2930Enabled { get; set; } - - // used only in testing - public ReleaseSpec Clone() => (ReleaseSpec)MemberwiseClone(); - - public bool IsEip1559Enabled - { - get => _isEip1559Enabled || IsEip4844Enabled; - set => _isEip1559Enabled = value; - } + get => _isEip1559Enabled || IsEip4844Enabled; + set => _isEip1559Enabled = value; + } - public bool IsEip3198Enabled { get; set; } - public bool IsEip3529Enabled { get; set; } - public bool IsEip3607Enabled { get; set; } - public bool IsEip3541Enabled { get; set; } - public bool ValidateChainId { get; set; } - public bool ValidateReceipts { get; set; } - public long Eip1559TransitionBlock { get; set; } - public ulong WithdrawalTimestamp { get; set; } - public ulong Eip4844TransitionTimestamp { get; set; } - public Address FeeCollector { get; set; } - public UInt256? Eip1559BaseFeeMinValue { get; set; } - public UInt256 ForkBaseFee { get; set; } = Eip1559Constants.DefaultForkBaseFee; - public UInt256 BaseFeeMaxChangeDenominator { get; set; } = Eip1559Constants.DefaultBaseFeeMaxChangeDenominator; - public long ElasticityMultiplier { get; set; } = Eip1559Constants.DefaultElasticityMultiplier; - public IBaseFeeCalculator BaseFeeCalculator { get; set; } = new DefaultBaseFeeCalculator(); - public bool IsEip1153Enabled { get; set; } - public bool IsEip3651Enabled { get; set; } - public bool IsEip3855Enabled { get; set; } - public bool IsEip3860Enabled { get; set; } - public bool IsEip4895Enabled { get; set; } - public bool IsEip4844Enabled { get; set; } - public bool IsEip7951Enabled { get; set; } - public bool IsRip7212Enabled { get; set; } - public bool IsOpGraniteEnabled { get; set; } - public bool IsOpHoloceneEnabled { get; set; } - public bool IsOpIsthmusEnabled { get; set; } - public bool IsOpJovianEnabled { get; set; } - public bool IsEip7623Enabled { get; set; } - public bool IsEip7883Enabled { get; set; } - public bool IsEip5656Enabled { get; set; } - public bool IsEip6780Enabled { get; set; } - public bool IsEip4788Enabled { get; set; } - public bool IsEip7702Enabled { get; set; } - public bool IsEip7823Enabled { get; set; } - public bool IsEip4844FeeCollectorEnabled { get; set; } - public bool IsEip7002Enabled { get; set; } - public bool IsEip7251Enabled { get; set; } - public bool IsEip7825Enabled { get; set; } - public bool IsEip7918Enabled { get; set; } - public bool IsEip7934Enabled { get; set; } - public int Eip7934MaxRlpBlockSize { get; set; } - public bool IsEip7907Enabled { get; set; } - - public ulong TargetBlobCount { get; set; } - public ulong MaxBlobCount { get; set; } - public ulong MaxBlobsPerTx => IsEip7594Enabled ? Math.Min(Eip7594Constants.MaxBlobsPerTx, MaxBlobCount) : MaxBlobCount; - public UInt256 BlobBaseFeeUpdateFraction { get; set; } - - - private Address _eip7251ContractAddress; - public Address Eip7251ContractAddress - { - get => IsEip7251Enabled ? _eip7251ContractAddress : null; - set => _eip7251ContractAddress = value; - } - private Address _eip7002ContractAddress; - public Address Eip7002ContractAddress - { - get => IsEip7002Enabled ? _eip7002ContractAddress : null; - set => _eip7002ContractAddress = value; - } + public bool IsEip3198Enabled { get; set; } + public bool IsEip3529Enabled { get; set; } + public bool IsEip3607Enabled { get; set; } + public bool IsEip3541Enabled { get; set; } + public bool ValidateChainId { get; set; } + public bool ValidateReceipts { get; set; } + public long Eip1559TransitionBlock { get; set; } + public ulong WithdrawalTimestamp { get; set; } + public ulong Eip4844TransitionTimestamp { get; set; } + public Address FeeCollector { get; set; } + public UInt256? Eip1559BaseFeeMinValue { get; set; } + public UInt256 ForkBaseFee { get; set; } = Eip1559Constants.DefaultForkBaseFee; + public UInt256 BaseFeeMaxChangeDenominator { get; set; } = Eip1559Constants.DefaultBaseFeeMaxChangeDenominator; + public long ElasticityMultiplier { get; set; } = Eip1559Constants.DefaultElasticityMultiplier; + public IBaseFeeCalculator BaseFeeCalculator { get; set; } = new DefaultBaseFeeCalculator(); + public bool IsEip1153Enabled { get; set; } + public bool IsEip3651Enabled { get; set; } + public bool IsEip3855Enabled { get; set; } + public bool IsEip3860Enabled { get; set; } + public bool IsEip4895Enabled { get; set; } + public bool IsEip4844Enabled { get; set; } + public bool IsEip7951Enabled { get; set; } + public bool IsRip7212Enabled { get; set; } + public bool IsOpGraniteEnabled { get; set; } + public bool IsOpHoloceneEnabled { get; set; } + public bool IsOpIsthmusEnabled { get; set; } + public bool IsOpJovianEnabled { get; set; } + public bool IsEip7623Enabled { get; set; } + public bool IsEip7883Enabled { get; set; } + public bool IsEip5656Enabled { get; set; } + public bool IsEip6780Enabled { get; set; } + public bool IsEip4788Enabled { get; set; } + public bool IsEip7702Enabled { get; set; } + public bool IsEip7823Enabled { get; set; } + public bool IsEip4844FeeCollectorEnabled { get; set; } + public bool IsEip7002Enabled { get; set; } + public bool IsEip7251Enabled { get; set; } + public bool IsEip7825Enabled { get; set; } + public bool IsEip7918Enabled { get; set; } + public bool IsEip7934Enabled { get; set; } + public int Eip7934MaxRlpBlockSize { get; set; } + public bool IsEip7907Enabled { get; set; } + + public ulong TargetBlobCount { get; set; } + public ulong MaxBlobCount { get; set; } + + public ulong MaxBlobsPerTx => + IsEip7594Enabled ? Math.Min(Eip7594Constants.MaxBlobsPerTx, MaxBlobCount) : MaxBlobCount; + + public UInt256 BlobBaseFeeUpdateFraction { get; set; } + + + private Address _eip7251ContractAddress; + + public Address Eip7251ContractAddress + { + get => IsEip7251Enabled ? _eip7251ContractAddress : null; + set => _eip7251ContractAddress = value; + } - private Address _eip4788ContractAddress; - public Address Eip4788ContractAddress - { - get => IsEip4788Enabled ? _eip4788ContractAddress : null; - set => _eip4788ContractAddress = value; - } + private Address _eip7002ContractAddress; - public bool IsEofEnabled { get; set; } + public Address Eip7002ContractAddress + { + get => IsEip7002Enabled ? _eip7002ContractAddress : null; + set => _eip7002ContractAddress = value; + } - public bool IsEip6110Enabled { get; set; } + private Address _eip4788ContractAddress; - private Address _depositContractAddress; - public Address DepositContractAddress - { - get => IsEip6110Enabled ? _depositContractAddress : null; - set => _depositContractAddress = value; - } - public bool IsEip2935Enabled { get; set; } - public bool IsEip7709Enabled { get; set; } + public Address Eip4788ContractAddress + { + get => IsEip4788Enabled ? _eip4788ContractAddress : null; + set => _eip4788ContractAddress = value; + } - private Address _eip2935ContractAddress; - private bool _isEip1559Enabled; + public bool IsEofEnabled { get; set; } - public Address Eip2935ContractAddress - { - get => IsEip2935Enabled ? _eip2935ContractAddress : null; - set => _eip2935ContractAddress = value; - } + public bool IsEip6110Enabled { get; set; } + + private Address _depositContractAddress; + + public Address DepositContractAddress + { + get => IsEip6110Enabled ? _depositContractAddress : null; + set => _depositContractAddress = value; + } + + public bool IsEip2935Enabled { get; set; } + public bool IsEip7709Enabled { get; set; } + + private Address _eip2935ContractAddress; + private bool _isEip1559Enabled; + + public Address Eip2935ContractAddress + { + get => IsEip2935Enabled ? _eip2935ContractAddress : null; + set => _eip2935ContractAddress = value; + } + + public bool IsEip7594Enabled { get; set; } - public bool IsEip7594Enabled { get; set; } + Array? IReleaseSpec.EvmInstructionsNoTrace { get; set; } - Array? IReleaseSpec.EvmInstructionsNoTrace { get; set; } + Array? IReleaseSpec.EvmInstructionsTraced { get; set; } + public bool IsEip7939Enabled { get; set; } + public bool IsRip7728Enabled { get; set; } - Array? IReleaseSpec.EvmInstructionsTraced { get; set; } - public bool IsEip7939Enabled { get; set; } - public bool IsRip7728Enabled { get; set; } + private FrozenSet? _precompiles; + FrozenSet IReleaseSpec.Precompiles => _precompiles ??= BuildPrecompilesCache(); + public long Eip2935RingBufferSize { get; set; } = Eip2935Constants.RingBufferSize; - private FrozenSet? _precompiles; - FrozenSet IReleaseSpec.Precompiles => _precompiles ??= BuildPrecompilesCache(); - public long Eip2935RingBufferSize { get; set; } = Eip2935Constants.RingBufferSize; + public virtual FrozenSet BuildPrecompilesCache() + { + HashSet cache = new(); - public virtual FrozenSet BuildPrecompilesCache() + cache.Add(PrecompiledAddresses.EcRecover); + cache.Add(PrecompiledAddresses.Sha256); + cache.Add(PrecompiledAddresses.Ripemd160); + cache.Add(PrecompiledAddresses.Identity); + + if (IsEip198Enabled) cache.Add(PrecompiledAddresses.ModExp); + if (IsEip196Enabled && IsEip197Enabled) { - HashSet cache = new(); - - cache.Add(PrecompiledAddresses.EcRecover); - cache.Add(PrecompiledAddresses.Sha256); - cache.Add(PrecompiledAddresses.Ripemd160); - cache.Add(PrecompiledAddresses.Identity); - - if (IsEip198Enabled) cache.Add(PrecompiledAddresses.ModExp); - if (IsEip196Enabled && IsEip197Enabled) - { - cache.Add(PrecompiledAddresses.Bn128Add); - cache.Add(PrecompiledAddresses.Bn128Mul); - cache.Add(PrecompiledAddresses.Bn128Pairing); - } - if (IsEip152Enabled) cache.Add(PrecompiledAddresses.Blake2F); - if (IsEip4844Enabled) cache.Add(PrecompiledAddresses.PointEvaluation); - if (IsEip2537Enabled) - { - cache.Add(PrecompiledAddresses.Bls12G1Add); - cache.Add(PrecompiledAddresses.Bls12G1Mul); - cache.Add(PrecompiledAddresses.Bls12G1MultiExp); - cache.Add(PrecompiledAddresses.Bls12G2Add); - cache.Add(PrecompiledAddresses.Bls12G2Mul); - cache.Add(PrecompiledAddresses.Bls12G2MultiExp); - cache.Add(PrecompiledAddresses.Bls12Pairing); - } - if (IsRip7212Enabled || IsEip7951Enabled) cache.Add(PrecompiledAddresses.P256Verify); - if (IsRip7728Enabled) cache.Add(PrecompiledAddresses.L1Sload); - - return cache.ToFrozenSet(); + cache.Add(PrecompiledAddresses.Bn128Add); + cache.Add(PrecompiledAddresses.Bn128Mul); + cache.Add(PrecompiledAddresses.Bn128Pairing); } + + if (IsEip152Enabled) cache.Add(PrecompiledAddresses.Blake2F); + if (IsEip4844Enabled) cache.Add(PrecompiledAddresses.PointEvaluation); + if (IsEip2537Enabled) + { + cache.Add(PrecompiledAddresses.Bls12G1Add); + cache.Add(PrecompiledAddresses.Bls12G1Msm); + cache.Add(PrecompiledAddresses.Bls12G2Add); + cache.Add(PrecompiledAddresses.Bls12G2Msm); + cache.Add(PrecompiledAddresses.Bls12PairingCheck); + cache.Add(PrecompiledAddresses.Bls12MapFpToG1); + cache.Add(PrecompiledAddresses.Bls12MapFp2ToG2); + } + + if (IsRip7212Enabled || IsEip7951Enabled) cache.Add(PrecompiledAddresses.P256Verify); + if (IsRip7728Enabled) cache.Add(PrecompiledAddresses.L1Sload); + + return cache.ToFrozenSet(); } } From f416cfd943e9c57d7039ffe3e77a742588644992 Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Mon, 15 Dec 2025 22:39:29 +0100 Subject: [PATCH 079/255] Update packages (#9907) --- Directory.Packages.props | 46 +- .../Nethermind.Runner/packages.lock.json | 612 +++++++++--------- 2 files changed, 329 insertions(+), 329 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 460430443d4..45b3f496737 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,10 +8,10 @@ - - + + - + @@ -20,14 +20,14 @@ - - + + - + - - + + @@ -37,13 +37,13 @@ - - + + - - - - + + + + @@ -58,7 +58,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -80,13 +80,13 @@ - - - - - - + + + + + + - + \ 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 de5f39f1097..333be533d51 100644 --- a/src/Nethermind/Nethermind.Runner/packages.lock.json +++ b/src/Nethermind/Nethermind.Runner/packages.lock.json @@ -19,9 +19,9 @@ }, "Microsoft.Extensions.FileProviders.Embedded": { "type": "Direct", - "requested": "[10.0.0, )", - "resolved": "10.0.0", - "contentHash": "ECaTMB4NdV9W1es9J6tN0yoXRPUHKMi5+2L7hcVZ5k9zVdxccIx6+vMllwEYcdTaO0mCETEmdH4F0KxCqgnPaw==" + "requested": "[10.0.1, )", + "resolved": "10.0.1", + "contentHash": "PkrDqw6uwm4Y7IucI3PjqwhCeCoHno3hzOeEt0hUrFI+ccYBC0X3NfQbhkFG46TgclnCyUDStmgJzpie9T9ZlQ==" }, "Microsoft.VisualStudio.Azure.Containers.Tools.Targets": { "type": "Direct", @@ -46,9 +46,9 @@ }, "System.CommandLine": { "type": "Direct", - "requested": "[2.0.0, )", - "resolved": "2.0.0", - "contentHash": "Bjklzc5NoxqAGFi7BcGlY2TWAdB06Bq3a5sfRr3ubMRU80Mf98eyq3Y2UgR6xRV0TLznZmfe5T7mUjOunRNcdA==" + "requested": "[2.0.1, )", + "resolved": "2.0.1", + "contentHash": "GLc43eDFq8KbpxIb7UhTwV0vC5CzB0NspJvfFbfhoW4O057xCJXuO18KLpVn9x3JykQn2mRske6+I6JXHwqmDg==" }, "AspNetCore.HealthChecks.UI.Core": { "type": "Transitive", @@ -527,8 +527,8 @@ }, "Polly.Core": { "type": "Transitive", - "resolved": "8.6.4", - "contentHash": "4AWqYnQ2TME0E+Mzovt1Uu+VyvpR84ymUldMcPw7Mbj799Phaag14CKrMtlJGx5jsvYP+S3oR1QmysgmXoD5cw==" + "resolved": "8.6.5", + "contentHash": "t+sUVrIwvo7UmsgHGgOG9F0GDZSRIm47u2ylH17Gvcv1q5hNEwgD5GoBlFyc0kh/pebmPyrAgvGsR/65ZBaXlg==" }, "Portable.BouncyCastle": { "type": "Transitive", @@ -605,8 +605,8 @@ }, "Testably.Abstractions.FileSystem.Interface": { "type": "Transitive", - "resolved": "9.0.0", - "contentHash": "uksk86YlnzAdyfVNu3wICU0X5iXVe9LF7Q3UkngNliHWEvM5gvAlOUr+jmd9JwmbJWISH5+i1vyXE02lEVz7WQ==" + "resolved": "10.0.0", + "contentHash": "tZOXFLGjkh8TxgMgKeEcM2HAlz9DwndGl6TFLo6ISHcszFX3FkuPMrtVbmqVjhooWNXrgJ/a9cH9ym5MZL1LAg==" }, "Tmds.LibC": { "type": "Transitive", @@ -622,20 +622,20 @@ "type": "Project", "dependencies": { "MathNet.Numerics.FSharp": "[5.0.0, )", - "Nethermind.Core": "[1.36.0-unstable, )" + "Nethermind.Core": "[1.37.0-unstable, )" } }, "nethermind.api": { "type": "Project", "dependencies": { - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Facade": "[1.36.0-unstable, )", - "Nethermind.Grpc": "[1.36.0-unstable, )", - "Nethermind.History": "[1.36.0-unstable, )", - "Nethermind.JsonRpc": "[1.36.0-unstable, )", - "Nethermind.Monitoring": "[1.36.0-unstable, )", - "Nethermind.Network": "[1.36.0-unstable, )", - "Nethermind.Sockets": "[1.36.0-unstable, )" + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Facade": "[1.37.0-unstable, )", + "Nethermind.Grpc": "[1.37.0-unstable, )", + "Nethermind.History": "[1.37.0-unstable, )", + "Nethermind.JsonRpc": "[1.37.0-unstable, )", + "Nethermind.Monitoring": "[1.37.0-unstable, )", + "Nethermind.Network": "[1.37.0-unstable, )", + "Nethermind.Sockets": "[1.37.0-unstable, )" } }, "nethermind.blockchain": { @@ -646,70 +646,70 @@ "Microsoft.ClearScript.V8.Native.osx-arm64": "[7.5.0, )", "Microsoft.ClearScript.V8.Native.osx-x64": "[7.5.0, )", "Microsoft.ClearScript.V8.Native.win-x64": "[7.5.0, )", - "Nethermind.Abi": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Db": "[1.36.0-unstable, )", - "Nethermind.Evm": "[1.36.0-unstable, )", - "Nethermind.Evm.Precompiles": "[1.36.0-unstable, )", - "Nethermind.Network.Stats": "[1.36.0-unstable, )", - "Nethermind.Specs": "[1.36.0-unstable, )", - "Nethermind.State": "[1.36.0-unstable, )", - "Nethermind.TxPool": "[1.36.0-unstable, )", - "Polly": "[8.6.4, )" + "Nethermind.Abi": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Db": "[1.37.0-unstable, )", + "Nethermind.Evm": "[1.37.0-unstable, )", + "Nethermind.Evm.Precompiles": "[1.37.0-unstable, )", + "Nethermind.Network.Stats": "[1.37.0-unstable, )", + "Nethermind.Specs": "[1.37.0-unstable, )", + "Nethermind.State": "[1.37.0-unstable, )", + "Nethermind.TxPool": "[1.37.0-unstable, )", + "Polly": "[8.6.5, )" } }, "nethermind.config": { "type": "Project", "dependencies": { - "Nethermind.Core": "[1.36.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", "NonBlocking": "[2.1.2, )", - "System.Configuration.ConfigurationManager": "[10.0.0, )" + "System.Configuration.ConfigurationManager": "[10.0.1, )" } }, "nethermind.consensus": { "type": "Project", "dependencies": { - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Config": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Crypto": "[1.36.0-unstable, )", - "Nethermind.Evm": "[1.36.0-unstable, )", - "Nethermind.TxPool": "[1.36.0-unstable, )" + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Config": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Crypto": "[1.37.0-unstable, )", + "Nethermind.Evm": "[1.37.0-unstable, )", + "Nethermind.TxPool": "[1.37.0-unstable, )" } }, "nethermind.consensus.aura": { "type": "Project", "dependencies": { "BouncyCastle.Cryptography": "[2.6.2, )", - "Nethermind.Abi": "[1.36.0-unstable, )", - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Facade": "[1.36.0-unstable, )", - "Nethermind.Init": "[1.36.0-unstable, )", - "Nethermind.Specs": "[1.36.0-unstable, )", - "Nethermind.Synchronization": "[1.36.0-unstable, )", + "Nethermind.Abi": "[1.37.0-unstable, )", + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Facade": "[1.37.0-unstable, )", + "Nethermind.Init": "[1.37.0-unstable, )", + "Nethermind.Specs": "[1.37.0-unstable, )", + "Nethermind.Synchronization": "[1.37.0-unstable, )", "Nito.Collections.Deque": "[1.2.1, )" } }, "nethermind.consensus.clique": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Consensus": "[1.36.0-unstable, )", - "Nethermind.JsonRpc": "[1.36.0-unstable, )" + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Consensus": "[1.37.0-unstable, )", + "Nethermind.JsonRpc": "[1.37.0-unstable, )" } }, "nethermind.consensus.ethash": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Consensus": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Crypto": "[1.36.0-unstable, )", - "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )", - "Nethermind.Specs": "[1.36.0-unstable, )" + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Consensus": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Crypto": "[1.37.0-unstable, )", + "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )", + "Nethermind.Specs": "[1.37.0-unstable, )" } }, "nethermind.core": { @@ -721,28 +721,28 @@ "Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )", "Microsoft.IdentityModel.JsonWebTokens": "[8.15.0, )", "Nethermind.Crypto.SecP256k1": "[1.5.0, )", - "Nethermind.Logging": "[1.36.0-unstable, )", + "Nethermind.Logging": "[1.37.0-unstable, )", "Nethermind.Numerics.Int256": "[1.3.6, )", "NonBlocking": "[2.1.2, )", - "TestableIO.System.IO.Abstractions.Wrappers": "[22.0.16, )" + "TestableIO.System.IO.Abstractions.Wrappers": "[22.1.0, )" } }, "nethermind.crypto": { "type": "Project", "dependencies": { "BouncyCastle.Cryptography": "[2.6.2, )", - "Ckzg.Bindings": "[2.1.5.1542, )", - "Nethermind.Core": "[1.36.0-unstable, )", + "Ckzg.Bindings": "[2.1.5.1544, )", + "Nethermind.Core": "[1.37.0-unstable, )", "Nethermind.Crypto.Bls": "[1.0.5, )", - "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )", - "System.Security.Cryptography.ProtectedData": "[10.0.0, )" + "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )", + "System.Security.Cryptography.ProtectedData": "[10.0.1, )" } }, "nethermind.db": { "type": "Project", "dependencies": { - "Nethermind.Config": "[1.36.0-unstable, )", - "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )", + "Nethermind.Config": "[1.37.0-unstable, )", + "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )", "NonBlocking": "[2.1.2, )" } }, @@ -750,8 +750,8 @@ "type": "Project", "dependencies": { "ConcurrentHashSet": "[1.3.0, )", - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Db": "[1.36.0-unstable, )", + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Db": "[1.37.0-unstable, )", "NonBlocking": "[2.1.2, )", "RocksDB": "[10.4.2.62659, 10.4.2.62659]" } @@ -759,96 +759,96 @@ "nethermind.db.rpc": { "type": "Project", "dependencies": { - "Nethermind.Db": "[1.36.0-unstable, )", - "Nethermind.JsonRpc": "[1.36.0-unstable, )", - "Nethermind.Serialization.Json": "[1.36.0-unstable, )", - "Nethermind.State": "[1.36.0-unstable, )" + "Nethermind.Db": "[1.37.0-unstable, )", + "Nethermind.JsonRpc": "[1.37.0-unstable, )", + "Nethermind.Serialization.Json": "[1.37.0-unstable, )", + "Nethermind.State": "[1.37.0-unstable, )" } }, "nethermind.era1": { "type": "Project", "dependencies": { "CommunityToolkit.HighPerformance": "[8.4.0, )", - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Consensus": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.JsonRpc": "[1.36.0-unstable, )", - "Nethermind.Merkleization": "[1.36.0-unstable, )", - "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )", - "Nethermind.Serialization.Ssz": "[1.36.0-unstable, )", - "Nethermind.State": "[1.36.0-unstable, )", + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Consensus": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.JsonRpc": "[1.37.0-unstable, )", + "Nethermind.Merkleization": "[1.37.0-unstable, )", + "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )", + "Nethermind.Serialization.Ssz": "[1.37.0-unstable, )", + "Nethermind.State": "[1.37.0-unstable, )", "Snappier": "[1.2.0, )" } }, "nethermind.ethstats": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Init": "[1.36.0-unstable, )", - "Nethermind.JsonRpc": "[1.36.0-unstable, )", - "Nethermind.Logging": "[1.36.0-unstable, )", - "Nethermind.Network": "[1.36.0-unstable, )", + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Init": "[1.37.0-unstable, )", + "Nethermind.JsonRpc": "[1.37.0-unstable, )", + "Nethermind.Logging": "[1.37.0-unstable, )", + "Nethermind.Network": "[1.37.0-unstable, )", "Websocket.Client": "[5.3.0, )" } }, "nethermind.evm": { "type": "Project", "dependencies": { - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Crypto": "[1.36.0-unstable, )", - "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )", - "Nethermind.Specs": "[1.36.0-unstable, )" + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Crypto": "[1.37.0-unstable, )", + "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )", + "Nethermind.Specs": "[1.37.0-unstable, )" } }, "nethermind.evm.precompiles": { "type": "Project", "dependencies": { - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Crypto": "[1.36.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Crypto": "[1.37.0-unstable, )", "Nethermind.Crypto.Bls": "[1.0.5, )", "Nethermind.Crypto.SecP256r1": "[1.0.0-preview.6, )", - "Nethermind.Evm": "[1.36.0-unstable, )", + "Nethermind.Evm": "[1.37.0-unstable, )", "Nethermind.GmpBindings": "[1.0.3, )", - "Nethermind.MclBindings": "[1.0.3, )", - "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )", - "Nethermind.Specs": "[1.36.0-unstable, )" + "Nethermind.MclBindings": "[1.0.4, )", + "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )", + "Nethermind.Specs": "[1.37.0-unstable, )" } }, "nethermind.externalsigner.plugin": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.JsonRpc": "[1.36.0-unstable, )" + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.JsonRpc": "[1.37.0-unstable, )" } }, "nethermind.facade": { "type": "Project", "dependencies": { - "Nethermind.Consensus": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Crypto": "[1.36.0-unstable, )", - "Nethermind.Synchronization": "[1.36.0-unstable, )", + "Nethermind.Consensus": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Crypto": "[1.37.0-unstable, )", + "Nethermind.Synchronization": "[1.37.0-unstable, )", "NonBlocking": "[2.1.2, )" } }, "nethermind.flashbots": { "type": "Project", "dependencies": { - "Nethermind.Merge.Plugin": "[1.36.0-unstable, )" + "Nethermind.Merge.Plugin": "[1.37.0-unstable, )" } }, "nethermind.grpc": { "type": "Project", "dependencies": { - "Google.Protobuf": "[3.33.1, )", - "Google.Protobuf.Tools": "[3.33.1, )", + "Google.Protobuf": "[3.33.2, )", + "Google.Protobuf.Tools": "[3.33.2, )", "Grpc": "[2.46.6, )", - "Nethermind.Config": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Serialization.Json": "[1.36.0-unstable, )" + "Nethermind.Config": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Serialization.Json": "[1.37.0-unstable, )" } }, "nethermind.healthchecks": { @@ -856,75 +856,75 @@ "dependencies": { "AspNetCore.HealthChecks.UI": "[9.0.0, )", "AspNetCore.HealthChecks.UI.InMemory.Storage": "[9.0.0, )", - "KubernetesClient": "[18.0.5, )", - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Merge.Plugin": "[1.36.0-unstable, )" + "KubernetesClient": "[18.0.13, )", + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Merge.Plugin": "[1.37.0-unstable, )" } }, "nethermind.history": { "type": "Project", "dependencies": { - "Nethermind.Consensus": "[1.36.0-unstable, )" + "Nethermind.Consensus": "[1.37.0-unstable, )" } }, "nethermind.hive": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Init": "[1.36.0-unstable, )" + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Init": "[1.37.0-unstable, )" } }, "nethermind.init": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Db.Rocks": "[1.36.0-unstable, )", - "Nethermind.Db.Rpc": "[1.36.0-unstable, )", - "Nethermind.Era1": "[1.36.0-unstable, )", - "Nethermind.Network.Discovery": "[1.36.0-unstable, )", - "Nethermind.Network.Dns": "[1.36.0-unstable, )", - "Nethermind.Network.Enr": "[1.36.0-unstable, )", - "Nethermind.Specs": "[1.36.0-unstable, )" + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Db.Rocks": "[1.37.0-unstable, )", + "Nethermind.Db.Rpc": "[1.37.0-unstable, )", + "Nethermind.Era1": "[1.37.0-unstable, )", + "Nethermind.Network.Discovery": "[1.37.0-unstable, )", + "Nethermind.Network.Dns": "[1.37.0-unstable, )", + "Nethermind.Network.Enr": "[1.37.0-unstable, )", + "Nethermind.Specs": "[1.37.0-unstable, )" } }, "nethermind.init.snapshot": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Init": "[1.36.0-unstable, )" + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Init": "[1.37.0-unstable, )" } }, "nethermind.jsonrpc": { "type": "Project", "dependencies": { - "Nethermind.Abi": "[1.36.0-unstable, )", - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Config": "[1.36.0-unstable, )", - "Nethermind.Consensus": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Crypto": "[1.36.0-unstable, )", - "Nethermind.Evm": "[1.36.0-unstable, )", - "Nethermind.Facade": "[1.36.0-unstable, )", - "Nethermind.Network.Dns": "[1.36.0-unstable, )", - "Nethermind.Sockets": "[1.36.0-unstable, )", - "Nethermind.Synchronization": "[1.36.0-unstable, )", - "Nethermind.Wallet": "[1.36.0-unstable, )" + "Nethermind.Abi": "[1.37.0-unstable, )", + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Config": "[1.37.0-unstable, )", + "Nethermind.Consensus": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Crypto": "[1.37.0-unstable, )", + "Nethermind.Evm": "[1.37.0-unstable, )", + "Nethermind.Facade": "[1.37.0-unstable, )", + "Nethermind.Network.Dns": "[1.37.0-unstable, )", + "Nethermind.Sockets": "[1.37.0-unstable, )", + "Nethermind.Synchronization": "[1.37.0-unstable, )", + "Nethermind.Wallet": "[1.37.0-unstable, )" } }, "nethermind.jsonrpc.tracestore": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Init": "[1.36.0-unstable, )" + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Init": "[1.37.0-unstable, )" } }, "nethermind.keystore": { "type": "Project", "dependencies": { - "Nethermind.Config": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Crypto": "[1.36.0-unstable, )", - "Nethermind.Serialization.Json": "[1.36.0-unstable, )", + "Nethermind.Config": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Crypto": "[1.37.0-unstable, )", + "Nethermind.Serialization.Json": "[1.37.0-unstable, )", "SCrypt": "[2.0.0.2, )" } }, @@ -935,41 +935,41 @@ "type": "Project", "dependencies": { "NLog": "[5.5.1, )", - "Nethermind.Logging": "[1.36.0-unstable, )" + "Nethermind.Logging": "[1.37.0-unstable, )" } }, "nethermind.merge.aura": { "type": "Project", "dependencies": { - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Consensus": "[1.36.0-unstable, )", - "Nethermind.Consensus.AuRa": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Db": "[1.36.0-unstable, )", - "Nethermind.Evm": "[1.36.0-unstable, )", - "Nethermind.Merge.Plugin": "[1.36.0-unstable, )", - "Nethermind.Specs": "[1.36.0-unstable, )", - "Nethermind.State": "[1.36.0-unstable, )" + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Consensus": "[1.37.0-unstable, )", + "Nethermind.Consensus.AuRa": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Db": "[1.37.0-unstable, )", + "Nethermind.Evm": "[1.37.0-unstable, )", + "Nethermind.Merge.Plugin": "[1.37.0-unstable, )", + "Nethermind.Specs": "[1.37.0-unstable, )", + "Nethermind.State": "[1.37.0-unstable, )" } }, "nethermind.merge.plugin": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )" + "Nethermind.Api": "[1.37.0-unstable, )" } }, "nethermind.merkleization": { "type": "Project", "dependencies": { - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Serialization.Ssz": "[1.36.0-unstable, )" + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Serialization.Ssz": "[1.37.0-unstable, )" } }, "nethermind.monitoring": { "type": "Project", "dependencies": { - "Nethermind.Config": "[1.36.0-unstable, )", - "Nethermind.Logging": "[1.36.0-unstable, )", + "Nethermind.Config": "[1.37.0-unstable, )", + "Nethermind.Logging": "[1.37.0-unstable, )", "prometheus-net.AspNetCore": "[8.2.1, )" } }, @@ -977,31 +977,31 @@ "type": "Project", "dependencies": { "Crc32.NET": "[1.2.0, )", - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Config": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Crypto": "[1.36.0-unstable, )", + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Config": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Crypto": "[1.37.0-unstable, )", "Nethermind.DotNetty.Handlers": "[1.0.2.76, )", - "Nethermind.Network.Contract": "[1.36.0-unstable, )", - "Nethermind.Network.Stats": "[1.36.0-unstable, )", - "Nethermind.Synchronization": "[1.36.0-unstable, )", + "Nethermind.Network.Contract": "[1.37.0-unstable, )", + "Nethermind.Network.Stats": "[1.37.0-unstable, )", + "Nethermind.Synchronization": "[1.37.0-unstable, )", "Snappier": "[1.2.0, )" } }, "nethermind.network.contract": { "type": "Project", "dependencies": { - "Nethermind.Config": "[1.36.0-unstable, )" + "Nethermind.Config": "[1.37.0-unstable, )" } }, "nethermind.network.discovery": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Crypto": "[1.36.0-unstable, )", - "Nethermind.Facade": "[1.36.0-unstable, )", - "Nethermind.Network": "[1.36.0-unstable, )", - "Nethermind.Network.Enr": "[1.36.0-unstable, )", + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Crypto": "[1.37.0-unstable, )", + "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, )" } }, @@ -1009,147 +1009,147 @@ "type": "Project", "dependencies": { "DnsClient": "[1.8.0, )", - "Nethermind.Network": "[1.36.0-unstable, )", - "Nethermind.Network.Enr": "[1.36.0-unstable, )" + "Nethermind.Network": "[1.37.0-unstable, )", + "Nethermind.Network.Enr": "[1.37.0-unstable, )" } }, "nethermind.network.enr": { "type": "Project", "dependencies": { - "Nethermind.Crypto": "[1.36.0-unstable, )", - "Nethermind.Network": "[1.36.0-unstable, )" + "Nethermind.Crypto": "[1.37.0-unstable, )", + "Nethermind.Network": "[1.37.0-unstable, )" } }, "nethermind.network.stats": { "type": "Project", "dependencies": { - "Nethermind.Config": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Logging": "[1.36.0-unstable, )", - "Nethermind.Network.Contract": "[1.36.0-unstable, )" + "Nethermind.Config": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Logging": "[1.37.0-unstable, )", + "Nethermind.Network.Contract": "[1.37.0-unstable, )" } }, "nethermind.optimism": { "type": "Project", "dependencies": { - "Google.Protobuf": "[3.33.1, )", - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Consensus": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Init": "[1.36.0-unstable, )", - "Nethermind.JsonRpc": "[1.36.0-unstable, )", + "Google.Protobuf": "[3.33.2, )", + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Consensus": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Init": "[1.37.0-unstable, )", + "Nethermind.JsonRpc": "[1.37.0-unstable, )", "Nethermind.Libp2p": "[1.0.0-preview.45, )", "Nethermind.Libp2p.Protocols.PubsubPeerDiscovery": "[1.0.0-preview.45, )", - "Nethermind.Merge.Plugin": "[1.36.0-unstable, )", + "Nethermind.Merge.Plugin": "[1.37.0-unstable, )", "Snappier": "[1.2.0, )" } }, "nethermind.seq": { "type": "Project", "dependencies": { - "Nethermind.Config": "[1.36.0-unstable, )" + "Nethermind.Config": "[1.37.0-unstable, )" } }, "nethermind.serialization.json": { "type": "Project", "dependencies": { "Microsoft.ClearScript.V8": "[7.5.0, )", - "Nethermind.Core": "[1.36.0-unstable, )" + "Nethermind.Core": "[1.37.0-unstable, )" } }, "nethermind.serialization.rlp": { "type": "Project", "dependencies": { - "Nethermind.Core": "[1.36.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", "Nethermind.DotNetty.Buffers": "[1.0.2.76, )" } }, "nethermind.serialization.ssz": { "type": "Project", "dependencies": { - "Nethermind.Core": "[1.36.0-unstable, )" + "Nethermind.Core": "[1.37.0-unstable, )" } }, "nethermind.shutter": { "type": "Project", "dependencies": { - "Google.Protobuf": "[3.33.1, )", - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Consensus": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Crypto": "[1.36.0-unstable, )", - "Nethermind.Init": "[1.36.0-unstable, )", + "Google.Protobuf": "[3.33.2, )", + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Consensus": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Crypto": "[1.37.0-unstable, )", + "Nethermind.Init": "[1.37.0-unstable, )", "Nethermind.Libp2p": "[1.0.0-preview.45, )", "Nethermind.Libp2p.Protocols.PubsubPeerDiscovery": "[1.0.0-preview.45, )", - "Nethermind.Merge.Plugin": "[1.36.0-unstable, )", - "Nethermind.Merkleization": "[1.36.0-unstable, )", - "Nethermind.Network.Discovery": "[1.36.0-unstable, )", - "Nethermind.Serialization.Ssz": "[1.36.0-unstable, )", - "Nethermind.Specs": "[1.36.0-unstable, )" + "Nethermind.Merge.Plugin": "[1.37.0-unstable, )", + "Nethermind.Merkleization": "[1.37.0-unstable, )", + "Nethermind.Network.Discovery": "[1.37.0-unstable, )", + "Nethermind.Serialization.Ssz": "[1.37.0-unstable, )", + "Nethermind.Specs": "[1.37.0-unstable, )" } }, "nethermind.sockets": { "type": "Project", "dependencies": { - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Logging": "[1.36.0-unstable, )", - "Nethermind.Serialization.Json": "[1.36.0-unstable, )" + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Logging": "[1.37.0-unstable, )", + "Nethermind.Serialization.Json": "[1.37.0-unstable, )" } }, "nethermind.specs": { "type": "Project", "dependencies": { - "Nethermind.Config": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Serialization.Json": "[1.36.0-unstable, )", + "Nethermind.Config": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Serialization.Json": "[1.37.0-unstable, )", "ZstdSharp.Port": "[0.8.6, )" } }, "nethermind.state": { "type": "Project", "dependencies": { - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Db": "[1.36.0-unstable, )", - "Nethermind.Evm": "[1.36.0-unstable, )", - "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )", - "Nethermind.Trie": "[1.36.0-unstable, )" + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Db": "[1.37.0-unstable, )", + "Nethermind.Evm": "[1.37.0-unstable, )", + "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )", + "Nethermind.Trie": "[1.37.0-unstable, )" } }, "nethermind.synchronization": { "type": "Project", "dependencies": { "ConcurrentHashSet": "[1.3.0, )", - "Nethermind.Consensus": "[1.36.0-unstable, )", - "Nethermind.History": "[1.36.0-unstable, )", - "Nethermind.Logging": "[1.36.0-unstable, )", - "Nethermind.Network.Contract": "[1.36.0-unstable, )", - "Nethermind.Trie": "[1.36.0-unstable, )", + "Nethermind.Consensus": "[1.37.0-unstable, )", + "Nethermind.History": "[1.37.0-unstable, )", + "Nethermind.Logging": "[1.37.0-unstable, )", + "Nethermind.Network.Contract": "[1.37.0-unstable, )", + "Nethermind.Trie": "[1.37.0-unstable, )", "NonBlocking": "[2.1.2, )" } }, "nethermind.taiko": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Blockchain": "[1.36.0-unstable, )", - "Nethermind.Consensus": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Evm": "[1.36.0-unstable, )", - "Nethermind.Evm.Precompiles": "[1.36.0-unstable, )", - "Nethermind.Init": "[1.36.0-unstable, )", - "Nethermind.JsonRpc": "[1.36.0-unstable, )", - "Nethermind.Logging": "[1.36.0-unstable, )", - "Nethermind.Merge.Plugin": "[1.36.0-unstable, )", - "Nethermind.Serialization.Json": "[1.36.0-unstable, )" + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Blockchain": "[1.37.0-unstable, )", + "Nethermind.Consensus": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Evm": "[1.37.0-unstable, )", + "Nethermind.Evm.Precompiles": "[1.37.0-unstable, )", + "Nethermind.Init": "[1.37.0-unstable, )", + "Nethermind.JsonRpc": "[1.37.0-unstable, )", + "Nethermind.Logging": "[1.37.0-unstable, )", + "Nethermind.Merge.Plugin": "[1.37.0-unstable, )", + "Nethermind.Serialization.Json": "[1.37.0-unstable, )" } }, "nethermind.trie": { "type": "Project", "dependencies": { - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Db": "[1.36.0-unstable, )", - "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Db": "[1.37.0-unstable, )", + "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )", "NonBlocking": "[2.1.2, )" } }, @@ -1157,39 +1157,39 @@ "type": "Project", "dependencies": { "Collections.Pooled": "[1.0.82, )", - "Nethermind.Config": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Crypto": "[1.36.0-unstable, )", - "Nethermind.Db": "[1.36.0-unstable, )", - "Nethermind.Evm": "[1.36.0-unstable, )", - "Nethermind.Network.Contract": "[1.36.0-unstable, )", - "Nethermind.State": "[1.36.0-unstable, )", + "Nethermind.Config": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Crypto": "[1.37.0-unstable, )", + "Nethermind.Db": "[1.37.0-unstable, )", + "Nethermind.Evm": "[1.37.0-unstable, )", + "Nethermind.Network.Contract": "[1.37.0-unstable, )", + "Nethermind.State": "[1.37.0-unstable, )", "NonBlocking": "[2.1.2, )" } }, "nethermind.upnp.plugin": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", + "Nethermind.Api": "[1.37.0-unstable, )", "Open.NAT.Core": "[2.1.0.5, )" } }, "nethermind.wallet": { "type": "Project", "dependencies": { - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.KeyStore": "[1.36.0-unstable, )", - "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )", - "Nethermind.TxPool": "[1.36.0-unstable, )" + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.KeyStore": "[1.37.0-unstable, )", + "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )", + "Nethermind.TxPool": "[1.37.0-unstable, )" } }, "nethermind.xdc": { "type": "Project", "dependencies": { - "Nethermind.Api": "[1.36.0-unstable, )", - "Nethermind.Consensus": "[1.36.0-unstable, )", - "Nethermind.Core": "[1.36.0-unstable, )", - "Nethermind.Init": "[1.36.0-unstable, )" + "Nethermind.Api": "[1.37.0-unstable, )", + "Nethermind.Consensus": "[1.37.0-unstable, )", + "Nethermind.Core": "[1.37.0-unstable, )", + "Nethermind.Init": "[1.37.0-unstable, )" } }, "AspNetCore.HealthChecks.UI": { @@ -1236,9 +1236,9 @@ }, "Ckzg.Bindings": { "type": "CentralTransitive", - "requested": "[2.1.5.1542, )", - "resolved": "2.1.5.1542", - "contentHash": "GFXmOjg5fZ8s+836/HdKiyXbJ+J73wVX6hNmUE6Isb1rA8dI2SMLeW1m48s+ZNIPN9ENJb8Daq1GwmMjBGjUVQ==" + "requested": "[2.1.5.1544, )", + "resolved": "2.1.5.1544", + "contentHash": "xKg/UV2QpE7A2Oe8Ipry2BLRxDSM0sRsKL5INwGkrNmrRkZbdVCjfbSg7Nubvtw2/c7OTGHeMh4gg35rd9MqOA==" }, "Collections.Pooled": { "type": "CentralTransitive", @@ -1285,15 +1285,15 @@ }, "Google.Protobuf": { "type": "CentralTransitive", - "requested": "[3.33.1, )", - "resolved": "3.33.1", - "contentHash": "RztiFmX9aOWDwfhxFzx/nS4fjs4DX7ZC7/XBEBl56k15lPGBftvbSwZkeo1mMCJHrNp1kK5iQYrFXB4MqCmBCA==" + "requested": "[3.33.2, )", + "resolved": "3.33.2", + "contentHash": "vZXVbrZgBqUkP5iWQi0CS6pucIS2MQdEYPS1duWCo8fGrrt4th6HTiHfLFX2RmAWAQl1oUnzGgyDBsfq7fHQJA==" }, "Google.Protobuf.Tools": { "type": "CentralTransitive", - "requested": "[3.33.1, )", - "resolved": "3.33.1", - "contentHash": "GxkbdNAc0NQVqwiUpaK30FIi3kBs131AoIiaC7cCSkK+KmCKlwGJOmrEv/iJTA+W3um+QEXGI6Fp1roOIGyXuA==" + "requested": "[3.33.2, )", + "resolved": "3.33.2", + "contentHash": "3YFiSs39mhBiAfeQ9u27JniqVNunVrYomNnSb8Rx6D3dJqC9Uwdpm5Xu2f2ZOGvUzkB114NAvU44KySOplgCzw==" }, "Grpc": { "type": "CentralTransitive", @@ -1306,9 +1306,9 @@ }, "KubernetesClient": { "type": "CentralTransitive", - "requested": "[18.0.5, )", - "resolved": "18.0.5", - "contentHash": "xkttIbnGNibYwAyZ0sqeQle2w90bfaJrkF8BaURWHfSMKPbHwys9t/wq1XmT64eA4WRVXLENYlXtqmWlEstG6A==", + "requested": "[18.0.13, )", + "resolved": "18.0.13", + "contentHash": "X5IuxmydftB148XeULtc7rD5/RvqLuW5SzkIjFovPgJpvV4RAoRqNPruVB7GEFu1Xg+zHVIk88WqdV8JjbgHbA==", "dependencies": { "Fractions": "7.3.0", "YamlDotNet": "16.3.0" @@ -1483,9 +1483,9 @@ }, "Nethermind.MclBindings": { "type": "CentralTransitive", - "requested": "[1.0.3, )", - "resolved": "1.0.3", - "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg==" + "requested": "[1.0.4, )", + "resolved": "1.0.4", + "contentHash": "F/HdZV0bWJs8HB5kR+00ljMRQr+SA5csTGkk/ZBawlcMvvIsXxkF7nOilGlrLlEDO3rPjilvoIzp8NDKUO36Ow==" }, "Nethermind.Numerics.Int256": { "type": "CentralTransitive", @@ -1531,11 +1531,11 @@ }, "Polly": { "type": "CentralTransitive", - "requested": "[8.6.4, )", - "resolved": "8.6.4", - "contentHash": "uuBsDoBw0oYrMe3uTWRjkT2sIkKh+ZZnnDrLb4Z+QANfeA4+7FJacx6E8CY5GAxXRoSgFrvUADEAQ7DPF6fGiw==", + "requested": "[8.6.5, )", + "resolved": "8.6.5", + "contentHash": "VqtW2ZE/ALvQMAH1cQY3qZ2cF2OXa3oe/HKMdOv6Q02HCoEW0rsFNfcBONXlHBe1TnjWW1vdRxBEkPeq0/2FHA==", "dependencies": { - "Polly.Core": "8.6.4" + "Polly.Core": "8.6.5" } }, "prometheus-net.AspNetCore": { @@ -1567,26 +1567,26 @@ }, "System.Configuration.ConfigurationManager": { "type": "CentralTransitive", - "requested": "[10.0.0, )", - "resolved": "10.0.0", - "contentHash": "0B+BzJ6pPMrRzJrVsttKf9MfDj6Syw9xoY+agcS9VssYQali1446+jTf5v1K94AMFUBxLXqDZlaTjO5edaI3jA==", + "requested": "[10.0.1, )", + "resolved": "10.0.1", + "contentHash": "HfOAIlSA8OuaxBZD6xjsUWhtB0KdKSWEfRId8gSGveLUjuP6G8IxfiFgJNxaiRIEC1kx4pSvz3Em5xW/J6LLxA==", "dependencies": { - "System.Security.Cryptography.ProtectedData": "10.0.0" + "System.Security.Cryptography.ProtectedData": "10.0.1" } }, "System.Security.Cryptography.ProtectedData": { "type": "CentralTransitive", - "requested": "[10.0.0, )", - "resolved": "10.0.0", - "contentHash": "qy6C3gQRTrfhFfuiIYU1jNwWfFdJpBVo1BARW7jgMm1zTEm3LRzLLyOLJGaAuKE+nZCGkEP71y4rj9NWjqLGdQ==" + "requested": "[10.0.1, )", + "resolved": "10.0.1", + "contentHash": "9SqHNq+lAjZeyPcm69FTQEjr+wsRYvkS3aW8yxoEndVYwDRkCrsP/44QPqpWHwzevoX26rkOoQ6kr7GZWngw2A==" }, "TestableIO.System.IO.Abstractions.Wrappers": { "type": "CentralTransitive", - "requested": "[22.0.16, )", - "resolved": "22.0.16", - "contentHash": "QUX0TLMvnRLEgvuMRotrZKN9eCdX4yzK7HJCaPj17T4jvUf+G4XifdLpB5wmRct2zKlscYzpWMOmHjKabse3yw==", + "requested": "[22.1.0, )", + "resolved": "22.1.0", + "contentHash": "IsW3jQqIiTN4GwdWFx+dzgRL5XR75UDTFVGuuIackPf2d7eH0KKyrx4wuIoASa1XnS9zhgLP39FKwJq6nbbx1w==", "dependencies": { - "Testably.Abstractions.FileSystem.Interface": "9.0.0" + "Testably.Abstractions.FileSystem.Interface": "10.0.0" } }, "Websocket.Client": { @@ -1627,9 +1627,9 @@ }, "Ckzg.Bindings": { "type": "CentralTransitive", - "requested": "[2.1.5.1542, )", - "resolved": "2.1.5.1542", - "contentHash": "GFXmOjg5fZ8s+836/HdKiyXbJ+J73wVX6hNmUE6Isb1rA8dI2SMLeW1m48s+ZNIPN9ENJb8Daq1GwmMjBGjUVQ==" + "requested": "[2.1.5.1544, )", + "resolved": "2.1.5.1544", + "contentHash": "xKg/UV2QpE7A2Oe8Ipry2BLRxDSM0sRsKL5INwGkrNmrRkZbdVCjfbSg7Nubvtw2/c7OTGHeMh4gg35rd9MqOA==" }, "Microsoft.ClearScript.V8.Native.linux-arm64": { "type": "CentralTransitive", @@ -1687,9 +1687,9 @@ }, "Nethermind.MclBindings": { "type": "CentralTransitive", - "requested": "[1.0.3, )", - "resolved": "1.0.3", - "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg==" + "requested": "[1.0.4, )", + "resolved": "1.0.4", + "contentHash": "F/HdZV0bWJs8HB5kR+00ljMRQr+SA5csTGkk/ZBawlcMvvIsXxkF7nOilGlrLlEDO3rPjilvoIzp8NDKUO36Ow==" }, "RocksDB": { "type": "CentralTransitive", @@ -1719,9 +1719,9 @@ }, "Ckzg.Bindings": { "type": "CentralTransitive", - "requested": "[2.1.5.1542, )", - "resolved": "2.1.5.1542", - "contentHash": "GFXmOjg5fZ8s+836/HdKiyXbJ+J73wVX6hNmUE6Isb1rA8dI2SMLeW1m48s+ZNIPN9ENJb8Daq1GwmMjBGjUVQ==" + "requested": "[2.1.5.1544, )", + "resolved": "2.1.5.1544", + "contentHash": "xKg/UV2QpE7A2Oe8Ipry2BLRxDSM0sRsKL5INwGkrNmrRkZbdVCjfbSg7Nubvtw2/c7OTGHeMh4gg35rd9MqOA==" }, "Microsoft.ClearScript.V8.Native.linux-arm64": { "type": "CentralTransitive", @@ -1779,9 +1779,9 @@ }, "Nethermind.MclBindings": { "type": "CentralTransitive", - "requested": "[1.0.3, )", - "resolved": "1.0.3", - "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg==" + "requested": "[1.0.4, )", + "resolved": "1.0.4", + "contentHash": "F/HdZV0bWJs8HB5kR+00ljMRQr+SA5csTGkk/ZBawlcMvvIsXxkF7nOilGlrLlEDO3rPjilvoIzp8NDKUO36Ow==" }, "RocksDB": { "type": "CentralTransitive", @@ -1811,9 +1811,9 @@ }, "Ckzg.Bindings": { "type": "CentralTransitive", - "requested": "[2.1.5.1542, )", - "resolved": "2.1.5.1542", - "contentHash": "GFXmOjg5fZ8s+836/HdKiyXbJ+J73wVX6hNmUE6Isb1rA8dI2SMLeW1m48s+ZNIPN9ENJb8Daq1GwmMjBGjUVQ==" + "requested": "[2.1.5.1544, )", + "resolved": "2.1.5.1544", + "contentHash": "xKg/UV2QpE7A2Oe8Ipry2BLRxDSM0sRsKL5INwGkrNmrRkZbdVCjfbSg7Nubvtw2/c7OTGHeMh4gg35rd9MqOA==" }, "Microsoft.ClearScript.V8.Native.linux-arm64": { "type": "CentralTransitive", @@ -1871,9 +1871,9 @@ }, "Nethermind.MclBindings": { "type": "CentralTransitive", - "requested": "[1.0.3, )", - "resolved": "1.0.3", - "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg==" + "requested": "[1.0.4, )", + "resolved": "1.0.4", + "contentHash": "F/HdZV0bWJs8HB5kR+00ljMRQr+SA5csTGkk/ZBawlcMvvIsXxkF7nOilGlrLlEDO3rPjilvoIzp8NDKUO36Ow==" }, "RocksDB": { "type": "CentralTransitive", @@ -1903,9 +1903,9 @@ }, "Ckzg.Bindings": { "type": "CentralTransitive", - "requested": "[2.1.5.1542, )", - "resolved": "2.1.5.1542", - "contentHash": "GFXmOjg5fZ8s+836/HdKiyXbJ+J73wVX6hNmUE6Isb1rA8dI2SMLeW1m48s+ZNIPN9ENJb8Daq1GwmMjBGjUVQ==" + "requested": "[2.1.5.1544, )", + "resolved": "2.1.5.1544", + "contentHash": "xKg/UV2QpE7A2Oe8Ipry2BLRxDSM0sRsKL5INwGkrNmrRkZbdVCjfbSg7Nubvtw2/c7OTGHeMh4gg35rd9MqOA==" }, "Microsoft.ClearScript.V8.Native.linux-arm64": { "type": "CentralTransitive", @@ -1963,9 +1963,9 @@ }, "Nethermind.MclBindings": { "type": "CentralTransitive", - "requested": "[1.0.3, )", - "resolved": "1.0.3", - "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg==" + "requested": "[1.0.4, )", + "resolved": "1.0.4", + "contentHash": "F/HdZV0bWJs8HB5kR+00ljMRQr+SA5csTGkk/ZBawlcMvvIsXxkF7nOilGlrLlEDO3rPjilvoIzp8NDKUO36Ow==" }, "RocksDB": { "type": "CentralTransitive", @@ -1995,9 +1995,9 @@ }, "Ckzg.Bindings": { "type": "CentralTransitive", - "requested": "[2.1.5.1542, )", - "resolved": "2.1.5.1542", - "contentHash": "GFXmOjg5fZ8s+836/HdKiyXbJ+J73wVX6hNmUE6Isb1rA8dI2SMLeW1m48s+ZNIPN9ENJb8Daq1GwmMjBGjUVQ==" + "requested": "[2.1.5.1544, )", + "resolved": "2.1.5.1544", + "contentHash": "xKg/UV2QpE7A2Oe8Ipry2BLRxDSM0sRsKL5INwGkrNmrRkZbdVCjfbSg7Nubvtw2/c7OTGHeMh4gg35rd9MqOA==" }, "Microsoft.ClearScript.V8.Native.linux-arm64": { "type": "CentralTransitive", @@ -2055,9 +2055,9 @@ }, "Nethermind.MclBindings": { "type": "CentralTransitive", - "requested": "[1.0.3, )", - "resolved": "1.0.3", - "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg==" + "requested": "[1.0.4, )", + "resolved": "1.0.4", + "contentHash": "F/HdZV0bWJs8HB5kR+00ljMRQr+SA5csTGkk/ZBawlcMvvIsXxkF7nOilGlrLlEDO3rPjilvoIzp8NDKUO36Ow==" }, "RocksDB": { "type": "CentralTransitive", From 2eb2a6210c48a064e77af26558eb6575c9102a40 Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Tue, 16 Dec 2025 13:29:54 +0800 Subject: [PATCH 080/255] Fix hanging scenario if persisted node not able to be pruned (#9931) * Fix haning scenation if persisted node not able to be pruned * Minor comment adjustment * Reduce warning if in commit buffer mode --- .../PruningScenariosTests.cs | 87 +++++++++++++++++++ .../Nethermind.Trie/Pruning/TrieStore.cs | 46 +++++++--- 2 files changed, 120 insertions(+), 13 deletions(-) diff --git a/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs b/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs index 7da686fe81d..77818a4f0c9 100644 --- a/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; +using FluentAssertions.Extensions; using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Crypto; @@ -428,6 +429,12 @@ public PruningContext CommitAndWaitForPruning() return Commit(waitForPruning: true); } + public PruningContext SyncPruneCheck() + { + _trieStore.SyncPruneCheck(); + return this; + } + public PruningContext DisposeAndRecreate() { _worldStateCloser!.Dispose(); @@ -1349,5 +1356,85 @@ public async Task Can_ContinueEvenWhenPruningIsBlocked(int maxBufferedCommit, in } } + + [Test] + public async Task Can_BeginScope_During_Persisted_Node_Pruning() + { + PruningContext ctx = PruningContext.InMemory + .WithPruningConfig((cfg) => + { + cfg.DirtyNodeShardBit = 12; // More shard, deliberately make it slow + }) + .WithMaxDepth(128) + .WithPersistedMemoryLimit(50.KiB()) + .WithPrunePersistedNodeParameter(1, 0.01) + .TurnOffPrune(); + + // Make a big state + for (int i = 0; i < 16_000; i++) + { + ctx.SetAccountBalance(i, (UInt256)i); + } + ctx.Commit(); + + // Make the big state go to pruning boundary + for (int i = 0; i < 128; i++) + { + ctx.Commit(); + } + + ctx + .AssertThatCachedPersistedNodeCountIs(0) + .TurnOnPrune() + .SyncPruneCheck() + .TurnOffPrune() + .AssertThatCachedPersistedNodeCountIs(21745L); + + // Make a different big state + for (int i = 0; i < 16_000; i++) + { + ctx.SetAccountBalance(i, (UInt256)(i + 1)); + } + ctx.Commit(); + + // Move pruning boundary again + for (int i = 0; i < 128 - 1; i++) + { + ctx.Commit(); + } + + // Make the exact same big state as the first try + for (int i = 0; i < 16_000; i++) + { + ctx.SetAccountBalance(i, (UInt256)i); + } + ctx.Commit(); + + ctx.TurnOnPrune(); + + TimeSpan syncPruneCheckTime = TimeSpan.Zero; + Task pruneTime = Task.Run(() => + { + long sw = Stopwatch.GetTimestamp(); + ctx.SyncPruneCheck(); + ctx.TurnOffPrune(); + ctx.AssertThatCachedPersistedNodeCountIs(21747L); + syncPruneCheckTime = Stopwatch.GetElapsedTime(sw); + }); + + long sw = Stopwatch.GetTimestamp(); + for (int i = 0; i < 1000; i++) + { + ctx.ExitScope(); + ctx.EnterScope(); + } + + TimeSpan exitEnterScopeTime = Stopwatch.GetElapsedTime(sw); + + await pruneTime; + + Assert.That(syncPruneCheckTime, Is.LessThan(5.Seconds())); // Does not hang + Assert.That(exitEnterScopeTime, Is.LessThan(syncPruneCheckTime)); // Is not blocked by prune + } } } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index 0e80d8f4cb0..309ac8ca7d5 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -588,17 +588,37 @@ internal void SyncPruneCheck() if (_prunePersistedNodePortion > 0) { - // `PrunePersistedNodes` only work on part of the partition at any one time. With commit buffer, - // it is possible that the commit buffer once flushed will immediately trigger another prune, which - // mean `PrunePersistedNodes` was not able to re-trigger multiple time, which make the persisted node - // cache even bigger which causes longer prune which causes bigger commit buffer, etc. - // So we loop it here until `ShouldPrunePersistedNode` return false. - int maxTry = _shardedDirtyNodeCount; - int i = 0; - while (i < maxTry && _pruningStrategy.ShouldPrunePersistedNode(CaptureCurrentState())) + try { - PrunePersistedNodes(); - i++; + // When `_pruningLock` is held, the begin commit will check for _toBePersistedBlockNumber in order + // to decide which block to be used as the boundary for the commit buffer. This number was re-set + // to -1 in `PersistAndPruneDirtyCache`. So we need to re-set it here, otherwrise `BeginScope` will hang + // until the prune persisted node loop is completed. + _toBePersistedBlockNumber = LastPersistedBlockNumber; + + // `PrunePersistedNodes` only work on part of the partition at any one time. With commit buffer, + // it is possible that the commit buffer once flushed will immediately trigger another prune, which + // mean `PrunePersistedNodes` was not able to re-trigger multiple time, which make the persisted node + // cache even bigger which causes longer prune which causes bigger commit buffer, etc. + // So we loop it here until `ShouldPrunePersistedNode` return false. + int startingShard = _lastPrunedShardIdx; + while (_lastPrunedShardIdx - startingShard < _shardedDirtyNodeCount && _pruningStrategy.ShouldPrunePersistedNode(CaptureCurrentState())) + { + PrunePersistedNodes(); + } + + if (!IsInCommitBufferMode && _lastPrunedShardIdx - startingShard >= _shardedDirtyNodeCount && _pruningStrategy.ShouldPrunePersistedNode(CaptureCurrentState())) + { + // A persisted nodes that was recommitted and is still within pruning boundary cannot be pruned. + // This should be rare but can happen, notably in mainnet block 4500000 around there, But this + // does mean that it will keep retrying to prune persisted nodes. The solution is to either increase + // the memory budget or reduce the pruning boundary. + if (_logger.IsWarn) _logger.Warn($"Unable to completely prune persisted nodes. Consider increasing pruning cache limit or reducing pruning boundary"); + } + } + finally + { + _toBePersistedBlockNumber = -1; } } } @@ -890,19 +910,19 @@ internal void PrunePersistedNodes() int shardCountToPrune = (int)((targetPruneMemory / (double)PersistedMemoryUsedByDirtyCache) * _shardedDirtyNodeCount); shardCountToPrune = Math.Max(1, Math.Min(shardCountToPrune, _shardedDirtyNodeCount)); - if (_logger.IsWarn) _logger.Debug($"Pruning persisted nodes {PersistedMemoryUsedByDirtyCache / 1.MB()} MB, Pruning {shardCountToPrune} shards starting from shard {_lastPrunedShardIdx}"); + if (_logger.IsWarn) _logger.Debug($"Pruning persisted nodes {PersistedMemoryUsedByDirtyCache / 1.MB()} MB, Pruning {shardCountToPrune} shards starting from shard {_lastPrunedShardIdx % _shardedDirtyNodeCount}"); long start = Stopwatch.GetTimestamp(); using ArrayPoolListRef pruneTask = new(shardCountToPrune); for (int i = 0; i < shardCountToPrune; i++) { - TrieStoreDirtyNodesCache dirtyNode = _dirtyNodes[_lastPrunedShardIdx]; + TrieStoreDirtyNodesCache dirtyNode = _dirtyNodes[_lastPrunedShardIdx % _shardedDirtyNodeCount]; pruneTask.Add(Task.Run(() => { dirtyNode.PruneCache(prunePersisted: true); })); - _lastPrunedShardIdx = (_lastPrunedShardIdx + 1) % _shardedDirtyNodeCount; + _lastPrunedShardIdx++; } Task.WaitAll(pruneTask.AsSpan()); From 91e235aca0dc189f8b1295415bbb95955ab3bebd Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Tue, 16 Dec 2025 13:33:20 +0300 Subject: [PATCH 081/255] Separate wrong nonce errors (#9941) * Separate wrong nonce errors --------- Co-authored-by: Lukasz Rozmej --- .../TransactionProcessor.cs | 13 +++--- .../BlockchainBridgeTests.cs | 44 +++++++++++++++---- .../Modules/Eth/SimulateTxExecutor.cs | 6 +-- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 903247ad5d4..1513feecd3c 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -566,8 +566,8 @@ protected virtual TransactionResult IncrementNonce(Transaction tx, BlockHeader h UInt256 nonce = WorldState.GetNonce(tx.SenderAddress!); if (validate && tx.Nonce != nonce) { - TraceLogInvalidTx(tx, $"WRONG_TRANSACTION_NONCE: {tx.Nonce} (expected {WorldState.GetNonce(tx.SenderAddress)})"); - return TransactionResult.WrongTransactionNonce; + TraceLogInvalidTx(tx, $"WRONG_TRANSACTION_NONCE: {tx.Nonce} (expected {nonce})"); + return tx.Nonce > nonce ? TransactionResult.TransactionNonceTooHigh : TransactionResult.TransactionNonceTooLow; } UInt256 newNonce = validate || nonce < ulong.MaxValue ? nonce + 1 : 0; @@ -962,7 +962,8 @@ private TransactionResult(ErrorType error = ErrorType.None, EvmExceptionType evm ErrorType.SenderHasDeployedCode => "sender has deployed code", ErrorType.SenderNotSpecified => "sender not specified", ErrorType.TransactionSizeOverMaxInitCodeSize => "EIP-3860 - transaction size over max init code size", - ErrorType.WrongTransactionNonce => "wrong transaction nonce", + ErrorType.TransactionNonceTooHigh => "transaction nonce is too high", + ErrorType.TransactionNonceTooLow => "transaction nonce is too low", _ => "" }; public static implicit operator TransactionResult(ErrorType error) => new(error); @@ -992,7 +993,8 @@ public static TransactionResult EvmException(EvmExceptionType evmExceptionType, public static readonly TransactionResult SenderHasDeployedCode = ErrorType.SenderHasDeployedCode; public static readonly TransactionResult SenderNotSpecified = ErrorType.SenderNotSpecified; public static readonly TransactionResult TransactionSizeOverMaxInitCodeSize = ErrorType.TransactionSizeOverMaxInitCodeSize; - public static readonly TransactionResult WrongTransactionNonce = ErrorType.WrongTransactionNonce; + public static readonly TransactionResult TransactionNonceTooHigh = ErrorType.TransactionNonceTooHigh; + public static readonly TransactionResult TransactionNonceTooLow = ErrorType.TransactionNonceTooLow; public enum ErrorType { @@ -1007,7 +1009,8 @@ public enum ErrorType SenderHasDeployedCode, SenderNotSpecified, TransactionSizeOverMaxInitCodeSize, - WrongTransactionNonce, + TransactionNonceTooHigh, + TransactionNonceTooLow, } } } diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index e82e8efe8b8..70f9635afe7 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -1,8 +1,7 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Autofac; @@ -25,7 +24,6 @@ using Nethermind.Facade.Find; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Facade.Simulate; -using NSubstitute.Core; namespace Nethermind.Facade.Test; @@ -350,31 +348,59 @@ public void EstimateGas_tx_returns_MalformedTransactionError() } [Test] - public void Call_tx_returns_WrongTransactionNonceError() + public void Call_tx_returns_TransactionNonceIsToHighError() { BlockHeader header = Build.A.BlockHeader .TestObject; Transaction tx = new() { GasLimit = 456 }; _transactionProcessor.CallAndRestore(Arg.Any(), Arg.Any()) - .Returns(TransactionResult.WrongTransactionNonce); + .Returns(TransactionResult.TransactionNonceTooHigh); CallOutput callOutput = _blockchainBridge.Call(header, tx); - Assert.That(callOutput.Error, Is.EqualTo("wrong transaction nonce")); + Assert.That(callOutput.Error, Is.EqualTo("transaction nonce is too high")); } [Test] - public void EstimateGas_tx_returns_WrongTransactionNonceError() + public void Call_tx_returns_TransactionNonceIsToLowError() { BlockHeader header = Build.A.BlockHeader .TestObject; Transaction tx = new() { GasLimit = 456 }; _transactionProcessor.CallAndRestore(Arg.Any(), Arg.Any()) - .Returns(TransactionResult.WrongTransactionNonce); + .Returns(TransactionResult.TransactionNonceTooLow); + + CallOutput callOutput = _blockchainBridge.Call(header, tx); + + Assert.That(callOutput.Error, Is.EqualTo("transaction nonce is too low")); + } + + [Test] + public void EstimateGas_tx_returns_TransactionNonceIsToHighError() + { + BlockHeader header = Build.A.BlockHeader + .TestObject; + Transaction tx = new() { GasLimit = 456 }; + _transactionProcessor.CallAndRestore(Arg.Any(), Arg.Any()) + .Returns(TransactionResult.TransactionNonceTooHigh); + + CallOutput callOutput = _blockchainBridge.EstimateGas(header, tx, 1); + + Assert.That(callOutput.Error, Is.EqualTo("transaction nonce is too high")); + } + + [Test] + public void EstimateGas_tx_returns_TransactionNonceIsTooLowError() + { + BlockHeader header = Build.A.BlockHeader + .TestObject; + Transaction tx = new() { GasLimit = 456 }; + _transactionProcessor.CallAndRestore(Arg.Any(), Arg.Any()) + .Returns(TransactionResult.TransactionNonceTooLow); CallOutput callOutput = _blockchainBridge.EstimateGas(header, tx, 1); - Assert.That(callOutput.Error, Is.EqualTo("wrong transaction nonce")); + Assert.That(callOutput.Error, Is.EqualTo("transaction nonce is too low")); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs index 02aafe4a5f5..9036676f507 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs @@ -1,7 +1,6 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -214,7 +213,8 @@ private static int MapSimulateErrorCode(TransactionResult txResult) TransactionResult.ErrorType.SenderHasDeployedCode => ErrorCodes.InvalidParams, TransactionResult.ErrorType.SenderNotSpecified => ErrorCodes.InternalError, TransactionResult.ErrorType.TransactionSizeOverMaxInitCodeSize => ErrorCodes.MaxInitCodeSizeExceeded, - TransactionResult.ErrorType.WrongTransactionNonce => ErrorCodes.InternalError, + TransactionResult.ErrorType.TransactionNonceTooHigh => ErrorCodes.InternalError, + TransactionResult.ErrorType.TransactionNonceTooLow => ErrorCodes.InternalError, _ => ErrorCodes.InternalError }; } From fd62e3d63b5bf2fcd323162e1701c0f70fe85424 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Tue, 16 Dec 2025 16:40:51 +0300 Subject: [PATCH 082/255] Add engine_getBlobsV3 (#9942) * Add engine_getBlobsV3 --------- Co-authored-by: Lukasz Rozmej --- .../Collections/ArrayPoolList.cs | 2 +- .../Nethermind.Facade/BlockchainBridge.cs | 2 +- .../EngineModuleTests.V1.cs | 3 +- .../EngineModuleTests.V3.cs | 2 +- .../EngineModuleTests.V5.cs | 78 ++++++++++++++++--- .../EngineRpcModule.Osaka.cs | 9 ++- .../EngineRpcModule.cs | 2 +- .../Handlers/EngineRpcCapabilitiesProvider.cs | 1 + .../Handlers/GetBlobsHandlerV2.cs | 33 ++++---- .../IEngineRpcModule.Osaka.cs | 8 +- .../Nethermind.Merge.Plugin/MergePlugin.cs | 2 +- .../TxPoolContentListsTests.cs | 2 +- .../Rpc/TaikoEngineRpcModule.cs | 2 +- 13 files changed, 109 insertions(+), 37 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Collections/ArrayPoolList.cs b/src/Nethermind/Nethermind.Core/Collections/ArrayPoolList.cs index cc8e1349d68..178027c5d29 100644 --- a/src/Nethermind/Nethermind.Core/Collections/ArrayPoolList.cs +++ b/src/Nethermind/Nethermind.Core/Collections/ArrayPoolList.cs @@ -243,7 +243,7 @@ public void Dispose() ArrayPoolListCore.Dispose(_arrayPool, ref _array, ref _count, ref _capacity, ref _disposed); #if DEBUG - GC.SuppressFinalize(this); + GC.SuppressFinalize(this); #endif } diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 80305a26023..2568c84941f 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -109,7 +109,7 @@ private bool TryGetCanonicalTransaction( return (null, 0, null, 0); } - public (TxReceipt? Receipt, Transaction Transaction, UInt256? baseFee) GetTransaction(Hash256 txHash, bool checkTxnPool = true) => + public (TxReceipt? Receipt, Transaction? Transaction, UInt256? baseFee) GetTransaction(Hash256 txHash, bool checkTxnPool = true) => TryGetCanonicalTransaction(txHash, out Transaction? tx, out TxReceipt? txReceipt, out Block? block, out TxReceipt[]? _) ? (txReceipt, tx, block.BaseFeePerGas) : checkTxnPool && txPool.TryGetPendingTransaction(txHash, out Transaction? transaction) diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs index bc10ea8e5b6..473d78f0df0 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs @@ -1553,7 +1553,8 @@ public void Should_return_expected_capabilities_for_mainnet() nameof(IEngineRpcModule.engine_newPayloadV4), nameof(IEngineRpcModule.engine_getPayloadV5), - nameof(IEngineRpcModule.engine_getBlobsV2) + nameof(IEngineRpcModule.engine_getBlobsV2), + nameof(IEngineRpcModule.engine_getBlobsV3) }; Assert.That(result, Is.EquivalentTo(expectedMethods)); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs index 4f29e8155cf..7940bc6c34b 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs @@ -385,7 +385,7 @@ public async Task NewPayloadV3_should_verify_blob_versioned_hashes_again Substitute.For>(), Substitute.For, IEnumerable>>(), Substitute.For>>(), - Substitute.For?>>(), + Substitute.For?>>(), Substitute.For(), chain.SpecProvider, new GCKeeper(NoGCStrategy.Instance, chain.LogManager), diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V5.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V5.cs index 681110c95fc..825da6cc4e1 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V5.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V5.cs @@ -52,7 +52,7 @@ public async Task GetBlobsV2_should_throw_if_more_than_128_requested_blobs([Valu request.Add(Bytes.FromHexString(i.ToString("X64"))); } - ResultWrapper?> result = await rpcModule.engine_getBlobsV2(request.ToArray()); + ResultWrapper?> result = await rpcModule.engine_getBlobsV2(request.ToArray()); if (requestSize > 128) { @@ -75,7 +75,7 @@ public async Task GetBlobsV2_should_handle_empty_request() }); IEngineRpcModule rpcModule = chain.EngineRpcModule; - ResultWrapper?> result = await rpcModule.engine_getBlobsV2([]); + ResultWrapper?> result = await rpcModule.engine_getBlobsV2([]); result.Result.Should().Be(Result.Success); result.Data.Should().BeEquivalentTo(ArraySegment.Empty); @@ -99,14 +99,14 @@ public async Task GetBlobsV2_should_return_requested_blobs([Values(1, 2, 3, 4, 5 chain.TxPool.SubmitTx(blobTx, TxHandlingOptions.None).Should().Be(AcceptTxResult.Accepted); - ResultWrapper?> result = await rpcModule.engine_getBlobsV2(blobTx.BlobVersionedHashes!); + ResultWrapper?> result = await rpcModule.engine_getBlobsV2(blobTx.BlobVersionedHashes!); ShardBlobNetworkWrapper wrapper = (ShardBlobNetworkWrapper)blobTx.NetworkWrapper!; result.Data.Should().NotBeNull(); - result.Data!.Select(static b => b.Blob).Should().BeEquivalentTo(wrapper.Blobs); - result.Data!.Select(static b => b.Proofs.Length).Should().HaveCount(numberOfBlobs); - result.Data!.Select(static b => b.Proofs).Should().BeEquivalentTo(wrapper.Proofs.Chunk(128)); + result.Data!.Select(static b => b!.Blob).Should().BeEquivalentTo(wrapper.Blobs); + result.Data!.Select(static b => b!.Proofs.Length).Should().HaveCount(numberOfBlobs); + result.Data!.Select(static b => b!.Proofs).Should().BeEquivalentTo(wrapper.Proofs.Chunk(128)); } [Test] @@ -127,7 +127,7 @@ public async Task GetBlobsV2_should_return_empty_array_when_blobs_not_found([Val .SignedAndResolved(chain.EthereumEcdsa, TestItem.PrivateKeyA).TestObject; // requesting hashes that are not present in TxPool - ResultWrapper?> result = await rpcModule.engine_getBlobsV2(blobTx.BlobVersionedHashes!); + ResultWrapper?> result = await rpcModule.engine_getBlobsV2(blobTx.BlobVersionedHashes!); result.Result.Should().Be(Result.Success); result.Data.Should().BeNull(); @@ -162,7 +162,7 @@ public async Task GetBlobsV2_should_return_empty_array_when_only_some_blobs_foun blobVersionedHashesRequest.Add(addActualHash ? blobTx.BlobVersionedHashes![actualIndex++]! : Bytes.FromHexString(i.ToString("X64"))); } - ResultWrapper?> result = await rpcModule.engine_getBlobsV2(blobVersionedHashesRequest.ToArray()); + ResultWrapper?> result = await rpcModule.engine_getBlobsV2(blobVersionedHashesRequest.ToArray()); if (multiplier > 1) { result.Result.Should().Be(Result.Success); @@ -173,9 +173,65 @@ public async Task GetBlobsV2_should_return_empty_array_when_only_some_blobs_foun ShardBlobNetworkWrapper wrapper = (ShardBlobNetworkWrapper)blobTx.NetworkWrapper!; result.Data.Should().NotBeNull(); - result.Data!.Select(static b => b.Blob).Should().BeEquivalentTo(wrapper.Blobs); - result.Data!.Select(static b => b.Proofs.Length).Should().HaveCount(numberOfBlobs); - result.Data!.Select(static b => b.Proofs).Should().BeEquivalentTo(wrapper.Proofs.Chunk(128)); + result.Data!.Select(static b => b!.Blob).Should().BeEquivalentTo(wrapper.Blobs); + result.Data!.Select(static b => b!.Proofs.Length).Should().HaveCount(numberOfBlobs); + result.Data!.Select(static b => b!.Proofs).Should().BeEquivalentTo(wrapper.Proofs.Chunk(128)); + } + } + + [Test] + public async Task GetBlobsV3_should_return_partial_results_with_nulls_for_missing_blobs([Values(1, 2, 3, 4, 5, 6)] int numberOfBlobs, [Values(1, 2)] int multiplier) + { + int requestSize = multiplier * numberOfBlobs; + + MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: Osaka.Instance, mergeConfig: new MergeConfig() + { + NewPayloadBlockProcessingTimeout = (int)TimeSpan.FromDays(1).TotalMilliseconds + }); + IEngineRpcModule rpcModule = chain.EngineRpcModule; + + Transaction blobTx = Build.A.Transaction + .WithShardBlobTxTypeAndFields(numberOfBlobs, spec: Osaka.Instance) + .WithMaxFeePerGas(1.GWei()) + .WithMaxPriorityFeePerGas(1.GWei()) + .WithMaxFeePerBlobGas(1000.Wei()) + .SignedAndResolved(chain.EthereumEcdsa, TestItem.PrivateKeyA).TestObject; + + chain.TxPool.SubmitTx(blobTx, TxHandlingOptions.None).Should().Be(AcceptTxResult.Accepted); + + List blobVersionedHashesRequest = new List(requestSize); + + int actualIndex = 0; + for (int i = 0; i < requestSize; i++) + { + bool addActualHash = i % multiplier == 0; + blobVersionedHashesRequest.Add(addActualHash ? blobTx.BlobVersionedHashes![actualIndex++]! : Bytes.FromHexString(i.ToString("X64"))); + } + + ResultWrapper?> result = await rpcModule.engine_getBlobsV3(blobVersionedHashesRequest.ToArray()); + + result.Result.Should().Be(Result.Success); + result.Data.Should().NotBeNull(); + result.Data!.Should().HaveCount(requestSize); + + ShardBlobNetworkWrapper wrapper = (ShardBlobNetworkWrapper)blobTx.NetworkWrapper!; + + // V3 returns partial results with nulls for missing blobs + int foundIndex = 0; + for (int i = 0; i < requestSize; i++) + { + bool shouldBeFound = i % multiplier == 0; + if (shouldBeFound) + { + result.Data!.ElementAt(i).Should().NotBeNull(); + result.Data!.ElementAt(i)!.Blob.Should().BeEquivalentTo(wrapper.Blobs[foundIndex]); + result.Data!.ElementAt(i)!.Proofs.Should().BeEquivalentTo(wrapper.Proofs.Skip(foundIndex * 128).Take(128)); + foundIndex++; + } + else + { + result.Data!.ElementAt(i).Should().BeNull(); + } } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Osaka.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Osaka.cs index fe52ec00e62..fcc4877246c 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Osaka.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Osaka.cs @@ -12,11 +12,14 @@ namespace Nethermind.Merge.Plugin; public partial class EngineRpcModule : IEngineRpcModule { private readonly IAsyncHandler _getPayloadHandlerV5; - private readonly IAsyncHandler?> _getBlobsHandlerV2; + private readonly IAsyncHandler?> _getBlobsHandlerV2; public Task> engine_getPayloadV5(byte[] payloadId) => _getPayloadHandlerV5.HandleAsync(payloadId); - public Task?>> engine_getBlobsV2(byte[][] blobVersionedHashes) - => _getBlobsHandlerV2.HandleAsync(blobVersionedHashes); + public Task?>> engine_getBlobsV2(byte[][] blobVersionedHashes) + => _getBlobsHandlerV2.HandleAsync(new(blobVersionedHashes)); + + public Task?>> engine_getBlobsV3(byte[][] blobVersionedHashes) + => _getBlobsHandlerV2.HandleAsync(new(blobVersionedHashes, true)); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.cs index ee951fa0a52..9d0edf55a74 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.cs @@ -34,7 +34,7 @@ public EngineRpcModule( IHandler transitionConfigurationHandler, IHandler, IEnumerable> capabilitiesHandler, IAsyncHandler> getBlobsHandler, - IAsyncHandler?> getBlobsHandlerV2, + IAsyncHandler?> getBlobsHandlerV2, IEngineRequestsTracker engineRequestsTracker, ISpecProvider specProvider, GCKeeper gcKeeper, diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/EngineRpcCapabilitiesProvider.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/EngineRpcCapabilitiesProvider.cs index 123ddd1a6f3..00e60cf5026 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/EngineRpcCapabilitiesProvider.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/EngineRpcCapabilitiesProvider.cs @@ -53,6 +53,7 @@ public EngineRpcCapabilitiesProvider(ISpecProvider specProvider) // Osaka _capabilities[nameof(IEngineRpcModule.engine_getPayloadV5)] = (spec.IsEip7594Enabled, spec.IsEip7594Enabled); _capabilities[nameof(IEngineRpcModule.engine_getBlobsV2)] = (spec.IsEip7594Enabled, false); + _capabilities[nameof(IEngineRpcModule.engine_getBlobsV3)] = (spec.IsEip7594Enabled, false); } return _capabilities; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetBlobsHandlerV2.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetBlobsHandlerV2.cs index c04978430f3..47d22383328 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetBlobsHandlerV2.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetBlobsHandlerV2.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Nethermind.Core.Collections; using Nethermind.JsonRpc; @@ -11,41 +10,45 @@ namespace Nethermind.Merge.Plugin.Handlers; -public class GetBlobsHandlerV2(ITxPool txPool) : IAsyncHandler?> +public class GetBlobsHandlerV2(ITxPool txPool) : IAsyncHandler?> { private const int MaxRequest = 128; - private static readonly Task?>> NotFound = Task.FromResult(ResultWrapper?>.Success(null)); + private static readonly Task?>> NotFound = Task.FromResult(ResultWrapper?>.Success(null)); - public Task?>> HandleAsync(byte[][] request) + public Task?>> HandleAsync(GetBlobsHandlerV2Request request) { - if (request.Length > MaxRequest) + if (request.BlobVersionedHashes.Length > MaxRequest) { var error = $"The number of requested blobs must not exceed {MaxRequest}"; - return ResultWrapper?>.Fail(error, MergeErrorCodes.TooLargeRequest); + return ResultWrapper?>.Fail(error, MergeErrorCodes.TooLargeRequest); } - Metrics.GetBlobsRequestsTotal += request.Length; + Metrics.GetBlobsRequestsTotal += request.BlobVersionedHashes.Length; - var count = txPool.GetBlobCounts(request); + int count = txPool.GetBlobCounts(request.BlobVersionedHashes); Metrics.GetBlobsRequestsInBlobpoolTotal += count; - // quick fail if we don't have some blob - if (count != request.Length) + // quick fail if we don't have some blob (unless partial return is allowed) + if (!request.AllowPartialReturn && count != request.BlobVersionedHashes.Length) { return ReturnEmptyArray(); } - ArrayPoolList response = new(request.Length); + ArrayPoolList response = new(request.BlobVersionedHashes.Length); try { - foreach (byte[] requestedBlobVersionedHash in request) + foreach (byte[] requestedBlobVersionedHash in request.BlobVersionedHashes) { if (txPool.TryGetBlobAndProofV1(requestedBlobVersionedHash, out byte[]? blob, out byte[][]? cellProofs)) { response.Add(new BlobAndProofV2(blob, cellProofs)); } + else if (request.AllowPartialReturn) + { + response.Add(null); + } else { // fail if we were not able to collect full blob data @@ -55,7 +58,7 @@ public class GetBlobsHandlerV2(ITxPool txPool) : IAsyncHandler?>.Success(response); + return ResultWrapper?>.Success(response); } catch { @@ -64,9 +67,11 @@ public class GetBlobsHandlerV2(ITxPool txPool) : IAsyncHandler?>> ReturnEmptyArray() + private Task?>> ReturnEmptyArray() { Metrics.GetBlobsRequestsFailureTotal++; return NotFound; } } + +public readonly record struct GetBlobsHandlerV2Request(byte[][] BlobVersionedHashes, bool AllowPartialReturn = false); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/IEngineRpcModule.Osaka.cs b/src/Nethermind/Nethermind.Merge.Plugin/IEngineRpcModule.Osaka.cs index b2cd12fe96f..bd05aa9e0c4 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/IEngineRpcModule.Osaka.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/IEngineRpcModule.Osaka.cs @@ -21,5 +21,11 @@ public partial interface IEngineRpcModule : IRpcModule Description = "Returns requested blobs and proofs.", IsSharable = true, IsImplemented = true)] - public Task?>> engine_getBlobsV2(byte[][] blobVersionedHashes); + public Task?>> engine_getBlobsV2(byte[][] blobVersionedHashes); + + [JsonRpcMethod( + Description = "Returns requested blobs and proofs.", + IsSharable = true, + IsImplemented = true)] + public Task?>> engine_getBlobsV3(byte[][] blobVersionedHashes); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs index d0f06ff7b25..73a85cae16e 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs @@ -330,7 +330,7 @@ protected override void Load(ContainerBuilder builder) .AddSingleton, IEnumerable>, ExchangeCapabilitiesHandler>() .AddSingleton() .AddSingleton>, GetBlobsHandler>() - .AddSingleton?>, GetBlobsHandlerV2>() + .AddSingleton?>, GetBlobsHandlerV2>() .AddSingleton() .AddSingleton((ctx) => diff --git a/src/Nethermind/Nethermind.Taiko.Test/TxPoolContentListsTests.cs b/src/Nethermind/Nethermind.Taiko.Test/TxPoolContentListsTests.cs index f34533be574..786ab8f6185 100644 --- a/src/Nethermind/Nethermind.Taiko.Test/TxPoolContentListsTests.cs +++ b/src/Nethermind/Nethermind.Taiko.Test/TxPoolContentListsTests.cs @@ -83,7 +83,7 @@ public int[][] Test_TxLists_AreConstructed( Substitute.For>(), Substitute.For, IEnumerable>>(), Substitute.For>>(), - Substitute.For?>>(), + Substitute.For?>>(), Substitute.For(), Substitute.For(), null!, diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs index dfa8fb64474..6bda82d9b35 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs @@ -46,7 +46,7 @@ public class TaikoEngineRpcModule(IAsyncHandler getPa IHandler transitionConfigurationHandler, IHandler, IEnumerable> capabilitiesHandler, IAsyncHandler> getBlobsHandler, - IAsyncHandler?> getBlobsHandlerV2, + IAsyncHandler?> getBlobsHandlerV2, IEngineRequestsTracker engineRequestsTracker, ISpecProvider specProvider, GCKeeper gcKeeper, From 353e9cea5646d9bffb48a90bb45b3868600f4698 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Tue, 16 Dec 2025 14:43:16 +0100 Subject: [PATCH 083/255] fix: only touch coinbase after successful transaction in state tests (#9865) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: only touch coinbase after successful transaction in state tests When a transaction fails validation (e.g., insufficient balance), the state test runner should not modify state at all. Previously, the coinbase account was created in InitializeTestState before transaction execution, causing state root divergence from geth when transactions failed validation. This fix moves coinbase creation to after successful transaction execution, matching geth's behavior: - Only touch coinbase when txResult == Ok - When validation fails, state remains unchanged from pre-state This was a consensus bug in the test framework (not production code) introduced in PR #9225. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * Update src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs * fix: update T8nExecutor to use new InitializeTestState signature The InitializeTestState method signature was changed to remove the coinbase parameter. T8nExecutor already creates the coinbase account separately (line 54), so we just need to update the call to match the new 3-argument signature. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: only touch coinbase after successful transaction in state tests When a transaction fails validation (e.g., insufficient balance), the state test runner should not modify state at all. Previously, the coinbase account was created in InitializeTestState before transaction execution, causing state root divergence from geth when transactions failed validation. This fix moves coinbase creation to after successful transaction execution, matching geth's behavior: - Only touch coinbase when txResult == Ok - When validation fails, state remains unchanged from pre-state This was a consensus bug in the test framework (not production code) introduced in PR #9225. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: add IsLegacy flag for backward-compatible coinbase handling in state tests Legacy tests expected coinbase to be created before transaction execution, which was a buggy behavior baked into their expected state roots. This adds an IsLegacy flag to preserve backward compatibility while new tests use the correct behavior of creating coinbase only after successful tx. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * Update src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs Co-authored-by: Alexey Osipov --------- Co-authored-by: Claude Co-authored-by: Lukasz Rozmej Co-authored-by: Alexey Osipov --- .../Ethereum.Test.Base/GeneralStateTest.cs | 6 +++ .../Ethereum.Test.Base/GeneralTestBase.cs | 41 ++++++++++++++----- .../LoadLegacyGeneralStateTestsStrategy.cs | 9 +++- tools/Evm/T8n/T8nExecutor.cs | 2 +- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/Nethermind/Ethereum.Test.Base/GeneralStateTest.cs b/src/Nethermind/Ethereum.Test.Base/GeneralStateTest.cs index 800ff17e843..098b7cc8682 100644 --- a/src/Nethermind/Ethereum.Test.Base/GeneralStateTest.cs +++ b/src/Nethermind/Ethereum.Test.Base/GeneralStateTest.cs @@ -13,6 +13,12 @@ namespace Ethereum.Test.Base { public class GeneralStateTest : EthereumTest { + /// + /// When true, uses legacy coinbase behavior (create before tx) for backward compatibility + /// with old test expectations that were computed with buggy coinbase timing. + /// + public bool IsLegacy { get; set; } + public IReleaseSpec? Fork { get; set; } public string? ForkName { get; set; } public Address? CurrentCoinbase { get; set; } diff --git a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs index 39dbc151790..e402b1716b7 100644 --- a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs @@ -89,7 +89,17 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) using IDisposable _ = stateProvider.BeginScope(null); ITransactionProcessor transactionProcessor = mainBlockProcessingContext.TransactionProcessor; - InitializeTestState(test.Pre, test.CurrentCoinbase, stateProvider, specProvider); + InitializeTestState(test.Pre, stateProvider, specProvider); + + // Legacy tests expect coinbase to be created BEFORE transaction execution + // (old buggy behavior that was baked into expected state roots). + // Modern tests correctly create coinbase only after successful tx. + if (test.IsLegacy && test.CurrentCoinbase is not null) + { + stateProvider.CreateAccountIfNotExists(test.CurrentCoinbase, UInt256.Zero); + stateProvider.Commit(specProvider.GetSpec((ForkActivation)1)); + stateProvider.RecalculateStateRoot(); + } BlockHeader header = new( test.PreviousHash, @@ -154,11 +164,29 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) { stateProvider.Commit(specProvider.GetSpec((ForkActivation)1)); stateProvider.CommitTree(1); + + // '@winsvega added a 0-wei reward to the miner, so we had to add that into the state test execution phase. He needed it for retesteth.' + // This must only happen after successful transaction execution, not when tx fails validation. + // For legacy tests, coinbase was already created before tx execution. + if (!test.IsLegacy) + { + stateProvider.CreateAccountIfNotExists(test.CurrentCoinbase, UInt256.Zero); + } + stateProvider.Commit(specProvider.GetSpec((ForkActivation)1)); stateProvider.RecalculateStateRoot(); } else { - stateProvider.Reset(); + // For legacy tests with failed tx, we need to recalculate root since coinbase was created + if (test.IsLegacy) + { + stateProvider.CommitTree(0); + stateProvider.RecalculateStateRoot(); + } + else + { + stateProvider.Reset(); + } } List differences = RunAssertions(test, stateProvider); @@ -176,7 +204,7 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) return testResult; } - public static void InitializeTestState(Dictionary preState, Address coinbase, IWorldState stateProvider, ISpecProvider specProvider) + public static void InitializeTestState(Dictionary preState, IWorldState stateProvider, ISpecProvider specProvider) { foreach (KeyValuePair accountState in preState) { @@ -194,13 +222,6 @@ public static void InitializeTestState(Dictionary preStat stateProvider.Commit(specProvider.GenesisSpec); stateProvider.CommitTree(0); stateProvider.Reset(); - - if (!stateProvider.AccountExists(coinbase)) - { - stateProvider.CreateAccount(coinbase, 0); - stateProvider.Commit(specProvider.GetSpec((ForkActivation)1)); - stateProvider.RecalculateStateRoot(); - } } private List RunAssertions(GeneralStateTest test, IWorldState stateProvider) diff --git a/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs index 93670a28c31..1c3a2309ad2 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs @@ -50,9 +50,14 @@ private IEnumerable LoadTestsFromDirectory(string testDir, string { FileTestsSource fileTestsSource = new(testFile, wildcard); var tests = fileTestsSource.LoadTests(TestType.State); - foreach (EthereumTest blockchainTest in tests) + foreach (EthereumTest ethereumTest in tests) { - blockchainTest.Category = testDir; + ethereumTest.Category = testDir; + // Mark legacy tests to use old coinbase behavior for backward compatibility + if (ethereumTest is GeneralStateTest generalStateTest) + { + generalStateTest.IsLegacy = true; + } } testsByName.AddRange(tests); diff --git a/tools/Evm/T8n/T8nExecutor.cs b/tools/Evm/T8n/T8nExecutor.cs index 7298e7149f5..95780e5c8e1 100644 --- a/tools/Evm/T8n/T8nExecutor.cs +++ b/tools/Evm/T8n/T8nExecutor.cs @@ -52,7 +52,7 @@ public static T8nExecutionResult Execute(T8nCommandArguments arguments) _logManager); stateProvider.CreateAccount(test.CurrentCoinbase, 0); - GeneralStateTestBase.InitializeTestState(test.Alloc, test.CurrentCoinbase, stateProvider, test.SpecProvider); + GeneralStateTestBase.InitializeTestState(test.Alloc, stateProvider, test.SpecProvider); Block block = test.ConstructBlock(); var withdrawalProcessor = new WithdrawalProcessor(stateProvider, _logManager); From 5d15a01215946dbc494fd4aac4534f1085ce4fb5 Mon Sep 17 00:00:00 2001 From: Marc Date: Tue, 16 Dec 2025 18:12:58 +0000 Subject: [PATCH 084/255] Gnosis Balancer permanent changes (#9946) * initial commit * fork info test, tidy * small tidy * load fork transition * fix test * use real gnosis json for test * simplify test * start aura check rewrite by timestamp count * reuse prague specs * osakagnosis * private praguegnosis * use array for overrides internally * formatting --------- Co-authored-by: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> --- src/Nethermind/Chains/gnosis.json | 7 ++- .../AuraBlockProcessorTests.cs | 59 ++++++++++++------- .../ChainSpecLoaderTest.cs | 24 +++++++- .../AuRaBlockProcessor.cs | 22 +++++-- .../Nethermind.Consensus.AuRa/AuRaPlugin.cs | 3 +- .../Config/AuRaChainSpecEngineParameters.cs | 21 +++++++ .../ContractRewriter.cs | 41 ++++++++++--- .../StartBlockProducerAuRa.cs | 4 +- .../Nethermind.Network.Test/ForkInfoTests.cs | 8 ++- .../Nethermind.Specs/GnosisSpecProvider.cs | 3 +- 10 files changed, 148 insertions(+), 44 deletions(-) diff --git a/src/Nethermind/Chains/gnosis.json b/src/Nethermind/Chains/gnosis.json index 44b95dd869f..3ed45d0397e 100644 --- a/src/Nethermind/Chains/gnosis.json +++ b/src/Nethermind/Chains/gnosis.json @@ -36,6 +36,11 @@ "21735000": { "0xf8D1677c8a0c961938bf2f9aDc3F3CFDA759A9d9": "0x6080604052600436106101b35763ffffffff60e060020a60003504166305d2035b81146101b857806306fdde03146101e1578063095ea7b31461026b5780630b26cf661461028f57806318160ddd146102b257806323b872dd146102d957806330adf81f14610303578063313ce567146103185780633644e5151461034357806339509351146103585780634000aea01461037c57806340c10f19146103ad57806342966c68146103d157806354fd4d50146103e957806366188463146103fe57806369ffa08a1461042257806370a0823114610449578063715018a61461046a578063726600ce1461047f5780637d64bcb4146104a05780637ecebe00146104b5578063859ba28c146104d65780638da5cb5b146105175780638fcbaf0c1461054857806395d89b4114610586578063a457c2d71461059b578063a9059cbb146105bf578063b753a98c146105e3578063bb35783b14610607578063c6a1dedf14610631578063cd59658314610646578063d505accf1461065b578063d73dd62314610694578063dd62ed3e146106b8578063f2d5d56b146106df578063f2fde38b14610703578063ff9e884d14610724575b600080fd5b3480156101c457600080fd5b506101cd61074b565b604080519115158252519081900360200190f35b3480156101ed57600080fd5b506101f661076c565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610230578181015183820152602001610218565b50505050905090810190601f16801561025d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561027757600080fd5b506101cd600160a060020a03600435166024356107fa565b34801561029b57600080fd5b506102b0600160a060020a0360043516610810565b005b3480156102be57600080fd5b506102c761086a565b60408051918252519081900360200190f35b3480156102e557600080fd5b506101cd600160a060020a0360043581169060243516604435610870565b34801561030f57600080fd5b506102c7610a38565b34801561032457600080fd5b5061032d610a5c565b6040805160ff9092168252519081900360200190f35b34801561034f57600080fd5b506102c7610a65565b34801561036457600080fd5b506101cd600160a060020a0360043516602435610a6b565b34801561038857600080fd5b506101cd60048035600160a060020a0316906024803591604435918201910135610aac565b3480156103b957600080fd5b506101cd600160a060020a0360043516602435610bbd565b3480156103dd57600080fd5b506102b0600435610cc8565b3480156103f557600080fd5b506101f6610cd5565b34801561040a57600080fd5b506101cd600160a060020a0360043516602435610d0c565b34801561042e57600080fd5b506102b0600160a060020a0360043581169060243516610de9565b34801561045557600080fd5b506102c7600160a060020a0360043516610e0e565b34801561047657600080fd5b506102b0610e29565b34801561048b57600080fd5b506101cd600160a060020a0360043516610e40565b3480156104ac57600080fd5b506101cd610e54565b3480156104c157600080fd5b506102c7600160a060020a0360043516610e5b565b3480156104e257600080fd5b506104eb610e6d565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b34801561052357600080fd5b5061052c610e78565b60408051600160a060020a039092168252519081900360200190f35b34801561055457600080fd5b506102b0600160a060020a0360043581169060243516604435606435608435151560ff60a4351660c43560e435610e87565b34801561059257600080fd5b506101f6610fc5565b3480156105a757600080fd5b506101cd600160a060020a036004351660243561101f565b3480156105cb57600080fd5b506101cd600160a060020a0360043516602435611032565b3480156105ef57600080fd5b506102b0600160a060020a0360043516602435611054565b34801561061357600080fd5b506102b0600160a060020a0360043581169060243516604435611064565b34801561063d57600080fd5b506102c7611075565b34801561065257600080fd5b5061052c611099565b34801561066757600080fd5b506102b0600160a060020a036004358116906024351660443560643560ff6084351660a43560c4356110a8565b3480156106a057600080fd5b506101cd600160a060020a0360043516602435611184565b3480156106c457600080fd5b506102c7600160a060020a036004358116906024351661120b565b3480156106eb57600080fd5b506102b0600160a060020a0360043516602435611236565b34801561070f57600080fd5b506102b0600160a060020a0360043516611241565b34801561073057600080fd5b506102c7600160a060020a0360043581169060243516611261565b60065474010000000000000000000000000000000000000000900460ff1681565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107f25780601f106107c7576101008083540402835291602001916107f2565b820191906000526020600020905b8154815290600101906020018083116107d557829003601f168201915b505050505081565b600061080733848461127e565b50600192915050565b600654600160a060020a0316331461082757600080fd5b610830816112c0565b151561083b57600080fd5b6007805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60045490565b600080600160a060020a038516151561088857600080fd5b600160a060020a038416151561089d57600080fd5b600160a060020a0385166000908152600360205260409020546108c6908463ffffffff6112c816565b600160a060020a0380871660009081526003602052604080822093909355908616815220546108fb908463ffffffff6112da16565b600160a060020a038086166000818152600360209081526040918290209490945580518781529051919392891692600080516020611d7283398151915292918290030190a3600160a060020a0385163314610a225761095a853361120b565b905060001981146109c457610975818463ffffffff6112c816565b600160a060020a038616600081815260056020908152604080832033808552908352928190208590558051948552519193600080516020611d92833981519152929081900390910190a3610a22565b600160a060020a0385166000908152600a602090815260408083203384529091529020541580610a175750600160a060020a0385166000908152600a602090815260408083203384529091529020544211155b1515610a2257600080fd5b610a2d8585856112ed565b506001949350505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60025460ff1681565b60085481565b336000818152600560209081526040808320600160a060020a03871684529091528120549091610807918590610aa7908663ffffffff6112da16565b61127e565b600084600160a060020a03811615801590610ad05750600160a060020a0381163014155b1515610adb57600080fd5b610ae58686611324565b1515610af057600080fd5b85600160a060020a031633600160a060020a03167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16878787604051808481526020018060200182810382528484828181526020019250808284376040519201829003965090945050505050a3610b65866112c0565b15610bb157610ba633878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843750611330945050505050565b1515610bb157600080fd5b50600195945050505050565b600654600090600160a060020a03163314610bd757600080fd5b60065474010000000000000000000000000000000000000000900460ff1615610bff57600080fd5b600454610c12908363ffffffff6112da16565b600455600160a060020a038316600090815260036020526040902054610c3e908363ffffffff6112da16565b600160a060020a038416600081815260036020908152604091829020939093558051858152905191927f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688592918290030190a2604080518381529051600160a060020a03851691600091600080516020611d728339815191529181900360200190a350600192915050565b610cd233826114ad565b50565b60408051808201909152600181527f3100000000000000000000000000000000000000000000000000000000000000602082015281565b336000908152600560209081526040808320600160a060020a0386168452909152812054808310610d6057336000908152600560209081526040808320600160a060020a0388168452909152812055610d95565b610d70818463ffffffff6112c816565b336000908152600560209081526040808320600160a060020a03891684529091529020555b336000818152600560209081526040808320600160a060020a038916808552908352928190205481519081529051929392600080516020611d92833981519152929181900390910190a35060019392505050565b600654600160a060020a03163314610e0057600080fd5b610e0a828261159c565b5050565b600160a060020a031660009081526003602052604090205490565b600654600160a060020a031633146101b357600080fd5b600754600160a060020a0390811691161490565b6000806000fd5b60096020526000908152604090205481565b600260056000909192565b600654600160a060020a031681565b600080861580610e975750864211155b1515610ea257600080fd5b604080517fea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb6020820152600160a060020a03808d16828401528b166060820152608081018a905260a0810189905287151560c0808301919091528251808303909101815260e0909101909152610f17906115da565b9150610f25828686866116e1565b600160a060020a038b8116911614610f3c57600080fd5b600160a060020a038a1660009081526009602052604090208054600181019091558814610f6857600080fd5b85610f74576000610f78565b6000195b905085610f86576000610f88565b865b600160a060020a03808c166000908152600a60209081526040808320938e1683529290522055610fb98a8a836118e3565b50505050505050505050565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107f25780601f106107c7576101008083540402835291602001916107f2565b600061102b8383610d0c565b9392505050565b600061103e8383611324565b151561104957600080fd5b6108073384846112ed565b61105f338383610870565b505050565b61106f838383610870565b50505050565b7fea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb81565b600754600160a060020a031690565b600080428610156110b857600080fd5b600160a060020a03808a1660008181526009602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c99281019290925281830193909352928b166060840152608083018a905260a0830182905260c08084018a90528151808503909101815260e090930190529250611149906115da565b9050611157818686866116e1565b600160a060020a038a811691161461116e57600080fd5b61117989898961127e565b505050505050505050565b336000908152600560209081526040808320600160a060020a03861684529091528120546111b8908363ffffffff6112da16565b336000818152600560209081526040808320600160a060020a038916808552908352928190208590558051948552519193600080516020611d92833981519152929081900390910190a350600192915050565b600160a060020a03918216600090815260056020908152604080832093909416825291909152205490565b61105f823383610870565b600654600160a060020a0316331461125857600080fd5b610cd281611a3e565b600a60209081526000928352604080842090915290825290205481565b6112898383836118e3565b60001981141561105f57600160a060020a038084166000908152600a60209081526040808320938616835292905290812055505050565b6000903b1190565b6000828211156112d457fe5b50900390565b818101828110156112e757fe5b92915050565b6112f682610e40565b1561105f5760408051600081526020810190915261131990849084908490611330565b151561105f57600080fd5b600061102b8383611abc565b600083600160a060020a031663a4c0ed3660e060020a028685856040516024018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156113a8578181015183820152602001611390565b50505050905090810190601f1680156113d55780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909916989098178852518151919790965086955093509150819050838360005b8381101561146357818101518382015260200161144b565b50505050905090810190601f1680156114905780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af1979650505050505050565b600160a060020a0382166000908152600360205260409020548111156114d257600080fd5b600160a060020a0382166000908152600360205260409020546114fb908263ffffffff6112c816565b600160a060020a038316600090815260036020526040902055600454611527908263ffffffff6112c816565b600455604080518281529051600160a060020a038416917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a2604080518281529051600091600160a060020a03851691600080516020611d728339815191529181900360200190a35050565b80600160a060020a03811615156115b257600080fd5b600160a060020a03831615156115d0576115cb82611b8b565b61105f565b61105f8383611b97565b6000600854826040518082805190602001908083835b6020831061160f5780518252601f1990920191602091820191016115f0565b51815160209384036101000a6000190180199092169116179052604080519290940182900382207f190100000000000000000000000000000000000000000000000000000000000083830152602283019790975260428083019790975283518083039097018752606290910192839052855192945084935085019190508083835b602083106116af5780518252601f199092019160209182019101611690565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912095945050505050565b6000808460ff16601b14806116f957508460ff16601c145b1515611775576040805160e560020a62461bcd02815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f7565000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611813576040805160e560020a62461bcd02815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f7565000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60408051600080825260208083018085528a905260ff8916838501526060830188905260808301879052925160019360a0808501949193601f19840193928390039091019190865af115801561186d573d6000803e3d6000fd5b5050604051601f190151915050600160a060020a03811615156118da576040805160e560020a62461bcd02815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b600160a060020a0383161515611968576040805160e560020a62461bcd028152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a03821615156119ee576040805160e560020a62461bcd02815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a0380841660008181526005602090815260408083209487168084529482529182902085905581518581529151600080516020611d928339815191529281900390910190a3505050565b600160a060020a0381161515611a5357600080fd5b600654604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b33600090815260036020526040812054821115611ad857600080fd5b600160a060020a0383161515611aed57600080fd5b33600090815260036020526040902054611b0d908363ffffffff6112c816565b3360009081526003602052604080822092909255600160a060020a03851681522054611b3f908363ffffffff6112da16565b600160a060020a038416600081815260036020908152604091829020939093558051858152905191923392600080516020611d728339815191529281900390910190a350600192915050565b3031610e0a8282611c44565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290518391600091600160a060020a038416916370a0823191602480830192602092919082900301818787803b158015611bfc57600080fd5b505af1158015611c10573d6000803e3d6000fd5b505050506040513d6020811015611c2657600080fd5b5051905061106f600160a060020a038516848363ffffffff611cac16565b604051600160a060020a0383169082156108fc029083906000818181858888f193505050501515610e0a578082611c79611d41565b600160a060020a039091168152604051908190036020019082f080158015611ca5573d6000803e3d6000fd5b5050505050565b82600160a060020a031663a9059cbb83836040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b158015611d0f57600080fd5b505af1158015611d23573d6000803e3d6000fd5b505050503d1561105f5760206000803e600051151561105f57600080fd5b604051602180611d51833901905600608060405260405160208060218339810160405251600160a060020a038116ff00ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a165627a7a72305820b96bb0733a3e45fdddafa592f51114d0cf16cad047ad60b9b91ae91eb772c6940029" } + }, + "rewriteBytecodeTimestamp": { + "1766419900": { + "0x506d1f9efe24f0d47853adca907eb8d89ae03207": "0x60806040526004361061002c575f3560e01c80638da5cb5b14610037578063b61d27f61461006157610033565b3661003357005b5f5ffd5b348015610042575f5ffd5b5061004b610091565b604051610058919061030a565b60405180910390f35b61007b600480360381019061007691906103e9565b6100a9565b60405161008891906104ca565b60405180910390f35b737be579238a6a621601eae2c346cda54d68f7dfee81565b60606100b3610247565b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610121576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161011890610544565b60405180910390fd5b5f8573ffffffffffffffffffffffffffffffffffffffff163b1161017a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610171906105ac565b60405180910390fd5b5f5f8673ffffffffffffffffffffffffffffffffffffffff168686866040516101a4929190610606565b5f6040518083038185875af1925050503d805f81146101de576040519150601f19603f3d011682016040523d82523d5f602084013e6101e3565b606091505b50915091508161023a575f815111156101ff5780518060208301fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023190610668565b60405180910390fd5b8092505050949350505050565b737be579238a6a621601eae2c346cda54d68f7dfee73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102c0906106d0565b60405180910390fd5b565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102f4826102cb565b9050919050565b610304816102ea565b82525050565b5f60208201905061031d5f8301846102fb565b92915050565b5f5ffd5b5f5ffd5b610334816102ea565b811461033e575f5ffd5b50565b5f8135905061034f8161032b565b92915050565b5f819050919050565b61036781610355565b8114610371575f5ffd5b50565b5f813590506103828161035e565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126103a9576103a8610388565b5b8235905067ffffffffffffffff8111156103c6576103c561038c565b5b6020830191508360018202830111156103e2576103e1610390565b5b9250929050565b5f5f5f5f6060858703121561040157610400610323565b5b5f61040e87828801610341565b945050602061041f87828801610374565b935050604085013567ffffffffffffffff8111156104405761043f610327565b5b61044c87828801610394565b925092505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61049c8261045a565b6104a68185610464565b93506104b6818560208601610474565b6104bf81610482565b840191505092915050565b5f6020820190508181035f8301526104e28184610492565b905092915050565b5f82825260208201905092915050565b7f7a65726f207461726765740000000000000000000000000000000000000000005f82015250565b5f61052e600b836104ea565b9150610539826104fa565b602082019050919050565b5f6020820190508181035f83015261055b81610522565b9050919050565b7f6e6f74206120636f6e74726163740000000000000000000000000000000000005f82015250565b5f610596600e836104ea565b91506105a182610562565b602082019050919050565b5f6020820190508181035f8301526105c38161058a565b9050919050565b5f81905092915050565b828183375f83830152505050565b5f6105ed83856105ca565b93506105fa8385846105d4565b82840190509392505050565b5f6106128284866105e2565b91508190509392505050565b7f63616c6c206661696c65640000000000000000000000000000000000000000005f82015250565b5f610652600b836104ea565b915061065d8261061e565b602082019050919050565b5f6020820190508181035f83015261067f81610646565b9050919050565b7f6e6f74206f776e657200000000000000000000000000000000000000000000005f82015250565b5f6106ba6009836104ea565b91506106c582610686565b602082019050919050565b5f6020820190508181035f8301526106e7816106ae565b905091905056fea2646970667358221220a8334a26f31db2a806db6c1bcc4107caa8ec5cbdc7b742cfec99b4f0cca066a364736f6c634300081e0033" + } } } } @@ -300,4 +305,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs index 9b1cd703442..710fd0c6d5d 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs @@ -21,17 +21,13 @@ using Nethermind.Core.Specs; using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; -using Nethermind.Db; using Nethermind.Evm; using Nethermind.Evm.State; -using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Specs; using Nethermind.Specs.Forks; -using Nethermind.State; -using Nethermind.Trie.Pruning; using Nethermind.TxPool; using NSubstitute; using NUnit.Framework; @@ -95,17 +91,24 @@ public void For_normal_processing_it_should_not_fail_with_gas_remaining_rules() } [Test] - public void Should_rewrite_contracts() + public void Should_rewrite_contracts([Values] bool isPostMerge) { - static BlockHeader Process(BranchProcessor auRaBlockProcessor, BlockHeader parent) + static BlockHeader Process(BranchProcessor auRaBlockProcessor, BlockHeader parent, IBlockTree blockTree, bool isPostMerge) { - BlockHeader header = Build.A.BlockHeader.WithAuthor(TestItem.AddressD).WithParent(parent).TestObject; + BlockHeader header = Build.A.BlockHeader + .WithAuthor(TestItem.AddressD) + .WithParent(parent) + .WithTimestamp(parent.Timestamp + 12) + .WithTotalDifficulty(0).TestObject; + header.IsPostMerge = isPostMerge; Block block = Build.A.Block.WithHeader(header).TestObject; - return auRaBlockProcessor.Process( + BlockHeader res = auRaBlockProcessor.Process( parent, new List { block }, ProcessingOptions.None, NullBlockTracer.Instance)[0].Header; + blockTree.Insert(res); + return res; } Dictionary> contractOverrides = new() @@ -128,8 +131,15 @@ static BlockHeader Process(BranchProcessor auRaBlockProcessor, BlockHeader paren }, }; - (BranchProcessor processor, IWorldState stateProvider) = - CreateProcessor(contractRewriter: new ContractRewriter(contractOverrides)); + (ulong, Address, byte[])[] contractOverridesTimestamp = [ + (1000024, TestItem.AddressC, Bytes.FromHexString("0x123")), + (1000024, TestItem.AddressD, Bytes.FromHexString("0x321")), + (1000036, TestItem.AddressC, Bytes.FromHexString("0x456")), + (1000036, TestItem.AddressD, Bytes.FromHexString("0x654")) + ]; + + (BranchProcessor processor, IWorldState stateProvider, IBlockTree blockTree) = + CreateProcessor(contractRewriter: new ContractRewriter(contractOverrides, contractOverridesTimestamp)); Hash256 stateRoot; @@ -137,6 +147,8 @@ static BlockHeader Process(BranchProcessor auRaBlockProcessor, BlockHeader paren { stateProvider.CreateAccount(TestItem.AddressA, UInt256.One); stateProvider.CreateAccount(TestItem.AddressB, UInt256.One); + stateProvider.CreateAccount(TestItem.AddressC, UInt256.One); + stateProvider.CreateAccount(TestItem.AddressD, UInt256.One); stateProvider.Commit(London.Instance); stateProvider.CommitTree(0); stateProvider.RecalculateStateRoot(); @@ -144,37 +156,44 @@ static BlockHeader Process(BranchProcessor auRaBlockProcessor, BlockHeader paren } BlockHeader currentBlock = Build.A.BlockHeader.WithNumber(0).WithStateRoot(stateRoot).TestObject; - currentBlock = Process(processor, currentBlock); + currentBlock = Process(processor, currentBlock, blockTree, isPostMerge); using (stateProvider.BeginScope(currentBlock)) { stateProvider.GetCode(TestItem.AddressA).Should().BeEquivalentTo(Array.Empty()); stateProvider.GetCode(TestItem.AddressB).Should().BeEquivalentTo(Array.Empty()); + stateProvider.GetCode(TestItem.AddressC).Should().BeEquivalentTo(Array.Empty()); + stateProvider.GetCode(TestItem.AddressD).Should().BeEquivalentTo(Array.Empty()); } - currentBlock = Process(processor, currentBlock); + currentBlock = Process(processor, currentBlock, blockTree, isPostMerge); using (stateProvider.BeginScope(currentBlock)) { stateProvider.GetCode(TestItem.AddressA).Should().BeEquivalentTo(Bytes.FromHexString("0x123")); stateProvider.GetCode(TestItem.AddressB).Should().BeEquivalentTo(Bytes.FromHexString("0x321")); + stateProvider.GetCode(TestItem.AddressC).Should().BeEquivalentTo(Bytes.FromHexString("0x123")); + stateProvider.GetCode(TestItem.AddressD).Should().BeEquivalentTo(Bytes.FromHexString("0x321")); } - currentBlock = Process(processor, currentBlock); + currentBlock = Process(processor, currentBlock, blockTree, isPostMerge); using (stateProvider.BeginScope(currentBlock)) { stateProvider.GetCode(TestItem.AddressA).Should().BeEquivalentTo(Bytes.FromHexString("0x456")); stateProvider.GetCode(TestItem.AddressB).Should().BeEquivalentTo(Bytes.FromHexString("0x654")); + stateProvider.GetCode(TestItem.AddressC).Should().BeEquivalentTo(Bytes.FromHexString("0x456")); + stateProvider.GetCode(TestItem.AddressD).Should().BeEquivalentTo(Bytes.FromHexString("0x654")); } } - private (BranchProcessor Processor, IWorldState StateProvider) CreateProcessor(ITxFilter? txFilter = null, ContractRewriter? contractRewriter = null) + private (BranchProcessor Processor, IWorldState StateProvider, IBlockTree blockTree) CreateProcessor(ITxFilter? txFilter = null, ContractRewriter? contractRewriter = null) { IWorldState stateProvider = TestWorldStateFactory.CreateForTest(); + IBlockTree blockTree = Build.A.BlockTree(GnosisSpecProvider.Instance).TestObject; ITransactionProcessor transactionProcessor = Substitute.For(); - AuRaBlockProcessor processor = new AuRaBlockProcessor( - HoodiSpecProvider.Instance, + AuRaBlockProcessor processor = new( + GnosisSpecProvider.Instance, TestBlockValidator.AlwaysValid, NoBlockRewards.Instance, new BlockProcessor.BlockValidationTransactionsExecutor(new ExecuteTransactionProcessorAdapter(transactionProcessor), stateProvider), @@ -182,22 +201,22 @@ static BlockHeader Process(BranchProcessor auRaBlockProcessor, BlockHeader paren NullReceiptStorage.Instance, new BeaconBlockRootHandler(transactionProcessor, stateProvider), LimboLogs.Instance, - Substitute.For(), + blockTree, new WithdrawalProcessor(stateProvider, LimboLogs.Instance), new ExecutionRequestsProcessor(transactionProcessor), auRaValidator: null, txFilter, contractRewriter: contractRewriter); - BranchProcessor branchProcessor = new BranchProcessor( + BranchProcessor branchProcessor = new( processor, - HoodiSpecProvider.Instance, + GnosisSpecProvider.Instance, stateProvider, new BeaconBlockRootHandler(transactionProcessor, stateProvider), Substitute.For(), LimboLogs.Instance); - return (branchProcessor, stateProvider); + return (branchProcessor, stateProvider, blockTree); } } } diff --git a/src/Nethermind/Nethermind.AuRa.Test/ChainSpecLoaderTest.cs b/src/Nethermind/Nethermind.AuRa.Test/ChainSpecLoaderTest.cs index 0de9680b784..b39857c9c0f 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/ChainSpecLoaderTest.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/ChainSpecLoaderTest.cs @@ -7,7 +7,6 @@ using Nethermind.Consensus.AuRa.Config; using Nethermind.Core; using Nethermind.Core.Extensions; -using Nethermind.Core.Test; using Nethermind.Logging; using Nethermind.Serialization.Json; using Nethermind.Specs; @@ -89,12 +88,31 @@ public void Can_load_posdao_with_rewriteBytecode() } }; - var auraParams = chainSpec.EngineChainSpecParametersProvider.GetChainSpecParameters(); - + AuRaChainSpecEngineParameters auraParams = chainSpec.EngineChainSpecParametersProvider.GetChainSpecParameters(); auraParams.RewriteBytecode.Should().BeEquivalentTo(expected); // posdao.json uses old modexp pricing format (divisor: 20) without modexp2565 transition // Therefore Eip2565Transition should be null chainSpec.Parameters.Eip2565Transition.Should().BeNull(); } + + [Test] + public void Can_load_gnosis_with_rewriteBytecodeGnosis() + { + string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../", "Chains/gnosis.json"); + ChainSpec chainSpec = LoadChainSpec(path); + IDictionary> expected = new Dictionary> + { + { + GnosisSpecProvider.BalancerTimestamp, new Dictionary() + { + {new Address("0x506d1f9efe24f0d47853adca907eb8d89ae03207"), Bytes.FromHexString("0x60806040526004361061002c575f3560e01c80638da5cb5b14610037578063b61d27f61461006157610033565b3661003357005b5f5ffd5b348015610042575f5ffd5b5061004b610091565b604051610058919061030a565b60405180910390f35b61007b600480360381019061007691906103e9565b6100a9565b60405161008891906104ca565b60405180910390f35b737be579238a6a621601eae2c346cda54d68f7dfee81565b60606100b3610247565b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610121576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161011890610544565b60405180910390fd5b5f8573ffffffffffffffffffffffffffffffffffffffff163b1161017a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610171906105ac565b60405180910390fd5b5f5f8673ffffffffffffffffffffffffffffffffffffffff168686866040516101a4929190610606565b5f6040518083038185875af1925050503d805f81146101de576040519150601f19603f3d011682016040523d82523d5f602084013e6101e3565b606091505b50915091508161023a575f815111156101ff5780518060208301fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023190610668565b60405180910390fd5b8092505050949350505050565b737be579238a6a621601eae2c346cda54d68f7dfee73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102c0906106d0565b60405180910390fd5b565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102f4826102cb565b9050919050565b610304816102ea565b82525050565b5f60208201905061031d5f8301846102fb565b92915050565b5f5ffd5b5f5ffd5b610334816102ea565b811461033e575f5ffd5b50565b5f8135905061034f8161032b565b92915050565b5f819050919050565b61036781610355565b8114610371575f5ffd5b50565b5f813590506103828161035e565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126103a9576103a8610388565b5b8235905067ffffffffffffffff8111156103c6576103c561038c565b5b6020830191508360018202830111156103e2576103e1610390565b5b9250929050565b5f5f5f5f6060858703121561040157610400610323565b5b5f61040e87828801610341565b945050602061041f87828801610374565b935050604085013567ffffffffffffffff8111156104405761043f610327565b5b61044c87828801610394565b925092505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61049c8261045a565b6104a68185610464565b93506104b6818560208601610474565b6104bf81610482565b840191505092915050565b5f6020820190508181035f8301526104e28184610492565b905092915050565b5f82825260208201905092915050565b7f7a65726f207461726765740000000000000000000000000000000000000000005f82015250565b5f61052e600b836104ea565b9150610539826104fa565b602082019050919050565b5f6020820190508181035f83015261055b81610522565b9050919050565b7f6e6f74206120636f6e74726163740000000000000000000000000000000000005f82015250565b5f610596600e836104ea565b91506105a182610562565b602082019050919050565b5f6020820190508181035f8301526105c38161058a565b9050919050565b5f81905092915050565b828183375f83830152505050565b5f6105ed83856105ca565b93506105fa8385846105d4565b82840190509392505050565b5f6106128284866105e2565b91508190509392505050565b7f63616c6c206661696c65640000000000000000000000000000000000000000005f82015250565b5f610652600b836104ea565b915061065d8261061e565b602082019050919050565b5f6020820190508181035f83015261067f81610646565b9050919050565b7f6e6f74206f776e657200000000000000000000000000000000000000000000005f82015250565b5f6106ba6009836104ea565b91506106c582610686565b602082019050919050565b5f6020820190508181035f8301526106e7816106ae565b905091905056fea2646970667358221220a8334a26f31db2a806db6c1bcc4107caa8ec5cbdc7b742cfec99b4f0cca066a364736f6c634300081e0033")}, + } + } + }; + + AuRaChainSpecEngineParameters auraParams = chainSpec.EngineChainSpecParametersProvider.GetChainSpecParameters(); + + auraParams.RewriteBytecodeTimestamp.Should().BeEquivalentTo(expected); + } } diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs index c4de02bb510..b710603c74f 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs @@ -80,11 +80,7 @@ public AuRaBlockProcessor(ISpecProvider specProvider, protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options, IReleaseSpec spec, CancellationToken token) { ValidateAuRa(block); - bool wereChanges = _contractRewriter?.RewriteContracts(block.Number, _stateProvider, spec) ?? false; - if (wereChanges) - { - _stateProvider.Commit(spec, commitRoots: true); - } + RewriteContracts(block, spec); AuRaValidator.OnBlockProcessingStart(block, options); TxReceipt[] receipts = base.ProcessBlock(block, blockTracer, options, spec, token); AuRaValidator.OnBlockProcessingEnd(block, receipts, options); @@ -92,9 +88,25 @@ protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTrace return receipts; } + private void RewriteContracts(Block block, IReleaseSpec spec) + { + bool wereChanges = _contractRewriter?.RewriteContracts(block.Number, _stateProvider, spec) ?? false; + BlockHeader? parent = _blockTree.FindParentHeader(block.Header, BlockTreeLookupOptions.None); + if (parent is not null) + { + wereChanges |= _contractRewriter?.RewriteContracts(block.Timestamp, parent.Timestamp, _stateProvider, spec) ?? false; + } + + if (wereChanges) + { + _stateProvider.Commit(spec, commitRoots: true); + } + } + // After PoS switch we need to revert to standard block processing, ignoring AuRa customizations protected TxReceipt[] PostMergeProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options, IReleaseSpec spec, CancellationToken token) { + RewriteContracts(block, spec); return base.ProcessBlock(block, blockTracer, options, spec, token); } diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaPlugin.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaPlugin.cs index 08f737898b7..d7f682349a3 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaPlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaPlugin.cs @@ -152,7 +152,8 @@ protected override void Load(ContainerBuilder builder) ITxFilter txFilter = txAuRaFilterBuilders.CreateAuRaTxFilter(new ServiceTxFilter()); IDictionary> rewriteBytecode = parameters.RewriteBytecode; - ContractRewriter? contractRewriter = rewriteBytecode?.Count > 0 ? new ContractRewriter(rewriteBytecode) : null; + (ulong, Address, byte[])[] rewriteBytecodeTimestamp = [.. parameters.RewriteBytecodeTimestampParsed]; + ContractRewriter? contractRewriter = rewriteBytecode?.Count > 0 || rewriteBytecodeTimestamp?.Length > 0 ? new(rewriteBytecode, rewriteBytecodeTimestamp) : null; AuRaContractGasLimitOverride? gasLimitOverride = gasLimitOverrideFactory.GetGasLimitCalculator(); diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Config/AuRaChainSpecEngineParameters.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Config/AuRaChainSpecEngineParameters.cs index c1beed8e1e8..705f81b1063 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Config/AuRaChainSpecEngineParameters.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Config/AuRaChainSpecEngineParameters.cs @@ -9,6 +9,7 @@ using System.Text.Json.Serialization; using Nethermind.Consensus.AuRa.Validators; using Nethermind.Core; +using Nethermind.Core.Collections; using Nethermind.Int256; using Nethermind.Specs; using Nethermind.Specs.ChainSpecStyle; @@ -54,6 +55,21 @@ public class AuRaChainSpecEngineParameters : IChainSpecEngineParameters public long PosdaoTransition { get; set; } = TransitionDisabled; public IDictionary> RewriteBytecode { get; set; } = new Dictionary>(); + public IDictionary> RewriteBytecodeTimestamp { get; set; } = new Dictionary>(); + + public IEnumerable<(ulong, Address, byte[])> RewriteBytecodeTimestampParsed + { + get + { + foreach (KeyValuePair> timestampOverrides in RewriteBytecodeTimestamp) + { + foreach (KeyValuePair addressOverride in timestampOverrides.Value) + { + yield return (timestampOverrides.Key, addressOverride.Key, addressOverride.Value); + } + } + } + } public Address WithdrawalContractAddress { get; set; } @@ -70,6 +86,11 @@ public void ApplyToReleaseSpec(ReleaseSpec spec, long startBlock, ulong? startTi spec.MaximumUncleCount = (int)(startBlock >= (MaximumUncleCountTransition ?? long.MaxValue) ? MaximumUncleCount ?? 2 : 2); } + public void AddTransitions(SortedSet blockNumbers, SortedSet timestamps) + { + timestamps.AddRange(RewriteBytecodeTimestamp.Keys); + } + static AuRaParameters.Validator LoadValidator(AuRaValidatorJson validatorJson, int level = 0) { AuRaParameters.ValidatorType validatorType = validatorJson.GetValidatorType(); diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/ContractRewriter.cs b/src/Nethermind/Nethermind.Consensus.AuRa/ContractRewriter.cs index 02498c9c75e..a0d55dae611 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/ContractRewriter.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/ContractRewriter.cs @@ -8,26 +8,51 @@ namespace Nethermind.Consensus.AuRa; -public class ContractRewriter +public class ContractRewriter( + IDictionary> contractOverrides, + (ulong, Address, byte[])[] contractOverridesTimestamp) { - private readonly IDictionary> _contractOverrides; + private readonly IDictionary> _contractOverrides = contractOverrides; + private readonly (ulong, Address, byte[])[] _contractOverridesTimestamp = contractOverridesTimestamp; - public ContractRewriter(IDictionary> contractOverrides) + public bool RewriteContracts(long blockNumber, IWorldState stateProvider, IReleaseSpec spec) { - _contractOverrides = contractOverrides; + bool result = false; + if (_contractOverrides.TryGetValue(blockNumber, out IDictionary overrides)) + { + result = InsertOverwriteCode(overrides, stateProvider, spec); + } + return result; } - public bool RewriteContracts(long blockNumber, IWorldState stateProvider, IReleaseSpec spec) + public bool RewriteContracts(ulong timestamp, ulong parentTimestamp, IWorldState stateProvider, IReleaseSpec spec) { bool result = false; - if (_contractOverrides.TryGetValue(blockNumber, out IDictionary overrides)) + foreach ((ulong Timestamp, Address Address, byte[] Code) codeOverride in _contractOverridesTimestamp) { - foreach (KeyValuePair contractOverride in overrides) + if (timestamp >= codeOverride.Timestamp && parentTimestamp < codeOverride.Timestamp) { - stateProvider.InsertCode(contractOverride.Key, contractOverride.Value, spec); + InsertOverwriteCode(codeOverride.Address, codeOverride.Code, stateProvider, spec); result = true; } } return result; } + + private static bool InsertOverwriteCode(IDictionary overrides, IWorldState stateProvider, IReleaseSpec spec) + { + bool result = false; + foreach (KeyValuePair contractOverride in overrides) + { + InsertOverwriteCode(contractOverride.Key, contractOverride.Value, stateProvider, spec); + result = true; + } + return result; + } + + private static void InsertOverwriteCode(Address address, byte[] code, IWorldState stateProvider, IReleaseSpec spec) + { + stateProvider.CreateAccountIfNotExists(address, 0, 0); + stateProvider.InsertCode(address, code, spec); + } } diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs index a92127f90d7..0254a504f2c 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs @@ -26,7 +26,6 @@ using Nethermind.Consensus.Validators; using Nethermind.Consensus.Withdrawals; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.Evm.State; @@ -158,7 +157,8 @@ private BlockProcessor CreateBlockProcessor(ITransactionProcessor txProcessor, I } IDictionary> rewriteBytecode = _parameters.RewriteBytecode; - ContractRewriter? contractRewriter = rewriteBytecode?.Count > 0 ? new ContractRewriter(rewriteBytecode) : null; + (ulong, Address, byte[])[] rewriteBytecodeTimestamp = [.. _parameters.RewriteBytecodeTimestampParsed]; + ContractRewriter? contractRewriter = rewriteBytecode?.Count > 0 || rewriteBytecodeTimestamp?.Length > 0 ? new(rewriteBytecode, rewriteBytecodeTimestamp) : null; var transactionExecutor = new BlockProcessor.BlockProductionTransactionsExecutor( new BuildUpTransactionProcessorAdapter(txProcessor), diff --git a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs index 6095b4a9224..8e33c0c7324 100644 --- a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs @@ -151,9 +151,11 @@ public void Fork_id_and_hash_as_expected_on_sepolia(long head, ulong headTimesta [TestCase(21735000, 0ul, "0x018479d3", GnosisSpecProvider.ShanghaiTimestamp, "First GIP-31 block")] [TestCase(31735000, GnosisSpecProvider.ShanghaiTimestamp, "0x2efe91ba", GnosisSpecProvider.CancunTimestamp, "First Shanghai timestamp")] [TestCase(41735000, GnosisSpecProvider.CancunTimestamp, "0x1384dfc1", GnosisSpecProvider.PragueTimestamp, "First Cancun timestamp")] - [TestCase(91735000, GnosisSpecProvider.CancunTimestamp, "0x1384dfc1", GnosisSpecProvider.PragueTimestamp, "Future Cancun timestamp")] - [TestCase(101735000, GnosisSpecProvider.PragueTimestamp, "0x2f095d4a", 0ul, "First Prague timestamp")] - [TestCase(101735000, GnosisSpecProvider.PragueTimestamp, "0x2f095d4a", 0ul, "Future Prague timestamp")] + [TestCase(91735000, GnosisSpecProvider.PragueTimestamp - 1, "0x1384dfc1", GnosisSpecProvider.PragueTimestamp, "Future Cancun timestamp")] + [TestCase(101735000, GnosisSpecProvider.PragueTimestamp, "0x2f095d4a", GnosisSpecProvider.BalancerTimestamp, "First Prague timestamp")] + [TestCase(101735000, GnosisSpecProvider.BalancerTimestamp - 1, "0x2f095d4a", GnosisSpecProvider.BalancerTimestamp, "Future Prague timestamp")] + [TestCase(111735000, GnosisSpecProvider.BalancerTimestamp, "0xd00284ad", 0ul, "First Balancer timestamp")] + [TestCase(111735000, GnosisSpecProvider.BalancerTimestamp + 100, "0xd00284ad", 0ul, "First Balancer timestamp")] public void Fork_id_and_hash_as_expected_on_gnosis(long head, ulong headTimestamp, string forkHashHex, ulong next, string description) { ChainSpecFileLoader loader = new(new EthereumJsonSerializer(), LimboTraceLogger.Instance); diff --git a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs index bef4339d291..91f6883c28f 100644 --- a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core; @@ -20,6 +20,7 @@ public class GnosisSpecProvider : ISpecProvider public const ulong ShanghaiTimestamp = 0x64c8edbc; public const ulong CancunTimestamp = 0x65ef4dbc; public const ulong PragueTimestamp = 0x68122dbc; + public const ulong BalancerTimestamp = 0x69496dbc; // does not alter specs public static readonly Address FeeCollector = new("0x6BBe78ee9e474842Dbd4AB4987b3CeFE88426A92"); private GnosisSpecProvider() { } From 4684324a9c6079748b4e494ddb6879b4479a3c2b Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Tue, 16 Dec 2025 21:08:15 +0100 Subject: [PATCH 085/255] Sign release builds (#9937) --- .../workflows/build-nethermind-packages.yml | 11 ++- .github/workflows/publish-nuget.yml | 21 +++++- .github/workflows/publish-packages.yml | 17 ++--- .github/workflows/release.yml | 67 ++++++++++++++----- scripts/build/publish-github.sh | 66 ------------------ 5 files changed, 85 insertions(+), 97 deletions(-) delete mode 100755 scripts/build/publish-github.sh diff --git a/.github/workflows/build-nethermind-packages.yml b/.github/workflows/build-nethermind-packages.yml index 030e1905e2c..a3e8263dacf 100644 --- a/.github/workflows/build-nethermind-packages.yml +++ b/.github/workflows/build-nethermind-packages.yml @@ -11,7 +11,6 @@ jobs: PACKAGE_DIR: pkg PACKAGE_RETENTION: 7 PUB_DIR: pub - SCRIPTS_PATH: ${{ github.workspace }}/scripts/build steps: - name: Check out repository uses: actions/checkout@v6 @@ -29,16 +28,14 @@ jobs: - name: Build Nethermind.Runner run: | - mkdir $GITHUB_WORKSPACE/$PUB_DIR - - docker build . -t nethermind-build -f $SCRIPTS_PATH/Dockerfile \ + mkdir $PUB_DIR + docker build . -t nethermind-build -f scripts/build/Dockerfile \ --build-arg COMMIT_HASH=$GITHUB_SHA \ --build-arg SOURCE_DATE_EPOCH=$(git log -1 --format=%ct) - - docker run --rm --mount type=bind,source=$GITHUB_WORKSPACE/$PUB_DIR,target=/output nethermind-build + docker run --rm --mount type=bind,source=./$PUB_DIR,target=/output nethermind-build - name: Archive packages - run: $SCRIPTS_PATH/archive.sh + run: scripts/build/archive.sh - name: Upload Nethermind Linux arm64 package uses: actions/upload-artifact@v4 diff --git a/.github/workflows/publish-nuget.yml b/.github/workflows/publish-nuget.yml index d2b44cbbb77..c9495bd65f8 100644 --- a/.github/workflows/publish-nuget.yml +++ b/.github/workflows/publish-nuget.yml @@ -14,16 +14,35 @@ jobs: uses: actions/checkout@v6 with: ref: ${{ github.event.release.tag_name }} + - name: Set up .NET uses: actions/setup-dotnet@v5 + - name: Download Nethermind reference assemblies + id: download run: | json=$(curl -s ${{ github.event.release.assets_url }}) - url=$(echo "$json" | jq -r '.[].browser_download_url | select(contains("ref-assemblies"))') + asset=$(echo "$json" | jq -r '.[] | select(.name | contains("ref-assemblies"))') + name=$(echo "$asset" | jq -r '.name') + url=$(echo "$asset" | jq -r '.browser_download_url') curl -sL $url -o refasm.zip unzip refasm.zip -d src/Nethermind/Nethermind.ReferenceAssemblies/ref + echo "asset-name=$name" >> $GITHUB_OUTPUT + - name: Submit package working-directory: src/Nethermind/Nethermind.ReferenceAssemblies run: | dotnet pack -c release dotnet nuget push ../artifacts/**/*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json + + - name: Create GitHub app token + id: gh-app + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ vars.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + + - name: Delete asset from release + env: + GITHUB_TOKEN: ${{ steps.gh-app.outputs.token }} + run: gh release delete-asset ${{ github.event.release.tag_name }} ${{ steps.download.outputs.asset-name }} -y diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml index 2596058e076..8c57f6e7a28 100644 --- a/.github/workflows/publish-packages.yml +++ b/.github/workflows/publish-packages.yml @@ -34,9 +34,9 @@ jobs: run: | version=${{ github.event.release.tag_name }} json=$(curl -sL ${{ github.event.release.assets_url }}) - arm64_url=$(echo "$json" | jq -r '.[].browser_download_url | select(contains("linux-arm64"))') + arm64_url=$(echo "$json" | jq -r '.[].browser_download_url | select(endswith("linux-arm64.zip"))') arm64_hash=$(curl -sL $arm64_url | sha256sum | awk '{print $1}') - x64_url=$(echo "$json" | jq -r '.[].browser_download_url | select(contains("linux-x64"))') + x64_url=$(echo "$json" | jq -r '.[].browser_download_url | select(endswith("linux-x64.zip"))') x64_hash=$(curl -sL $x64_url | sha256sum | awk '{print $1}') awk -i inplace -v n=1 '/url/ { if (++count == n) sub(/url.*/, "url='$arm64_url'"); } 1' debian/postinst awk -i inplace -v n=2 '/url/ { if (++count == n) sub(/url.*/, "url='$x64_url'"); } 1' debian/postinst @@ -92,7 +92,7 @@ jobs: WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_TOKEN }} run: | $releaseInfo = curl -sL ${{ github.event.release.assets_url }} | ConvertFrom-Json - $releaseUrl = $releaseInfo | Where-Object -Property name -match 'windows' | Select -ExpandProperty browser_download_url + $releaseUrl = $releaseInfo | Where-Object -Property name -like '*windows-x64.zip' | Select-Object -ExpandProperty browser_download_url curl -sL https://aka.ms/wingetcreate/latest -o wingetcreate.exe ./wingetcreate update Nethermind.Nethermind -s -v ${{ github.event.release.tag_name }} -u $releaseUrl @@ -103,13 +103,13 @@ jobs: env: FORMULA: nethermind.rb steps: - - name: Authenticate App + - name: Create GitHub app token id: gh-app uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }} - repositories: "homebrew-nethermind" + repositories: homebrew-nethermind - name: Check out homebrew-nethermind repository uses: actions/checkout@v6 @@ -120,15 +120,16 @@ jobs: - name: Update formula file run: | json=$(curl -sL ${{ github.event.release.assets_url }}) - x64_url=$(echo "$json" | jq -r '.[].browser_download_url | select(contains("macos-x64"))') - x64_hash=$(curl -sL $x64_url | shasum -a 256 | awk '{print $1}') - arm64_url=$(echo "$json" | jq -r '.[].browser_download_url | select(contains("macos-arm64"))') + arm64_url=$(echo "$json" | jq -r '.[].browser_download_url | select(endswith("macos-arm64.zip"))') arm64_hash=$(curl -sL $arm64_url | shasum -a 256 | awk '{print $1}') + x64_url=$(echo "$json" | jq -r '.[].browser_download_url | select(endswith("macos-x64.zip"))') + x64_hash=$(curl -sL $x64_url | shasum -a 256 | awk '{print $1}') sed -i "s/version .*/version \"${{ github.event.release.tag_name }}\"/" $FORMULA awk -i inplace -v n=1 '/url/ { if (++count == n) sub(/url.*/, "url \"'$x64_url'\""); } 1' $FORMULA awk -i inplace -v n=2 '/url/ { if (++count == n) sub(/url.*/, "url \"'$arm64_url'\""); } 1' $FORMULA awk -i inplace -v n=1 '/sha256/ { if (++count == n) sub(/sha256.*/, "sha256 \"'$x64_hash'\""); } 1' $FORMULA awk -i inplace -v n=2 '/sha256/ { if (++count == n) sub(/sha256.*/, "sha256 \"'$arm64_hash'\""); } 1' $FORMULA + - name: Submit package env: GH_TOKEN: ${{ steps.gh-app.outputs.token }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3743330f3e0..4690a16497b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,6 @@ env: PACKAGE_DIR: pkg PACKAGE_RETENTION: 7 PUB_DIR: pub - SCRIPTS_PATH: ${{ github.workspace }}/scripts/build jobs: build: @@ -44,16 +43,29 @@ jobs: - name: Build Nethermind.Runner id: build run: | - mkdir $GITHUB_WORKSPACE/$PUB_DIR - - docker build . -t nethermind-build -f $SCRIPTS_PATH/Dockerfile \ + mkdir $PUB_DIR + docker build . -t nethermind-build -f scripts/build/Dockerfile \ --build-arg COMMIT_HASH=$GITHUB_SHA \ --build-arg SOURCE_DATE_EPOCH=$(git log -1 --format=%ct) - - docker run --rm --mount type=bind,source=$GITHUB_WORKSPACE/$PUB_DIR,target=/output nethermind-build + docker run --rm --mount type=bind,source=./$PUB_DIR,target=/output nethermind-build - name: Archive packages - run: $SCRIPTS_PATH/archive.sh + run: scripts/build/archive.sh + + - name: Sign packages + env: + GPG_PASSPHRASE: ${{ secrets.PPA_GPG_PASSPHRASE }} + GPG_SECRET_KEY: ${{ secrets.PPA_GPG_SECRET_KEY }} + working-directory: ${{ env.PACKAGE_DIR }} + run: | + printf '%s' "$GPG_SECRET_KEY" | base64 --decode | gpg --import --no-tty --batch --yes + + for rid in "linux-arm64" "linux-x64" "macos-arm64" "macos-x64" "windows-x64"; do + file_name=$(basename *$rid*) + gpg --no-tty --batch --yes --pinentry-mode loopback \ + --passphrase-file <(printf '%s' "$GPG_PASSPHRASE") \ + -o "$file_name.asc" -ab "$file_name" + done - name: Upload Nethermind Linux arm64 package uses: actions/upload-artifact@v4 @@ -116,7 +128,7 @@ jobs: - name: Check out Nethermind repository uses: actions/checkout@v6 - - name: Authenticate App + - name: Create GitHub app token id: gh-app uses: actions/create-github-app-token@v2 with: @@ -132,12 +144,38 @@ jobs: env: GIT_TAG: ${{ needs.build.outputs.version }} GITHUB_TOKEN: ${{ steps.gh-app.outputs.token }} - PACKAGE_PREFIX: ${{ needs.build.outputs.package-prefix }} - PRERELEASE: ${{ needs.build.outputs.prerelease }} run: | - cp $GITHUB_WORKSPACE/$PACKAGE_DIR/**/*.zip $GITHUB_WORKSPACE/$PACKAGE_DIR - rm -rf $GITHUB_WORKSPACE/$PACKAGE_DIR/*/ - $SCRIPTS_PATH/publish-github.sh + cp $PACKAGE_DIR/**/*.zip $PACKAGE_DIR/**/*.zip.asc $PACKAGE_DIR + rm -rf $PACKAGE_DIR/*/ + echo "Publishing packages to GitHub" + prerelease=${{ needs.build.outputs.prerelease && '1' || '' }} + if gh release view $GIT_TAG >/dev/null 2>&1; then publish=1; else publish=0; fi + + if (( !publish )); then + echo "Drafting release $GIT_TAG" + relnotes=$(cat <<'EOF' + # Release notes + + ### [CONTENT PLACEHOLDER] + + #### Build signatures + + The packages are signed with the following OpenPGP key: `AD12 7976 5093 C675 9CD8 A400 24A7 7461 6F1E 617E` + EOF + ) + gh release create $GIT_TAG -t v$GIT_TAG -d ${prerelease:+-p} -F <(printf '%s' "$relnotes") + fi + + cd $PACKAGE_DIR + echo "Uploading assets" + gh release upload $GIT_TAG *.zip *.zip.asc + + if (( publish )); then + echo "Publishing release $GIT_TAG" + gh release edit $GIT_TAG --verify-tag -t v$GIT_TAG ${prerelease:+-p} ${prerelease:---latest} + fi + + echo "Publishing completed" publish-docker: name: Publish to Docker Hub @@ -147,7 +185,7 @@ jobs: - name: Check out Nethermind repository uses: actions/checkout@v6 - - name: Authenticate App + - name: Create GitHub app token id: gh-app uses: actions/create-github-app-token@v2 with: @@ -172,7 +210,6 @@ jobs: for suffix in "" ".chiseled"; do tag_suffix=$([[ -z "$suffix" ]] && echo "" || echo "-${suffix:1}") - docker buildx build . --platform=linux/amd64,linux/arm64 -f Dockerfile$suffix \ ${{ needs.build.outputs.prerelease == 'false' && '-t $image:latest$tag_suffix' || '' }} \ -t "$image:${{ needs.build.outputs.version }}$tag_suffix" \ diff --git a/scripts/build/publish-github.sh b/scripts/build/publish-github.sh deleted file mode 100755 index 121a6975643..00000000000 --- a/scripts/build/publish-github.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash -# SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -# SPDX-License-Identifier: LGPL-3.0-only - -set -e - -echo "Publishing packages to GitHub" - -release_id=$(curl https://api.github.com/repos/$GITHUB_REPOSITORY/releases \ - -X GET \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer $GITHUB_TOKEN" | jq -r '.[] | select(.tag_name == "'$GIT_TAG'") | .id') - -should_publish=true - -if [[ -z "$release_id" ]]; then - echo "Drafting release $GIT_TAG" - - body=$(printf \ - '{"tag_name": "%s", "target_commitish": "%s", "name": "v%s", "body": "# Release notes\\n\\n", "draft": true, "prerelease": %s}' \ - $GIT_TAG $GITHUB_SHA $GIT_TAG $PRERELEASE) - - release_id=$(curl https://api.github.com/repos/$GITHUB_REPOSITORY/releases \ - -X POST \ - --fail-with-body \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer $GITHUB_TOKEN" \ - -d "$body" | jq -r '.id') - - should_publish=false -fi - -cd $GITHUB_WORKSPACE/$PACKAGE_DIR - -for rid in "linux-arm64" "linux-x64" "macos-arm64" "macos-x64" "windows-x64" "ref-assemblies"; do - file_name=$(basename *$rid*) - - echo "Uploading $file_name" - - curl https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/$release_id/assets?name=$file_name \ - -X POST \ - --fail-with-body \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer $GITHUB_TOKEN" \ - -H "Content-Type: application/octet-stream" \ - --data-binary @"$file_name" -done - -if [[ "$should_publish" == "true" ]]; then - echo "Publishing release $GIT_TAG" - - make_latest=$([[ "$PRERELEASE" == "true" ]] && echo "false" || echo "true") - - body=$(printf \ - '{"target_commitish": "%s", "name": "v%s", "draft": false, "make_latest": "%s", "prerelease": %s}' \ - $GITHUB_SHA $GIT_TAG $make_latest $PRERELEASE) - - curl https://api.github.com/repos/$GITHUB_REPOSITORY/releases/$release_id \ - -X PATCH \ - --fail-with-body \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer $GITHUB_TOKEN" \ - -d "$body" -fi - -echo "Publishing completed" From a1d41086f7d5abd50a910ed4f6f687e1ac8b9f47 Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Wed, 17 Dec 2025 12:49:57 +0100 Subject: [PATCH 086/255] Increase default rlp collection limit to 4MB (#9957) --- src/Nethermind/Nethermind.Serialization.Rlp/RlpLimit.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/RlpLimit.cs b/src/Nethermind/Nethermind.Serialization.Rlp/RlpLimit.cs index b794d2090d1..2da1c24da2b 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/RlpLimit.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/RlpLimit.cs @@ -10,7 +10,7 @@ namespace Nethermind.Serialization.Rlp; public record struct RlpLimit(int Limit, string TypeName = "", ReadOnlyMemory PropertyName = default) { - // We shouldn't allocate any single array bigger than 1M + // We shouldn't allocate any single array bigger than 4M public static readonly RlpLimit DefaultLimit = new(); public static readonly RlpLimit Bloom = For(Core.Bloom.ByteLength); public static readonly RlpLimit L4 = new(4); @@ -20,7 +20,7 @@ public record struct RlpLimit(int Limit, string TypeName = "", ReadOnlyMemory Date: Thu, 18 Dec 2025 12:16:31 +0100 Subject: [PATCH 087/255] Auto-update fast sync settings (#9964) Co-authored-by: kamilchodola --- src/Nethermind/Nethermind.Runner/configs/base-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/base-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/chiado.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/gnosis.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/joc-testnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sepolia.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-mainnet.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-sepolia.json | 4 ++-- 14 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index 8a663659b58..1409e9e1e44 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 39430000, - "PivotHash": "0xd8a2be662628c294991c74aac8c3b329dddde2d59d36d40e35a2efe282c0213e" + "PivotNumber": 39620000, + "PivotHash": "0x11d162aaef5cd230f283abe65b55adeac1f9c287b13b286c257a4e0423fe2ba9" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index 1fff2474ded..c8c2117e48e 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 34940000, - "PivotHash": "0x2a7dc9daa709a6d3764ebbcb7e8c6c76d5c4d85682bdcd68f70079695558449c" + "PivotNumber": 35130000, + "PivotHash": "0xf15b14c3e63b1e81aa3123bec4028b4dc39374ddec42dcee6ac0280c2142ac90" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.json b/src/Nethermind/Nethermind.Runner/configs/chiado.json index 243bee7e36d..386570d5a5d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.json +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.json @@ -18,8 +18,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 19220000, - "PivotHash": "0xb50db9ad75826fda6a46c1c638867f9ff33d1569439fc69bdfe80daded1e003b", + "PivotNumber": 19290000, + "PivotHash": "0x566186d34021566f4b7ffb9b4a69d17388c8c6deb12e661b2a52ff84da41ca46", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": 10000000000, "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.json b/src/Nethermind/Nethermind.Runner/configs/gnosis.json index d2d51b23b36..78c0d137c26 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.json +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.json @@ -14,8 +14,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 43620000, - "PivotHash": "0x231c912a780bd0e68440db9b97fb01f5cd98d8efcac983fe1ba0c9b21a890f5e", + "PivotNumber": 43700000, + "PivotHash": "0x11d61ff1fad7e3d718e7dc2cb8d1c92002de4c1b8bf84c91ced85ac6c160797a", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000, diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json index 2ce10b1cbb5..5d129dd23c2 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 21200000, - "PivotHash": "0x9d93c2f009f93a4d42ee60fa2ba6ca417262d9c48b1dc8a1fa024a3c2abd407b", - "PivotTotalDifficulty": "38299258" + "PivotNumber": 21280000, + "PivotHash": "0xfb02d595da52ec9b0786e49aedb95fa3e951610bac60d1c4f7e82b64914a5c5f", + "PivotTotalDifficulty": "38417974" }, "Metrics": { "NodeName": "JOC-Mainnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json index ef4fc753a69..eb02506e5d7 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 14810000, - "PivotHash": "0x60d753d8e2a77906e13afeb59724e46baed553b41d4f68b7cb08769843929783", - "PivotTotalDifficulty": "24684265" + "PivotNumber": 14880000, + "PivotHash": "0x0330ea0f3aabd4b3028160bd9a72537f19be3f882dbb21124dfdaa2eba897e4e", + "PivotTotalDifficulty": "24793747" }, "Metrics": { "NodeName": "JOC-Testnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json index f2d85dd3c12..fa74ec60d2a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 26640000, - "PivotHash": "0x1488cbc5d34bec7d0bf5b6c45e8f9b459432085df6394e584364ba56d9e0c35a", + "PivotNumber": 26810000, + "PivotHash": "0xd167ec6b9abec18e0177e653eb820e4f01e76f74771ca85ffe4c0a7e601295f5", "PivotTotalDifficulty": "0", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json index a6c1c20c6ce..1974130d56a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 21980000, - "PivotHash": "0xd659545fc933b0b0f9c380b17aee455745d2c07d2e58ba90e64a29cbfd5a74f6", + "PivotNumber": 22170000, + "PivotHash": "0xc59438af96822433eecaecbe039d4c8fc1c39f40a08147b30007511dac2bebee", "PivotTotalDifficulty": "37331807", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index 3e60d205321..3063dde0b2b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -10,8 +10,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 24006000, - "PivotHash": "0x85fcf18757692f28b86ecbe9f53b2585d34e1e5628cb8d931095ddde297b57b3", + "PivotNumber": 24038000, + "PivotHash": "0xb4a0f7ea2cdbf38eccd02e9886c84b54f46e19c47f211331b50d37457591b4cb", "PivotTotalDifficulty": "58750003716598352816469", "FastSyncCatchUpHeightDelta": "10000000000", "AncientReceiptsBarrier": 15537394, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index 28bdd097e74..cde07f1ce99 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -15,8 +15,8 @@ "FastSyncCatchUpHeightDelta": "10000000000", "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, - "PivotNumber": 145020000, - "PivotHash": "0x4a0fe1c9d2d524e86bfe1616776eccef51dc0ae4f52ccc75be6d78250ea69fb1" + "PivotNumber": 145220000, + "PivotHash": "0x98023a4c5642b838ff8ddd30599e41677fbf390239922c3500e97652d4457f25" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index 730e6cd78f5..99129734a1b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 36920000, - "PivotHash": "0xaaeb3d1d61a6c15e2ec8e47d0ce484d7f63ff3c3ee1bbc7bdfe6f002e8e9691c" + "PivotNumber": 37110000, + "PivotHash": "0xd42d26ed6ba04979fdb91ec8f5fecd8107bd22e2bb5ced0fe6da1f385bfaa710" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index 16012549209..7a55dc6d32e 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -17,8 +17,8 @@ "FastSync": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 9834000, - "PivotHash": "0xfa68a96d9a0535ee4bd8bd5296eaf18e7cde94837a9f7666d64fc51dadcfcc47", + "PivotNumber": 9865000, + "PivotHash": "0x9968e7b98d7356e1d04c5622ca7bb5690cb9ff125756739cee12825c6d1ea76e", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 1450409, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index 3fef418af9c..6c1dd05d974 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 23160000, - "PivotHash": "0xd142112c202e111d34d1fa01a3e2ce669e372fb463960fcac81e48060f2734a7" + "PivotNumber": 23350000, + "PivotHash": "0x2a465940100d53df2bfd56ed499ffdf166fa8ef48d7917c04bc87cdb14deea7e" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index 01f0118da44..7d9ba964a49 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 22550000, - "PivotHash": "0xc6cb3a21f360071de9a7450f933c33a146e5cb1dffb152a45da3f00bf9ebc673" + "PivotNumber": 22740000, + "PivotHash": "0xf1bf98478bdb00ff8b5201917cb67c4eeffa238b8de28af92f9a5fb73aaf276c" }, "Discovery": { "DiscoveryVersion": "V5" From 168fc481b4a3775076a85a23d2fdba308c5967ac Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Thu, 18 Dec 2025 14:19:08 +0100 Subject: [PATCH 088/255] Fix/limit get proof (#9967) * limit and deduplicate getProof * const * fix merge --- .../Modules/Eth/EthRpcModuleTests.cs | 11 ++++++++++- .../Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs | 11 +++++++++-- .../Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs | 6 +++++- src/Nethermind/Nethermind.Optimism/CL/IL2Api.cs | 3 ++- src/Nethermind/Nethermind.Optimism/CL/L2Api.cs | 3 ++- .../Nethermind.State/Proofs/AccountProofCollector.cs | 4 ++-- 6 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index 98d795f7cb7..9f8c5fb387e 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -33,6 +33,7 @@ using Nethermind.Facade.Filters; using Nethermind.Int256; using Nethermind.JsonRpc.Client; +using Nethermind.JsonRpc.Modules.Eth; using Nethermind.Serialization.Json; using Nethermind.Serialization.Rlp; using Nethermind.Specs; @@ -820,13 +821,21 @@ public async Task Eth_get_proof() } [Test] - public async Task Eth_get_proof_withTrimmedStorageKey() + public async Task Eth_get_proof_withTrimmedAndDuplicatedStorageKey() { using Context ctx = await Context.Create(); string serialized = await ctx.Test.TestEthRpc("eth_getProof", TestBlockchain.AccountA.ToString(), "[\"0x1\"]", "0x2"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"accountProof\":[\"0xf8718080808080a0fc8311b2cabe1a1b33ea04f1865132a44aa0c17c567acd233422f9cfb516877480808080a0be8ea164b2fb1567e2505295dae6d8a9fe5f09e9c5ac854a7da23b2bc5f8523ca053692ab7cdc9bb02a28b1f45afe7be86cb27041ea98586e6ff05d98c9b0667138080808080\",\"0xf8518080808080a00dd1727b2abb59c0a6ac75c01176a9d1a276b0049d5fe32da3e1551096549e258080808080808080a038ca33d3070331da1ccf804819da57fcfc83358cadbef1d8bde89e1a346de5098080\",\"0xf872a020227dead52ea912e013e7641ccd6b3b174498e55066b0c174a09c8c3cc4bf5eb84ff84d01893635c9adc5de9fadf7a0475ae75f323761db271e75cbdae41aede237e48bc04127fb6611f0f33298f72ba0dbe576b4818846aa77e82f4ed5fa78f92766b141f282d36703886d196df39322\"],\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"balance\":\"0x3635c9adc5de9fadf7\",\"codeHash\":\"0xdbe576b4818846aa77e82f4ed5fa78f92766b141f282d36703886d196df39322\",\"nonce\":\"0x1\",\"storageHash\":\"0x475ae75f323761db271e75cbdae41aede237e48bc04127fb6611f0f33298f72b\",\"storageProof\":[{\"key\":\"0x1\",\"proof\":[\"0xe7a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf68483abcdef\"],\"value\":\"0xabcdef\"}]},\"id\":67}"), serialized.Replace("\"", "\\\"")); } + [Test] + public async Task Eth_get_proof_withTooManyKeys() + { + using Context ctx = await Context.Create(); + string serialized = await ctx.Test.TestEthRpc("eth_getProof", TestBlockchain.AccountA.ToString(), $"[{string.Join(", ", Enumerable.Range(1, EthRpcModule.GetProofStorageKeyLimit + 1).Select(i => "\"" + i.ToHexString() + "\""))}]", "0x2"); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"storageKeys: 1001 is over the query limit 1000.\"},\"id\":67}")); + } + [Test] public async Task Eth_get_block_by_number_empty_param() { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index 2dffcfa9733..db87edeed9d 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -67,6 +67,7 @@ public partial class EthRpcModule( IForkInfo forkInfo, ulong? secondsPerSlot) : IEthRpcModule { + public const int GetProofStorageKeyLimit = 1000; protected readonly Encoding _messageEncoding = Encoding.UTF8; protected readonly IJsonRpcConfig _rpcConfig = rpcConfig ?? throw new ArgumentNullException(nameof(rpcConfig)); protected readonly IBlockchainBridge _blockchainBridge = blockchainBridge ?? throw new ArgumentNullException(nameof(blockchainBridge)); @@ -660,9 +661,15 @@ ResultWrapper> FailWithNoHeadersSyncedYet(SearchResult eth_getProof(Address accountAddress, UInt256[] storageKeys, - BlockParameter blockParameter) + public ResultWrapper eth_getProof(Address accountAddress, HashSet storageKeys, BlockParameter? blockParameter) { + if (storageKeys.Count > GetProofStorageKeyLimit) + { + return ResultWrapper.Fail( + $"storageKeys: {storageKeys.Count} is over the query limit {GetProofStorageKeyLimit}.", + ErrorCodes.InvalidParams); + } + SearchResult searchResult = _blockFinder.SearchForHeader(blockParameter); if (searchResult.IsError) { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs index 3e829e01007..1c486bf41fe 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs @@ -281,7 +281,11 @@ ResultWrapper eth_getTransactionByBlockNumberAndIndex( IsImplemented = true, IsSharable = true, ExampleResponse = " \"accountProof\": [\"0xf90211a0446f43a2d3e433732c75bcf3519f4844e0441a4d39b31395ee9a65700c30d3b4a0b9720db63afe9909418fb6e02c9d9f225310856549cc1b66b486041f2d867250a046e6e560e52d4fe0d2f6609f489ba85f18ad1655fee18452588dc08388fbd711a01e68f36c91bd15cbf65587d6db2a7cbd6635907291e77dd80152161da9a28a48a0d2178a1891c26ccaa2d2cec82c231a0640a26a1f5e07c7b5493761bdb3aa94e5a0fa909327d406980a2e602eadd3f56cf8dc89320d4662340962e9cac2beee3d8da0a0fc71e7dec6320a993b4b65b2f82544910d0a4a7c6f8c5a1ebaa38357d259e3a0680161dec84c5f1c8d5e2a585c9708b1b6fbc2dc664a432e045d99f5e7d89259a0f76a745765be58d46d795c44d3900a4a05b6396530244d50822616c8bbb11e19a0594824352d58f5caff819c8df9581b6a41d0e94eb584ed0431d48b48f320bb5ca0e762eb52b2bcacd728fac605de6229dc83588001ecddcd3b454b64c393ee69eda0d319cf1021af0a8535e4916c3404c84917957d73d0711f71fd6456b4533993bba0878240238a894e6fa798671ac3792563c6666a7c7fba8066d090b65d6a7aa701a03c03fdb4d8f4b241442814cbab24ddb42b75c78874f92fedc162b65d0820fc4da06a3318509aa9ff009b9acb9b348f197a134a46a46295714f436d4fbb19057e69a04139df1b6e0a59b093b35f34f9e5e890bc06832e63b366d768dc29e8638b828480\",\"0xf90211a023459f17e04fba3d19c6993f5be413969842fdbdc85d234a91b2f6b08a38be87a0153060eafecbff55ef0794802ef722b6c66698141cdc0610352d3a426976adeba0bd642b7c5111a1fd09da33feb6df031dc352b6cb20fbbe5ebe3eb328db233bd4a0705bff29e05c7ef69c07fecaa5db2457b2f124befc82f9fe6b0e54c8e35632eba03c1b4ffc076434de97050d2351c24689cfaefaa6cf8dc398dd3b8ce365e652c1a0a1ebf845ea0eb252e2a2e5c422ccd74878a3733144dfd62bcaad34758cc98652a01e4184586f5bdbb17ba74fd87539f02378c7adcef99f1538108f9555520e32d6a0b8acdfd5b644fa2c9a54f68039a3af4c6562c1e7f91ea9e63bda5a849f1260b6a05c1f036a2e7a5829799fc7df2d87eac3e7aee55df461b040c36f5b5c61781059a0a67fd871d32642e44120331f76c2616096d04d7fa1a7db421bafbc39713d8bfba085c15b7ab64f61670f4422adb82176d5808fad4abde6fddda507b0e5ff92ba14a0d95e8f16a39d4e52c67c617eef486adcd947854373ac074ff498150c7ca1ab5da03d9d7be595000872ad6aec05667ad85e1aaaeb2050a692818d3e60d8f1628d8ba0984c657192b052d13fb717051631d67fbc83dd5dcb4d074a2fddc01aa122d95ba03643408862d758aea269c05027a1cd616c957e0db5daea529b56964db8b4f04ba01020dce8d692c3d84d9ae3e42c35e4d8adbddf7b4dd3e09e543fc980849f016e80\",\"0xf90211a04c71b4b56ed723da1c1353ec1b4c23e71dfa821664d4041c1ee1770221f507b6a031c851f261a38df9b2bece1a1cb6985bccfaa10d2bb15954b82cd2ceaad87032a08a4a3d0cc260cf0e0fef54490ce45796fdd3f522451976ca7834563c839c630fa003d074f79074566cd33a3d6a57b6ca8426ca9ea972f66b5dfde00f73287fcfcea07003d29a5bd192038600118ab5941af5c79c1f0fc6184ad564180b809c36c7c4a05f181c50402dcff567abe1c6679a8d5e3825125abca4d969c7cbf76503416813a06a85dfca80e442ef79b66162099d52eaf67718589eb794755ce57dc071a85cdaa085cba9e6937a8a5f0a7d1b5ee9eb9f03c40f89eb13d9d4e0e5fbc574c2b852faa063f93dce441a3373cfc2d1c855884682dfd8d09d1eb9844c73d88eb8d5a7cdfda0e4bc0d2597e5fd0a4cd5e76a03b657ef8959264bdeaf95c4412ebd4ff736ce44a00239290e698aa04485e0c342cfb76ccf27a3e45a161b8b1b534e0c46707b92c8a0080c3439fb84730924539797aad8d017c5f7e008314ed9086450d80ec2b0d7aba0861dbe37b9b9e0f58b6fdb83eec28045c5f7f1861530f47f78fc8a2b18a6bd8da0036697e8dc063e9086d115d468c934a01123adb3c66dcc236ee4aa8141888626a033c6f574ee79d9b1322e9ca1131a5984b33cc8881e6ac8ebd6ca36f3437cedcda07fc2855e6bb0f276202094dffe49f2b62f2366d9aba9db3ffe76d62bcdc29f0d80\",\"0xf90211a06995d919b53eefa0b097d75c2a5dee2c54109a06d3b60586327fa0086437b801a05c7d7c92f9f1e49cf27c5d97b4a96302f033d42df5b1d7c013ef05031d67e567a05278417d007913a1e7d6606fb464e7b81f6cee91b6a1d250c67b3822d9fc68d8a0fba6d9cd68fe72db07af9d99e30c32502e0afb15ee9712f6781014195444b9e1a07dca25ba23f429b5960d9feb23367e2a088e50211f280118b7f1703e6d47103fa0399eb6e0d4390688f6b28df56c7ad72d6b6cbac9066110c6a727fe35cd889e9da08ef84ddaa3b70095fb5624878289744740a9f8761ef1132ba722abc977a218ffa04296811ae184892e2d5ecc18d05fc6279d6168eb0f3abb1f97d8d0a0721c12fba05c46766c579b8a0b8a0b79b84f6cd1e5dae1c53a2988883b0385daa2cf3bdf82a01a4ba17dd1b59147a321dd374a22a0d959f1a79d70132db7f1a8b89968ff6062a0f7ffc6f3921c6bccd47c862519409e63f51d39aaa215819c664b1adb48a940b0a0dc6e636385407900a649917fb772b0972d50d197e9fd5cdb853a1c98a29e6a47a0674b224cf784c59ca937bfebbdcd8dec05ddbd57400b04f5965558a0c2d2299ca0f95ce8c921c5b17ebf74563f2496a88631aa6a697bfd9e3e22b326efa453115ea0fc133bc6b9dd098933c816660df2959074f47dfc4ab3a10fd2059a2b2e0e911aa057cac15218d6013890df78eec099144ba2000e3eea73a3498d0eb9b1f733459080\",\"0xf90211a0400aafe69a1a482277db720d12b9c0b98695f5dd78c6faf5421b3ddac50165a6a0235987542e4b37aa8e6957776c9dff11d6818797db5ad505de5e0049045c7e20a0f573b4776f8b323b7d55850300d53855cfa6fa5fe6e36ba64da6bb263fef774aa0b3a36d14d660c3492785b0f1488a2231b6d83bd51268685b95ba9267aa331fe2a0096e8c65bae8fce7d234710a1e1b8c98bd4fb2d56f8bb2eda7ef20d1cf31c7e2a059194c8bf50c2ac393c4c60a59c7ddf0c515bd9f545fc4ef212629a8b96af62aa0ffe882f4e2f1e8e49c7777f6f9b4438a9f31d4e5cefe82c96fdd3587d9a95173a00127ced7fdbdd57cd5ed8b766c9312c09e0c67a350087d22b4cc7b2d17a45479a0cfc030a250448838caa716cd2767cd1a4837b29019f474980720c94fe2ce412ea079ec358d2b4122692bf70eb73a0ddb0ff4bfeb05d503fe1acafe068e2d3d33cfa0733e2ccdc638ca3c940c566c742a1b9d58f7caaa062e8a121c07f5e3367160a8a0aa1f403798b71c67b821e6f6128cc5366bebe145ebd563714cf9972b2474814ea01b988afc628922aeed3de606a8a462093f1c0c803a563bbe178552a360bad1e1a0082741e2219024bf4e19f5b1b0643e5e885cb7dfb4cdc0a51faf5bd9f92ff9b6a03c86490fe8f0256be44b95815086d95cb62fdbc3ede63ca08d12d68f274b7fc5a03a81565e860ac32921ed4c9f4e0ace3b341c342abd030d4955f2d1e64dd81d2b80\",\"0xf8f1a0bd9a0d9559513a6c7bf427816142d254d5a9049e9ff385f3514b50cb828951fc808080a07d37353f509c9bdc99635bd75fde71a6ef99271154ac4ffd5c437e0b951d5eaca029e3beec2f52c99a1fa73251ed64486f2766af3dcb950900679f7fd740badfdaa09b348c93803521a41bd2a754e3ea5435bb2663724cdfb70a87984458b53f03dea0904e696aceac8c89e2825e0dae8add52a9b46faef2ffbabb932e8bc1267e48ba80a0935dedba6ec5fb5b89285993c5f1be0cb77492e63e11bb38b5aca18011699eb8a06b52f587932dfb669f6cbefe35b251c6d8e6b5e8a2e1c1a7c2a452a4f2917b0d808080808080\"],\"address\":\"0x7f0d15c7faae65896648c8273b6d7e43f58fa842\",\"balance\":\"0x0\",\"codeHash\":\"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\",\"nonce\":\"0x0\",\"storageHash\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"storageProof\":[{\"key\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"proof\":[],\"value\":\"0x00\"]")] - ResultWrapper eth_getProof([JsonRpcParameter(ExampleValue = "[\"0x7F0d15C7FAae65896648C8273B6d7E43f58Fa842\",[ \"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\" ],\"latest\"]")] Address accountAddress, UInt256[] hashRate, BlockParameter blockParameter); + ResultWrapper eth_getProof( + [JsonRpcParameter(ExampleValue = "[\"0x7F0d15C7FAae65896648C8273B6d7E43f58Fa842\",[ \"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\" ],\"latest\"]")] + Address accountAddress, + HashSet storageKeys, + BlockParameter? blockParameter = null); [JsonRpcMethod(IsImplemented = true, Description = "Retrieves Accounts via Address and Blocknumber", IsSharable = true)] ResultWrapper eth_getAccount([JsonRpcParameter(ExampleValue = "[\"0xaa00000000000000000000000000000000000000\", \"latest\"]")] Address accountAddress, BlockParameter? blockParameter = null); diff --git a/src/Nethermind/Nethermind.Optimism/CL/IL2Api.cs b/src/Nethermind/Nethermind.Optimism/CL/IL2Api.cs index 311b95ec989..fffbc284dad 100644 --- a/src/Nethermind/Nethermind.Optimism/CL/IL2Api.cs +++ b/src/Nethermind/Nethermind.Optimism/CL/IL2Api.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using System.Threading.Tasks; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -17,7 +18,7 @@ public interface IL2Api Task GetHeadBlock(); Task GetFinalizedBlock(); Task GetSafeBlock(); - Task GetProof(Address accountAddress, UInt256[] storageKeys, long blockNumber); + Task GetProof(Address accountAddress, HashSet storageKeys, long blockNumber); Task ForkChoiceUpdatedV3( Hash256 headHash, Hash256 finalizedHash, Hash256 safeHash, OptimismPayloadAttributes? payloadAttributes = null); diff --git a/src/Nethermind/Nethermind.Optimism/CL/L2Api.cs b/src/Nethermind/Nethermind.Optimism/CL/L2Api.cs index 8affb3fc6d2..1c48a34e744 100644 --- a/src/Nethermind/Nethermind.Optimism/CL/L2Api.cs +++ b/src/Nethermind/Nethermind.Optimism/CL/L2Api.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Nethermind.Blockchain.Find; @@ -133,7 +134,7 @@ public async Task GetHeadBlock() }; } - public Task GetProof(Address accountAddress, UInt256[] storageKeys, long blockNumber) + public Task GetProof(Address accountAddress, HashSet storageKeys, long blockNumber) { // TODO: Retry logic var result = l2EthRpc.eth_getProof(accountAddress, storageKeys, new BlockParameter(blockNumber)); diff --git a/src/Nethermind/Nethermind.State/Proofs/AccountProofCollector.cs b/src/Nethermind/Nethermind.State/Proofs/AccountProofCollector.cs index fbe3410dbe7..c1f57a417e5 100644 --- a/src/Nethermind/Nethermind.State/Proofs/AccountProofCollector.cs +++ b/src/Nethermind/Nethermind.State/Proofs/AccountProofCollector.cs @@ -112,13 +112,13 @@ public AccountProofCollector(ReadOnlySpan hashedAddress, params byte[][]? { } - public AccountProofCollector(Address address, params byte[][] storageKeys) + public AccountProofCollector(Address? address, params byte[][] storageKeys) : this(Keccak.Compute(address?.Bytes ?? Address.Zero.Bytes).Bytes, storageKeys) { _accountProof.Address = _address = address ?? throw new ArgumentNullException(nameof(address)); } - public AccountProofCollector(Address address, UInt256[] storageKeys) + public AccountProofCollector(Address? address, IEnumerable storageKeys) : this(address, storageKeys.Select(ToKey).ToArray()) { } From 150acda02636808a4f55ecea0dc31c91dd8863bb Mon Sep 17 00:00:00 2001 From: Forostovec Date: Thu, 18 Dec 2025 16:43:35 +0200 Subject: [PATCH 089/255] feat(merkle): remove unused RootOfNull to avoid dead code and startup allocation (#9898) --- src/Nethermind/Nethermind.Merkleization/Merkle.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Merkleization/Merkle.cs b/src/Nethermind/Nethermind.Merkleization/Merkle.cs index a16074877f3..9d70ff0da3d 100644 --- a/src/Nethermind/Nethermind.Merkleization/Merkle.cs +++ b/src/Nethermind/Nethermind.Merkleization/Merkle.cs @@ -28,12 +28,9 @@ private static void BuildZeroHashes() } } - private static readonly UInt256 RootOfNull; - static Merkle() { BuildZeroHashes(); - RootOfNull = new UInt256(new Root(SHA256.HashData([])).AsSpan().ToArray()); } public static ulong NextPowerOfTwo(uint v) From 6adcba422a3faf94a449fdb6d32f02adddc8af2d Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Thu, 18 Dec 2025 18:10:57 +0100 Subject: [PATCH 090/255] Fix/rlp decode array checks (#9968) * Add report test cases * Add checks to `DecodeArray` and `DecodeByteArrays` * Remove TODOs * Always check for `DecodeArray` and similar * More missing checks * fix build * compact storage encoding fix * more fix * Different way of handling compact encoding of receipts * Increase discovery tests timeout * fix * refactor --------- Co-authored-by: Lautaro Emanuel --- .../Receipts/ReceiptsIteratorTests.cs | 14 ++--- .../Encoding/ShardBlobTxDecoderTests.cs | 51 +++++++++++++++++++ .../E2EDiscoveryTests.cs | 2 +- .../Rlpx/FrameHeaderReader.cs | 2 + .../OptimismReceiptStorageDecoder.cs | 6 +-- .../ReceiptArrayStorageDecoder.cs | 22 +++----- .../ReceiptMessageDecoder.cs | 5 ++ .../Nethermind.Serialization.Rlp/Rlp.cs | 22 +++++++- .../RlpDecoderExtensions.cs | 10 ++++ .../Nethermind.Serialization.Rlp/RlpStream.cs | 19 +++++-- 10 files changed, 120 insertions(+), 33 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs index 0e939e90943..ad7d30e5256 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs @@ -25,12 +25,12 @@ public void SmokeTestWithRecovery() .Block .WithTransactions(3, MainnetSpecProvider.Instance) .TestObject; - TxReceipt[] receipts = new[] - { + TxReceipt[] receipts = + [ Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressA).TestObject, Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressB).TestObject, - Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressC).TestObject, - }; + Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressC).TestObject + ]; ReceiptsIterator iterator = CreateIterator(receipts, block); @@ -84,11 +84,11 @@ public void SmokeTest() .WithTransactions(3, MainnetSpecProvider.Instance) .TestObject; TxReceipt[] receipts = - { + [ Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressA).TestObject, Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressB).TestObject, - Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressC).TestObject, - }; + Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressC).TestObject + ]; ReceiptsIterator iterator = CreateIterator(receipts, block); diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/ShardBlobTxDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/ShardBlobTxDecoderTests.cs index 61ceea3d2bf..e5099188283 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/ShardBlobTxDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/ShardBlobTxDecoderTests.cs @@ -43,6 +43,17 @@ public void Roundtrip_ExecutionPayloadForm_for_shard_blobs((Transaction Tx, stri decoded.Should().BeEquivalentTo(testCase.Tx, testCase.Description); } + [Test] + public void TestDecodeTamperedBlob() + { + var bytes = Bytes.FromHexString( + "b8aa03f8a7018001808252089400000000000000000000000000000000000000000180c001f841a00100000000000000000000000000000000000000000000000000000000000000a0010000000000000000000000000000000000000000000000000000000000000080a00fb9ad625df88e2fea9e088b69a31497f0d9b767067db8c03fd2453d7092e7bfa0086f2930db968d992d0fb06ddc903ca5522ba38bedc0530eb28b61082897efa1"); + var stream = new RlpStream(bytes); + + var tryDecode = () => _txDecoder.Decode(stream); + tryDecode.Should().Throw(); + } + [TestCaseSource(nameof(TestCaseSource))] public void Roundtrip_ValueDecoderContext_ExecutionPayloadForm_for_shard_blobs((Transaction Tx, string Description) testCase) { @@ -59,6 +70,46 @@ public void Roundtrip_ValueDecoderContext_ExecutionPayloadForm_for_shard_blobs(( decoded.Should().BeEquivalentTo(testCase.Tx, testCase.Description); } + private static IEnumerable TamperedTestCaseSource() + { + yield return Build.A.Transaction + .WithShardBlobTxTypeAndFields(2, false) + .WithChainId(TestBlockchainIds.ChainId) + .SignedAndResolved() + .TestObject; + yield return Build.A.Transaction + .WithShardBlobTxTypeAndFields(2, false) + .WithChainId(TestBlockchainIds.ChainId) + .WithNonce(0) + .SignedAndResolved() + .TestObject; + } + + [TestCaseSource(nameof(TamperedTestCaseSource))] + public void Tampered_Roundtrip_ExecutionPayloadForm_for_shard_blobs(Transaction tx) + { + var stream = new RlpStream(_txDecoder.GetLength(tx, RlpBehaviors.None)); + _txDecoder.Encode(stream, tx); + // Tamper with sequence length + { + var itemsLength = 0; + foreach (var array in tx.BlobVersionedHashes!) + { + itemsLength += Rlp.LengthOf(array); + } + + // Position where it starts encoding `BlobVersionedHashes` + stream.Position = 37; + // Accepts `itemsLength - 10` all the way to `itemsLength - 1` + stream.StartSequence(itemsLength - 1); + } + stream.Position = 0; + + // Decoding should fail + var tryDecode = () => _txDecoder.Decode(stream); + tryDecode.Should().Throw(); + } + [TestCaseSource(nameof(ShardBlobTxTests))] public void NetworkWrapper_is_decoded_correctly(string rlp, Hash256 signedHash, RlpBehaviors rlpBehaviors) { diff --git a/src/Nethermind/Nethermind.Network.Discovery.Test/E2EDiscoveryTests.cs b/src/Nethermind/Nethermind.Network.Discovery.Test/E2EDiscoveryTests.cs index 96496142fc6..779863fc269 100644 --- a/src/Nethermind/Nethermind.Network.Discovery.Test/E2EDiscoveryTests.cs +++ b/src/Nethermind/Nethermind.Network.Discovery.Test/E2EDiscoveryTests.cs @@ -26,7 +26,7 @@ namespace Nethermind.Network.Discovery.Test; [TestFixture(DiscoveryVersion.V5)] public class E2EDiscoveryTests(DiscoveryVersion discoveryVersion) { - private static TimeSpan TestTimeout = TimeSpan.FromSeconds(5); + private static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(10); /// /// Common code for all node diff --git a/src/Nethermind/Nethermind.Network/Rlpx/FrameHeaderReader.cs b/src/Nethermind/Nethermind.Network/Rlpx/FrameHeaderReader.cs index b029327ae99..07229a2ef53 100644 --- a/src/Nethermind/Nethermind.Network/Rlpx/FrameHeaderReader.cs +++ b/src/Nethermind/Nethermind.Network/Rlpx/FrameHeaderReader.cs @@ -30,6 +30,8 @@ public FrameInfo ReadFrameHeader(IByteBuffer input) bool isChunked = totalPacketSize.HasValue || contextId.HasValue && _currentContextId == contextId && contextId != 0; bool isFirst = totalPacketSize.HasValue || !isChunked; + + headerBodyItems.Check(headerDataEnd); return new FrameInfo(isChunked, isFirst, frameSize, totalPacketSize ?? frameSize); } diff --git a/src/Nethermind/Nethermind.Optimism/OptimismReceiptStorageDecoder.cs b/src/Nethermind/Nethermind.Optimism/OptimismReceiptStorageDecoder.cs index dc046174dd1..59f4d41627b 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismReceiptStorageDecoder.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismReceiptStorageDecoder.cs @@ -137,8 +137,7 @@ public OptimismTxReceipt Decode(ref ValueDecoderContext decoderContext, return txReceipt; } - public void DecodeStructRef(scoped ref ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors, - out TxReceiptStructRef item) + public void DecodeStructRef(scoped ref ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors, out TxReceiptStructRef item) { // Note: This method runs at 2.5 million times/sec on my machine item = new TxReceiptStructRef(); @@ -165,8 +164,7 @@ public void DecodeStructRef(scoped ref ValueDecoderContext decoderContext, RlpBe decoderContext.DecodeAddressStructRef(out item.Sender); item.GasUsedTotal = (long)decoderContext.DecodeUBigInt(); - (int prefixLength, int contentLength) = - decoderContext.PeekPrefixAndContentLength(); + (int prefixLength, int contentLength) = decoderContext.PeekPrefixAndContentLength(); int logsBytes = contentLength + prefixLength; item.LogsRlp = decoderContext.Data.Slice(decoderContext.Position, logsBytes); diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptArrayStorageDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptArrayStorageDecoder.cs index 656d754581b..b044b4b3788 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptArrayStorageDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptArrayStorageDecoder.cs @@ -64,7 +64,7 @@ protected override TxReceipt[] DecodeInternal(RlpStream rlpStream, RlpBehaviors if (rlpStream.PeekByte() == CompactEncoding) { rlpStream.ReadByte(); - return CompactDecoder.DecodeArray(rlpStream, RlpBehaviors.Storage); + return CompactDecoder.DecodeArray(rlpStream, RlpBehaviors.Storage | RlpBehaviors.AllowExtraBytes); } else { @@ -113,7 +113,7 @@ public TxReceipt[] Decode(in Span receiptsData) if (receiptsData.Length > 0 && receiptsData[0] == CompactEncoding) { var decoderContext = new Rlp.ValueDecoderContext(receiptsData[1..]); - return CompactValueDecoder.DecodeArray(ref decoderContext, RlpBehaviors.Storage); + return CompactValueDecoder.DecodeArray(ref decoderContext, RlpBehaviors.Storage | RlpBehaviors.AllowExtraBytes); } else { @@ -148,18 +148,10 @@ public TxReceipt DeserializeReceiptObsolete(Hash256 hash, Span receiptData } } - public static bool IsCompactEncoding(Span receiptsData) - { - return receiptsData.Length > 0 && receiptsData[0] == CompactEncoding; - } + public static bool IsCompactEncoding(Span receiptsData) => receiptsData.Length > 0 && receiptsData[0] == CompactEncoding; - public IReceiptRefDecoder GetRefDecoder(Span receiptsData) - { - if (IsCompactEncoding(receiptsData)) - { - return (IReceiptRefDecoder)CompactValueDecoder; - } - - return (IReceiptRefDecoder)ValueDecoder; - } + public IReceiptRefDecoder GetRefDecoder(Span receiptsData) => + IsCompactEncoding(receiptsData) + ? (IReceiptRefDecoder)CompactValueDecoder + : (IReceiptRefDecoder)ValueDecoder; } diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs index dc25bc96d35..7106903da14 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs @@ -72,6 +72,11 @@ protected override TxReceipt DecodeInternal(ref Rlp.ValueDecoderContext ctx, Rlp } txReceipt.Logs = entries; + if ((rlpBehaviors & RlpBehaviors.AllowExtraBytes) != RlpBehaviors.AllowExtraBytes) + { + ctx.Check(lastCheck); + } + return txReceipt; } diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs b/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs index 5f796e5db26..b16af62649d 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs @@ -212,6 +212,11 @@ public static T[] DecodeArray(RlpStream rlpStream, IRlpStreamDecoder? rlpD result[i] = rlpDecoder.Decode(rlpStream, rlpBehaviors); } + if ((rlpBehaviors & RlpBehaviors.AllowExtraBytes) != RlpBehaviors.AllowExtraBytes) + { + rlpStream.Check(checkPosition); + } + return result; } @@ -223,7 +228,7 @@ public static ArrayPoolList DecodeArrayPool(RlpStream rlpStream, RlpBehavi : throw new RlpException($"{nameof(Rlp)} does not support decoding {typeof(T).Name}"); } - public static ArrayPoolList DecodeArrayPool(RlpStream rlpStream, IRlpStreamDecoder? rlpDecoder, RlpBehaviors rlpBehaviors = RlpBehaviors.None, RlpLimit? limit = null) + public static ArrayPoolList DecodeArrayPool(RlpStream rlpStream, IRlpStreamDecoder rlpDecoder, RlpBehaviors rlpBehaviors = RlpBehaviors.None, RlpLimit? limit = null) { int checkPosition = rlpStream.ReadSequenceLength() + rlpStream.Position; int length = rlpStream.PeekNumberOfItemsRemaining(checkPosition); @@ -234,6 +239,11 @@ public static ArrayPoolList DecodeArrayPool(RlpStream rlpStream, IRlpStrea result.Add(rlpDecoder.Decode(rlpStream, rlpBehaviors)); } + if ((rlpBehaviors & RlpBehaviors.AllowExtraBytes) != RlpBehaviors.AllowExtraBytes) + { + rlpStream.Check(checkPosition); + } + return result; } @@ -1536,7 +1546,8 @@ public byte[][] DecodeByteArrays() return []; } - int itemsCount = PeekNumberOfItemsRemaining(Position + length); + int checkPosition = Position + length; + int itemsCount = PeekNumberOfItemsRemaining(checkPosition); byte[][] result = new byte[itemsCount][]; for (int i = 0; i < itemsCount; i++) @@ -1544,6 +1555,8 @@ public byte[][] DecodeByteArrays() result[i] = DecodeByteArray(); } + Check(checkPosition); + return result; } @@ -1599,6 +1612,11 @@ public T[] DecodeArray(IRlpValueDecoder? decoder = null, bool checkPositio } } + if (checkPositions) + { + Check(positionCheck); + } + return result; } diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/RlpDecoderExtensions.cs b/src/Nethermind/Nethermind.Serialization.Rlp/RlpDecoderExtensions.cs index b371f2d0d37..16202a6baf7 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/RlpDecoderExtensions.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/RlpDecoderExtensions.cs @@ -25,6 +25,11 @@ public static T[] DecodeArray(this IRlpStreamDecoder decoder, RlpStream rl result[i] = decoder.Decode(rlpStream, rlpBehaviors); } + if ((rlpBehaviors & RlpBehaviors.AllowExtraBytes) != RlpBehaviors.AllowExtraBytes) + { + rlpStream.Check(checkPosition); + } + return result; } @@ -39,6 +44,11 @@ public static T[] DecodeArray(this IRlpValueDecoder decoder, ref Rlp.Value result[i] = decoder.Decode(ref decoderContext, rlpBehaviors); } + if ((rlpBehaviors & RlpBehaviors.AllowExtraBytes) != RlpBehaviors.AllowExtraBytes) + { + decoderContext.Check(checkPosition); + } + return result; } diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs b/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs index ab853eadbe9..1344451f712 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs @@ -25,10 +25,8 @@ public class RlpStream { private static readonly HeaderDecoder _headerDecoder = new(); private static readonly BlockDecoder _blockDecoder = new(); - private static readonly BlockBodyDecoder _blockBodyDecoder = new(); private static readonly BlockInfoDecoder _blockInfoDecoder = new(); private static readonly TxDecoder _txDecoder = TxDecoder.Instance; - private static readonly ReceiptMessageDecoder _receiptDecoder = new(); private static readonly WithdrawalDecoder _withdrawalDecoder = new(); private static readonly LogEntryDecoder _logEntryDecoder = LogEntryDecoder.Instance; @@ -73,7 +71,7 @@ public void EncodeArray(T?[]? items, RlpBehaviors rlpBehaviors = RlpBehaviors StartSequence(contentLength); - foreach (var item in items) + foreach (T? item in items) { decoder.Encode(this, item, rlpBehaviors); } @@ -953,6 +951,11 @@ public T[] DecodeArray(Func decodeItem, bool checkPositions = t } } + if (checkPositions) + { + Check(positionCheck); + } + return result; } @@ -975,6 +978,11 @@ public ArrayPoolList DecodeArrayPoolList(Func decodeItem, bo } } + if (checkPositions) + { + Check(positionCheck); + } + return result; } @@ -1227,7 +1235,8 @@ public byte[][] DecodeByteArrays(RlpLimit? limit = null) return []; } - int itemsCount = PeekNumberOfItemsRemaining(Position + length); + int checkPosition = Position + length; + int itemsCount = PeekNumberOfItemsRemaining(checkPosition); GuardLimit(itemsCount, limit); byte[][] result = new byte[itemsCount][]; @@ -1236,6 +1245,8 @@ public byte[][] DecodeByteArrays(RlpLimit? limit = null) result[i] = DecodeByteArray(); } + Check(checkPosition); + return result; } From e52f4d1861195802159bbd1637ca0a325b506329 Mon Sep 17 00:00:00 2001 From: phrwlk Date: Fri, 19 Dec 2025 02:33:44 +0200 Subject: [PATCH 091/255] fix: dispose IEraStore when EraImporter.Import fails early (#9978) --- src/Nethermind/Nethermind.Era1/EraImporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Era1/EraImporter.cs b/src/Nethermind/Nethermind.Era1/EraImporter.cs index 76baecd536c..515e309b58c 100644 --- a/src/Nethermind/Nethermind.Era1/EraImporter.cs +++ b/src/Nethermind/Nethermind.Era1/EraImporter.cs @@ -49,7 +49,7 @@ public async Task Import(string src, long from, long to, string? accumulatorFile trustedAccumulators = (await fileSystem.File.ReadAllLinesAsync(accumulatorFile, cancellation)).Select(EraPathUtils.ExtractHashFromAccumulatorAndCheckSumEntry).ToHashSet(); } - IEraStore eraStore = eraStoreFactory.Create(src, trustedAccumulators); + using IEraStore eraStore = eraStoreFactory.Create(src, trustedAccumulators); long lastBlockInStore = eraStore.LastBlock; if (to == 0) to = long.MaxValue; From cdd758f47477214fdb39f31b45a831ad67d605ff Mon Sep 17 00:00:00 2001 From: Nikita Mescheryakov Date: Thu, 18 Dec 2025 22:46:41 -0300 Subject: [PATCH 092/255] Remove rpc from hive worflow (#9971) fix workflow --- .github/workflows/hive-tests.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/hive-tests.yml b/.github/workflows/hive-tests.yml index 79f786cc933..1211cfcb1a6 100644 --- a/.github/workflows/hive-tests.yml +++ b/.github/workflows/hive-tests.yml @@ -10,13 +10,12 @@ on: description: Test suite type: choice options: - - '' + - 'all' - devp2p - ethereum/consensus - ethereum/eest - ethereum/engine - ethereum/graphql - - ethereum/rpc - ethereum/rpc-compat - ethereum/sync limit: @@ -56,8 +55,8 @@ jobs: strategy: fail-fast: false matrix: - test-suite: ${{ fromJson(github.event.inputs.test-suite == '' && - '["ethereum/engine","ethereum/graphql","ethereum/rpc","ethereum/rpc-compat","ethereum/sync"]' || + test-suite: ${{ fromJson(github.event.inputs.test-suite == 'all' && + '["ethereum/engine","ethereum/graphql","ethereum/rpc-compat","ethereum/sync"]' || format('["{0}"]', github.event.inputs.test-suite) ) }} steps: From df92349ca7a8e1fee85e841d492bbd01664ae3a1 Mon Sep 17 00:00:00 2001 From: Damian Orzechowski <114909782+damian-orzechowski@users.noreply.github.com> Date: Fri, 19 Dec 2025 12:46:45 +0100 Subject: [PATCH 093/255] Elevate access for ABI decode override more easily (#9977) Increase access for decode --- src/Nethermind/Nethermind.Abi/AbiType.Sequence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Abi/AbiType.Sequence.cs b/src/Nethermind/Nethermind.Abi/AbiType.Sequence.cs index 3f9ae167b10..701134ffd8f 100644 --- a/src/Nethermind/Nethermind.Abi/AbiType.Sequence.cs +++ b/src/Nethermind/Nethermind.Abi/AbiType.Sequence.cs @@ -75,7 +75,7 @@ internal static byte[][] EncodeSequence(int length, IEnumerable types, return encodedParts; } - internal static (object[], int) DecodeSequence(int length, IEnumerable types, byte[] data, bool packed, int startPosition) + public static (object[], int) DecodeSequence(int length, IEnumerable types, byte[] data, bool packed, int startPosition) { (Array array, int position) = DecodeSequence(typeof(object), length, types, data, packed, startPosition); return ((object[])array, position); From 02cc6bc36f496fceb7f03333be9c994886ea630a Mon Sep 17 00:00:00 2001 From: Nikita Mescheryakov Date: Fri, 19 Dec 2025 10:37:40 -0300 Subject: [PATCH 094/255] Run all tests on master (#9979) * fix * fix --- .github/workflows/hive-tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/hive-tests.yml b/.github/workflows/hive-tests.yml index 1211cfcb1a6..d1bb92f9ec3 100644 --- a/.github/workflows/hive-tests.yml +++ b/.github/workflows/hive-tests.yml @@ -55,7 +55,9 @@ jobs: strategy: fail-fast: false matrix: - test-suite: ${{ fromJson(github.event.inputs.test-suite == 'all' && + test-suite: ${{ fromJson(( + github.event_name == 'push' || + (github.event_name == 'workflow_dispatch' && github.event.inputs.test-suite == 'all')) && '["ethereum/engine","ethereum/graphql","ethereum/rpc-compat","ethereum/sync"]' || format('["{0}"]', github.event.inputs.test-suite) ) }} From 6e94189a4379ab89cfcb52317e7475429e2afd6b Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Fri, 19 Dec 2025 15:27:09 +0100 Subject: [PATCH 095/255] Remove parsing Uint256 from statics (#9980) --- src/Nethermind/Nethermind.Crypto/Secp256K1Curve.cs | 3 ++- .../Handlers/ExchangeTransitionConfigurationV1Handler.cs | 3 ++- src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs | 4 +++- src/Nethermind/Nethermind.Specs/Forks/00_Olympic.cs | 2 +- src/Nethermind/Nethermind.Specs/Forks/06_Byzantium.cs | 2 +- src/Nethermind/Nethermind.Specs/Forks/07_Constantinople.cs | 2 +- src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs | 3 ++- src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs | 7 ++++--- 8 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/Nethermind/Nethermind.Crypto/Secp256K1Curve.cs b/src/Nethermind/Nethermind.Crypto/Secp256K1Curve.cs index 83c8e8fb12b..1d8559f421e 100644 --- a/src/Nethermind/Nethermind.Crypto/Secp256K1Curve.cs +++ b/src/Nethermind/Nethermind.Crypto/Secp256K1Curve.cs @@ -18,7 +18,8 @@ public static class Secp256K1Curve - BigInteger.Pow(2, 4) - 1; */ - public static readonly UInt256 N = UInt256.Parse("115792089237316195423570985008687907852837564279074904382605163141518161494337"); + // 115792089237316195423570985008687907852837564279074904382605163141518161494337 + public static readonly UInt256 N = new(13822214165235122497ul, 13451932020343611451ul, 18446744073709551614ul, 18446744073709551615ul); public static readonly UInt256 NMinusOne = N - 1; public static readonly UInt256 HalfN = N / 2; public static readonly UInt256 HalfNPlusOne = HalfN + 1; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeTransitionConfigurationV1Handler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeTransitionConfigurationV1Handler.cs index 5d19260b008..e00f06fe20d 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeTransitionConfigurationV1Handler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeTransitionConfigurationV1Handler.cs @@ -16,7 +16,8 @@ public class ExchangeTransitionConfigurationV1Handler : IHandler ShanghaiTimestamp; - public UInt256? TerminalTotalDifficulty { get; private set; } = UInt256.Parse("231707791542740786049188744689299064356246512"); + + // 231707791542740786049188744689299064356246512 + public UInt256? TerminalTotalDifficulty { get; private set; } = new UInt256(18446744073375486960ul, 18446744073709551615ul, 680927ul); public IReleaseSpec GenesisSpec => London.Instance; public long? DaoBlockNumber => null; public ulong? BeaconChainGenesisTimestamp => BeaconChainGenesisTimestampConst; diff --git a/src/Nethermind/Nethermind.Specs/Forks/00_Olympic.cs b/src/Nethermind/Nethermind.Specs/Forks/00_Olympic.cs index 3850d3dd360..a9408a3d61c 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/00_Olympic.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/00_Olympic.cs @@ -19,7 +19,7 @@ protected Olympic() MaxCodeSize = long.MaxValue; MinGasLimit = 5000; GasLimitBoundDivisor = 0x0400; - BlockReward = UInt256.Parse("5000000000000000000"); + BlockReward = new UInt256(5000000000000000000ul); DifficultyBoundDivisor = 0x0800; IsEip3607Enabled = true; MaximumUncleCount = 2; diff --git a/src/Nethermind/Nethermind.Specs/Forks/06_Byzantium.cs b/src/Nethermind/Nethermind.Specs/Forks/06_Byzantium.cs index a41a41dbd86..f37711dfd26 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/06_Byzantium.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/06_Byzantium.cs @@ -14,7 +14,7 @@ public class Byzantium : SpuriousDragon protected Byzantium() { Name = "Byzantium"; - BlockReward = UInt256.Parse("3000000000000000000"); + BlockReward = new UInt256(3000000000000000000ul); DifficultyBombDelay = 3000000L; IsEip100Enabled = true; IsEip140Enabled = true; diff --git a/src/Nethermind/Nethermind.Specs/Forks/07_Constantinople.cs b/src/Nethermind/Nethermind.Specs/Forks/07_Constantinople.cs index b922cf5bb33..c6804bf92a7 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/07_Constantinople.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/07_Constantinople.cs @@ -14,7 +14,7 @@ public class Constantinople : Byzantium protected Constantinople() { Name = "Constantinople"; - BlockReward = UInt256.Parse("2000000000000000000"); + BlockReward = new UInt256(2000000000000000000ul); DifficultyBombDelay = 5000000L; IsEip145Enabled = true; IsEip1014Enabled = true; diff --git a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs index 91f6883c28f..7e7ebb248c5 100644 --- a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs @@ -55,7 +55,8 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public ForkActivation? MergeBlockNumber { get; private set; } public ulong TimestampFork => ShanghaiTimestamp; - public UInt256? TerminalTotalDifficulty { get; private set; } = UInt256.Parse("8626000000000000000000058750000000000000000000"); + // 8626000000000000000000058750000000000000000000 + public UInt256? TerminalTotalDifficulty { get; private set; } = new UInt256(15847367919172845568ul, 12460455203863319017ul, 25349535ul); public IReleaseSpec GenesisSpec => Byzantium.Instance; public long? DaoBlockNumber => null; public ulong? BeaconChainGenesisTimestamp => BeaconChainGenesisTimestampConst; diff --git a/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs b/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs index 1c3425fe3ba..9e9f7b91332 100644 --- a/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs @@ -65,13 +65,14 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD TerminalTotalDifficulty = terminalTotalDifficulty; } - public ulong NetworkId { get; } = Core.BlockchainIds.Mainnet; + public ulong NetworkId => Core.BlockchainIds.Mainnet; public ulong ChainId => NetworkId; public long? DaoBlockNumber => DaoBlockNumberConst; public ulong? BeaconChainGenesisTimestamp => BeaconChainGenesisTimestampConst; public ForkActivation? MergeBlockNumber { get; private set; } = null; - public ulong TimestampFork { get; } = ShanghaiBlockTimestamp; - public UInt256? TerminalTotalDifficulty { get; private set; } = UInt256.Parse("58750000000000000000000"); + public ulong TimestampFork => ShanghaiBlockTimestamp; + // 58750000000000000000000 + public UInt256? TerminalTotalDifficulty { get; private set; } = new UInt256(15566869308787654656ul, 3184ul); public IReleaseSpec GenesisSpec => Frontier.Instance; public static ForkActivation ShanghaiActivation { get; } = (ParisBlockNumber + 1, ShanghaiBlockTimestamp); public static ForkActivation CancunActivation { get; } = (ParisBlockNumber + 2, CancunBlockTimestamp); From 0478126f6a1c3d50e6cdebaab8c61bcfc2029107 Mon Sep 17 00:00:00 2001 From: 0xFloki Date: Fri, 19 Dec 2025 15:30:18 +0100 Subject: [PATCH 096/255] perf: Remove redundant ToArray() allocation in TrieStore warning log (#9969) * Update TrieStore.cs * Update src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs --------- Co-authored-by: Lukasz Rozmej --- src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index 309ac8ca7d5..c079db77353 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -785,7 +785,11 @@ private void SaveSnapshot() { // This is a hang. It should recover itself as new finalized block is set. But it will hang if we for some reason // does not process in the finalized branch at all. - if (_logger.IsWarn) _logger.Warn($"Unable to determine finalized state root at block {effectiveFinalizedBlockNumber}. Available state roots {string.Join(", ", commitSetsAtFinalizedBlock.Select(c => c.StateRoot.ToString()).ToArray())}"); + if (_logger.IsWarn) + { + using ArrayPoolListRef roots = commitSetsAtFinalizedBlock.Select(c => c.StateRoot.ToString()); + _logger.Warn($"Unable to determine finalized state root at block {effectiveFinalizedBlockNumber}. Available state roots {string.Join(", ", roots.AsSpan())}"); + } return (candidateSets, null); } From c739d43d6437a645f677f0cf24c3cd2d378319fc Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Fri, 19 Dec 2025 15:33:32 +0100 Subject: [PATCH 097/255] Optimise MemDb for ZK (#9952) --- src/Nethermind/Nethermind.Db/MemDb.cs | 61 ++++++++++----------------- 1 file changed, 23 insertions(+), 38 deletions(-) diff --git a/src/Nethermind/Nethermind.Db/MemDb.cs b/src/Nethermind/Nethermind.Db/MemDb.cs index af6f4313e07..e4fd0566073 100644 --- a/src/Nethermind/Nethermind.Db/MemDb.cs +++ b/src/Nethermind/Nethermind.Db/MemDb.cs @@ -18,8 +18,14 @@ public class MemDb : IFullDb public long ReadsCount { get; private set; } public long WritesCount { get; private set; } +#if ZK + private readonly Dictionary _db; + private readonly Dictionary.AlternateLookup> _spanDb; +#else private readonly ConcurrentDictionary _db; private readonly ConcurrentDictionary.AlternateLookup> _spanDb; +#endif + public MemDb(string name) : this(0, 0) @@ -46,11 +52,15 @@ public MemDb(int writeDelay, int readDelay) { _writeDelay = writeDelay; _readDelay = readDelay; +#if ZK + _db = new Dictionary(Bytes.EqualityComparer); +#else _db = new ConcurrentDictionary(Bytes.EqualityComparer); +#endif _spanDb = _db.GetAlternateLookup>(); } - public string Name { get; } + public string Name { get; } = nameof(MemDb); public virtual byte[]? this[ReadOnlySpan key] { @@ -80,22 +90,18 @@ public virtual byte[]? this[ReadOnlySpan key] public virtual void Remove(ReadOnlySpan key) { +#if ZK + _spanDb.Remove(key); +#else _spanDb.TryRemove(key, out _); +#endif } - public bool KeyExists(ReadOnlySpan key) - { - return _spanDb.ContainsKey(key); - } - - public IDb Innermost => this; + public bool KeyExists(ReadOnlySpan key) => _spanDb.ContainsKey(key); public virtual void Flush(bool onlyWal = false) { } - public void Clear() - { - _db.Clear(); - } + public void Clear() => _db.Clear(); public IEnumerable> GetAll(bool ordered = false) => ordered ? OrderedDb : _db; @@ -103,35 +109,20 @@ public void Clear() public IEnumerable GetAllValues(bool ordered = false) => ordered ? OrderedDb.Select(kvp => kvp.Value) : Values; - public virtual IWriteBatch StartWriteBatch() - { - return this.LikeABatch(); - } + public virtual IWriteBatch StartWriteBatch() => this.LikeABatch(); public ICollection Keys => _db.Keys; public ICollection Values => _db.Values; public int Count => _db.Count; - public static long GetSize() => 0; - public static long GetCacheSize(bool includeCacheSize) => 0; - public static long GetIndexSize() => 0; - public static long GetMemtableSize() => 0; - - public void Dispose() - { - } + public void Dispose() { } public bool PreferWriteByArray => true; - public virtual Span GetSpan(ReadOnlySpan key) - { - return Get(key).AsSpan(); - } + public virtual Span GetSpan(ReadOnlySpan key) => Get(key).AsSpan(); - public void DangerousReleaseMemory(in ReadOnlySpan span) - { - } + public void DangerousReleaseMemory(in ReadOnlySpan span) { } public virtual byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) { @@ -154,19 +145,13 @@ public virtual void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags WritesCount++; if (value is null) { - _spanDb.TryRemove(key, out _); + Remove(key); return; } _spanDb[key] = value; } - public IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) - { - return new IDbMeta.DbMetric() - { - Size = Count - }; - } + public IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) => new() { Size = Count }; private IEnumerable> OrderedDb => _db.OrderBy(kvp => kvp.Key, Bytes.Comparer); } From 4b46205eeb8c28cf1728c124a7cc49aa63cb5354 Mon Sep 17 00:00:00 2001 From: Daniil Ankushin Date: Fri, 19 Dec 2025 12:17:30 -0300 Subject: [PATCH 098/255] feat(evm): generify VirtualMachine with policy-based gas tracking (#9846) --- .../Nethermind.Blockchain.Test/ReorgTests.cs | 4 +- .../TransactionProcessorEip7702Tests.cs | 4 +- .../TransactionProcessorTests.cs | 15 +- .../IBlockProducerFactory.cs | 2 - .../Nethermind.Consensus/IMiningConfig.cs | 1 - .../Nethermind.Consensus/MiningConfig.cs | 3 - .../AutoReadOnlyTxProcessingEnvFactory.cs | 1 - ...sor.BlockProductionTransactionsExecutor.cs | 1 - .../Processing/BranchProcessor.cs | 1 - .../CensorshipDetector/CensorshipDetector.cs | 1 - .../Processing/IBlockCachePreWarmer.cs | 1 - .../Processing/IBlockProcessor.cs | 1 - .../Processing/NullBlockProcessor.cs | 1 - .../Processing/ShareableTxProcessingSource.cs | 2 - .../Stateless/StatelessBlockProcessingEnv.cs | 13 +- .../Nethermind.Consensus/Stateless/Witness.cs | 2 - .../Tracing/BlockProcessorFacade.cs | 1 - .../Nethermind.Consensus/TxFilterBuilders.cs | 1 - .../Validators/TxValidator.cs | 2 +- .../Nethermind.Evm.Benchmark/EvmBenchmarks.cs | 7 +- .../MultipleUnsignedOperations.cs | 7 +- .../StaticCallBenchmarks.cs | 7 +- .../Nethermind.Evm.Test/Eip2028Tests.cs | 16 +- .../Eip3198BaseFeeTests.cs | 2 +- .../Eip3529RefundsTests.cs | 2 +- .../Nethermind.Evm.Test/Eip3541Tests.cs | 2 +- .../Eip7516BlobBaseFeeTests.cs | 2 +- .../Nethermind.Evm.Test/Eip7623Tests.cs | 8 +- .../EvmPooledMemoryTests.cs | 4 +- .../Nethermind.Evm.Test/EvmStateTests.cs | 243 ------------- .../GasPriceExtractorTests.cs | 2 +- .../IntrinsicGasCalculatorTests.cs | 14 +- .../Tracing/DebugTracerTests.cs | 5 +- .../Tracing/GasEstimationTests.cs | 6 +- .../TransactionProcessorEip4844Tests.cs | 4 +- .../TransactionProcessorEip7623Tests.cs | 4 +- .../TransactionProcessorFeeTests.cs | 4 +- .../VirtualMachineTestsBase.cs | 6 +- .../Nethermind.Evm.Test/VmStateTests.cs | 244 +++++++++++++ src/Nethermind/Nethermind.Evm/CallResult.cs | 8 +- .../Nethermind.Evm/EvmPooledMemory.cs | 44 +-- .../GasPolicy/EthereumGasPolicy.cs | 224 ++++++++++++ .../Nethermind.Evm/GasPolicy/IGasPolicy.cs | 208 +++++++++++ .../Nethermind.Evm/IVirtualMachine.cs | 31 +- .../Instructions/EvmCalculations.cs | 167 +-------- .../Instructions/EvmInstructions.Bitwise.cs | 9 +- .../Instructions/EvmInstructions.Call.cs | 87 ++--- .../Instructions/EvmInstructions.CodeCopy.cs | 75 ++-- .../EvmInstructions.ControlFlow.cs | 66 ++-- .../Instructions/EvmInstructions.Create.cs | 41 ++- .../Instructions/EvmInstructions.Crypto.cs | 10 +- .../EvmInstructions.Environment.cs | 303 +++++++++------- .../Instructions/EvmInstructions.Eof.cs | 211 +++++++----- .../EvmInstructions.Math1Param.cs | 21 +- .../EvmInstructions.Math2Param.cs | 20 +- .../EvmInstructions.Math3Param.cs | 6 +- .../Instructions/EvmInstructions.Shifts.cs | 17 +- .../Instructions/EvmInstructions.Stack.cs | 81 +++-- .../Instructions/EvmInstructions.Storage.cs | 125 ++++--- .../Instructions/EvmInstructions.cs | 324 +++++++++--------- .../Nethermind.Evm/IntrinsicGasCalculator.cs | 40 ++- src/Nethermind/Nethermind.Evm/StackPool.cs | 4 +- .../Tracing/Debugger/DebugTracer.cs | 36 +- .../SystemTransactionProcessor.cs | 8 +- .../TransactionProcessor.cs | 94 +++-- .../Nethermind.Evm/VirtualMachine.Warmup.cs | 36 +- .../Nethermind.Evm/VirtualMachine.cs | 233 ++++++------- .../{EvmState.cs => VmState.cs} | 62 ++-- .../Modules/BlockProcessingModule.cs | 4 +- .../Nethermind.Init/Steps/EvmWarmer.cs | 2 +- .../OptimismBlockReceiptTracer.cs | 1 + .../OptimismTransactionProcessor.cs | 5 +- .../TransactionProcessorTests.cs | 2 +- .../TaikoTransactionProcessor.cs | 5 +- .../MasternodeVotingContractTests.cs | 4 +- tools/Evm/T8n/T8nExecutor.cs | 4 +- 76 files changed, 1885 insertions(+), 1379 deletions(-) delete mode 100644 src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs create mode 100644 src/Nethermind/Nethermind.Evm.Test/VmStateTests.cs create mode 100644 src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs create mode 100644 src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs rename src/Nethermind/Nethermind.Evm/{EvmState.cs => VmState.cs} (88%) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs index 03fa6387221..b8acad1530f 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs @@ -91,11 +91,11 @@ public void Setup() transactionComparerProvider.GetDefaultComparer()); BlockhashCache blockhashCache = new(blockTreeBuilder.HeaderStore, LimboLogs.Instance); BlockhashProvider blockhashProvider = new(blockhashCache, stateProvider, LimboLogs.Instance); - VirtualMachine virtualMachine = new( + EthereumVirtualMachine virtualMachine = new( blockhashProvider, specProvider, LimboLogs.Instance); - TransactionProcessor transactionProcessor = new( + EthereumTransactionProcessor transactionProcessor = new( BlobBaseFeeCalculator.Instance, specProvider, stateProvider, diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs index 872ff2e15cd..56f236010aa 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs @@ -43,8 +43,8 @@ public void Setup() _stateProvider = TestWorldStateFactory.CreateForTest(); _worldStateCloser = _stateProvider.BeginScope(IWorldState.PreGenesis); EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); - VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + EthereumVirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); + _transactionProcessor = new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId); } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs index aca28678395..b0224d317c5 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs @@ -13,6 +13,7 @@ using Nethermind.Crypto; using Nethermind.Db; using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Blockchain.Tracing.GethStyle; using Nethermind.Blockchain.Tracing.ParityStyle; @@ -65,8 +66,8 @@ public void Setup() _baseBlock = Build.A.BlockHeader.WithStateRoot(_stateProvider.StateRoot).TestObject; EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); - VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + EthereumVirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); + _transactionProcessor = new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId); } @@ -407,7 +408,7 @@ public void Can_estimate_with_refund() Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(initByteCode).WithGasLimit(gasLimit).TestObject; Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; - IntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(tx, MuirGlacier.Instance); + EthereumIntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(tx, MuirGlacier.Instance); GethLikeTxMemoryTracer gethTracer = new(tx, GethTraceOptions.Default); var blkCtx = new BlockExecutionContext(block.Header, _specProvider.GetSpec(block.Header)); @@ -450,7 +451,7 @@ public void Can_estimate_with_destroy_refund_and_below_intrinsic_pre_berlin() Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; IReleaseSpec releaseSpec = MuirGlacier.Instance; - IntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(tx, releaseSpec); + EthereumIntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(tx, releaseSpec); var blkCtx = new BlockExecutionContext(block.Header, releaseSpec); _transactionProcessor.Execute(initTx, blkCtx, NullTxTracer.Instance); @@ -518,7 +519,7 @@ public void Can_estimate_with_stipend() Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; IReleaseSpec releaseSpec = MuirGlacier.Instance; - IntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(tx, releaseSpec); + EthereumIntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(tx, releaseSpec); GethLikeTxMemoryTracer gethTracer = new(tx, GethTraceOptions.Default); var blkCtx = new BlockExecutionContext(block.Header, releaseSpec); @@ -562,7 +563,7 @@ public void Can_estimate_with_stipend_and_refund() Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; IReleaseSpec releaseSpec = _specProvider.GetSpec(block.Header); - IntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(tx, releaseSpec); + EthereumIntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(tx, releaseSpec); GethLikeTxMemoryTracer gethTracer = new(tx, GethTraceOptions.Default); var blkCtx = new BlockExecutionContext(block.Header, releaseSpec); @@ -604,7 +605,7 @@ public void Can_estimate_with_single_call() Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; IReleaseSpec releaseSpec = _specProvider.GetSpec(block.Header); - IntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(tx, releaseSpec); + EthereumIntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(tx, releaseSpec); var blkCtx = new BlockExecutionContext(block.Header, releaseSpec); _transactionProcessor.Execute(initTx, blkCtx, NullTxTracer.Instance); diff --git a/src/Nethermind/Nethermind.Consensus/IBlockProducerFactory.cs b/src/Nethermind/Nethermind.Consensus/IBlockProducerFactory.cs index f89cef995db..15ac802c7a3 100644 --- a/src/Nethermind/Nethermind.Consensus/IBlockProducerFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/IBlockProducerFactory.cs @@ -1,8 +1,6 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Consensus.Transactions; - namespace Nethermind.Consensus; public interface IBlockProducerFactory diff --git a/src/Nethermind/Nethermind.Consensus/IMiningConfig.cs b/src/Nethermind/Nethermind.Consensus/IMiningConfig.cs index 1b9734c51e6..3bd63ff5145 100644 --- a/src/Nethermind/Nethermind.Consensus/IMiningConfig.cs +++ b/src/Nethermind/Nethermind.Consensus/IMiningConfig.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Config; -using Nethermind.Int256; namespace Nethermind.Consensus; diff --git a/src/Nethermind/Nethermind.Consensus/MiningConfig.cs b/src/Nethermind/Nethermind.Consensus/MiningConfig.cs index aa7772f5958..2e7b5177ef2 100644 --- a/src/Nethermind/Nethermind.Consensus/MiningConfig.cs +++ b/src/Nethermind/Nethermind.Consensus/MiningConfig.cs @@ -1,9 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Config; -using Nethermind.Int256; - namespace Nethermind.Consensus; public class MiningConfig : IMiningConfig diff --git a/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs index ce6a7f705b0..f8496e46569 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs @@ -5,7 +5,6 @@ using Autofac; using Nethermind.Blockchain; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs index 1418fe28401..8071dc34907 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using Nethermind.Blockchain.Tracing; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs index a2742e38bfe..ce070783a71 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Nethermind.Blockchain; using Nethermind.Blockchain.BeaconBlockRoot; using Nethermind.Core; using Nethermind.Core.Extensions; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/CensorshipDetector/CensorshipDetector.cs b/src/Nethermind/Nethermind.Consensus/Processing/CensorshipDetector/CensorshipDetector.cs index cc56f546338..b225e7e5cb7 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/CensorshipDetector/CensorshipDetector.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/CensorshipDetector/CensorshipDetector.cs @@ -4,7 +4,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Core; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/IBlockCachePreWarmer.cs b/src/Nethermind/Nethermind.Consensus/Processing/IBlockCachePreWarmer.cs index a62b840652a..2a371513293 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/IBlockCachePreWarmer.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/IBlockCachePreWarmer.cs @@ -5,7 +5,6 @@ using System.Threading; using System.Threading.Tasks; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Core.Eip2930; using Nethermind.Core.Specs; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs index 718d7e3e8fe..2adaabe6f4b 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Threading; using Nethermind.Blockchain.Tracing; using Nethermind.Core; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs index 51b998dcae4..819aabd99c2 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Threading; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Evm.Tracing; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ShareableTxProcessingSource.cs b/src/Nethermind/Nethermind.Consensus/Processing/ShareableTxProcessingSource.cs index b0ea3a22b5d..dbdcda33322 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ShareableTxProcessingSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ShareableTxProcessingSource.cs @@ -4,10 +4,8 @@ using Microsoft.Extensions.ObjectPool; using Nethermind.Blockchain; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; -using Nethermind.State; namespace Nethermind.Consensus.Processing; diff --git a/src/Nethermind/Nethermind.Consensus/Stateless/StatelessBlockProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Stateless/StatelessBlockProcessingEnv.cs index 551e5c665ff..b145d04b4d7 100644 --- a/src/Nethermind/Nethermind.Consensus/Stateless/StatelessBlockProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Stateless/StatelessBlockProcessingEnv.cs @@ -1,31 +1,22 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; -using System.Collections.Generic; -using System.Linq; using Nethermind.Blockchain; using Nethermind.Blockchain.BeaconBlockRoot; using Nethermind.Blockchain.Blocks; -using Nethermind.Blockchain.Find; -using Nethermind.Blockchain.Headers; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.ExecutionRequests; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; using Nethermind.Consensus.Withdrawals; -using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Core.Specs; -using Nethermind.Db; using Nethermind.Evm; using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; using Nethermind.State; using Nethermind.Trie; -using Nethermind.Trie.Pruning; namespace Nethermind.Consensus.Stateless; @@ -81,7 +72,7 @@ private IBlockProcessor GetProcessor() private ITransactionProcessor CreateTransactionProcessor(IWorldState state, IBlockhashCache blockhashCache) { BlockhashProvider blockhashProvider = new(blockhashCache, state, logManager); - VirtualMachine vm = new(blockhashProvider, specProvider, logManager); - return new TransactionProcessor(BlobBaseFeeCalculator.Instance, specProvider, state, vm, new EthereumCodeInfoRepository(state), logManager); + EthereumVirtualMachine vm = new(blockhashProvider, specProvider, logManager); + return new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, specProvider, state, vm, new EthereumCodeInfoRepository(state), logManager); } } diff --git a/src/Nethermind/Nethermind.Consensus/Stateless/Witness.cs b/src/Nethermind/Nethermind.Consensus/Stateless/Witness.cs index e6a139d4cb9..30ccd459154 100644 --- a/src/Nethermind/Nethermind.Consensus/Stateless/Witness.cs +++ b/src/Nethermind/Nethermind.Consensus/Stateless/Witness.cs @@ -7,10 +7,8 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Db; -using Nethermind.Logging; using Nethermind.Serialization.Rlp; using Nethermind.Trie; -using Nethermind.Trie.Pruning; namespace Nethermind.Consensus.Stateless; diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/BlockProcessorFacade.cs b/src/Nethermind/Nethermind.Consensus/Tracing/BlockProcessorFacade.cs index 3ba3590e63c..fabb1b7d57c 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/BlockProcessorFacade.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/BlockProcessorFacade.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; -using Nethermind.Blockchain; using Nethermind.Consensus.Processing; using Nethermind.Core; using Nethermind.Core.Specs; diff --git a/src/Nethermind/Nethermind.Consensus/TxFilterBuilders.cs b/src/Nethermind/Nethermind.Consensus/TxFilterBuilders.cs index 39bd8807bf6..294b4f667d5 100644 --- a/src/Nethermind/Nethermind.Consensus/TxFilterBuilders.cs +++ b/src/Nethermind/Nethermind.Consensus/TxFilterBuilders.cs @@ -3,7 +3,6 @@ using Nethermind.Config; using Nethermind.Consensus.Transactions; -using Nethermind.Core.Specs; namespace Nethermind.Consensus { diff --git a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs index f1bb22feeea..bec7ae4e8d2 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs @@ -124,7 +124,7 @@ private IntrinsicGasTxValidator() { } public ValidationResult IsWellFormed(Transaction transaction, IReleaseSpec releaseSpec) { // This is unnecessarily calculated twice - at validation and execution times. - IntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(transaction, releaseSpec); + EthereumIntrinsicGas intrinsicGas = IntrinsicGasCalculator.Calculate(transaction, releaseSpec); return transaction.GasLimit < intrinsicGas.MinimalGas ? TxErrorMessages.IntrinsicGasTooLow : ValidationResult.Success; diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs index 9295fc1f5db..1d3225fe6b6 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs @@ -11,6 +11,7 @@ using Nethermind.Db; using Nethermind.Evm.CodeAnalysis; using Nethermind.Specs; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.State; using Nethermind.Evm.Tracing; using Nethermind.Int256; @@ -32,7 +33,7 @@ public class EvmBenchmarks private IVirtualMachine _virtualMachine; private BlockHeader _header = new BlockHeader(Keccak.Zero, Keccak.Zero, Address.Zero, UInt256.One, MainnetSpecProvider.IstanbulBlockNumber, Int64.MaxValue, 1UL, Bytes.Empty); private IBlockhashProvider _blockhashProvider = new TestBlockhashProvider(); - private EvmState _evmState; + private VmState _evmState; private IWorldState _stateProvider; [GlobalSetup] @@ -45,7 +46,7 @@ public void GlobalSetup() _stateProvider.CreateAccount(Address.Zero, 1000.Ether()); _stateProvider.Commit(_spec); EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); - _virtualMachine = new VirtualMachine(_blockhashProvider, MainnetSpecProvider.Instance, LimboLogs.Instance); + _virtualMachine = new EthereumVirtualMachine(_blockhashProvider, MainnetSpecProvider.Instance, LimboLogs.Instance); _virtualMachine.SetBlockExecutionContext(new BlockExecutionContext(_header, _spec)); _virtualMachine.SetTxExecutionContext(new TxExecutionContext(Address.Zero, codeInfoRepository, null, 0)); @@ -60,7 +61,7 @@ public void GlobalSetup() inputData: default ); - _evmState = EvmState.RentTopLevel(long.MaxValue, ExecutionType.TRANSACTION, _environment, new StackAccessTracker(), _stateProvider.TakeSnapshot()); + _evmState = VmState.RentTopLevel(EthereumGasPolicy.FromLong(long.MaxValue), ExecutionType.TRANSACTION, _environment, new StackAccessTracker(), _stateProvider.TakeSnapshot()); } [GlobalCleanup] diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs index a627a5e4691..4f2d0447718 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs @@ -11,6 +11,7 @@ using Nethermind.Core.Test; using Nethermind.Db; using Nethermind.Evm.CodeAnalysis; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.State; using Nethermind.Evm.Tracing; using Nethermind.Int256; @@ -31,7 +32,7 @@ public class MultipleUnsignedOperations private IVirtualMachine _virtualMachine; private readonly BlockHeader _header = new(Keccak.Zero, Keccak.Zero, Address.Zero, UInt256.One, MainnetSpecProvider.MuirGlacierBlockNumber, Int64.MaxValue, 1UL, Bytes.Empty); private readonly IBlockhashProvider _blockhashProvider = new TestBlockhashProvider(); - private EvmState _evmState; + private VmState _evmState; private IWorldState _stateProvider; private readonly byte[] _bytecode = Prepare.EvmCode @@ -77,7 +78,7 @@ public void GlobalSetup() Console.WriteLine(MuirGlacier.Instance); EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); - _virtualMachine = new VirtualMachine(_blockhashProvider, MainnetSpecProvider.Instance, new OneLoggerLogManager(NullLogger.Instance)); + _virtualMachine = new EthereumVirtualMachine(_blockhashProvider, MainnetSpecProvider.Instance, new OneLoggerLogManager(NullLogger.Instance)); _virtualMachine.SetBlockExecutionContext(new BlockExecutionContext(_header, _spec)); _virtualMachine.SetTxExecutionContext(new TxExecutionContext(Address.Zero, codeInfoRepository, null, 0)); @@ -92,7 +93,7 @@ public void GlobalSetup() inputData: default ); - _evmState = EvmState.RentTopLevel(100_000_000L, ExecutionType.TRANSACTION, _environment, new StackAccessTracker(), _stateProvider.TakeSnapshot()); + _evmState = VmState.RentTopLevel(EthereumGasPolicy.FromLong(100_000_000L), ExecutionType.TRANSACTION, _environment, new StackAccessTracker(), _stateProvider.TakeSnapshot()); } [GlobalCleanup] diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs index 3f5d0c4ca16..600590d9dcd 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs @@ -12,6 +12,7 @@ using Nethermind.Db; using Nethermind.Evm.CodeAnalysis; using Nethermind.Specs; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.State; using Nethermind.Evm.Tracing; using Nethermind.Int256; @@ -32,7 +33,7 @@ public class StaticCallBenchmarks private IVirtualMachine _virtualMachine; private BlockHeader _header = new BlockHeader(Keccak.Zero, Keccak.Zero, Address.Zero, UInt256.One, MainnetSpecProvider.MuirGlacierBlockNumber, Int64.MaxValue, 1UL, Bytes.Empty); private IBlockhashProvider _blockhashProvider = new TestBlockhashProvider(); - private EvmState _evmState; + private VmState _evmState; private IWorldState _stateProvider; public IEnumerable Bytecodes @@ -88,7 +89,7 @@ public void GlobalSetup() Console.WriteLine(MuirGlacier.Instance); EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); - _virtualMachine = new VirtualMachine(_blockhashProvider, MainnetSpecProvider.Instance, new OneLoggerLogManager(NullLogger.Instance)); + _virtualMachine = new EthereumVirtualMachine(_blockhashProvider, MainnetSpecProvider.Instance, new OneLoggerLogManager(NullLogger.Instance)); _virtualMachine.SetBlockExecutionContext(new BlockExecutionContext(_header, _spec)); _virtualMachine.SetTxExecutionContext(new TxExecutionContext(Address.Zero, codeInfoRepository, null, 0)); _environment = ExecutionEnvironment.Rent( @@ -102,7 +103,7 @@ public void GlobalSetup() inputData: default ); - _evmState = EvmState.RentTopLevel(100_000_000L, ExecutionType.TRANSACTION, _environment, new StackAccessTracker(), _stateProvider.TakeSnapshot()); + _evmState = VmState.RentTopLevel(EthereumGasPolicy.FromLong(100_000_000L), ExecutionType.TRANSACTION, _environment, new StackAccessTracker(), _stateProvider.TakeSnapshot()); } [GlobalCleanup] diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip2028Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip2028Tests.cs index e0286a9a48d..cb82a017a79 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip2028Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip2028Tests.cs @@ -23,8 +23,8 @@ private class AfterIstanbul : Eip2028Tests public void non_zero_transaction_data_cost_should_be_16() { Transaction transaction = new Transaction { Data = new byte[] { 1 }, To = Address.Zero }; - IntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); - cost.Should().Be(new IntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataNonZeroEip2028, + EthereumIntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); + cost.Should().Be(new EthereumIntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataNonZeroEip2028, FloorGas: 0)); } @@ -32,8 +32,8 @@ public void non_zero_transaction_data_cost_should_be_16() public void zero_transaction_data_cost_should_be_4() { Transaction transaction = new Transaction { Data = new byte[] { 0 }, To = Address.Zero }; - IntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); - cost.Should().Be(new IntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataZero, + EthereumIntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); + cost.Should().Be(new EthereumIntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataZero, FloorGas: 0)); } } @@ -47,8 +47,8 @@ private class BeforeIstanbul : Eip2028Tests public void non_zero_transaction_data_cost_should_be_68() { Transaction transaction = new Transaction { Data = new byte[] { 1 }, To = Address.Zero }; - IntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); - cost.Should().Be(new IntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataNonZero, + EthereumIntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); + cost.Should().Be(new EthereumIntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataNonZero, FloorGas: 0)); } @@ -56,8 +56,8 @@ public void non_zero_transaction_data_cost_should_be_68() public void zero_transaction_data_cost_should_be_4() { Transaction transaction = new Transaction { Data = new byte[] { 0 }, To = Address.Zero }; - IntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); - cost.Should().Be(new IntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataZero, + EthereumIntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); + cost.Should().Be(new EthereumIntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataZero, FloorGas: 0)); } } diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs index 6f65342dcc8..22bc16baa34 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs @@ -27,7 +27,7 @@ public class Eip3198BaseFeeTests : VirtualMachineTestsBase [TestCase(false, 0, false)] public void Base_fee_opcode_should_return_expected_results(bool eip3198Enabled, int baseFee, bool send1559Tx) { - _processor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, SpecProvider, TestState, Machine, CodeInfoRepository, LimboLogs.Instance); + _processor = new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, SpecProvider, TestState, Machine, CodeInfoRepository, LimboLogs.Instance); byte[] code = Prepare.EvmCode .Op(Instruction.BASEFEE) .PushData(0) diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs index d170bf21d2c..de51c08b541 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs @@ -74,7 +74,7 @@ private void Test(string codeHex, long gasUsed, long refund, byte originalValue, TestState.CreateAccount(Recipient, 1.Ether()); TestState.Set(new StorageCell(Recipient, 0), new[] { originalValue }); TestState.Commit(eip3529Enabled ? London.Instance : Berlin.Instance); - _processor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, SpecProvider, TestState, Machine, CodeInfoRepository, LimboLogs.Instance); + _processor = new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, SpecProvider, TestState, Machine, CodeInfoRepository, LimboLogs.Instance); long blockNumber = eip3529Enabled ? MainnetSpecProvider.LondonBlockNumber : MainnetSpecProvider.LondonBlockNumber - 1; (Block block, Transaction transaction) = PrepareTx(blockNumber, 100000, Bytes.FromHexString(codeHex)); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs index d9585be6ec8..d28235fa0ac 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs @@ -89,7 +89,7 @@ void DeployCodeAndAssertTx(string code, bool eip3541Enabled, ContractDeployment ContractDeployment.CREATE2 => Prepare.EvmCode.Create2(byteCode, salt, UInt256.Zero).Done, _ => byteCode, }; - _processor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, SpecProvider, TestState, Machine, CodeInfoRepository, LimboLogs.Instance); + _processor = new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, SpecProvider, TestState, Machine, CodeInfoRepository, LimboLogs.Instance); long blockNumber = eip3541Enabled ? MainnetSpecProvider.LondonBlockNumber : MainnetSpecProvider.LondonBlockNumber - 1; (Block block, Transaction transaction) = PrepareTx(blockNumber, 100000, createContract); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip7516BlobBaseFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip7516BlobBaseFeeTests.cs index 74d5b538a98..5344bdae0d4 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip7516BlobBaseFeeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip7516BlobBaseFeeTests.cs @@ -28,7 +28,7 @@ public class Eip7516BlobBaseFeeTests : VirtualMachineTestsBase [TestCase(false, 0ul)] public void Blob_Base_fee_opcode_should_return_expected_results(bool eip7516Enabled, ulong excessBlobGas) { - _processor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, SpecProvider, TestState, Machine, CodeInfoRepository, LimboLogs.Instance); + _processor = new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, SpecProvider, TestState, Machine, CodeInfoRepository, LimboLogs.Instance); byte[] code = Prepare.EvmCode .Op(Instruction.BLOBBASEFEE) .PushData(0) diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip7623Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip7623Tests.cs index b67e8283c53..674159d89f2 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip7623Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip7623Tests.cs @@ -18,8 +18,8 @@ public class Eip7623Tests : VirtualMachineTestsBase public void non_zero_data_transaction_floor_cost_should_be_40() { var transaction = new Transaction { Data = new byte[] { 1 }, To = Address.Zero }; - IntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); - cost.Should().Be(new IntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataNonZeroEip2028, + EthereumIntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); + cost.Should().Be(new EthereumIntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataNonZeroEip2028, FloorGas: GasCostOf.Transaction + GasCostOf.TotalCostFloorPerTokenEip7623 * 4)); } @@ -27,8 +27,8 @@ public void non_zero_data_transaction_floor_cost_should_be_40() public void zero_data_transaction_floor_cost_should_be_10() { var transaction = new Transaction { Data = new byte[] { 0 }, To = Address.Zero }; - IntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); - cost.Should().Be(new IntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataZero, + EthereumIntrinsicGas cost = IntrinsicGasCalculator.Calculate(transaction, Spec); + cost.Should().Be(new EthereumIntrinsicGas(Standard: GasCostOf.Transaction + GasCostOf.TxDataZero, FloorGas: GasCostOf.Transaction + GasCostOf.TotalCostFloorPerTokenEip7623)); } } diff --git a/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs b/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs index a9b4d90e875..e5247e92c5a 100644 --- a/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs @@ -319,11 +319,11 @@ private static string Run(byte[] input) IWorldState stateProvider = TestWorldStateFactory.CreateForTest(); ISpecProvider specProvider = new TestSpecProvider(London.Instance); EthereumCodeInfoRepository codeInfoRepository = new(stateProvider); - VirtualMachine virtualMachine = new( + EthereumVirtualMachine virtualMachine = new( new TestBlockhashProvider(specProvider), specProvider, LimboLogs.Instance); - ITransactionProcessor transactionProcessor = new TransactionProcessor( + ITransactionProcessor transactionProcessor = new EthereumTransactionProcessor( BlobBaseFeeCalculator.Instance, specProvider, stateProvider, diff --git a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs b/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs deleted file mode 100644 index ec3060c5cd9..00000000000 --- a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs +++ /dev/null @@ -1,243 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using FluentAssertions; -using Nethermind.Core; -using Nethermind.Core.Extensions; -using Nethermind.Core.Test.Builders; -using Nethermind.Evm.State; -using NUnit.Framework; - -namespace Nethermind.Evm.Test -{ - public class EvmStateTests - { - [Test] - public void Things_are_cold_to_start_with() - { - EvmState evmState = CreateEvmState(); - StorageCell storageCell = new(TestItem.AddressA, 1); - evmState.AccessTracker.IsCold(TestItem.AddressA).Should().BeTrue(); - evmState.AccessTracker.IsCold(storageCell).Should().BeTrue(); - } - - [Test] - public void Can_warm_address_up_twice() - { - EvmState evmState = CreateEvmState(); - Address address = TestItem.AddressA; - evmState.AccessTracker.WarmUp(address); - evmState.AccessTracker.WarmUp(address); - evmState.AccessTracker.IsCold(address).Should().BeFalse(); - } - - [Test] - public void Can_warm_up_many() - { - EvmState evmState = CreateEvmState(); - for (int i = 0; i < TestItem.Addresses.Length; i++) - { - evmState.AccessTracker.WarmUp(TestItem.Addresses[i]); - evmState.AccessTracker.WarmUp(new StorageCell(TestItem.Addresses[i], 1)); - } - - for (int i = 0; i < TestItem.Addresses.Length; i++) - { - evmState.AccessTracker.IsCold(TestItem.Addresses[i]).Should().BeFalse(); - evmState.AccessTracker.IsCold(new StorageCell(TestItem.Addresses[i], 1)).Should().BeFalse(); - } - } - - [Test] - public void Can_warm_storage_up_twice() - { - EvmState evmState = CreateEvmState(); - Address address = TestItem.AddressA; - StorageCell storageCell = new(address, 1); - evmState.AccessTracker.WarmUp(storageCell); - evmState.AccessTracker.WarmUp(storageCell); - evmState.AccessTracker.IsCold(storageCell).Should().BeFalse(); - } - - [Test] - public void Nothing_to_commit() - { - EvmState parentEvmState = CreateEvmState(); - using (EvmState evmState = CreateEvmState(parentEvmState)) - { - evmState.CommitToParent(parentEvmState); - } - } - - [Test] - public void Nothing_to_restore() - { - EvmState parentEvmState = CreateEvmState(); - using EvmState evmState = CreateEvmState(parentEvmState); - } - - [Test] - public void Address_to_commit_keeps_it_warm() - { - EvmState parentEvmState = CreateEvmState(); - using (EvmState evmState = CreateEvmState(parentEvmState)) - { - evmState.AccessTracker.WarmUp(TestItem.AddressA); - evmState.CommitToParent(parentEvmState); - } - - parentEvmState.AccessTracker.IsCold(TestItem.AddressA).Should().BeFalse(); - } - - [Test] - public void Address_to_restore_keeps_it_cold() - { - EvmState parentEvmState = CreateEvmState(); - using (EvmState evmState = CreateEvmState(parentEvmState)) - { - evmState.AccessTracker.WarmUp(TestItem.AddressA); - } - - parentEvmState.AccessTracker.IsCold(TestItem.AddressA).Should().BeTrue(); - } - - [Test] - public void Storage_to_commit_keeps_it_warm() - { - EvmState parentEvmState = CreateEvmState(); - StorageCell storageCell = new(TestItem.AddressA, 1); - using (EvmState evmState = CreateEvmState(parentEvmState)) - { - evmState.AccessTracker.WarmUp(storageCell); - evmState.CommitToParent(parentEvmState); - } - - parentEvmState.AccessTracker.IsCold(storageCell).Should().BeFalse(); - } - - [Test] - public void Storage_to_restore_keeps_it_cold() - { - EvmState parentEvmState = CreateEvmState(); - StorageCell storageCell = new(TestItem.AddressA, 1); - using (EvmState evmState = CreateEvmState(parentEvmState)) - { - evmState.AccessTracker.WarmUp(storageCell); - } - - parentEvmState.AccessTracker.IsCold(storageCell).Should().BeTrue(); - } - - [Test] - public void Logs_are_committed() - { - EvmState parentEvmState = CreateEvmState(); - LogEntry logEntry = new(Address.Zero, Bytes.Empty, []); - using (EvmState evmState = CreateEvmState(parentEvmState)) - { - evmState.AccessTracker.Logs.Add(logEntry); - evmState.CommitToParent(parentEvmState); - } - - parentEvmState.AccessTracker.Logs.Contains(logEntry).Should().BeTrue(); - } - - [Test] - public void Logs_are_restored() - { - EvmState parentEvmState = CreateEvmState(); - LogEntry logEntry = new(Address.Zero, Bytes.Empty, []); - using (EvmState evmState = CreateEvmState(parentEvmState)) - { - evmState.AccessTracker.Logs.Add(logEntry); - } - - parentEvmState.AccessTracker.Logs.Contains(logEntry).Should().BeFalse(); - } - - [Test] - public void Destroy_list_is_committed() - { - EvmState parentEvmState = CreateEvmState(); - using (EvmState evmState = CreateEvmState(parentEvmState)) - { - evmState.AccessTracker.ToBeDestroyed(Address.Zero); - evmState.CommitToParent(parentEvmState); - } - - parentEvmState.AccessTracker.DestroyList.Contains(Address.Zero).Should().BeTrue(); - } - - [Test] - public void Destroy_list_is_restored() - { - EvmState parentEvmState = CreateEvmState(); - using (EvmState evmState = CreateEvmState(parentEvmState)) - { - evmState.AccessTracker.ToBeDestroyed(Address.Zero); - } - - parentEvmState.AccessTracker.DestroyList.Contains(Address.Zero).Should().BeFalse(); - } - - [Test] - public void Commit_adds_refunds() - { - EvmState parentEvmState = CreateEvmState(); - using (EvmState evmState = CreateEvmState(parentEvmState)) - { - evmState.Refund = 333; - evmState.CommitToParent(parentEvmState); - } - - parentEvmState.Refund.Should().Be(333); - } - - [Test] - public void Restore_does_not_add_refunds() - { - EvmState parentEvmState = CreateEvmState(); - using (EvmState evmState = CreateEvmState(parentEvmState)) - { - evmState.Refund = 333; - } - - parentEvmState.Refund.Should().Be(0); - } - - [Test] - public void Can_dispose_without_init() - { - EvmState evmState = CreateEvmState(); - evmState.Dispose(); - } - - [Test] - public void Can_dispose_after_init() - { - EvmState evmState = CreateEvmState(); - evmState.InitializeStacks(); - evmState.Dispose(); - } - - private static EvmState CreateEvmState(EvmState parentEvmState = null, bool isContinuation = false) => - parentEvmState is null - ? EvmState.RentTopLevel(10000, - ExecutionType.CALL, - RentExecutionEnvironment(), - new StackAccessTracker(), - Snapshot.Empty) - : EvmState.RentFrame(10000, - 0, - 0, - ExecutionType.CALL, - false, - false, - RentExecutionEnvironment(), - parentEvmState.AccessTracker, - Snapshot.Empty); - - private static ExecutionEnvironment RentExecutionEnvironment() => - ExecutionEnvironment.Rent(null, null, null, null, 0, default, default, default); - } -} diff --git a/src/Nethermind/Nethermind.Evm.Test/GasPriceExtractorTests.cs b/src/Nethermind/Nethermind.Evm.Test/GasPriceExtractorTests.cs index 2705534a68f..1af4cd3301a 100644 --- a/src/Nethermind/Nethermind.Evm.Test/GasPriceExtractorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/GasPriceExtractorTests.cs @@ -35,7 +35,7 @@ public void Intrinsic_gas_cost_assumption_is_correct() Rlp rlp = BuildHeader(); Transaction tx = Build.A.Transaction.WithData(rlp.Bytes).TestObject; - IntrinsicGas gasCost = IntrinsicGasCalculator.Calculate(tx, Spec); + EthereumIntrinsicGas gasCost = IntrinsicGasCalculator.Calculate(tx, Spec); gasCost.FloorGas.Should().Be(0); gasCost.Standard.Should().BeLessThan(21000 + 9600); } diff --git a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs index cac1206d630..23d53fa5540 100644 --- a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs @@ -54,8 +54,8 @@ public class IntrinsicGasCalculatorTests [TestCaseSource(nameof(TestCaseSource))] public void Intrinsic_cost_is_calculated_properly((Transaction Tx, long Cost, string Description) testCase) { - IntrinsicGas gas = IntrinsicGasCalculator.Calculate(testCase.Tx, Berlin.Instance); - gas.Should().Be(new IntrinsicGas(Standard: testCase.Cost, FloorGas: 0)); + EthereumIntrinsicGas gas = IntrinsicGasCalculator.Calculate(testCase.Tx, Berlin.Instance); + gas.Should().Be(new EthereumIntrinsicGas(Standard: testCase.Cost, FloorGas: 0)); } [TestCaseSource(nameof(AccessTestCaseSource))] @@ -85,8 +85,8 @@ void Test(IReleaseSpec spec, bool supportsAccessLists) } else { - IntrinsicGas gas = IntrinsicGasCalculator.Calculate(tx, spec); - gas.Should().Be(new IntrinsicGas(Standard: 21000 + testCase.Cost, FloorGas: 0), spec.Name); + EthereumIntrinsicGas gas = IntrinsicGasCalculator.Calculate(tx, spec); + gas.Should().Be(new EthereumIntrinsicGas(Standard: 21000 + testCase.Cost, FloorGas: 0), spec.Name); } } @@ -110,7 +110,7 @@ public void Intrinsic_cost_of_data_is_calculated_properly((byte[] Data, int OldC void Test(IReleaseSpec spec, GasOptions options) { - IntrinsicGas gas = IntrinsicGasCalculator.Calculate(tx, spec); + EthereumIntrinsicGas gas = IntrinsicGasCalculator.Calculate(tx, spec); bool isAfterRepricing = options.HasFlag(GasOptions.AfterRepricing); bool floorCostEnabled = options.HasFlag(GasOptions.FloorCostEnabled); @@ -120,7 +120,7 @@ void Test(IReleaseSpec spec, GasOptions options) testCase.Data.ToHexString()); gas.FloorGas.Should().Be(floorCostEnabled ? testCase.FloorCost : 0); - gas.Should().Be(new IntrinsicGas( + gas.Should().Be(new EthereumIntrinsicGas( Standard: 21000 + (isAfterRepricing ? testCase.NewCost : testCase.OldCost), FloorGas: floorCostEnabled ? testCase.FloorCost : 0), spec.Name, testCase.Data.ToHexString()); @@ -205,7 +205,7 @@ public void Calculate_TxHasAuthorizationList_ReturnsExpectedCostOfTx((Authorizat .WithAuthorizationCode(testCase.AuthorizationList) .TestObject; - IntrinsicGas gas = IntrinsicGasCalculator.Calculate(tx, Prague.Instance); + EthereumIntrinsicGas gas = IntrinsicGasCalculator.Calculate(tx, Prague.Instance); gas.Standard.Should().Be(GasCostOf.Transaction + (testCase.ExpectedCost)); } diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs index 134b2736ee8..c4bfadd34fa 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs @@ -10,6 +10,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Evm.Tracing.Debugger; using Nethermind.Core; +using Nethermind.Evm.GasPolicy; namespace Nethermind.Evm.Test; @@ -380,10 +381,10 @@ public void Use_Debug_Tracer_To_Check_Assertion_Live(string bytecodeHex) if (tracer.CanReadState) { // we alter the value stored in memory to force EQ check at the end to fail - if (gasAvailable_pre_MSTORE is null) gasAvailable_pre_MSTORE = tracer.CurrentState.GasAvailable; + if (gasAvailable_pre_MSTORE is null) gasAvailable_pre_MSTORE = EthereumGasPolicy.GetRemainingGas(tracer.CurrentState.Gas); else { - long gasAvailable_post_MSTORE = tracer.CurrentState.GasAvailable; + long gasAvailable_post_MSTORE = EthereumGasPolicy.GetRemainingGas(tracer.CurrentState.Gas); Assert.That(gasAvailable_pre_MSTORE - gasAvailable_post_MSTORE, Is.EqualTo(GasCostOf.VeryLow)); } tracer.MoveNext(); diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs index 20ed04b918a..b7ea5200d44 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs @@ -674,7 +674,7 @@ private class TestEnvironment : IDisposable { public ISpecProvider _specProvider; public IEthereumEcdsa _ethereumEcdsa; - public TransactionProcessor _transactionProcessor; + public EthereumTransactionProcessor _transactionProcessor; public IWorldState _stateProvider; public EstimateGasTracer tracer; public GasEstimator estimator; @@ -690,8 +690,8 @@ public TestEnvironment() _stateProvider.CommitTree(0); EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); - VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + EthereumVirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); + _transactionProcessor = new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId); tracer = new(); diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs index 16d1dba46bd..d0fc8e2ac58 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs @@ -38,8 +38,8 @@ public void Setup() _stateProvider = TestWorldStateFactory.CreateForTest(); _worldStateCloser = _stateProvider.BeginScope(IWorldState.PreGenesis); EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); - VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + EthereumVirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); + _transactionProcessor = new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId); } diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip7623Tests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip7623Tests.cs index 69ed6870c84..1865ecfc8a2 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip7623Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip7623Tests.cs @@ -36,8 +36,8 @@ public void Setup() _stateProvider = TestWorldStateFactory.CreateForTest(); _worldStateCloser = _stateProvider.BeginScope(IWorldState.PreGenesis); EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); - VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + EthereumVirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); + _transactionProcessor = new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId); } diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs index 50f593d378b..adf9866fb05 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs @@ -48,8 +48,8 @@ public void Setup() _stateProvider.CommitTree(0); EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); - VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + EthereumVirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); + _transactionProcessor = new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId); } diff --git a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs index 5031e029d19..b45550ea705 100644 --- a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs +++ b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs @@ -37,7 +37,7 @@ public abstract class VirtualMachineTestsBase private IDb _stateDb; private IDisposable _worldStateCloser; - protected VirtualMachine Machine { get; private set; } + protected EthereumVirtualMachine Machine { get; private set; } protected CodeInfoRepository CodeInfoRepository { get; private set; } protected IWorldState TestState { get; private set; } protected static Address Contract { get; } = new("0xd75a3a95360e44a3874e691fb48d77855f127069"); @@ -72,8 +72,8 @@ public virtual void Setup() _ethereumEcdsa = new EthereumEcdsa(SpecProvider.ChainId); IBlockhashProvider blockhashProvider = new TestBlockhashProvider(SpecProvider); CodeInfoRepository = new EthereumCodeInfoRepository(TestState); - Machine = new VirtualMachine(blockhashProvider, SpecProvider, logManager); - _processor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, SpecProvider, TestState, Machine, CodeInfoRepository, logManager); + Machine = new EthereumVirtualMachine(blockhashProvider, SpecProvider, logManager); + _processor = new EthereumTransactionProcessor(BlobBaseFeeCalculator.Instance, SpecProvider, TestState, Machine, CodeInfoRepository, logManager); } [TearDown] diff --git a/src/Nethermind/Nethermind.Evm.Test/VmStateTests.cs b/src/Nethermind/Nethermind.Evm.Test/VmStateTests.cs new file mode 100644 index 00000000000..8fc3e9a8b58 --- /dev/null +++ b/src/Nethermind/Nethermind.Evm.Test/VmStateTests.cs @@ -0,0 +1,244 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using FluentAssertions; +using Nethermind.Core; +using Nethermind.Core.Extensions; +using Nethermind.Core.Test.Builders; +using Nethermind.Evm.GasPolicy; +using Nethermind.Evm.State; +using NUnit.Framework; + +namespace Nethermind.Evm.Test +{ + public class VmStateTests + { + [Test] + public void Things_are_cold_to_start_with() + { + VmState vmState = CreateEvmState(); + StorageCell storageCell = new(TestItem.AddressA, 1); + vmState.AccessTracker.IsCold(TestItem.AddressA).Should().BeTrue(); + vmState.AccessTracker.IsCold(storageCell).Should().BeTrue(); + } + + [Test] + public void Can_warm_address_up_twice() + { + VmState vmState = CreateEvmState(); + Address address = TestItem.AddressA; + vmState.AccessTracker.WarmUp(address); + vmState.AccessTracker.WarmUp(address); + vmState.AccessTracker.IsCold(address).Should().BeFalse(); + } + + [Test] + public void Can_warm_up_many() + { + VmState vmState = CreateEvmState(); + for (int i = 0; i < TestItem.Addresses.Length; i++) + { + vmState.AccessTracker.WarmUp(TestItem.Addresses[i]); + vmState.AccessTracker.WarmUp(new StorageCell(TestItem.Addresses[i], 1)); + } + + for (int i = 0; i < TestItem.Addresses.Length; i++) + { + vmState.AccessTracker.IsCold(TestItem.Addresses[i]).Should().BeFalse(); + vmState.AccessTracker.IsCold(new StorageCell(TestItem.Addresses[i], 1)).Should().BeFalse(); + } + } + + [Test] + public void Can_warm_storage_up_twice() + { + VmState vmState = CreateEvmState(); + Address address = TestItem.AddressA; + StorageCell storageCell = new(address, 1); + vmState.AccessTracker.WarmUp(storageCell); + vmState.AccessTracker.WarmUp(storageCell); + vmState.AccessTracker.IsCold(storageCell).Should().BeFalse(); + } + + [Test] + public void Nothing_to_commit() + { + VmState parentVmState = CreateEvmState(); + using (VmState vmState = CreateEvmState(parentVmState)) + { + vmState.CommitToParent(parentVmState); + } + } + + [Test] + public void Nothing_to_restore() + { + VmState parentVmState = CreateEvmState(); + using VmState vmState = CreateEvmState(parentVmState); + } + + [Test] + public void Address_to_commit_keeps_it_warm() + { + VmState parentVmState = CreateEvmState(); + using (VmState vmState = CreateEvmState(parentVmState)) + { + vmState.AccessTracker.WarmUp(TestItem.AddressA); + vmState.CommitToParent(parentVmState); + } + + parentVmState.AccessTracker.IsCold(TestItem.AddressA).Should().BeFalse(); + } + + [Test] + public void Address_to_restore_keeps_it_cold() + { + VmState parentVmState = CreateEvmState(); + using (VmState vmState = CreateEvmState(parentVmState)) + { + vmState.AccessTracker.WarmUp(TestItem.AddressA); + } + + parentVmState.AccessTracker.IsCold(TestItem.AddressA).Should().BeTrue(); + } + + [Test] + public void Storage_to_commit_keeps_it_warm() + { + VmState parentVmState = CreateEvmState(); + StorageCell storageCell = new(TestItem.AddressA, 1); + using (VmState vmState = CreateEvmState(parentVmState)) + { + vmState.AccessTracker.WarmUp(storageCell); + vmState.CommitToParent(parentVmState); + } + + parentVmState.AccessTracker.IsCold(storageCell).Should().BeFalse(); + } + + [Test] + public void Storage_to_restore_keeps_it_cold() + { + VmState parentVmState = CreateEvmState(); + StorageCell storageCell = new(TestItem.AddressA, 1); + using (VmState vmState = CreateEvmState(parentVmState)) + { + vmState.AccessTracker.WarmUp(storageCell); + } + + parentVmState.AccessTracker.IsCold(storageCell).Should().BeTrue(); + } + + [Test] + public void Logs_are_committed() + { + VmState parentVmState = CreateEvmState(); + LogEntry logEntry = new(Address.Zero, Bytes.Empty, []); + using (VmState vmState = CreateEvmState(parentVmState)) + { + vmState.AccessTracker.Logs.Add(logEntry); + vmState.CommitToParent(parentVmState); + } + + parentVmState.AccessTracker.Logs.Contains(logEntry).Should().BeTrue(); + } + + [Test] + public void Logs_are_restored() + { + VmState parentVmState = CreateEvmState(); + LogEntry logEntry = new(Address.Zero, Bytes.Empty, []); + using (VmState vmState = CreateEvmState(parentVmState)) + { + vmState.AccessTracker.Logs.Add(logEntry); + } + + parentVmState.AccessTracker.Logs.Contains(logEntry).Should().BeFalse(); + } + + [Test] + public void Destroy_list_is_committed() + { + VmState parentVmState = CreateEvmState(); + using (VmState vmState = CreateEvmState(parentVmState)) + { + vmState.AccessTracker.ToBeDestroyed(Address.Zero); + vmState.CommitToParent(parentVmState); + } + + parentVmState.AccessTracker.DestroyList.Contains(Address.Zero).Should().BeTrue(); + } + + [Test] + public void Destroy_list_is_restored() + { + VmState parentVmState = CreateEvmState(); + using (VmState vmState = CreateEvmState(parentVmState)) + { + vmState.AccessTracker.ToBeDestroyed(Address.Zero); + } + + parentVmState.AccessTracker.DestroyList.Contains(Address.Zero).Should().BeFalse(); + } + + [Test] + public void Commit_adds_refunds() + { + VmState parentVmState = CreateEvmState(); + using (VmState vmState = CreateEvmState(parentVmState)) + { + vmState.Refund = 333; + vmState.CommitToParent(parentVmState); + } + + parentVmState.Refund.Should().Be(333); + } + + [Test] + public void Restore_does_not_add_refunds() + { + VmState parentVmState = CreateEvmState(); + using (VmState vmState = CreateEvmState(parentVmState)) + { + vmState.Refund = 333; + } + + parentVmState.Refund.Should().Be(0); + } + + [Test] + public void Can_dispose_without_init() + { + VmState vmState = CreateEvmState(); + vmState.Dispose(); + } + + [Test] + public void Can_dispose_after_init() + { + VmState vmState = CreateEvmState(); + vmState.InitializeStacks(); + vmState.Dispose(); + } + + private static VmState CreateEvmState(VmState parentVmState = null, bool isContinuation = false) => + parentVmState is null + ? VmState.RentTopLevel(EthereumGasPolicy.FromLong(10000), + ExecutionType.CALL, + RentExecutionEnvironment(), + new StackAccessTracker(), + Snapshot.Empty) + : VmState.RentFrame(EthereumGasPolicy.FromLong(10000), + 0, + 0, + ExecutionType.CALL, + false, + false, + RentExecutionEnvironment(), + parentVmState.AccessTracker, + Snapshot.Empty); + + private static ExecutionEnvironment RentExecutionEnvironment() => + ExecutionEnvironment.Rent(null, null, null, null, 0, default, default, default); + } +} diff --git a/src/Nethermind/Nethermind.Evm/CallResult.cs b/src/Nethermind/Nethermind.Evm/CallResult.cs index 744d65a9304..08d88379284 100644 --- a/src/Nethermind/Nethermind.Evm/CallResult.cs +++ b/src/Nethermind/Nethermind.Evm/CallResult.cs @@ -3,10 +3,12 @@ using System; using Nethermind.Evm.CodeAnalysis; +using Nethermind.Evm.GasPolicy; namespace Nethermind.Evm; -public partial class VirtualMachine +public partial class VirtualMachine + where TGasPolicy : struct, IGasPolicy { protected readonly ref struct CallResult { @@ -23,7 +25,7 @@ protected readonly ref struct CallResult public static CallResult InvalidAddressRange => new(EvmExceptionType.AddressOutOfRange); public static CallResult Empty(int fromVersion) => new(container: null, output: default, precompileSuccess: null, fromVersion); - public CallResult(EvmState stateToExecute) + public CallResult(VmState stateToExecute) { StateToExecute = stateToExecute; Output = (null, Array.Empty()); @@ -61,7 +63,7 @@ private CallResult(EvmExceptionType exceptionType) ExceptionType = exceptionType; } - public EvmState? StateToExecute { get; } + public VmState? StateToExecute { get; } public (ICodeInfo Container, ReadOnlyMemory Bytes) Output { get; } public EvmExceptionType ExceptionType { get; } public bool ShouldRevert { get; } diff --git a/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs b/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs index 81e8e985680..df531b37ca6 100644 --- a/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs +++ b/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs @@ -45,8 +45,8 @@ ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_memory), offset), public bool TrySaveByte(in UInt256 location, byte value) { - CheckMemoryAccessViolation(in location, WordSize, out _, out bool outOfGas); - if (outOfGas) return false; + CheckMemoryAccessViolation(in location, WordSize, out _, out bool isViolation); + if (isViolation) return false; UpdateSize(location.u0 + 1); @@ -61,8 +61,8 @@ public bool TrySave(in UInt256 location, Span value) return true; } - CheckMemoryAccessViolation(in location, (ulong)value.Length, out ulong newLength, out bool outOfGas); - if (outOfGas) return false; + CheckMemoryAccessViolation(in location, (ulong)value.Length, out ulong newLength, out bool isViolation); + if (isViolation) return false; UpdateSize(newLength); @@ -70,19 +70,19 @@ public bool TrySave(in UInt256 location, Span value) return true; } - private static void CheckMemoryAccessViolation(in UInt256 location, in UInt256 length, out ulong newLength, out bool outOfGas) + private static void CheckMemoryAccessViolation(in UInt256 location, in UInt256 length, out ulong newLength, out bool isViolation) { if (length.IsLargerThanULong()) { - outOfGas = true; + isViolation = true; newLength = 0; return; } - CheckMemoryAccessViolation(in location, length.u0, out newLength, out outOfGas); + CheckMemoryAccessViolation(in location, length.u0, out newLength, out isViolation); } - private static void CheckMemoryAccessViolation(in UInt256 location, ulong length, out ulong newLength, out bool outOfGas) + private static void CheckMemoryAccessViolation(in UInt256 location, ulong length, out ulong newLength, out bool isViolation) { // Check for overflow and ensure the word-aligned size fits in int. // Word alignment can add up to 31 bytes, so we use (int.MaxValue - WordSize + 1) as the limit. @@ -91,7 +91,7 @@ private static void CheckMemoryAccessViolation(in UInt256 location, ulong length if (location.IsLargerThanULong() || length > MaxMemorySize) { - outOfGas = true; + isViolation = true; newLength = 0; return; } @@ -99,12 +99,12 @@ private static void CheckMemoryAccessViolation(in UInt256 location, ulong length ulong totalSize = location.u0 + length; if (totalSize < location.u0 || totalSize > MaxMemorySize) { - outOfGas = true; + isViolation = true; newLength = 0; return; } - outOfGas = false; + isViolation = false; newLength = totalSize; } @@ -116,8 +116,8 @@ public bool TrySave(in UInt256 location, byte[] value) } ulong length = (ulong)value.Length; - CheckMemoryAccessViolation(in location, length, out ulong newLength, out bool outOfGas); - if (outOfGas) return false; + CheckMemoryAccessViolation(in location, length, out ulong newLength, out bool isViolation); + if (isViolation) return false; UpdateSize(newLength); @@ -134,10 +134,10 @@ public bool TrySave(in UInt256 location, in ZeroPaddedSpan value) } ulong length = (ulong)value.Length; - CheckMemoryAccessViolation(in location, length, out ulong newLength, out bool outOfGas); - outOfGas |= location.u0 > int.MaxValue; + CheckMemoryAccessViolation(in location, length, out ulong newLength, out bool isViolation); + isViolation |= location.u0 > int.MaxValue; - if (outOfGas) return false; + if (isViolation) return false; UpdateSize(newLength); @@ -157,8 +157,8 @@ static void ClearPadding(byte[] memory, int offset, int length) public bool TryLoadSpan(scoped in UInt256 location, out Span data) { - CheckMemoryAccessViolation(in location, WordSize, out ulong newLength, out bool outOfGas); - if (outOfGas) + CheckMemoryAccessViolation(in location, WordSize, out ulong newLength, out bool isViolation); + if (isViolation) { data = default; return false; @@ -177,8 +177,8 @@ public bool TryLoadSpan(scoped in UInt256 location, scoped in UInt256 length, ou return true; } - CheckMemoryAccessViolation(in location, in length, out ulong newLength, out bool outOfGas); - if (outOfGas) + CheckMemoryAccessViolation(in location, in length, out ulong newLength, out bool isViolation); + if (isViolation) { data = default; return false; @@ -197,8 +197,8 @@ public bool TryLoad(in UInt256 location, in UInt256 length, out ReadOnlyMemory +/// Standard Ethereum single-dimensional gas.Value policy. +/// +public struct EthereumGasPolicy : IGasPolicy +{ + public long Value; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static EthereumGasPolicy FromLong(long value) => new() { Value = value }; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long GetRemainingGas(in EthereumGasPolicy gas) => gas.Value; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Consume(ref EthereumGasPolicy gas, long cost) => + gas.Value -= cost; + + public static void ConsumeSelfDestructGas(ref EthereumGasPolicy gas) + => Consume(ref gas, GasCostOf.SelfDestructEip150); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Refund(ref EthereumGasPolicy gas, in EthereumGasPolicy childGas) => + gas.Value += childGas.Value; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void SetOutOfGas(ref EthereumGasPolicy gas) => gas.Value = 0; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ConsumeAccountAccessGasWithDelegation(ref EthereumGasPolicy gas, + IReleaseSpec spec, + ref readonly StackAccessTracker accessTracker, + bool isTracingAccess, + Address address, + Address? delegated, + bool chargeForWarm = true) + { + if (!spec.UseHotAndColdStorage) + return true; + + bool notOutOfGas = ConsumeAccountAccessGas(ref gas, spec, in accessTracker, isTracingAccess, address, chargeForWarm); + return notOutOfGas + && (delegated is null + || ConsumeAccountAccessGas(ref gas, spec, in accessTracker, isTracingAccess, delegated, chargeForWarm)); + } + + public static bool ConsumeAccountAccessGas(ref EthereumGasPolicy gas, + IReleaseSpec spec, + ref readonly StackAccessTracker accessTracker, + bool isTracingAccess, + Address address, + bool chargeForWarm = true) + { + bool result = true; + if (spec.UseHotAndColdStorage) + { + if (isTracingAccess) + { + // Ensure that tracing simulates access-list behavior. + accessTracker.WarmUp(address); + } + + // If the account is cold (and not a precompile), charge the cold access cost. + if (!spec.IsPrecompile(address) && accessTracker.WarmUp(address)) + { + result = UpdateGas(ref gas, GasCostOf.ColdAccountAccess); + } + else if (chargeForWarm) + { + // Otherwise, if warm access should be charged, apply the warm read cost. + result = UpdateGas(ref gas, GasCostOf.WarmStateRead); + } + } + + return result; + } + + public static bool ConsumeStorageAccessGas(ref EthereumGasPolicy gas, + ref readonly StackAccessTracker accessTracker, + bool isTracingAccess, + in StorageCell storageCell, + StorageAccessType storageAccessType, + IReleaseSpec spec) + { + // If the spec requires hot/cold storage tracking, determine if extra gas should be charged. + if (!spec.UseHotAndColdStorage) + return true; + // When tracing access, ensure the storage cell is marked as warm to simulate inclusion in the access list. + if (isTracingAccess) + { + accessTracker.WarmUp(in storageCell); + } + + // If the storage cell is still cold, apply the higher cold access cost and mark it as warm. + if (accessTracker.WarmUp(in storageCell)) + return UpdateGas(ref gas, GasCostOf.ColdSLoad); + // For SLOAD operations on already warmed-up storage, apply a lower warm-read cost. + if (storageAccessType == StorageAccessType.SLOAD) + return UpdateGas(ref gas, GasCostOf.WarmStateRead); + return true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool UpdateMemoryCost(ref EthereumGasPolicy gas, + in UInt256 position, + in UInt256 length, VmState vmState) + { + long memoryCost = vmState.Memory.CalculateMemoryCost(in position, length, out bool outOfGas); + if (memoryCost == 0L) + return !outOfGas; + return UpdateGas(ref gas, memoryCost); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool UpdateGas(ref EthereumGasPolicy gas, + long gasCost) + { + if (GetRemainingGas(gas) < gasCost) + return false; + + Consume(ref gas, gasCost); + return true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void UpdateGasUp(ref EthereumGasPolicy gas, + long refund) + { + gas.Value += refund; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ConsumeStorageWrite(ref EthereumGasPolicy gas, bool isSlotCreation, IReleaseSpec spec) + { + long cost = isSlotCreation ? GasCostOf.SSet : spec.GetSStoreResetCost(); + return UpdateGas(ref gas, cost); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ConsumeCallValueTransfer(ref EthereumGasPolicy gas) + => UpdateGas(ref gas, GasCostOf.CallValue); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ConsumeNewAccountCreation(ref EthereumGasPolicy gas) + => UpdateGas(ref gas, GasCostOf.NewAccount); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ConsumeLogEmission(ref EthereumGasPolicy gas, long topicCount, long dataSize) + { + long cost = GasCostOf.Log + topicCount * GasCostOf.LogTopic + dataSize * GasCostOf.LogData; + return UpdateGas(ref gas, cost); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static EthereumGasPolicy Max(in EthereumGasPolicy a, in EthereumGasPolicy b) => + a.Value >= b.Value ? a : b; + + public static EthereumGasPolicy CalculateIntrinsicGas(Transaction tx, IReleaseSpec spec) + { + long gas = GasCostOf.Transaction + + DataCost(tx, spec) + + CreateCost(tx, spec) + + IntrinsicGasCalculator.AccessListCost(tx, spec) + + AuthorizationListCost(tx, spec); + return new() { Value = gas }; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static EthereumGasPolicy CreateAvailableFromIntrinsic(long gasLimit, in EthereumGasPolicy intrinsicGas) + => new() { Value = gasLimit - intrinsicGas.Value }; + + private static long CreateCost(Transaction tx, IReleaseSpec spec) => + tx.IsContractCreation && spec.IsEip2Enabled ? GasCostOf.TxCreate : 0; + + private static long DataCost(Transaction tx, IReleaseSpec spec) + { + long baseDataCost = tx.IsContractCreation && spec.IsEip3860Enabled + ? EvmCalculations.Div32Ceiling((UInt256)tx.Data.Length) * GasCostOf.InitCodeWord + : 0; + + long tokensInCallData = CalculateTokensInCallData(tx, spec); + return baseDataCost + tokensInCallData * GasCostOf.TxDataZero; + } + + private static long CalculateTokensInCallData(Transaction tx, IReleaseSpec spec) + { + long txDataNonZeroMultiplier = spec.IsEip2028Enabled + ? GasCostOf.TxDataNonZeroMultiplierEip2028 + : GasCostOf.TxDataNonZeroMultiplier; + ReadOnlySpan data = tx.Data.Span; + int totalZeros = data.CountZeros(); + return totalZeros + (data.Length - totalZeros) * txDataNonZeroMultiplier; + } + + private static long AuthorizationListCost(Transaction tx, IReleaseSpec spec) + { + AuthorizationTuple[]? authList = tx.AuthorizationList; + if (authList is not null) + { + if (!spec.IsAuthorizationListEnabled) + ThrowAuthorizationListNotEnabled(spec); + return authList.Length * GasCostOf.NewAccount; + } + return 0; + } + + [DoesNotReturn, StackTraceHidden] + private static void ThrowAuthorizationListNotEnabled(IReleaseSpec spec) => + throw new InvalidDataException($"Transaction with an authorization list received within the context of {spec.Name}. EIP-7702 is not enabled."); +} diff --git a/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs b/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs new file mode 100644 index 00000000000..40459a6200a --- /dev/null +++ b/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs @@ -0,0 +1,208 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.Int256; + +namespace Nethermind.Evm.GasPolicy; + +/// +/// Defines a gas policy for EVM execution. +/// +/// The implementing type +public interface IGasPolicy where TSelf : struct, IGasPolicy +{ + /// + /// Creates a new gas instance from a long value. + /// This is primarily used for warmup/testing scenarios. + /// Main execution flow should pass TGasPolicy directly through EvmState. + /// + /// The initial gas value + /// A new gas instance + static abstract TSelf FromLong(long value); + + /// + /// Get the remaining single-dimensional gas available for execution. + /// This is what's checked against zero to detect out-of-gas conditions. + /// + /// The gas state to query. + /// Remaining gas (negative values indicate out-of-gas) + static abstract long GetRemainingGas(in TSelf gas); + + /// + /// Consume gas for an EVM operation. + /// + /// The gas state to update. + /// The gas cost to consume. + static abstract void Consume(ref TSelf gas, long cost); + + /// + /// Consume gas for SelfDestruct operation. + /// + /// The gas state to update. + static abstract void ConsumeSelfDestructGas(ref TSelf gas); + + /// + /// Refund gas from a child call frame. + /// Merges the child gas state back into the parent, preserving any tracking data. + /// + /// The parent gas state to refund into. + /// The child gas state to merge from. + static abstract void Refund(ref TSelf gas, in TSelf childGas); + + /// + /// Mark the gas state as out of gas. + /// Called when execution exhausts all gas. + /// + /// The gas state to update. + static abstract void SetOutOfGas(ref TSelf gasState); + + /// + /// Charges gas for accessing an account, including potential delegation lookups. + /// This method ensures that both the requested account and its delegated account (if any) are properly charged. + /// + /// The gas state to update. + /// The release specification governing gas costs. + /// The access tracker for cold/warm state. + /// Whether access tracing is enabled. + /// The target account address. + /// The delegated account address, if any. + /// If true, charge even if the account is already warm. + /// True if gas was successfully charged; otherwise false. + static abstract bool ConsumeAccountAccessGasWithDelegation(ref TSelf gas, + IReleaseSpec spec, + ref readonly StackAccessTracker accessTracker, + bool isTracingAccess, + Address address, + Address? delegated, + bool chargeForWarm = true); + + /// + /// Charges gas for accessing an account based on its storage state (cold vs. warm). + /// Precompiles are treated as exceptions to the cold/warm gas charge. + /// + /// The gas state to update. + /// The release specification governing gas costs. + /// The access tracker for cold/warm state. + /// Whether access tracing is enabled. + /// The target account address. + /// If true, applies the warm read gas cost even if the account is warm. + /// True if the gas charge was successful; otherwise false. + static abstract bool ConsumeAccountAccessGas(ref TSelf gas, + IReleaseSpec spec, + ref readonly StackAccessTracker accessTracker, + bool isTracingAccess, + Address address, + bool chargeForWarm = true); + + /// + /// Charges the appropriate gas cost for accessing a storage cell, taking into account whether the access is cold or warm. + /// + /// For cold storage accesses (or if not previously warmed up), a higher gas cost is applied. For warm access during SLOAD, + /// a lower cost is deducted. + /// + /// + /// The gas state to update. + /// The access tracker for cold/warm state. + /// Whether access tracing is enabled. + /// The target storage cell being accessed. + /// Indicates whether the access is for a load (SLOAD) or store (SSTORE) operation. + /// The release specification which governs gas metering and storage access rules. + /// true if the gas charge was successfully applied; otherwise, false indicating an out-of-gas condition. + static abstract bool ConsumeStorageAccessGas(ref TSelf gas, + ref readonly StackAccessTracker accessTracker, + bool isTracingAccess, + in StorageCell storageCell, + StorageAccessType storageAccessType, + IReleaseSpec spec); + + /// + /// Calculates and deducts the gas cost for accessing a specific memory region. + /// + /// The gas state to update. + /// The starting position in memory. + /// The length of the memory region. + /// The current EVM state. + /// true if sufficient gas was available and deducted; otherwise, false. + static abstract bool UpdateMemoryCost(ref TSelf gas, + in UInt256 position, + in UInt256 length, VmState vmState); + + /// + /// Deducts a specified gas cost from the available gas. + /// + /// The gas state to update. + /// The gas cost to deduct. + /// true if there was enough gas; otherwise, false. + static abstract bool UpdateGas(ref TSelf gas, long gasCost); + + /// + /// Refunds gas by adding the specified amount back to the available gas. + /// + /// The gas state to update. + /// The gas amount to refund. + static abstract void UpdateGasUp(ref TSelf gas, long refund); + + /// + /// Charges gas for SSTORE write operation (after cold/warm access cost). + /// Cost is calculated internally based on whether it's a slot creation or update. + /// + /// The gas state to update. + /// True if creating a new slot (original was zero). + /// The release specification for determining reset cost. + /// True if sufficient gas available + static abstract bool ConsumeStorageWrite(ref TSelf gas, bool isSlotCreation, IReleaseSpec spec); + + /// + /// Charges gas for CALL value transfer. + /// + /// The gas state to update. + /// True if sufficient gas available + static abstract bool ConsumeCallValueTransfer(ref TSelf gas); + + /// + /// Charges gas for new account creation (25000 gas). + /// + /// The gas state to update. + /// True if sufficient gas available + static abstract bool ConsumeNewAccountCreation(ref TSelf gas); + + /// + /// Charges gas for LOG emission with topic and data costs. + /// Cost is calculated internally: GasCostOf.Log + topicCount * GasCostOf.LogTopic + dataSize * GasCostOf.LogData + /// + /// The gas state to update. + /// Number of topics. + /// Size of log data in bytes. + /// True if sufficient gas available + static abstract bool ConsumeLogEmission(ref TSelf gas, long topicCount, long dataSize); + + /// + /// Returns the maximum of two gas values. + /// Used for MinimalGas calculation in IntrinsicGas. + /// + /// First gas value. + /// Second gas value. + /// The gas value with greater remaining gas. + static abstract TSelf Max(in TSelf a, in TSelf b); + + /// + /// Calculates intrinsic gas for a transaction. + /// Returns TGasPolicy allowing implementations to track gas breakdown by category. + /// + /// The transaction to calculate intrinsic gas for. + /// The release specification governing gas costs. + /// The intrinsic gas as TGasPolicy. + static abstract TSelf CalculateIntrinsicGas(Transaction tx, IReleaseSpec spec); + + /// + /// Creates available gas from gas limit minus intrinsic gas, preserving any tracking data. + /// For simple implementations, this is a subtraction. For multi-dimensional gas tracking, + /// this preserves the breakdown categories from intrinsic gas. + /// + /// The transaction gas limit. + /// The intrinsic gas to subtract. + /// Available gas with preserved tracking data. + static abstract TSelf CreateAvailableFromIntrinsic(long gasLimit, in TSelf intrinsicGas); +} diff --git a/src/Nethermind/Nethermind.Evm/IVirtualMachine.cs b/src/Nethermind/Nethermind.Evm/IVirtualMachine.cs index f2bc60da5c8..c13306a47fe 100644 --- a/src/Nethermind/Nethermind.Evm/IVirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/IVirtualMachine.cs @@ -1,21 +1,28 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using Nethermind.Core; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.State; using Nethermind.Evm.Tracing; -namespace Nethermind.Evm +namespace Nethermind.Evm; + +public interface IVirtualMachine + where TGasPolicy : struct, IGasPolicy +{ + TransactionSubstate ExecuteTransaction(VmState state, IWorldState worldState, ITxTracer txTracer) + where TTracingInst : struct, IFlag; + ref readonly BlockExecutionContext BlockExecutionContext { get; } + ref readonly TxExecutionContext TxExecutionContext { get; } + void SetBlockExecutionContext(in BlockExecutionContext blockExecutionContext); + void SetTxExecutionContext(in TxExecutionContext txExecutionContext); + int OpCodeCount { get; } +} + +/// +/// Non-generic IVirtualMachine for backward compatibility with EthereumGasPolicy. +/// +public interface IVirtualMachine : IVirtualMachine { - public interface IVirtualMachine - { - TransactionSubstate ExecuteTransaction(EvmState state, IWorldState worldState, ITxTracer txTracer) - where TTracingInst : struct, IFlag; - ref readonly BlockExecutionContext BlockExecutionContext { get; } - ref readonly TxExecutionContext TxExecutionContext { get; } - void SetBlockExecutionContext(in BlockExecutionContext blockExecutionContext); - void SetTxExecutionContext(in TxExecutionContext txExecutionContext); - int OpCodeCount { get; } - } } diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmCalculations.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmCalculations.cs index 9e1ee181851..3f52dd37c43 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmCalculations.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmCalculations.cs @@ -4,176 +4,15 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; -using Nethermind.Core; -using Nethermind.Core.Specs; using Nethermind.Int256; namespace Nethermind.Evm; +/// +/// Utility calculations for EVM operations. +/// public static class EvmCalculations { - /// - /// Charges gas for accessing an account, including potential delegation lookups. - /// This method ensures that both the requested account and its delegated account (if any) are properly charged. - /// - /// Reference to the available gas which will be updated. - /// The virtual machine instance. - /// The target account address. - /// If true, charge even if the account is already warm. - /// True if gas was successfully charged; otherwise false. - public static bool ChargeAccountAccessGasWithDelegation(ref long gasAvailable, VirtualMachine vm, Address address, bool chargeForWarm = true) - { - IReleaseSpec spec = vm.Spec; - if (!spec.UseHotAndColdStorage) - { - // No extra cost if hot/cold storage is not used. - return true; - } - bool notOutOfGas = ChargeAccountAccessGas(ref gasAvailable, vm, address, chargeForWarm); - return notOutOfGas - && (!vm.TxExecutionContext.CodeInfoRepository.TryGetDelegation(address, spec, out Address delegated) - // Charge additional gas for the delegated account if it exists. - || ChargeAccountAccessGas(ref gasAvailable, vm, delegated, chargeForWarm)); - } - - /// - /// Charges gas for accessing an account based on its storage state (cold vs. warm). - /// Precompiles are treated as exceptions to the cold/warm gas charge. - /// - /// Reference to the available gas which will be updated. - /// The virtual machine instance. - /// The target account address. - /// If true, applies the warm read gas cost even if the account is warm. - /// True if the gas charge was successful; otherwise false. - public static bool ChargeAccountAccessGas(ref long gasAvailable, VirtualMachine vm, Address address, bool chargeForWarm = true) - { - bool result = true; - IReleaseSpec spec = vm.Spec; - if (spec.UseHotAndColdStorage) - { - EvmState vmState = vm.EvmState; - if (vm.TxTracer.IsTracingAccess) - { - // Ensure that tracing simulates access-list behavior. - vmState.AccessTracker.WarmUp(address); - } - - // If the account is cold (and not a precompile), charge the cold access cost. - if (!spec.IsPrecompile(address) && vmState.AccessTracker.WarmUp(address)) - { - result = UpdateGas(GasCostOf.ColdAccountAccess, ref gasAvailable); - } - else if (chargeForWarm) - { - // Otherwise, if warm access should be charged, apply the warm read cost. - result = UpdateGas(GasCostOf.WarmStateRead, ref gasAvailable); - } - } - - return result; - } - - /// - /// Charges the appropriate gas cost for accessing a storage cell, taking into account whether the access is cold or warm. - /// - /// For cold storage accesses (or if not previously warmed up), a higher gas cost is applied. For warm accesses during SLOAD, - /// a lower cost is deducted. - /// - /// - /// The remaining gas, passed by reference and reduced by the access cost. - /// The virtual machine instance. - /// The target storage cell being accessed. - /// Indicates whether the access is for a load (SLOAD) or store (SSTORE) operation. - /// The release specification which governs gas metering and storage access rules. - /// true if the gas charge was successfully applied; otherwise, false indicating an out-of-gas condition. - public static bool ChargeStorageAccessGas( - ref long gasAvailable, - VirtualMachine vm, - in StorageCell storageCell, - StorageAccessType storageAccessType, - IReleaseSpec spec) - { - EvmState vmState = vm.EvmState; - bool result = true; - - // If the spec requires hot/cold storage tracking, determine if extra gas should be charged. - if (spec.UseHotAndColdStorage) - { - // When tracing access, ensure the storage cell is marked as warm to simulate inclusion in the access list. - ref readonly StackAccessTracker accessTracker = ref vmState.AccessTracker; - if (vm.TxTracer.IsTracingAccess) - { - accessTracker.WarmUp(in storageCell); - } - - // If the storage cell is still cold, apply the higher cold access cost and mark it as warm. - if (accessTracker.WarmUp(in storageCell)) - { - result = UpdateGas(GasCostOf.ColdSLoad, ref gasAvailable); - } - // For SLOAD operations on already warmed-up storage, apply a lower warm-read cost. - else if (storageAccessType == StorageAccessType.SLOAD) - { - result = UpdateGas(GasCostOf.WarmStateRead, ref gasAvailable); - } - } - - return result; - } - - /// - /// Calculates and deducts the gas cost for accessing a specific memory region. - /// - /// The current EVM state. - /// The remaining gas available. - /// The starting position in memory. - /// The length of the memory region. - /// true if sufficient gas was available and deducted; otherwise, false. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool UpdateMemoryCost(EvmState vmState, ref long gasAvailable, in UInt256 position, in UInt256 length) - { - // Calculate additional gas cost for any memory expansion. - long memoryCost = vmState.Memory.CalculateMemoryCost(in position, length, out bool outOfGas); - if (memoryCost != 0L) - { - if (!UpdateGas(memoryCost, ref gasAvailable)) - { - return false; - } - } - - return !outOfGas; - } - - /// - /// Deducts a specified gas cost from the available gas. - /// - /// The gas cost to deduct. - /// The remaining gas available. - /// true if there was sufficient gas; otherwise, false. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool UpdateGas(long gasCost, ref long gasAvailable) - { - if (gasAvailable < gasCost) - { - return false; - } - - gasAvailable -= gasCost; - return true; - } - - /// - /// Refunds gas by adding the specified amount back to the available gas. - /// - /// The gas amount to refund. - /// The current gas available. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void UpdateGasUp(long refund, ref long gasAvailable) - { - gasAvailable += refund; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Div32Ceiling(in UInt256 length, out bool outOfGas) { diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Bitwise.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Bitwise.cs index aaeec10e0bf..7bffb4e634a 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Bitwise.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Bitwise.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using System.Runtime.Intrinsics; +using Nethermind.Evm.GasPolicy; using static System.Runtime.CompilerServices.Unsafe; namespace Nethermind.Evm; @@ -34,18 +35,20 @@ public interface IOpBitwise /// Executes a bitwise operation defined by on the top two stack elements. /// This method reads the operands as 256-bit vectors from unaligned memory and writes the result back directly. /// + /// The gas policy used for gas accounting. /// The specific bitwise operation to execute. /// An unused virtual machine instance parameter. /// The EVM stack from which operands are retrieved and where the result is stored. - /// The remaining gas, reduced by the operation’s cost. + /// The gas which is updated by the operation's cost. /// The program counter (unused in this operation). /// An indicating success or a stack underflow error. [SkipLocalsInit] - public static EvmExceptionType InstructionBitwise(VirtualMachine _, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionBitwise(VirtualMachine _, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TOpBitwise : struct, IOpBitwise { // Deduct the operation's gas cost. - gasAvailable -= TOpBitwise.GasCost; + TGasPolicy.Consume(ref gas, TOpBitwise.GasCost); // Pop the first operand from the stack by reference to minimize copying. ref byte bytesRef = ref stack.PopBytesByRef(); diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs index a739311a24c..e802d92416f 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Call.cs @@ -6,10 +6,10 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Evm.CodeAnalysis; +using Nethermind.Evm.GasPolicy; using Nethermind.Int256; using Nethermind.Evm.State; - -using static Nethermind.Evm.VirtualMachine; +using static Nethermind.Evm.VirtualMachineStatics; namespace Nethermind.Evm; @@ -83,17 +83,17 @@ public struct OpStaticCall : IOpCall /// /// The current virtual machine instance containing execution state. /// The EVM stack for retrieving call parameters and pushing results. - /// Reference to the available gas, which is deducted according to various call costs. + /// The gas which is updated by the operation's cost. /// Reference to the current program counter (not modified by this method). /// /// An value indicating success or the type of error encountered. /// [SkipLocalsInit] - public static EvmExceptionType InstructionCall( - VirtualMachine vm, + public static EvmExceptionType InstructionCall(VirtualMachine vm, ref EvmStack stack, - ref long gasAvailable, + ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TOpCall : struct, IOpCall where TTracingInst : struct, IFlag { @@ -109,7 +109,7 @@ public static EvmExceptionType InstructionCall( Address codeSource = stack.PopAddress(); if (codeSource is null) goto StackUnderflow; - ExecutionEnvironment env = vm.EvmState.Env; + ExecutionEnvironment env = vm.VmState.Env; // Determine the call value based on the call type. UInt256 callValue; if (typeof(TOpCall) == typeof(OpStaticCall)) @@ -135,12 +135,15 @@ public static EvmExceptionType InstructionCall( goto StackUnderflow; // Charge gas for accessing the account's code (including delegation logic if applicable). - if (!EvmCalculations.ChargeAccountAccessGasWithDelegation(ref gasAvailable, vm, codeSource)) goto OutOfGas; + bool _ = vm.TxExecutionContext.CodeInfoRepository + .TryGetDelegation(codeSource, vm.Spec, out Address delegated); + if (!TGasPolicy.ConsumeAccountAccessGasWithDelegation(ref gas, vm.Spec, in vm.VmState.AccessTracker, + vm.TxTracer.IsTracingAccess, codeSource, delegated)) goto OutOfGas; // For non-delegate calls, the transfer value is the call value. UInt256 transferValue = typeof(TOpCall) == typeof(OpDelegateCall) ? UInt256.Zero : callValue; // Enforce static call restrictions: no value transfer allowed unless it's a CALLCODE. - if (vm.EvmState.IsStatic && !transferValue.IsZero && typeof(TOpCall) != typeof(OpCallCode)) + if (vm.VmState.IsStatic && !transferValue.IsZero && typeof(TOpCall) != typeof(OpCallCode)) return EvmExceptionType.StaticCallViolation; // Determine caller and target based on the call type. @@ -149,12 +152,10 @@ public static EvmExceptionType InstructionCall( ? codeSource : env.ExecutingAccount; - long gasExtra = 0L; - // Add extra gas cost if value is transferred. if (!transferValue.IsZero) { - gasExtra += GasCostOf.CallValue; + if (!TGasPolicy.ConsumeCallValueTransfer(ref gas)) goto OutOfGas; } IReleaseSpec spec = vm.Spec; @@ -162,18 +163,17 @@ public static EvmExceptionType InstructionCall( // Charge additional gas if the target account is new or considered empty. if (!spec.ClearEmptyAccountWhenTouched && !state.AccountExists(target)) { - gasExtra += GasCostOf.NewAccount; + if (!TGasPolicy.ConsumeNewAccountCreation(ref gas)) goto OutOfGas; } else if (spec.ClearEmptyAccountWhenTouched && transferValue != 0 && state.IsDeadAccount(target)) { - gasExtra += GasCostOf.NewAccount; + if (!TGasPolicy.ConsumeNewAccountCreation(ref gas)) goto OutOfGas; } - // Update gas: call cost, memory expansion for input and output, and extra gas. - if (!EvmCalculations.UpdateGas(spec.GetCallCost(), ref gasAvailable) || - !EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in dataOffset, dataLength) || - !EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in outputOffset, outputLength) || - !EvmCalculations.UpdateGas(gasExtra, ref gasAvailable)) + // Update gas: call cost and memory expansion for input and output. + if (!TGasPolicy.UpdateGas(ref gas, spec.GetCallCost()) || + !TGasPolicy.UpdateMemoryCost(ref gas, in dataOffset, dataLength, vm.VmState) || + !TGasPolicy.UpdateMemoryCost(ref gas, in outputOffset, outputLength, vm.VmState)) goto OutOfGas; // Retrieve code information for the call and schedule background analysis if needed. @@ -183,9 +183,13 @@ public static EvmExceptionType InstructionCall( if (spec.IsEip7907Enabled) { uint excessContractSize = (uint)Math.Max(0, codeInfo.CodeSpan.Length - CodeSizeConstants.MaxCodeSizeEip170); - if (excessContractSize > 0 && !ChargeForLargeContractAccess(excessContractSize, codeSource, in vm.EvmState.AccessTracker, ref gasAvailable)) + if (excessContractSize > 0 && !ChargeForLargeContractAccess(excessContractSize, codeSource, in vm.VmState.AccessTracker, ref gas)) goto OutOfGas; } + + // Get remaining gas for 63/64 calculation + long gasAvailable = TGasPolicy.GetRemainingGas(in gas); + // Apply the 63/64 gas rule if enabled. if (spec.Use63Over64Rule) { @@ -196,7 +200,7 @@ public static EvmExceptionType InstructionCall( if (gasLimit >= long.MaxValue) goto OutOfGas; long gasLimitUl = (long)gasLimit; - if (!EvmCalculations.UpdateGas(gasLimitUl, ref gasAvailable)) goto OutOfGas; + if (!TGasPolicy.UpdateGas(ref gas, gasLimitUl)) goto OutOfGas; // Add call stipend if value is being transferred. if (!transferValue.IsZero) @@ -218,21 +222,21 @@ public static EvmExceptionType InstructionCall( if (vm.TxTracer.IsTracingRefunds) { // Specific to Parity tracing: inspect 32 bytes from data offset. - ReadOnlyMemory? memoryTrace = vm.EvmState.Memory.Inspect(in dataOffset, 32); + ReadOnlyMemory? memoryTrace = vm.VmState.Memory.Inspect(in dataOffset, 32); vm.TxTracer.ReportMemoryChange(dataOffset, memoryTrace is null ? default : memoryTrace.Value.Span); } if (TTracingInst.IsActive) { - vm.TxTracer.ReportOperationRemainingGas(gasAvailable); + vm.TxTracer.ReportOperationRemainingGas(TGasPolicy.GetRemainingGas(in gas)); vm.TxTracer.ReportOperationError(EvmExceptionType.NotEnoughBalance); } // Refund the remaining gas to the caller. - EvmCalculations.UpdateGasUp(gasLimitUl, ref gasAvailable); + TGasPolicy.UpdateGasUp(ref gas, gasLimitUl); if (TTracingInst.IsActive) { - vm.TxTracer.ReportGasUpdateForVmTrace(gasLimitUl, gasAvailable); + vm.TxTracer.ReportGasUpdateForVmTrace(gasLimitUl, TGasPolicy.GetRemainingGas(in gas)); } return EvmExceptionType.None; } @@ -247,12 +251,12 @@ public static EvmExceptionType InstructionCall( { vm.ReturnDataBuffer = default; stack.PushBytes(StatusCode.SuccessBytes.Span); - EvmCalculations.UpdateGasUp(gasLimitUl, ref gasAvailable); + TGasPolicy.UpdateGasUp(ref gas, gasLimitUl); return FastCall(vm, spec, in transferValue, target); } // Load call data from memory. - if (!vm.EvmState.Memory.TryLoad(in dataOffset, dataLength, out ReadOnlyMemory callData)) + if (!vm.VmState.Memory.TryLoad(in dataOffset, dataLength, out ReadOnlyMemory callData)) goto OutOfGas; // Construct the execution environment for the call. ExecutionEnvironment callEnv = ExecutionEnvironment.Rent( @@ -273,22 +277,22 @@ public static EvmExceptionType InstructionCall( } // Rent a new call frame for executing the call. - vm.ReturnData = EvmState.RentFrame( - gasAvailable: gasLimitUl, + vm.ReturnData = VmState.RentFrame( + gas: TGasPolicy.FromLong(gasLimitUl), outputDestination: outputOffset.ToLong(), outputLength: outputLength.ToLong(), executionType: TOpCall.ExecutionType, - isStatic: TOpCall.IsStatic || vm.EvmState.IsStatic, + isStatic: TOpCall.IsStatic || vm.VmState.IsStatic, isCreateOnPreExistingAccount: false, env: callEnv, - stateForAccessLists: in vm.EvmState.AccessTracker, + stateForAccessLists: in vm.VmState.AccessTracker, snapshot: in snapshot); return EvmExceptionType.None; // Fast-call path for non-contract calls: // Directly credit the target account and avoid constructing a full call frame. - static EvmExceptionType FastCall(VirtualMachine vm, IReleaseSpec spec, in UInt256 transferValue, Address target) + static EvmExceptionType FastCall(VirtualMachine vm, IReleaseSpec spec, in UInt256 transferValue, Address target) { IWorldState state = vm.WorldState; state.AddToBalanceAndCreateIfNotExists(target, transferValue, spec); @@ -305,12 +309,13 @@ static EvmExceptionType FastCall(VirtualMachine vm, IReleaseSpec spec, in UInt25 return EvmExceptionType.OutOfGas; } - private static bool ChargeForLargeContractAccess(uint excessContractSize, Address codeAddress, in StackAccessTracker accessTracer, ref long gasAvailable) + private static bool ChargeForLargeContractAccess(uint excessContractSize, Address codeAddress, in StackAccessTracker accessTracer, ref TGasPolicy gas) + where TGasPolicy : struct, IGasPolicy { if (accessTracer.WarmUpLargeContract(codeAddress)) { long largeContractCost = GasCostOf.InitCodeWord * EvmCalculations.Div32Ceiling(excessContractSize, out bool outOfGas); - if (outOfGas || !EvmCalculations.UpdateGas(largeContractCost, ref gasAvailable)) return false; + if (outOfGas || !TGasPolicy.UpdateGas(ref gas, largeContractCost)) return false; } return true; @@ -323,21 +328,21 @@ private static bool ChargeForLargeContractAccess(uint excessContractSize, Addres /// /// The current virtual machine instance. /// The EVM stack from which the offset and length are popped. - /// Reference to the available gas, adjusted by memory expansion cost. + /// The gas which is updated by the operation's cost. /// Reference to the program counter (unused in this operation). /// /// on success; otherwise, an error such as , /// , or . /// [SkipLocalsInit] - public static EvmExceptionType InstructionReturn( - VirtualMachine vm, + public static EvmExceptionType InstructionReturn(VirtualMachine vm, ref EvmStack stack, - ref long gasAvailable, + ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { // RETURN is not allowed during contract creation. - if (vm.EvmState.ExecutionType is ExecutionType.EOFCREATE or ExecutionType.TXCREATE) + if (vm.VmState.ExecutionType is ExecutionType.EOFCREATE or ExecutionType.TXCREATE) { goto BadInstruction; } @@ -348,8 +353,8 @@ public static EvmExceptionType InstructionReturn( goto StackUnderflow; // Update the memory cost for the region being returned. - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in position, in length) || - !vm.EvmState.Memory.TryLoad(in position, in length, out ReadOnlyMemory returnData)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in position, in length, vm.VmState) || + !vm.VmState.Memory.TryLoad(in position, in length, out ReadOnlyMemory returnData)) { goto OutOfGas; } diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs index af7e0c8a0b0..783f8d77039 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs @@ -7,6 +7,7 @@ using Nethermind.Core.Specs; using Nethermind.Evm.CodeAnalysis; using Nethermind.Evm.EvmObjectFormat; +using Nethermind.Evm.GasPolicy; namespace Nethermind.Evm; @@ -18,14 +19,16 @@ internal static partial class EvmInstructions /// Provides a mechanism to retrieve a code segment for code copy operations. /// Implementers return a ReadOnlySpan of bytes representing the code to copy. /// - public interface IOpCodeCopy + /// The gas policy type parameter. + public interface IOpCodeCopy + where TGasPolicy : struct, IGasPolicy { /// /// Gets the code to be copied. /// /// The virtual machine instance providing execution context. /// A read-only span of bytes containing the code. - abstract static ReadOnlySpan GetCode(VirtualMachine vm); + abstract static ReadOnlySpan GetCode(VirtualMachine vm); } /// @@ -33,6 +36,7 @@ public interface IOpCodeCopy /// Pops three parameters from the stack: destination memory offset, source offset, and length. /// It then deducts gas based on the memory expansion and performs the copy using the provided code source. /// + /// The gas policy used for gas accounting. /// /// A struct implementing that defines the code source to copy from. /// @@ -41,18 +45,19 @@ public interface IOpCodeCopy /// /// The current virtual machine instance. /// The EVM stack used for operand retrieval and result storage. - /// Reference to the available gas; reduced by the operation’s cost. + /// The gas which is updated by the operation's cost. /// Reference to the current program counter (unused in this operation). /// /// on success, or an appropriate error code if an error occurs. /// [SkipLocalsInit] - public static EvmExceptionType InstructionCodeCopy( - VirtualMachine vm, + public static EvmExceptionType InstructionCodeCopy( + VirtualMachine vm, ref EvmStack stack, - ref long gasAvailable, + ref TGasPolicy gas, ref int programCounter) - where TOpCodeCopy : struct, IOpCodeCopy + where TGasPolicy : struct, IGasPolicy + where TOpCodeCopy : struct, IOpCodeCopy where TTracingInst : struct, IFlag { // Pop destination offset, source offset, and copy length. @@ -63,20 +68,20 @@ public static EvmExceptionType InstructionCodeCopy( // Deduct gas for the operation plus the cost for memory expansion. // Gas cost is calculated as a fixed "VeryLow" cost plus a per-32-bytes cost. - gasAvailable -= GasCostOf.VeryLow + GasCostOf.Memory * EvmCalculations.Div32Ceiling(in result, out bool outOfGas); + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow + GasCostOf.Memory * EvmCalculations.Div32Ceiling(in result, out bool outOfGas)); if (outOfGas) goto OutOfGas; // Only perform the copy if length (result) is non-zero. if (!result.IsZero) { // Check and update memory expansion cost. - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in a, result)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in a, result, vm.VmState)) goto OutOfGas; // Obtain the code slice with zero-padding if needed. ZeroPaddedSpan slice = TOpCodeCopy.GetCode(vm).SliceWithZeroPadding(in b, (int)result); // Save the slice into memory at the destination offset. - if (!vm.EvmState.Memory.TrySave(in a, in slice)) goto OutOfGas; + if (!vm.VmState.Memory.TrySave(in a, in slice)) goto OutOfGas; // If tracing is enabled, report the memory change. if (TTracingInst.IsActive) @@ -96,19 +101,21 @@ public static EvmExceptionType InstructionCodeCopy( /// /// Retrieves call data as the source for a code copy. /// - public struct OpCallDataCopy : IOpCodeCopy + public struct OpCallDataCopy : IOpCodeCopy + where TGasPolicy : struct, IGasPolicy { - public static ReadOnlySpan GetCode(VirtualMachine vm) - => vm.EvmState.Env.InputData.Span; + public static ReadOnlySpan GetCode(VirtualMachine vm) + => vm.VmState.Env.InputData.Span; } /// /// Retrieves the executing code as the source for a code copy. /// - public struct OpCodeCopy : IOpCodeCopy + public struct OpCodeCopy : IOpCodeCopy + where TGasPolicy : struct, IGasPolicy { - public static ReadOnlySpan GetCode(VirtualMachine vm) - => vm.EvmState.Env.CodeInfo.CodeSpan; + public static ReadOnlySpan GetCode(VirtualMachine vm) + => vm.VmState.Env.CodeInfo.CodeSpan; } /// @@ -116,22 +123,23 @@ public static ReadOnlySpan GetCode(VirtualMachine vm) /// Pops an address and three parameters (destination offset, source offset, and length) from the stack. /// Validates account access and memory expansion, then copies the external code into memory. /// + /// The gas policy used for gas accounting. /// /// A struct implementing that indicates whether tracing is active. /// /// The current virtual machine instance. /// The EVM stack for operand retrieval and memory copy operations. - /// Reference to the available gas; reduced by both external code access and memory costs. + /// The gas which is updated by the operation's cost. /// Reference to the program counter (unused in this operation). /// /// on success, or an appropriate error code on failure. /// [SkipLocalsInit] - public static EvmExceptionType InstructionExtCodeCopy( - VirtualMachine vm, + public static EvmExceptionType InstructionExtCodeCopy(VirtualMachine vm, ref EvmStack stack, - ref long gasAvailable, + ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { IReleaseSpec spec = vm.Spec; @@ -145,17 +153,17 @@ public static EvmExceptionType InstructionExtCodeCopy( goto StackUnderflow; // Deduct gas cost: cost for external code access plus memory expansion cost. - gasAvailable -= spec.GetExtCodeCost() + GasCostOf.Memory * EvmCalculations.Div32Ceiling(in result, out bool outOfGas); + TGasPolicy.Consume(ref gas, spec.GetExtCodeCost() + GasCostOf.Memory * EvmCalculations.Div32Ceiling(in result, out bool outOfGas)); if (outOfGas) goto OutOfGas; // Charge gas for account access (considering hot/cold storage costs). - if (!EvmCalculations.ChargeAccountAccessGas(ref gasAvailable, vm, address)) + if (!TGasPolicy.ConsumeAccountAccessGas(ref gas, spec, in vm.VmState.AccessTracker, vm.TxTracer.IsTracingAccess, address)) goto OutOfGas; if (!result.IsZero) { // Update memory cost if the destination region requires expansion. - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in a, result)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in a, result, vm.VmState)) goto OutOfGas; ICodeInfo codeInfo = vm.CodeInfoRepository @@ -167,7 +175,7 @@ public static EvmExceptionType InstructionExtCodeCopy( if (spec.IsEip7907Enabled) { uint excessContractSize = (uint)Math.Max(0, externalCode.Length - CodeSizeConstants.MaxCodeSizeEip170); - if (excessContractSize > 0 && !ChargeForLargeContractAccess(excessContractSize, address, in vm.EvmState.AccessTracker, ref gasAvailable)) + if (excessContractSize > 0 && !ChargeForLargeContractAccess(excessContractSize, address, in vm.VmState.AccessTracker, ref gas)) goto OutOfGas; } @@ -180,7 +188,7 @@ public static EvmExceptionType InstructionExtCodeCopy( // Slice the external code starting at the source offset with appropriate zero-padding. ZeroPaddedSpan slice = externalCode.SliceWithZeroPadding(in b, (int)result); // Save the slice into memory at the destination offset. - if (!vm.EvmState.Memory.TrySave(in a, in slice)) goto OutOfGas; + if (!vm.VmState.Memory.TrySave(in a, in slice)) goto OutOfGas; // Report memory changes if tracing is enabled. if (TTracingInst.IsActive) @@ -202,38 +210,39 @@ public static EvmExceptionType InstructionExtCodeCopy( /// Pops an account address from the stack, validates access, and pushes the code size onto the stack. /// Additionally, applies peephole optimizations for common contract checks. /// + /// The gas policy used for gas accounting. /// /// A struct implementing indicating if instruction tracing is active. /// /// The virtual machine instance. /// The EVM stack from which the account address is popped and where the code size is pushed. - /// Reference to the available gas; reduced by external code cost. + /// The gas which is updated by the operation's cost. /// Reference to the program counter, which may be adjusted during optimization. /// /// on success, or an appropriate error code if an error occurs. /// [SkipLocalsInit] - public static EvmExceptionType InstructionExtCodeSize( - VirtualMachine vm, + public static EvmExceptionType InstructionExtCodeSize(VirtualMachine vm, ref EvmStack stack, - ref long gasAvailable, + ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { IReleaseSpec spec = vm.Spec; // Deduct the gas cost for external code access. - gasAvailable -= spec.GetExtCodeCost(); + TGasPolicy.Consume(ref gas, spec.GetExtCodeCost()); // Pop the account address from the stack. Address address = stack.PopAddress(); if (address is null) goto StackUnderflow; // Charge gas for accessing the account's state. - if (!EvmCalculations.ChargeAccountAccessGas(ref gasAvailable, vm, address)) + if (!TGasPolicy.ConsumeAccountAccessGas(ref gas, spec, in vm.VmState.AccessTracker, vm.TxTracer.IsTracingAccess, address)) goto OutOfGas; // Attempt a peephole optimization when tracing is not active and code is available. - ReadOnlySpan codeSection = vm.EvmState.Env.CodeInfo.CodeSpan; + ReadOnlySpan codeSection = vm.VmState.Env.CodeInfo.CodeSpan; if (!TTracingInst.IsActive && programCounter < codeSection.Length) { bool optimizeAccess = false; @@ -261,7 +270,7 @@ public static EvmExceptionType InstructionExtCodeSize( vm.OpCodeCount++; programCounter++; // Deduct very-low gas cost for the next operation (ISZERO, GT, or EQ). - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); // Determine if the account is a contract by checking the loaded CodeHash. bool isCodeLengthNotZero = vm.WorldState.IsContract(address); diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs index d0b99f8e889..e8d9e1adbab 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs @@ -6,6 +6,7 @@ using System.Runtime.Intrinsics; using Nethermind.Core.Specs; using Nethermind.Core; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.State; namespace Nethermind.Evm; @@ -20,17 +21,18 @@ internal static partial class EvmInstructions /// /// The virtual machine instance. /// The execution stack where the program counter is pushed. - /// Reference to the remaining gas; reduced by the gas cost. + /// The gas which is updated by the operation's cost. /// The current program counter. /// /// on success. /// [SkipLocalsInit] - public static EvmExceptionType InstructionProgramCounter(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionProgramCounter(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Deduct the base gas cost for reading the program counter. - gasAvailable -= GasCostOf.Base; + TGasPolicy.Consume(ref gas, GasCostOf.Base); // The program counter pushed is adjusted by -1 to reflect the correct opcode location. stack.PushUInt32((uint)(programCounter - 1)); @@ -43,16 +45,17 @@ public static EvmExceptionType InstructionProgramCounter(VirtualMa /// /// The virtual machine instance. /// The execution stack. - /// Reference to the remaining gas; reduced by the jump destination cost. + /// The gas which is updated by the operation's cost. /// The current program counter. /// /// on success. /// [SkipLocalsInit] - public static EvmExceptionType InstructionJumpDest(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionJumpDest(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { // Deduct the gas cost specific for a jump destination marker. - gasAvailable -= GasCostOf.JumpDest; + TGasPolicy.Consume(ref gas, GasCostOf.JumpDest); return EvmExceptionType.None; } @@ -64,21 +67,22 @@ public static EvmExceptionType InstructionJumpDest(VirtualMachine vm, ref EvmSta /// /// The virtual machine instance. /// The execution stack from which the jump destination is popped. - /// Reference to the remaining gas; reduced by the gas cost for jumping. + /// Reference to the gas state; reduced by the gas cost for jumping. /// Reference to the program counter that may be updated with the jump destination. /// /// on success; or /// on failure. /// [SkipLocalsInit] - public static EvmExceptionType InstructionJump(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionJump(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { // Deduct the gas cost for performing a jump. - gasAvailable -= GasCostOf.Jump; + TGasPolicy.Consume(ref gas, GasCostOf.Jump); // Pop the jump destination from the stack. if (!stack.PopUInt256(out UInt256 result)) goto StackUnderflow; // Validate the jump destination and update the program counter if valid. - if (!Jump(result, ref programCounter, vm.EvmState.Env)) goto InvalidJumpDestination; + if (!Jump(result, ref programCounter, vm.VmState.Env)) goto InvalidJumpDestination; return EvmExceptionType.None; // Jump forward to be unpredicted by the branch predictor. @@ -95,7 +99,7 @@ public static EvmExceptionType InstructionJump(VirtualMachine vm, ref EvmStack s /// /// The virtual machine instance. /// The execution stack from which the jump destination and condition are popped. - /// Reference to the remaining gas; reduced by the cost for conditional jump. + /// Reference to the gas state; reduced by the cost for conditional jump. /// Reference to the program counter that may be updated on a jump. /// /// on success; returns @@ -103,10 +107,11 @@ public static EvmExceptionType InstructionJump(VirtualMachine vm, ref EvmStack s /// [SkipLocalsInit] [MethodImpl(MethodImplOptions.NoInlining)] - public static EvmExceptionType InstructionJumpIf(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionJumpIf(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { // Deduct the high gas cost for a conditional jump. - gasAvailable -= GasCostOf.JumpI; + TGasPolicy.Consume(ref gas, GasCostOf.JumpI); // Pop the jump destination. if (!stack.PopUInt256(out UInt256 result)) goto StackUnderflow; @@ -114,7 +119,7 @@ public static EvmExceptionType InstructionJumpIf(VirtualMachine vm, ref EvmStack if (isOverflow) goto StackUnderflow; if (shouldJump) { - if (!Jump(result, ref programCounter, vm.EvmState.Env)) goto InvalidJumpDestination; + if (!Jump(result, ref programCounter, vm.VmState.Env)) goto InvalidJumpDestination; } return EvmExceptionType.None; @@ -146,10 +151,11 @@ private static bool TestJumpCondition(ref EvmStack stack, out bool isOverflow) /// In EOFCREATE or TXCREATE executions, the STOP opcode is considered illegal. /// [SkipLocalsInit] - public static EvmExceptionType InstructionStop(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionStop(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { // In contract creation contexts, a STOP is not permitted. - if (vm.EvmState.ExecutionType is ExecutionType.EOFCREATE or ExecutionType.TXCREATE) + if (vm.VmState.ExecutionType is ExecutionType.EOFCREATE or ExecutionType.TXCREATE) { return EvmExceptionType.BadInstruction; } @@ -163,7 +169,8 @@ public static EvmExceptionType InstructionStop(VirtualMachine vm, ref EvmStack s /// and returns a revert exception. /// [SkipLocalsInit] - public static EvmExceptionType InstructionRevert(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionRevert(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { // Attempt to pop memory offset and length; if either fails, signal a stack underflow. if (!stack.PopUInt256(out UInt256 position) || @@ -173,8 +180,8 @@ public static EvmExceptionType InstructionRevert(VirtualMachine vm, ref EvmStack } // Ensure sufficient gas for any required memory expansion. - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in position, in length) || - !vm.EvmState.Memory.TryLoad(in position, in length, out ReadOnlyMemory returnData)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in position, in length, vm.VmState) || + !vm.VmState.Memory.TryLoad(in position, in length, out ReadOnlyMemory returnData)) { goto OutOfGas; } @@ -195,12 +202,13 @@ public static EvmExceptionType InstructionRevert(VirtualMachine vm, ref EvmStack /// and marks the executing account for destruction. /// [SkipLocalsInit] - private static EvmExceptionType InstructionSelfDestruct(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + private static EvmExceptionType InstructionSelfDestruct(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { // Increment metrics for self-destruct operations. Metrics.IncrementSelfDestructs(); - EvmState vmState = vm.EvmState; + VmState vmState = vm.VmState; IReleaseSpec spec = vm.Spec; IWorldState state = vm.WorldState; @@ -211,7 +219,7 @@ private static EvmExceptionType InstructionSelfDestruct(VirtualMachine vm, ref E // If Shanghai DDoS protection is active, charge the appropriate gas cost. if (spec.UseShanghaiDDosProtection) { - gasAvailable -= GasCostOf.SelfDestructEip150; + TGasPolicy.ConsumeSelfDestructGas(ref gas); } // Pop the inheritor address from the stack; signal underflow if missing. @@ -220,7 +228,7 @@ private static EvmExceptionType InstructionSelfDestruct(VirtualMachine vm, ref E goto StackUnderflow; // Charge gas for account access; if insufficient, signal out-of-gas. - if (!EvmCalculations.ChargeAccountAccessGas(ref gasAvailable, vm, inheritor, chargeForWarm: false)) + if (!TGasPolicy.ConsumeAccountAccessGas(ref gas, spec, in vmState.AccessTracker, vm.TxTracer.IsTracingAccess, inheritor, false)) goto OutOfGas; Address executingAccount = vmState.Env.ExecutingAccount; @@ -237,7 +245,7 @@ private static EvmExceptionType InstructionSelfDestruct(VirtualMachine vm, ref E // For certain specs, charge gas if transferring to a dead account. if (spec.ClearEmptyAccountWhenTouched && !result.IsZero && state.IsDeadAccount(inheritor)) { - if (!EvmCalculations.UpdateGas(GasCostOf.NewAccount, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.NewAccount)) goto OutOfGas; } @@ -245,7 +253,7 @@ private static EvmExceptionType InstructionSelfDestruct(VirtualMachine vm, ref E bool inheritorAccountExists = state.AccountExists(inheritor); if (!spec.ClearEmptyAccountWhenTouched && !inheritorAccountExists && spec.UseShanghaiDDosProtection) { - if (!EvmCalculations.UpdateGas(GasCostOf.NewAccount, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.NewAccount)) goto OutOfGas; } @@ -280,16 +288,18 @@ private static EvmExceptionType InstructionSelfDestruct(VirtualMachine vm, ref E /// /// Handles invalid opcodes by deducting a high gas cost and returning a BadInstruction error. /// - public static EvmExceptionType InstructionInvalid(VirtualMachine _, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionInvalid(VirtualMachine _, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { - gasAvailable -= GasCostOf.High; + TGasPolicy.Consume(ref gas, GasCostOf.High); return EvmExceptionType.BadInstruction; } /// /// Default handler for undefined opcodes, always returning a BadInstruction error. /// - public static EvmExceptionType InstructionBadInstruction(VirtualMachine _, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionBadInstruction(VirtualMachine _, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy => EvmExceptionType.BadInstruction; /// diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs index 77cf13c8743..f7056954d04 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs @@ -7,10 +7,10 @@ using Nethermind.Core.Specs; using Nethermind.Evm.CodeAnalysis; using Nethermind.Evm.EvmObjectFormat; +using Nethermind.Evm.GasPolicy; using Nethermind.Int256; using Nethermind.Evm.State; - -using static Nethermind.Evm.VirtualMachine; +using static Nethermind.Evm.VirtualMachineStatics; namespace Nethermind.Evm; @@ -59,19 +59,21 @@ public struct OpCreate2 : IOpCreate /// This method performs validation, gas and memory cost calculations, state updates, /// and delegates execution to a new call frame for the contract's initialization code. /// + /// The gas policy implementation. /// The type of create operation (either or ). /// Tracing instructions type used for instrumentation if active. /// The current virtual machine instance. /// Reference to the EVM stack. - /// Reference to the gas counter available for execution. + /// Reference to the gas state. /// Reference to the program counter. /// An indicating success or the type of exception encountered. [SkipLocalsInit] - public static EvmExceptionType InstructionCreate( - VirtualMachine vm, + public static EvmExceptionType InstructionCreate( + VirtualMachine vm, ref EvmStack stack, - ref long gasAvailable, + ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TOpCreate : struct, IOpCreate where TTracingInst : struct, IFlag { @@ -80,12 +82,12 @@ public static EvmExceptionType InstructionCreate( // Obtain the current EVM specification and check if the call is static (static calls cannot create contracts). IReleaseSpec spec = vm.Spec; - if (vm.EvmState.IsStatic) + if (vm.VmState.IsStatic) goto StaticCallViolation; // Reset the return data buffer as contract creation does not use previous return data. vm.ReturnData = null; - ExecutionEnvironment env = vm.EvmState.Env; + ExecutionEnvironment env = vm.VmState.Env; IWorldState state = vm.WorldState; // Pop parameters off the stack: value to transfer, memory position for the initialization code, @@ -119,11 +121,11 @@ public static EvmExceptionType InstructionCreate( : 0); // Check gas sufficiency: if outOfGas flag was set during gas division or if gas update fails. - if (outOfGas || !EvmCalculations.UpdateGas(gasCost, ref gasAvailable)) + if (outOfGas || !TGasPolicy.UpdateGas(ref gas, gasCost)) goto OutOfGas; // Update memory gas cost based on the required memory expansion for the init code. - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in memoryPositionOfInitCode, in initCodeLength)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in memoryPositionOfInitCode, in initCodeLength, vm.VmState)) goto OutOfGas; // Verify call depth does not exceed the maximum allowed. If exceeded, return early with empty data. @@ -136,7 +138,7 @@ public static EvmExceptionType InstructionCreate( } // Load the initialization code from memory based on the specified position and length. - if (!vm.EvmState.Memory.TryLoad(in memoryPositionOfInitCode, in initCodeLength, out ReadOnlyMemory initCode)) + if (!vm.VmState.Memory.TryLoad(in memoryPositionOfInitCode, in initCodeLength, out ReadOnlyMemory initCode)) goto OutOfGas; // Check that the executing account has sufficient balance to transfer the specified value. @@ -158,6 +160,9 @@ public static EvmExceptionType InstructionCreate( goto None; } + // Get remaining gas for the create operation. + long gasAvailable = TGasPolicy.GetRemainingGas(in gas); + // End tracing if enabled, prior to switching to the new call frame. if (TTracingInst.IsActive) vm.EndInstructionTrace(gasAvailable); @@ -165,7 +170,7 @@ public static EvmExceptionType InstructionCreate( // Calculate gas available for the contract creation call. // Use the 63/64 gas rule if specified in the current EVM specification. long callGas = spec.Use63Over64Rule ? gasAvailable - gasAvailable / 64L : gasAvailable; - if (!EvmCalculations.UpdateGas(callGas, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, callGas)) goto OutOfGas; // Compute the contract address: @@ -178,7 +183,7 @@ public static EvmExceptionType InstructionCreate( // For EIP-2929 support, pre-warm the contract address in the access tracker to account for hot/cold storage costs. if (spec.UseHotAndColdStorage) { - vm.EvmState.AccessTracker.WarmUp(contractAddress); + vm.VmState.AccessTracker.WarmUp(contractAddress); } // Special case: if EOF code format is enabled and the init code starts with the EOF marker, @@ -187,7 +192,7 @@ public static EvmExceptionType InstructionCreate( { vm.ReturnDataBuffer = Array.Empty(); stack.PushZero(); - EvmCalculations.UpdateGasUp(callGas, ref gasAvailable); + TGasPolicy.UpdateGasUp(ref gas, callGas); goto None; } @@ -233,15 +238,15 @@ public static EvmExceptionType InstructionCreate( inputData: in _emptyMemory); // Rent a new frame to run the initialization code in the new execution environment. - vm.ReturnData = EvmState.RentFrame( - gasAvailable: callGas, + vm.ReturnData = VmState.RentFrame( + gas: TGasPolicy.FromLong(callGas), outputDestination: 0, outputLength: 0, executionType: TOpCreate.ExecutionType, - isStatic: vm.EvmState.IsStatic, + isStatic: vm.VmState.IsStatic, isCreateOnPreExistingAccount: accountExists, env: callEnv, - stateForAccessLists: in vm.EvmState.AccessTracker, + stateForAccessLists: in vm.VmState.AccessTracker, snapshot: in snapshot); None: return EvmExceptionType.None; diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Crypto.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Crypto.cs index 53ec615ac20..f0015a84489 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Crypto.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Crypto.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm.GasPolicy; namespace Nethermind.Evm; @@ -18,7 +19,8 @@ internal static partial class EvmInstructions /// and pushes the resulting 256-bit hash onto the stack. /// [SkipLocalsInit] - public static EvmExceptionType InstructionKeccak256(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionKeccak256(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Ensure two 256-bit words are available (memory offset and length). @@ -26,12 +28,12 @@ public static EvmExceptionType InstructionKeccak256(VirtualMachine goto StackUnderflow; // Deduct gas: base cost plus additional cost per 32-byte word. - gasAvailable -= GasCostOf.Sha3 + GasCostOf.Sha3Word * EvmCalculations.Div32Ceiling(in b, out bool outOfGas); + TGasPolicy.Consume(ref gas, GasCostOf.Sha3 + GasCostOf.Sha3Word * EvmCalculations.Div32Ceiling(in b, out bool outOfGas)); if (outOfGas) goto OutOfGas; - EvmState vmState = vm.EvmState; + VmState vmState = vm.VmState; // Charge gas for any required memory expansion. - if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in a, b) || + if (!TGasPolicy.UpdateMemoryCost(ref gas, in a, b, vmState) || !vmState.Memory.TryLoadSpan(in a, b, out Span bytes)) { goto OutOfGas; diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Environment.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Environment.cs index e8679333e2d..7e770d5ec07 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Environment.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Environment.cs @@ -7,9 +7,9 @@ using Nethermind.Core.Specs; using Nethermind.Core.Crypto; using Nethermind.Evm.EvmObjectFormat; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.State; - -using static Nethermind.Evm.VirtualMachine; +using static Nethermind.Evm.VirtualMachineStatics; namespace Nethermind.Evm; @@ -21,7 +21,9 @@ internal static partial class EvmInstructions /// Defines an environment introspection operation that returns a byte span. /// Implementations should provide a static gas cost and a static Operation method. /// - public interface IOpBlkAddress + /// The gas policy type parameter. + public interface IOpBlkAddress + where TGasPolicy : struct, IGasPolicy { /// /// The gas cost for the operation. @@ -30,15 +32,17 @@ public interface IOpBlkAddress /// /// Executes the operation and returns the result as address. /// - /// The current virtual machine state. - abstract static Address Operation(VirtualMachine vm); + /// The current virtual machine instance. + abstract static Address Operation(VirtualMachine vm); } /// /// Defines an environment introspection operation that returns a big endian word. /// Implementations should provide a static gas cost and a static Operation method. /// - public interface IOpEnv32Bytes + /// The gas policy type parameter. + public interface IOpEnv32Bytes + where TGasPolicy : struct, IGasPolicy { /// /// The gas cost for the operation. @@ -47,15 +51,17 @@ public interface IOpEnv32Bytes /// /// Executes the operation and returns the result as ref to big endian word. /// - /// The current virtual machine state. - abstract static ref readonly ValueHash256 Operation(VirtualMachine vm); + /// The current virtual machine instance. + abstract static ref readonly ValueHash256 Operation(VirtualMachine vm); } /// /// Defines an environment introspection operation that returns an Address. /// Implementations should provide a static gas cost and a static Operation method. /// - public interface IOpEnvAddress + /// The gas policy type parameter. + public interface IOpEnvAddress + where TGasPolicy : struct, IGasPolicy { /// /// The gas cost for the operation. @@ -65,13 +71,15 @@ public interface IOpEnvAddress /// Executes the operation and returns the result as address. /// /// The current virtual machine state. - abstract static Address Operation(EvmState vmState); + abstract static Address Operation(VmState vmState); } /// /// Defines an environment introspection operation that returns a 256-bit unsigned integer. /// - public interface IOpEnvUInt256 + /// The gas policy type parameter. + public interface IOpEnvUInt256 + where TGasPolicy : struct, IGasPolicy { virtual static long GasCost => GasCostOf.Base; /// @@ -79,82 +87,92 @@ public interface IOpEnvUInt256 /// /// The current virtual machine state. /// The resulting 256-bit unsigned integer. - abstract static ref readonly UInt256 Operation(EvmState vmState); + abstract static ref readonly UInt256 Operation(VmState vmState); } /// /// Defines an environment introspection operation that returns a 256-bit unsigned integer. /// - public interface IOpBlkUInt256 + /// The gas policy type parameter. + public interface IOpBlkUInt256 + where TGasPolicy : struct, IGasPolicy { virtual static long GasCost => GasCostOf.Base; /// /// Executes the operation and returns the result as a UInt256. /// - /// The current virtual machine state. + /// The current virtual machine instance. /// The resulting 256-bit unsigned integer. - abstract static ref readonly UInt256 Operation(VirtualMachine vm); + abstract static ref readonly UInt256 Operation(VirtualMachine vm); } /// /// Defines an environment introspection operation that returns a 32-bit unsigned integer. /// - public interface IOpEnvUInt32 + /// The gas policy type parameter. + public interface IOpEnvUInt32 + where TGasPolicy : struct, IGasPolicy { virtual static long GasCost => GasCostOf.Base; /// /// Executes the operation and returns the result as a UInt32. /// /// The current virtual machine state. - abstract static uint Operation(EvmState vmState); + abstract static uint Operation(VmState vmState); } /// /// Defines an environment introspection operation that returns a 64-bit unsigned integer. /// - public interface IOpEnvUInt64 + /// The gas policy type parameter. + public interface IOpEnvUInt64 + where TGasPolicy : struct, IGasPolicy { virtual static long GasCost => GasCostOf.Base; /// /// Executes the operation and returns the result as a UInt64. /// /// The current virtual machine state. - abstract static ulong Operation(EvmState vmState); + abstract static ulong Operation(VmState vmState); } /// /// Defines an environment introspection operation that returns a 64-bit unsigned integer. /// - public interface IOpBlkUInt64 + /// The gas policy type parameter. + public interface IOpBlkUInt64 + where TGasPolicy : struct, IGasPolicy { virtual static long GasCost => GasCostOf.Base; /// /// Executes the operation and returns the result as a UInt64. /// - /// The current virtual machine state. - abstract static ulong Operation(VirtualMachine vm); + /// The current virtual machine instance. + abstract static ulong Operation(VirtualMachine vm); } /// /// Executes an environment introspection opcode that returns an Address. /// Generic parameter TOpEnv defines the concrete operation. /// + /// The gas policy used for gas accounting. /// The specific operation implementation. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// An EVM exception type if an error occurs. [SkipLocalsInit] - public static EvmExceptionType InstructionEnvAddress(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) - where TOpEnv : struct, IOpEnvAddress + public static EvmExceptionType InstructionEnvAddress(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy + where TOpEnv : struct, IOpEnvAddress where TTracingInst : struct, IFlag { // Deduct the gas cost as defined by the operation implementation. - gasAvailable -= TOpEnv.GasCost; + TGasPolicy.Consume(ref gas, TOpEnv.GasCost); // Execute the operation and retrieve the result. - Address result = TOpEnv.Operation(vm.EvmState); + Address result = TOpEnv.Operation(vm.VmState); // Push the resulting bytes onto the EVM stack. stack.PushAddress(result); @@ -166,19 +184,21 @@ public static EvmExceptionType InstructionEnvAddress(Virtu /// Executes an block introspection opcode that returns an Address. /// Generic parameter TOpEnv defines the concrete operation. /// + /// The gas policy used for gas accounting. /// The specific operation implementation. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// An EVM exception type if an error occurs. [SkipLocalsInit] - public static EvmExceptionType InstructionBlkAddress(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) - where TOpEnv : struct, IOpBlkAddress + public static EvmExceptionType InstructionBlkAddress(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy + where TOpEnv : struct, IOpBlkAddress where TTracingInst : struct, IFlag { // Deduct the gas cost as defined by the operation implementation. - gasAvailable -= TOpEnv.GasCost; + TGasPolicy.Consume(ref gas, TOpEnv.GasCost); // Execute the operation and retrieve the result. Address result = TOpEnv.Operation(vm); @@ -192,20 +212,22 @@ public static EvmExceptionType InstructionBlkAddress(Virtu /// /// Executes an environment introspection opcode that returns a UInt256 value. /// + /// The gas policy used for gas accounting. /// The specific operation implementation. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// An EVM exception type if an error occurs. [SkipLocalsInit] - public static EvmExceptionType InstructionEnvUInt256(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) - where TOpEnv : struct, IOpEnvUInt256 + public static EvmExceptionType InstructionEnvUInt256(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy + where TOpEnv : struct, IOpEnvUInt256 where TTracingInst : struct, IFlag { - gasAvailable -= TOpEnv.GasCost; + TGasPolicy.Consume(ref gas, TOpEnv.GasCost); - ref readonly UInt256 result = ref TOpEnv.Operation(vm.EvmState); + ref readonly UInt256 result = ref TOpEnv.Operation(vm.VmState); stack.PushUInt256(in result); @@ -215,18 +237,20 @@ public static EvmExceptionType InstructionEnvUInt256(Virtu /// /// Executes an environment introspection opcode that returns a UInt256 value. /// + /// The gas policy used for gas accounting. /// The specific operation implementation. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// An EVM exception type if an error occurs. [SkipLocalsInit] - public static EvmExceptionType InstructionBlkUInt256(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) - where TOpEnv : struct, IOpBlkUInt256 + public static EvmExceptionType InstructionBlkUInt256(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy + where TOpEnv : struct, IOpBlkUInt256 where TTracingInst : struct, IFlag { - gasAvailable -= TOpEnv.GasCost; + TGasPolicy.Consume(ref gas, TOpEnv.GasCost); ref readonly UInt256 result = ref TOpEnv.Operation(vm); @@ -238,20 +262,22 @@ public static EvmExceptionType InstructionBlkUInt256(Virtu /// /// Executes an environment introspection opcode that returns a UInt32 value. /// + /// The gas policy used for gas accounting. /// The specific operation implementation. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// An EVM exception type if an error occurs. [SkipLocalsInit] - public static EvmExceptionType InstructionEnvUInt32(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) - where TOpEnv : struct, IOpEnvUInt32 + public static EvmExceptionType InstructionEnvUInt32(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy + where TOpEnv : struct, IOpEnvUInt32 where TTracingInst : struct, IFlag { - gasAvailable -= TOpEnv.GasCost; + TGasPolicy.Consume(ref gas, TOpEnv.GasCost); - uint result = TOpEnv.Operation(vm.EvmState); + uint result = TOpEnv.Operation(vm.VmState); stack.PushUInt32(result); @@ -261,20 +287,22 @@ public static EvmExceptionType InstructionEnvUInt32(Virtua /// /// Executes an environment introspection opcode that returns a UInt64 value. /// + /// The gas policy used for gas accounting. /// The specific operation implementation. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// An EVM exception type if an error occurs. [SkipLocalsInit] - public static EvmExceptionType InstructionEnvUInt64(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) - where TOpEnv : struct, IOpEnvUInt64 + public static EvmExceptionType InstructionEnvUInt64(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy + where TOpEnv : struct, IOpEnvUInt64 where TTracingInst : struct, IFlag { - gasAvailable -= TOpEnv.GasCost; + TGasPolicy.Consume(ref gas, TOpEnv.GasCost); - ulong result = TOpEnv.Operation(vm.EvmState); + ulong result = TOpEnv.Operation(vm.VmState); stack.PushUInt64(result); @@ -284,18 +312,20 @@ public static EvmExceptionType InstructionEnvUInt64(Virtua /// /// Executes an environment introspection opcode that returns a UInt64 value. /// + /// The gas policy used for gas accounting. /// The specific operation implementation. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// An EVM exception type if an error occurs. [SkipLocalsInit] - public static EvmExceptionType InstructionBlkUInt64(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) - where TOpEnv : struct, IOpBlkUInt64 + public static EvmExceptionType InstructionBlkUInt64(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy + where TOpEnv : struct, IOpBlkUInt64 where TTracingInst : struct, IFlag { - gasAvailable -= TOpEnv.GasCost; + TGasPolicy.Consume(ref gas, TOpEnv.GasCost); ulong result = TOpEnv.Operation(vm); @@ -307,18 +337,20 @@ public static EvmExceptionType InstructionBlkUInt64(Virtua /// /// Executes an environment introspection opcode that returns a UInt64 value. /// + /// The gas policy used for gas accounting. /// The specific operation implementation. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// An EVM exception type if an error occurs. [SkipLocalsInit] - public static EvmExceptionType InstructionEnv32Bytes(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) - where TOpEnv : struct, IOpEnv32Bytes + public static EvmExceptionType InstructionEnv32Bytes(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy + where TOpEnv : struct, IOpEnv32Bytes where TTracingInst : struct, IFlag { - gasAvailable -= TOpEnv.GasCost; + TGasPolicy.Consume(ref gas, TOpEnv.GasCost); ref readonly ValueHash256 result = ref TOpEnv.Operation(vm); @@ -330,63 +362,71 @@ public static EvmExceptionType InstructionEnv32Bytes(Virtu /// /// Returns the size of the transaction call data. /// - public struct OpCallDataSize : IOpEnvUInt32 + public struct OpCallDataSize : IOpEnvUInt32 + where TGasPolicy : struct, IGasPolicy { - public static uint Operation(EvmState vmState) + public static uint Operation(VmState vmState) => (uint)vmState.Env.InputData.Length; } /// /// Returns the size of the executing code. /// - public struct OpCodeSize : IOpEnvUInt32 + public struct OpCodeSize : IOpEnvUInt32 + where TGasPolicy : struct, IGasPolicy { - public static uint Operation(EvmState vmState) + public static uint Operation(VmState vmState) => (uint)vmState.Env.CodeInfo.CodeSpan.Length; } /// /// Returns the timestamp of the current block. /// - public struct OpTimestamp : IOpBlkUInt64 + public struct OpTimestamp : IOpBlkUInt64 + where TGasPolicy : struct, IGasPolicy { - public static ulong Operation(VirtualMachine vm) + public static ulong Operation(VirtualMachine vm) => vm.BlockExecutionContext.Header.Timestamp; } /// /// Returns the block number of the current block. /// - public struct OpNumber : IOpBlkUInt64 + public struct OpNumber : IOpBlkUInt64 + where TGasPolicy : struct, IGasPolicy { - public static ulong Operation(VirtualMachine vm) + public static ulong Operation(VirtualMachine vm) => vm.BlockExecutionContext.Number; } /// /// Returns the gas limit of the current block. /// - public struct OpGasLimit : IOpBlkUInt64 + public struct OpGasLimit : IOpBlkUInt64 + where TGasPolicy : struct, IGasPolicy { - public static ulong Operation(VirtualMachine vm) + public static ulong Operation(VirtualMachine vm) => vm.BlockExecutionContext.GasLimit; } /// /// Returns the current size of the EVM memory. /// - public struct OpMSize : IOpEnvUInt64 + public struct OpMSize : IOpEnvUInt64 + where TGasPolicy : struct, IGasPolicy { - public static ulong Operation(EvmState vmState) + public static ulong Operation(VmState vmState) => vmState.Memory.Size; } /// /// Returns the base fee per gas for the current block. /// - public struct OpBaseFee : IOpBlkUInt256 + public struct OpBaseFee : IOpBlkUInt256 + where TGasPolicy : struct, IGasPolicy { - public static ref readonly UInt256 Operation(VirtualMachine vm) + + public static ref readonly UInt256 Operation(VirtualMachine vm) => ref vm.BlockExecutionContext.Header.BaseFeePerGas; } @@ -394,14 +434,16 @@ public static ref readonly UInt256 Operation(VirtualMachine vm) /// Implements the BLOBBASEFEE opcode. /// Returns the blob base fee from the block header. /// + /// The gas policy used for gas accounting. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// /// , or if blob base fee not set. /// - public static EvmExceptionType InstructionBlobBaseFee(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionBlobBaseFee(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { ref readonly BlockExecutionContext context = ref vm.BlockExecutionContext; @@ -409,7 +451,7 @@ public static EvmExceptionType InstructionBlobBaseFee(VirtualMachi if (!context.Header.ExcessBlobGas.HasValue) goto BadInstruction; // Charge the base gas cost for this opcode. - gasAvailable -= GasCostOf.Base; + TGasPolicy.Consume(ref gas, GasCostOf.Base); stack.Push32Bytes(in context.BlobBaseFee); return EvmExceptionType.None; @@ -421,63 +463,70 @@ public static EvmExceptionType InstructionBlobBaseFee(VirtualMachi /// /// Returns the gas price for the transaction. /// - public struct OpGasPrice : IOpBlkUInt256 + public struct OpGasPrice : IOpBlkUInt256 + where TGasPolicy : struct, IGasPolicy { - public static ref readonly UInt256 Operation(VirtualMachine vm) + public static ref readonly UInt256 Operation(VirtualMachine vm) => ref vm.TxExecutionContext.GasPrice; } /// /// Returns the value transferred with the current call. /// - public struct OpCallValue : IOpEnvUInt256 + public struct OpCallValue : IOpEnvUInt256 + where TGasPolicy : struct, IGasPolicy { - public static ref readonly UInt256 Operation(EvmState vmState) + public static ref readonly UInt256 Operation(VmState vmState) => ref vmState.Env.Value; } /// /// Returns the address of the currently executing account. /// - public struct OpAddress : IOpEnvAddress + public struct OpAddress : IOpEnvAddress + where TGasPolicy : struct, IGasPolicy { - public static Address Operation(EvmState vmState) + public static Address Operation(VmState vmState) => vmState.Env.ExecutingAccount; } /// /// Returns the address of the caller of the current execution context. /// - public struct OpCaller : IOpEnvAddress + public struct OpCaller : IOpEnvAddress + where TGasPolicy : struct, IGasPolicy { - public static Address Operation(EvmState vmState) + public static Address Operation(VmState vmState) => vmState.Env.Caller; } /// /// Returns the origin address of the transaction. /// - public struct OpOrigin : IOpEnv32Bytes + public struct OpOrigin : IOpEnv32Bytes + where TGasPolicy : struct, IGasPolicy { - public static ref readonly ValueHash256 Operation(VirtualMachine vm) + public static ref readonly ValueHash256 Operation(VirtualMachine vm) => ref vm.TxExecutionContext.Origin; } /// /// Returns the coinbase (beneficiary) address for the current block. /// - public struct OpCoinbase : IOpBlkAddress + public struct OpCoinbase : IOpBlkAddress + where TGasPolicy : struct, IGasPolicy { - public static Address Operation(VirtualMachine vm) + public static Address Operation(VirtualMachine vm) => vm.BlockExecutionContext.Coinbase; } /// /// Returns the chain identifier. /// - public struct OpChainId : IOpEnv32Bytes + public struct OpChainId : IOpEnv32Bytes + where TGasPolicy : struct, IGasPolicy { - public static ref readonly ValueHash256 Operation(VirtualMachine vm) + public static ref readonly ValueHash256 Operation(VirtualMachine vm) => ref vm.ChainId; } @@ -485,9 +534,10 @@ public static ref readonly ValueHash256 Operation(VirtualMachine vm) /// Retrieves and pushes the balance of an account. /// The address is popped from the stack. /// + /// The gas policy used for gas accounting. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// /// if gas is available, @@ -495,18 +545,19 @@ public static ref readonly ValueHash256 Operation(VirtualMachine vm) /// or if not enough items on stack. /// [SkipLocalsInit] - public static EvmExceptionType InstructionBalance(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionBalance(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { IReleaseSpec spec = vm.Spec; // Deduct gas cost for balance operation as per specification. - gasAvailable -= spec.GetBalanceCost(); + TGasPolicy.Consume(ref gas, spec.GetBalanceCost()); Address address = stack.PopAddress(); if (address is null) goto StackUnderflow; // Charge gas for account access. If insufficient gas remains, abort. - if (!EvmCalculations.ChargeAccountAccessGas(ref gasAvailable, vm, address)) goto OutOfGas; + if (!TGasPolicy.ConsumeAccountAccessGas(ref gas, spec, in vm.VmState.AccessTracker, vm.TxTracer.IsTracingAccess, address)) goto OutOfGas; ref readonly UInt256 result = ref vm.WorldState.GetBalance(address); stack.PushUInt256(in result); @@ -522,21 +573,23 @@ public static EvmExceptionType InstructionBalance(VirtualMachine v /// /// Pushes the balance of the executing account onto the stack. /// + /// The gas policy used for gas accounting. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// /// /// [SkipLocalsInit] - public static EvmExceptionType InstructionSelfBalance(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionSelfBalance(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - gasAvailable -= GasCostOf.SelfBalance; + TGasPolicy.Consume(ref gas, GasCostOf.SelfBalance); // Get balance for currently executing account. - ref readonly UInt256 result = ref vm.WorldState.GetBalance(vm.EvmState.Env.ExecutingAccount); + ref readonly UInt256 result = ref vm.WorldState.GetBalance(vm.VmState.Env.ExecutingAccount); stack.PushUInt256(in result); return EvmExceptionType.None; @@ -546,9 +599,10 @@ public static EvmExceptionType InstructionSelfBalance(VirtualMachi /// Retrieves the code hash of an external account. /// Returns zero if the account does not exist or is considered dead. /// + /// The gas policy used for gas accounting. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// /// if gas is available, @@ -556,16 +610,17 @@ public static EvmExceptionType InstructionSelfBalance(VirtualMachi /// or if not enough items on stack. /// [SkipLocalsInit] - public static EvmExceptionType InstructionExtCodeHash(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionExtCodeHash(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { IReleaseSpec spec = vm.Spec; - gasAvailable -= spec.GetExtCodeHashCost(); + TGasPolicy.Consume(ref gas, spec.GetExtCodeHashCost()); Address address = stack.PopAddress(); if (address is null) goto StackUnderflow; // Check if enough gas for account access and charge accordingly. - if (!EvmCalculations.ChargeAccountAccessGas(ref gasAvailable, vm, address)) goto OutOfGas; + if (!TGasPolicy.ConsumeAccountAccessGas(ref gas, spec, in vm.VmState.AccessTracker, vm.TxTracer.IsTracingAccess, address)) goto OutOfGas; IWorldState state = vm.WorldState; // For dead accounts, the specification requires pushing zero. @@ -592,9 +647,10 @@ public static EvmExceptionType InstructionExtCodeHash(VirtualMachi /// Retrieves the code hash of an external account, considering the possibility of an EOF-validated contract. /// If the code is an EOF contract, a predefined EOF hash is pushed. /// + /// The gas policy used for gas accounting. /// The virtual machine instance. /// The execution stack where the gas value will be pushed. - /// Reference to the current available gas, which is modified by this operation. + /// Reference to the gas state, updated by the operation's cost. /// The current program counter. /// /// if gas is available, @@ -602,15 +658,16 @@ public static EvmExceptionType InstructionExtCodeHash(VirtualMachi /// or if not enough items on stack. /// [SkipLocalsInit] - public static EvmExceptionType InstructionExtCodeHashEof(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionExtCodeHashEof(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { IReleaseSpec spec = vm.Spec; - gasAvailable -= spec.GetExtCodeHashCost(); + TGasPolicy.Consume(ref gas, spec.GetExtCodeHashCost()); Address address = stack.PopAddress(); if (address is null) goto StackUnderflow; - if (!EvmCalculations.ChargeAccountAccessGas(ref gasAvailable, vm, address)) goto OutOfGas; + if (!TGasPolicy.ConsumeAccountAccessGas(ref gas, spec, in vm.VmState.AccessTracker, vm.TxTracer.IsTracingAccess, address)) goto OutOfGas; IWorldState state = vm.WorldState; if (state.IsDeadAccount(address)) @@ -644,19 +701,21 @@ public static EvmExceptionType InstructionExtCodeHashEof(VirtualMa /// Implements the PREVRANDAO opcode. /// Pushes the previous random value (post-merge) or block difficulty (pre-merge) onto the stack. /// + /// The gas policy used for gas accounting. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// /// /// [SkipLocalsInit] - public static EvmExceptionType InstructionPrevRandao(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionPrevRandao(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Charge the base gas cost for this opcode. - gasAvailable -= GasCostOf.Base; + TGasPolicy.Consume(ref gas, GasCostOf.Base); stack.Push32Bytes(in vm.BlockExecutionContext.PrevRandao); return EvmExceptionType.None; } @@ -665,25 +724,27 @@ public static EvmExceptionType InstructionPrevRandao(VirtualMachin /// Pushes the remaining gas onto the stack. /// The gas available is decremented by the base cost, and if negative, an OutOfGas error is returned. /// + /// The gas policy used for gas accounting. /// The virtual machine instance. /// The execution stack where the gas value will be pushed. - /// Reference to the current available gas, which is modified by this operation. + /// Reference to the gas state, updated by the operation's cost. /// The current program counter. /// /// if gas is available, or if the gas becomes negative. /// [SkipLocalsInit] - public static EvmExceptionType InstructionGas(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionGas(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Deduct the base gas cost for reading gas. - gasAvailable -= GasCostOf.Base; + TGasPolicy.Consume(ref gas, GasCostOf.Base); // If gas falls below zero after cost deduction, signal out-of-gas error. - if (gasAvailable < 0) goto OutOfGas; + if (TGasPolicy.GetRemainingGas(in gas) < 0) goto OutOfGas; // Push the remaining gas (as unsigned 64-bit) onto the stack. - stack.PushUInt64((ulong)gasAvailable); + stack.PushUInt64((ulong)TGasPolicy.GetRemainingGas(in gas)); return EvmExceptionType.None; // Jump forward to be unpredicted by the branch predictor. @@ -696,20 +757,22 @@ public static EvmExceptionType InstructionGas(VirtualMachine vm, r /// Pops an index from the stack and uses it to select a blob hash from the versioned hashes array. /// If the index is invalid, pushes zero. /// + /// The gas policy used for gas accounting. /// The virtual machine instance. /// The execution stack from which the index is popped and where the blob hash is pushed. - /// Reference to the available gas; reduced by the blob hash cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// /// on success; otherwise, /// if there are insufficient elements on the stack. /// [SkipLocalsInit] - public static EvmExceptionType InstructionBlobHash(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionBlobHash(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Deduct the gas cost for blob hash operation. - gasAvailable -= GasCostOf.BlobHash; + TGasPolicy.Consume(ref gas, GasCostOf.BlobHash); // Pop the blob index from the stack. if (!stack.PopUInt256(out UInt256 result)) goto StackUnderflow; @@ -740,20 +803,22 @@ public static EvmExceptionType InstructionBlobHash(VirtualMachine /// If no valid block hash exists, pushes a zero value. /// Additionally, reports the block hash if block hash tracing is enabled. /// + /// The gas policy used for gas accounting. /// The virtual machine instance. /// The execution stack from which the block number is popped and where the block hash is pushed. - /// Reference to the available gas; reduced by the block hash operation cost. + /// Reference to the gas state, updated by the operation's cost. /// The program counter. /// /// if the operation completes successfully; /// otherwise, if there are insufficient stack elements. /// [SkipLocalsInit] - public static EvmExceptionType InstructionBlockHash(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionBlockHash(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Deduct the gas cost for block hash operation. - gasAvailable -= GasCostOf.BlockHash; + TGasPolicy.Consume(ref gas, GasCostOf.BlockHash); // Pop the block number from the stack. if (!stack.PopUInt256(out UInt256 a)) goto StackUnderflow; diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs index 73dbe12a592..0141d37ba68 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Eof.cs @@ -9,10 +9,10 @@ using Nethermind.Evm.CodeAnalysis; using Nethermind.Evm.EvmObjectFormat; using Nethermind.Evm.EvmObjectFormat.Handlers; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.Tracing; using Nethermind.Evm.State; - -using static Nethermind.Evm.VirtualMachine; +using static Nethermind.Evm.VirtualMachineStatics; namespace Nethermind.Evm; @@ -60,17 +60,20 @@ public struct OpEofStaticCall : IOpEofCall /// Retrieves the length of the return data buffer and pushes it onto the stack. /// Deducts the base gas cost from the available gas. /// + /// The gas policy used for gas accounting. + /// Tracing flag type. /// The current virtual machine instance. /// Reference to the operand stack. - /// Reference to the remaining gas counter. + /// Reference to the gas state. /// Reference to the current program counter. /// An indicating the outcome. [SkipLocalsInit] - public static EvmExceptionType InstructionReturnDataSize(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionReturnDataSize(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Deduct base gas cost for this instruction. - gasAvailable -= GasCostOf.Base; + TGasPolicy.Consume(ref gas, GasCostOf.Base); // Push the length of the return data buffer (as a 32-bit unsigned integer) onto the stack. stack.PushUInt32((uint)vm.ReturnDataBuffer.Length); @@ -92,7 +95,8 @@ public static EvmExceptionType InstructionReturnDataSize(VirtualMa /// Reference to the current program counter. /// An representing success or the type of failure. [SkipLocalsInit] - public static EvmExceptionType InstructionReturnDataCopy(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionReturnDataCopy(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Pop the required parameters: destination memory offset, source offset in return data, and number of bytes to copy. @@ -104,12 +108,12 @@ public static EvmExceptionType InstructionReturnDataCopy(VirtualMa } // Deduct the fixed gas cost and the memory cost based on the size (rounded up to 32-byte words). - gasAvailable -= GasCostOf.VeryLow + GasCostOf.Memory * EvmCalculations.Div32Ceiling(in size, out bool outOfGas); + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow + GasCostOf.Memory * EvmCalculations.Div32Ceiling(in size, out bool outOfGas)); if (outOfGas) goto OutOfGas; ReadOnlyMemory returnDataBuffer = vm.ReturnDataBuffer; // For legacy (non-EOF) code, ensure that the copy does not exceed the available return data. - if (vm.EvmState.Env.CodeInfo.Version == 0 && + if (vm.VmState.Env.CodeInfo.Version == 0 && (UInt256.AddOverflow(size, sourceOffset, out UInt256 result) || result > returnDataBuffer.Length)) { goto AccessViolation; @@ -119,12 +123,12 @@ public static EvmExceptionType InstructionReturnDataCopy(VirtualMa if (!size.IsZero) { // Update memory cost for expanding memory to accommodate the destination slice. - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in destOffset, size)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in destOffset, size, vm.VmState)) return EvmExceptionType.OutOfGas; // Get the source slice; if the requested range exceeds the buffer length, it is zero-padded. ZeroPaddedSpan slice = returnDataBuffer.Span.SliceWithZeroPadding(sourceOffset, (int)size); - if (!vm.EvmState.Memory.TrySave(in destOffset, in slice)) goto OutOfGas; + if (!vm.VmState.Memory.TrySave(in destOffset, in slice)) goto OutOfGas; // Report the memory change if tracing is active. if (TTracingInst.IsActive) @@ -153,16 +157,17 @@ public static EvmExceptionType InstructionReturnDataCopy(VirtualMa /// Reference to the program counter. /// An representing success or an error. [SkipLocalsInit] - public static EvmExceptionType InstructionDataLoad(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionDataLoad(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; // Ensure the instruction is only valid for non-legacy (EOF) code. if (codeInfo.Version == 0) goto BadInstruction; // Deduct gas required for data loading. - if (!EvmCalculations.UpdateGas(GasCostOf.DataLoad, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.DataLoad)) goto OutOfGas; // Pop the offset from the stack. @@ -184,14 +189,15 @@ public static EvmExceptionType InstructionDataLoad(VirtualMachine /// Advances the program counter accordingly. /// [SkipLocalsInit] - public static EvmExceptionType InstructionDataLoadN(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionDataLoadN(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; if (codeInfo.Version == 0) goto BadInstruction; - if (!EvmCalculations.UpdateGas(GasCostOf.DataLoadN, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.DataLoadN)) goto OutOfGas; // Read a 16-bit immediate operand from the code. @@ -215,14 +221,15 @@ public static EvmExceptionType InstructionDataLoadN(VirtualMachine /// Pushes the size of the code's data section onto the stack. /// [SkipLocalsInit] - public static EvmExceptionType InstructionDataSize(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionDataSize(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; if (codeInfo.Version == 0) goto BadInstruction; - if (!EvmCalculations.UpdateGas(GasCostOf.DataSize, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.DataSize)) goto OutOfGas; stack.PushUInt32((uint)codeInfo.DataSection.Length); @@ -240,10 +247,11 @@ public static EvmExceptionType InstructionDataSize(VirtualMachine /// The source offset, destination memory offset, and number of bytes are specified on the stack. /// [SkipLocalsInit] - public static EvmExceptionType InstructionDataCopy(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionDataCopy(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; if (codeInfo.Version == 0) goto BadInstruction; @@ -256,7 +264,7 @@ public static EvmExceptionType InstructionDataCopy(VirtualMachine } // Calculate memory expansion gas cost and deduct overall gas for data copy. - if (!EvmCalculations.UpdateGas(GasCostOf.DataCopy + GasCostOf.Memory * EvmCalculations.Div32Ceiling(in size, out bool outOfGas), ref gasAvailable) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.DataCopy + GasCostOf.Memory * EvmCalculations.Div32Ceiling(in size, out bool outOfGas)) || outOfGas) { goto OutOfGas; @@ -265,11 +273,11 @@ public static EvmExceptionType InstructionDataCopy(VirtualMachine if (!size.IsZero) { // Update memory cost for the destination region. - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in memOffset, size)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in memOffset, size, vm.VmState)) goto OutOfGas; // Retrieve the slice from the data section with zero padding if necessary. ZeroPaddedSpan dataSectionSlice = codeInfo.DataSection.SliceWithZeroPadding(offset, (int)size); - if (!vm.EvmState.Memory.TrySave(in memOffset, in dataSectionSlice)) goto OutOfGas; + if (!vm.VmState.Memory.TrySave(in memOffset, in dataSectionSlice)) goto OutOfGas; if (TTracingInst.IsActive) { @@ -292,13 +300,14 @@ public static EvmExceptionType InstructionDataCopy(VirtualMachine /// Reads a two-byte signed offset from the code section and adjusts the program counter accordingly. /// [SkipLocalsInit] - public static EvmExceptionType InstructionRelativeJump(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionRelativeJump(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; if (codeInfo.Version == 0) goto BadInstruction; - if (!EvmCalculations.UpdateGas(GasCostOf.RJump, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.RJump)) goto OutOfGas; // Read a signed 16-bit offset and adjust the program counter. @@ -318,13 +327,14 @@ public static EvmExceptionType InstructionRelativeJump(VirtualMachine vm, ref Ev /// Pops a condition value; if non-zero, jumps by the signed offset embedded in the code. /// [SkipLocalsInit] - public static EvmExceptionType InstructionRelativeJumpIf(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionRelativeJumpIf(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; if (codeInfo.Version == 0) goto BadInstruction; - if (!EvmCalculations.UpdateGas(GasCostOf.RJumpi, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.RJumpi)) goto OutOfGas; // Pop the condition word. @@ -352,13 +362,14 @@ public static EvmExceptionType InstructionRelativeJumpIf(VirtualMachine vm, ref /// Uses the top-of-stack value as an index into a list of jump offsets, then jumps accordingly. /// [SkipLocalsInit] - public static EvmExceptionType InstructionJumpTable(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionJumpTable(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; if (codeInfo.Version == 0) goto BadInstruction; - if (!EvmCalculations.UpdateGas(GasCostOf.RJumpv, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.RJumpv)) goto OutOfGas; // Pop the table index from the stack. @@ -392,15 +403,16 @@ public static EvmExceptionType InstructionJumpTable(VirtualMachine vm, ref EvmSt /// Sets up the return state and verifies stack and call depth constraints before transferring control. /// [SkipLocalsInit] - public static EvmExceptionType InstructionCallFunction(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionCallFunction(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { - ICodeInfo iCodeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo iCodeInfo = vm.VmState.Env.CodeInfo; if (iCodeInfo.Version == 0) goto BadInstruction; EofCodeInfo codeInfo = (EofCodeInfo)iCodeInfo; - if (!EvmCalculations.UpdateGas(GasCostOf.Callf, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.Callf)) goto OutOfGas; ReadOnlySpan codeSection = codeInfo.CodeSection.Span; @@ -416,11 +428,11 @@ public static EvmExceptionType InstructionCallFunction(VirtualMachine vm, ref Ev } // Ensure there is room on the return stack. - if (vm.EvmState.ReturnStackHead == Eof1.RETURN_STACK_MAX_HEIGHT) + if (vm.VmState.ReturnStackHead == Eof1.RETURN_STACK_MAX_HEIGHT) goto InvalidSubroutineEntry; // Push current state onto the return stack. - vm.EvmState.ReturnStack[vm.EvmState.ReturnStackHead++] = new EvmState.ReturnState + vm.VmState.ReturnStack[vm.VmState.ReturnStackHead++] = new ReturnState { Index = vm.SectionIndex, Height = stack.Head - inputCount, @@ -447,17 +459,18 @@ public static EvmExceptionType InstructionCallFunction(VirtualMachine vm, ref Ev /// Returns from a subroutine call by restoring the state from the return stack. /// [SkipLocalsInit] - public static EvmExceptionType InstructionReturnFunction(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionReturnFunction(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; if (codeInfo.Version == 0) goto BadInstruction; - if (!EvmCalculations.UpdateGas(GasCostOf.Retf, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.Retf)) goto OutOfGas; // Pop the return state from the return stack. - EvmState.ReturnState stackFrame = vm.EvmState.ReturnStack[--vm.EvmState.ReturnStackHead]; + ReturnState stackFrame = vm.VmState.ReturnStack[--vm.VmState.ReturnStackHead]; vm.SectionIndex = stackFrame.Index; programCounter = stackFrame.Offset; @@ -474,15 +487,16 @@ public static EvmExceptionType InstructionReturnFunction(VirtualMachine vm, ref /// Verifies that the target section does not cause a stack overflow. /// [SkipLocalsInit] - public static EvmExceptionType InstructionJumpFunction(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionJumpFunction(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { - ICodeInfo iCodeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo iCodeInfo = vm.VmState.Env.CodeInfo; if (iCodeInfo.Version == 0) goto BadInstruction; EofCodeInfo codeInfo = (EofCodeInfo)iCodeInfo; - if (!EvmCalculations.UpdateGas(GasCostOf.Jumpf, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.Jumpf)) goto OutOfGas; // Read the target section index from the code. @@ -512,14 +526,15 @@ public static EvmExceptionType InstructionJumpFunction(VirtualMachine vm, ref Ev /// The immediate value (n) specifies that the (n+1)th element from the top is duplicated. /// [SkipLocalsInit] - public static EvmExceptionType InstructionDupN(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionDupN(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; if (codeInfo.Version == 0) goto BadInstruction; - if (!EvmCalculations.UpdateGas(GasCostOf.Dupn, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.Dupn)) goto OutOfGas; // Read the immediate operand. @@ -542,14 +557,15 @@ public static EvmExceptionType InstructionDupN(VirtualMachine vm, /// Swaps the top-of-stack with the (n+1)th element. /// [SkipLocalsInit] - public static EvmExceptionType InstructionSwapN(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionSwapN(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; if (codeInfo.Version == 0) goto BadInstruction; - if (!EvmCalculations.UpdateGas(GasCostOf.Swapn, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.Swapn)) goto OutOfGas; // Immediate operand determines the swap index. @@ -571,14 +587,15 @@ public static EvmExceptionType InstructionSwapN(VirtualMachine vm, /// The high nibble and low nibble of the operand specify the two swap distances. /// [SkipLocalsInit] - public static EvmExceptionType InstructionExchange(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionExchange(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; if (codeInfo.Version == 0) goto BadInstruction; - if (!EvmCalculations.UpdateGas(GasCostOf.Swapn, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.Swapn)) goto OutOfGas; ReadOnlySpan codeSection = codeInfo.CodeSection.Span; @@ -608,18 +625,19 @@ public static EvmExceptionType InstructionExchange(VirtualMachine /// A tracing flag type to conditionally report events. /// [SkipLocalsInit] - public static EvmExceptionType InstructionEofCreate(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionEofCreate(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { Metrics.IncrementCreates(); vm.ReturnData = null; IReleaseSpec spec = vm.Spec; - ExecutionEnvironment env = vm.EvmState.Env; + ExecutionEnvironment env = vm.VmState.Env; if (env.CodeInfo.Version == 0) goto BadInstruction; - if (vm.EvmState.IsStatic) + if (vm.VmState.IsStatic) goto StaticCallViolation; // Cast the current code info to EOF-specific container type. @@ -627,7 +645,7 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine ExecutionType currentContext = ExecutionType.EOFCREATE; // 1. Deduct the creation gas cost. - if (!EvmCalculations.UpdateGas(GasCostOf.TxCreate, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.TxCreate)) goto OutOfGas; ReadOnlySpan codeSection = container.CodeSection.Span; @@ -644,11 +662,11 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine } // 4. Charge for memory expansion for the input data. - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in dataOffset, dataSize)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in dataOffset, dataSize, vm.VmState)) goto OutOfGas; // 5. Load the init code (EOF subContainer) from the container using the given index. - ReadOnlySpan initContainer = container.ContainerSection.Span[(Range)container.ContainerSectionOffset(initContainerIndex).Value]; + ReadOnlySpan initContainer = container.ContainerSection.Span[(Range)container.ContainerSectionOffset(initContainerIndex)!.Value]; // EIP-3860: Check that the init code size does not exceed the maximum allowed. if (spec.IsEip3860Enabled) { @@ -659,7 +677,7 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine // 6. Deduct gas for keccak256 hashing of the init code. long numberOfWordsInInitCode = EvmCalculations.Div32Ceiling((UInt256)initContainer.Length, out bool outOfGas); long hashCost = GasCostOf.Sha3Word * numberOfWordsInInitCode; - if (outOfGas || !EvmCalculations.UpdateGas(hashCost, ref gasAvailable)) + if (outOfGas || !TGasPolicy.UpdateGas(ref gas, hashCost)) goto OutOfGas; IWorldState state = vm.WorldState; @@ -674,8 +692,9 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine } // 9. Determine gas available for the new contract execution, applying the 63/64 rule if enabled. + long gasAvailable = TGasPolicy.GetRemainingGas(in gas); long callGas = spec.Use63Over64Rule ? gasAvailable - gasAvailable / 64L : gasAvailable; - if (!EvmCalculations.UpdateGas(callGas, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, callGas)) goto OutOfGas; // 10. Increment the nonce of the sender account. @@ -694,11 +713,11 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine if (spec.UseHotAndColdStorage) { // Warm up the target address for subsequent storage accesses. - vm.EvmState.AccessTracker.WarmUp(contractAddress); + vm.VmState.AccessTracker.WarmUp(contractAddress); } if (TTracingInst.IsActive) - vm.EndInstructionTrace(gasAvailable); + vm.EndInstructionTrace(TGasPolicy.GetRemainingGas(in gas)); // Take a snapshot before modifying state for the new contract. Snapshot snapshot = state.TakeSnapshot(); @@ -726,7 +745,7 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine ICodeInfo codeInfo = CodeInfoFactory.CreateCodeInfo(initContainer.ToArray(), spec, ValidationStrategy.ExtractHeader); // 8. Prepare the callData from the caller’s memory slice. - if (!vm.EvmState.Memory.TryLoad(dataOffset, dataSize, out ReadOnlyMemory callData)) + if (!vm.VmState.Memory.TryLoad(dataOffset, dataSize, out ReadOnlyMemory callData)) goto OutOfGas; // Set up the execution environment for the new contract. @@ -740,15 +759,15 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine value: in value, inputData: in callData); - vm.ReturnData = EvmState.RentFrame( - gasAvailable: callGas, + vm.ReturnData = VmState.RentFrame( + gas: TGasPolicy.FromLong(callGas), outputDestination: 0, outputLength: 0, executionType: currentContext, - isStatic: vm.EvmState.IsStatic, + isStatic: vm.VmState.IsStatic, isCreateOnPreExistingAccount: accountExists, env: callEnv, - stateForAccessLists: in vm.EvmState.AccessTracker, + stateForAccessLists: in vm.VmState.AccessTracker, snapshot: in snapshot); return EvmExceptionType.None; @@ -766,17 +785,18 @@ public static EvmExceptionType InstructionEofCreate(VirtualMachine /// Extracts the deployment code from a specified container section and prepares the return data. /// [SkipLocalsInit] - public static EvmExceptionType InstructionReturnCode(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionReturnCode(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { // This instruction is only valid in create contexts. - if (!vm.EvmState.ExecutionType.IsAnyCreateEof()) + if (!vm.VmState.ExecutionType.IsAnyCreateEof()) goto BadInstruction; - if (!EvmCalculations.UpdateGas(GasCostOf.ReturnCode, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.ReturnCode)) goto OutOfGas; IReleaseSpec spec = vm.Spec; - EofCodeInfo codeInfo = (EofCodeInfo)vm.EvmState.Env.CodeInfo; + EofCodeInfo codeInfo = (EofCodeInfo)vm.VmState.Env.CodeInfo; // Read the container section index from the code. byte sectionIdx = codeInfo.CodeSection.Span[programCounter++]; @@ -788,7 +808,7 @@ public static EvmExceptionType InstructionReturnCode(VirtualMachine vm, ref EvmS stack.PopUInt256(out UInt256 a); stack.PopUInt256(out UInt256 b); - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in a, b)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in a, b, vm.VmState)) goto OutOfGas; int projectedNewSize = (int)b + deployCodeInfo.DataSection.Length; @@ -799,7 +819,7 @@ public static EvmExceptionType InstructionReturnCode(VirtualMachine vm, ref EvmS } // Load the memory slice as the return data buffer. - if (!vm.EvmState.Memory.TryLoad(a, b, out vm.ReturnDataBuffer)) + if (!vm.VmState.Memory.TryLoad(a, b, out vm.ReturnDataBuffer)) goto OutOfGas; vm.ReturnData = deployCodeInfo; @@ -818,15 +838,16 @@ public static EvmExceptionType InstructionReturnCode(VirtualMachine vm, ref EvmS /// This instruction is only valid when EOF is enabled. /// [SkipLocalsInit] - public static EvmExceptionType InstructionReturnDataLoad(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionReturnDataLoad(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { IReleaseSpec spec = vm.Spec; - ICodeInfo codeInfo = vm.EvmState.Env.CodeInfo; + ICodeInfo codeInfo = vm.VmState.Env.CodeInfo; if (!spec.IsEofEnabled || codeInfo.Version == 0) goto BadInstruction; - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); if (!stack.PopUInt256(out UInt256 offset)) goto StackUnderflow; @@ -854,7 +875,8 @@ public static EvmExceptionType InstructionReturnDataLoad(VirtualMa /// A tracing flag type used to report VM state changes during the call. /// [SkipLocalsInit] - public static EvmExceptionType InstructionEofCall(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionEofCall(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TOpEofCall : struct, IOpEofCall where TTracingInst : struct, IFlag { @@ -864,7 +886,7 @@ public static EvmExceptionType InstructionEofCall(Virt IReleaseSpec spec = vm.Spec; vm.ReturnData = null; - ExecutionEnvironment env = vm.EvmState.Env; + ExecutionEnvironment env = vm.VmState.Env; IWorldState state = vm.WorldState; // This instruction is only available for EOF-enabled contracts. @@ -902,10 +924,10 @@ public static EvmExceptionType InstructionEofCall(Virt } // 3. For non-static calls, ensure that a non-zero transfer value is not used in a static context. - if (vm.EvmState.IsStatic && !transferValue.IsZero) + if (vm.VmState.IsStatic && !transferValue.IsZero) goto StaticCallViolation; // 4. Charge additional gas if a value is transferred in a standard call. - if (typeof(TOpEofCall) == typeof(OpEofCall) && !transferValue.IsZero && !EvmCalculations.UpdateGas(GasCostOf.CallValue, ref gasAvailable)) + if (typeof(TOpEofCall) == typeof(OpEofCall) && !transferValue.IsZero && !TGasPolicy.UpdateGas(ref gas, GasCostOf.CallValue)) goto OutOfGas; // 5. Validate that the targetBytes represent a proper 20-byte address (high 12 bytes must be zero). @@ -920,22 +942,25 @@ public static EvmExceptionType InstructionEofCall(Virt : codeSource; // 6. Update memory cost for the call data. - if (!EvmCalculations.UpdateMemoryCost(vm.EvmState, ref gasAvailable, in dataOffset, in dataLength)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in dataOffset, in dataLength, vm.VmState)) goto OutOfGas; // 7. Account access gas: ensure target is warm or charge extra gas for cold access. - if (!EvmCalculations.ChargeAccountAccessGasWithDelegation(ref gasAvailable, vm, codeSource)) - goto OutOfGas; + bool _ = vm.TxExecutionContext.CodeInfoRepository + .TryGetDelegation(codeSource, vm.Spec, out Address delegated); + if (!TGasPolicy.ConsumeAccountAccessGasWithDelegation(ref gas, vm.Spec, in vm.VmState.AccessTracker, + vm.TxTracer.IsTracingAccess, codeSource, delegated)) goto OutOfGas; // 8. If the target does not exist or is considered a "dead" account when value is transferred, // charge for account creation. if ((!spec.ClearEmptyAccountWhenTouched && !state.AccountExists(codeSource)) || (spec.ClearEmptyAccountWhenTouched && transferValue != 0 && state.IsDeadAccount(codeSource))) { - if (!EvmCalculations.UpdateGas(GasCostOf.NewAccount, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.NewAccount)) goto OutOfGas; } // 9. Compute the gas available to the callee after reserving a minimum. + long gasAvailable = TGasPolicy.GetRemainingGas(in gas); long callGas = gasAvailable - Math.Max(gasAvailable / 64, MIN_RETAINED_GAS); // 10. Check that the call gas is sufficient, the caller has enough balance, and the call depth is within limits. @@ -951,7 +976,7 @@ public static EvmExceptionType InstructionEofCall(Virt ITxTracer txTracer = vm.TxTracer; if (TTracingInst.IsActive) { - ReadOnlyMemory memoryTrace = vm.EvmState.Memory.Inspect(in dataOffset, 32); + ReadOnlyMemory memoryTrace = vm.VmState.Memory.Inspect(in dataOffset, 32); txTracer.ReportMemoryChange(dataOffset, memoryTrace.Span); txTracer.ReportOperationRemainingGas(gasAvailable); txTracer.ReportOperationError(EvmExceptionType.NotEnoughBalance); @@ -975,8 +1000,8 @@ public static EvmExceptionType InstructionEofCall(Virt } // 12. Deduct gas for the call and prepare the call data. - if (!EvmCalculations.UpdateGas(callGas, ref gasAvailable) || - !vm.EvmState.Memory.TryLoad(in dataOffset, dataLength, out ReadOnlyMemory callData)) + if (!TGasPolicy.UpdateGas(ref gas, callGas) || + !vm.VmState.Memory.TryLoad(in dataOffset, dataLength, out ReadOnlyMemory callData)) { goto OutOfGas; } @@ -997,15 +1022,15 @@ public static EvmExceptionType InstructionEofCall(Virt value: in callValue, inputData: in callData); - vm.ReturnData = EvmState.RentFrame( - gasAvailable: callGas, + vm.ReturnData = VmState.RentFrame( + gas: TGasPolicy.FromLong(callGas), outputDestination: 0, outputLength: 0, executionType: TOpEofCall.ExecutionType, - isStatic: TOpEofCall.IsStatic || vm.EvmState.IsStatic, + isStatic: TOpEofCall.IsStatic || vm.VmState.IsStatic, isCreateOnPreExistingAccount: false, env: callEnv, - stateForAccessLists: in vm.EvmState.AccessTracker, + stateForAccessLists: in vm.VmState.AccessTracker, snapshot: in snapshot); return EvmExceptionType.None; diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math1Param.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math1Param.cs index 115e1090fdd..65c2c6f2815 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math1Param.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math1Param.cs @@ -6,9 +6,10 @@ using System.Runtime.Intrinsics; using Nethermind.Core; using Nethermind.Core.Extensions; +using Nethermind.Evm.GasPolicy; using Nethermind.Int256; using static System.Runtime.CompilerServices.Unsafe; -using static Nethermind.Evm.VirtualMachine; +using static Nethermind.Evm.VirtualMachineStatics; namespace Nethermind.Evm; @@ -40,21 +41,23 @@ public interface IOpMath1Param /// The operation is defined by the generic parameter , /// which implements . /// + /// The gas policy used for gas accounting. /// A struct implementing for the specific math operation. /// An unused virtual machine instance. /// The EVM stack from which the operand is read and where the result is written. - /// Reference to the available gas, reduced by the operation's cost. + /// Reference to the gas state, updated by the operation's cost. /// Reference to the program counter (unused in this operation). /// /// if the operation completes successfully; otherwise, /// if the stack is empty. /// [SkipLocalsInit] - public static EvmExceptionType InstructionMath1Param(VirtualMachine _, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionMath1Param(VirtualMachine _, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TOpMath : struct, IOpMath1Param { // Deduct the gas cost associated with the math operation. - gasAvailable -= TOpMath.GasCost; + TGasPolicy.Consume(ref gas, TOpMath.GasCost); // Peek at the top element of the stack without removing it. // This avoids an unnecessary pop/push sequence. @@ -110,10 +113,11 @@ public struct OpCLZ : IOpMath1Param /// Extracts a byte from a 256-bit word at the position specified by the stack. /// [SkipLocalsInit] - public static EvmExceptionType InstructionByte(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionByte(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); // Pop the byte position and the 256-bit word. if (!stack.PopUInt256(out UInt256 a)) @@ -150,9 +154,10 @@ public static EvmExceptionType InstructionByte(VirtualMachine vm, /// Performs sign extension on a 256-bit integer in-place based on a specified byte index. /// [SkipLocalsInit] - public static EvmExceptionType InstructionSignExtend(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionSignExtend(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { - gasAvailable -= GasCostOf.Low; + TGasPolicy.Consume(ref gas, GasCostOf.Low); // Pop the index to determine which byte to use for sign extension. if (!stack.PopUInt256(out UInt256 a)) diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs index c5254acff00..78ab517518a 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs @@ -5,8 +5,9 @@ using System.Runtime.CompilerServices; using Nethermind.Core; using Nethermind.Core.Extensions; -using static Nethermind.Evm.VirtualMachine; +using Nethermind.Evm.GasPolicy; using static System.Runtime.CompilerServices.Unsafe; +using static Nethermind.Evm.VirtualMachineStatics; namespace Nethermind.Evm; @@ -38,22 +39,24 @@ public interface IOpMath2Param /// This method pops two UInt256 operands from the stack, applies the operation, /// and then pushes the result onto the stack. /// + /// The gas policy used for gas accounting. /// A struct implementing that defines the specific operation. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// The gas state which is updated by the operation's cost. /// Reference to the program counter. /// /// if the operation completes successfully; /// otherwise, if insufficient stack elements are available. /// [SkipLocalsInit] - public static EvmExceptionType InstructionMath2Param(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionMath2Param(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TOpMath : struct, IOpMath2Param where TTracingInst : struct, IFlag { // Deduct the gas cost for the specific math operation. - gasAvailable -= TOpMath.GasCost; + TGasPolicy.Consume(ref gas, TOpMath.GasCost); // Pop two operands from the stack. If either pop fails, jump to the underflow handler. if (!stack.PopUInt256(out UInt256 a) || !stack.PopUInt256(out UInt256 b)) goto StackUnderflow; @@ -253,17 +256,18 @@ public static void Operation(in UInt256 a, in UInt256 b, out UInt256 result) /// /// The virtual machine instance. /// The execution stack where the program counter is pushed. - /// Reference to the remaining gas; reduced by the gas cost. + /// Reference to the gas state; updated by the gas cost. /// The current program counter. /// /// on success; or if not enough items on stack. /// [SkipLocalsInit] - public static EvmExceptionType InstructionExp(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionExp(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Charge the fixed gas cost for exponentiation. - gasAvailable -= GasCostOf.Exp; + TGasPolicy.Consume(ref gas, GasCostOf.Exp); // Pop the base value from the stack. if (!stack.PopUInt256(out UInt256 a)) @@ -283,7 +287,7 @@ public static EvmExceptionType InstructionExp(VirtualMachine vm, r { int expSize = 32 - leadingZeros; // Deduct gas proportional to the number of 32-byte words needed to represent the exponent. - gasAvailable -= vm.Spec.GetExpByteCost() * expSize; + TGasPolicy.Consume(ref gas, vm.Spec.GetExpByteCost() * expSize); if (a.IsZero) { diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math3Param.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math3Param.cs index e6708f6e850..f9600b8dde3 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math3Param.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math3Param.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using Nethermind.Core; +using Nethermind.Evm.GasPolicy; namespace Nethermind.Evm; @@ -17,11 +18,12 @@ public interface IOpMath3Param } [SkipLocalsInit] - public static EvmExceptionType InstructionMath3Param(VirtualMachine _, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionMath3Param(VirtualMachine _, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TOpMath : struct, IOpMath3Param where TTracingInst : struct, IFlag { - gasAvailable -= TOpMath.GasCost; + TGasPolicy.Consume(ref gas, TOpMath.GasCost); if (!stack.PopUInt256(out UInt256 a) || !stack.PopUInt256(out UInt256 b) || !stack.PopUInt256(out UInt256 c)) goto StackUnderflow; diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Shifts.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Shifts.cs index 8c5bf453f80..c53d6bc1981 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Shifts.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Shifts.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using Nethermind.Core; +using Nethermind.Evm.GasPolicy; using static System.Runtime.CompilerServices.Unsafe; namespace Nethermind.Evm; @@ -38,22 +39,24 @@ public interface IOpShift /// The operation pops the shift amount and the value to shift, unless the shift amount is 256 or more. /// In that case, the value operand is discarded and zero is pushed as the result. /// + /// The gas policy used for gas accounting. /// The specific shift operation (e.g. left or right shift). /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// The gas state which is updated by the operation's cost. /// Reference to the program counter. /// /// if the operation completes successfully; /// otherwise, if there are insufficient stack elements. /// [SkipLocalsInit] - public static EvmExceptionType InstructionShift(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionShift(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TOpShift : struct, IOpShift where TTracingInst : struct, IFlag { // Deduct gas cost specific to the shift operation. - gasAvailable -= TOpShift.GasCost; + TGasPolicy.Consume(ref gas, TOpShift.GasCost); // Pop the shift amount from the stack. if (!stack.PopUInt256(out UInt256 a)) goto StackUnderflow; @@ -85,20 +88,22 @@ public static EvmExceptionType InstructionShift(VirtualM /// Pops a shift amount and a value from the stack, interprets the value as signed, /// and performs an arithmetic right shift. /// + /// The gas policy used for gas accounting. /// The virtual machine instance (unused in the operation logic). /// The EVM stack used for operands and result storage. - /// Reference to the available gas, reduced by the operation's cost. + /// The gas state which is updated by the operation's cost. /// Reference to the program counter (unused in this operation). /// /// if successful; otherwise, /// if insufficient stack elements are available. /// [SkipLocalsInit] - public static EvmExceptionType InstructionSar(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionSar(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Deduct the gas cost for the arithmetic shift operation. - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); // Pop the shift amount and the value to be shifted. if (!stack.PopUInt256(out UInt256 a) || !stack.PopUInt256(out UInt256 b)) goto StackUnderflow; diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs index 9ac15c682f9..ebe50e55f70 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Stack.cs @@ -8,10 +8,11 @@ using System.Runtime.Intrinsics; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm.GasPolicy; +using Nethermind.Int256; namespace Nethermind.Evm; -using Int256; using Word = Vector256; using static Unsafe; @@ -23,15 +24,16 @@ internal static partial class EvmInstructions /// /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// The gas state which is reduced by the operation's cost. /// The program counter. /// if successful; otherwise, . [SkipLocalsInit] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static EvmExceptionType InstructionPop(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionPop(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { // Deduct the minimal gas cost for a POP operation. - gasAvailable -= GasCostOf.Base; + TGasPolicy.Consume(ref gas, GasCostOf.Base); // Pop from the stack; if nothing to pop, signal a stack underflow. return stack.PopLimbo() ? EvmExceptionType.None : EvmExceptionType.StackUnderflow; } @@ -114,14 +116,15 @@ public struct Op2 : IOpCount { public static int Count => 2; } /// Push operation for two bytes. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static EvmExceptionType InstructionPush2(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionPush2(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { const int Size = sizeof(ushort); // Deduct a very low gas cost for the push operation. - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); // Retrieve the code segment containing immediate data. - ReadOnlySpan code = vm.EvmState.Env.CodeInfo.CodeSpan; + ReadOnlySpan code = vm.VmState.Env.CodeInfo.CodeSpan; ref byte bytes = ref MemoryMarshal.GetReference(code); int remainingCode = code.Length - programCounter; @@ -141,12 +144,12 @@ public static EvmExceptionType InstructionPush2(VirtualMachine vm, if (nextInstruction == Instruction.JUMP) { - gasAvailable -= GasCostOf.Jump; + TGasPolicy.Consume(ref gas, GasCostOf.Jump); vm.OpCodeCount++; } else { - gasAvailable -= GasCostOf.JumpI; + TGasPolicy.Consume(ref gas, GasCostOf.JumpI); vm.OpCodeCount++; bool shouldJump = TestJumpCondition(ref stack, out bool isOverflow); if (isOverflow) goto StackUnderflow; @@ -159,7 +162,7 @@ public static EvmExceptionType InstructionPush2(VirtualMachine vm, } // Validate the jump destination and update the program counter if valid. - if (!Jump((int)destination, ref programCounter, vm.EvmState.Env)) + if (!Jump((int)destination, ref programCounter, vm.VmState.Env)) goto InvalidJumpDestination; goto Success; @@ -482,14 +485,15 @@ public static void Push(int length, ref EvmStack stack, int progra /// /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// The gas state which is reduced by the operation's cost. /// The program counter. /// on success. [SkipLocalsInit] - public static EvmExceptionType InstructionPush0(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionPush0(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - gasAvailable -= GasCostOf.Base; + TGasPolicy.Consume(ref gas, GasCostOf.Base); stack.PushZero(); return EvmExceptionType.None; } @@ -498,21 +502,24 @@ public static EvmExceptionType InstructionPush0(VirtualMachine vm, /// Executes a PUSH instruction. /// Reads immediate data of a fixed length from the code and pushes it onto the stack. /// + /// The gas policy implementation. /// The push operation implementation defining the byte count. + /// The tracing flag. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// The gas state which is reduced by the operation's cost. /// Reference to the program counter, which will be advanced. /// on success. [SkipLocalsInit] - public static EvmExceptionType InstructionPush(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) - where TOpCount : IOpCount + public static EvmExceptionType InstructionPush(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy + where TOpCount : struct, IOpCount where TTracingInst : struct, IFlag { // Deduct a very low gas cost for the push operation. - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); // Retrieve the code segment containing immediate data. - ReadOnlySpan code = vm.EvmState.Env.CodeInfo.CodeSpan; + ReadOnlySpan code = vm.VmState.Env.CodeInfo.CodeSpan; // Use the push method defined by the specific push operation. TOpCount.Push(TOpCount.Count, ref stack, programCounter, code); // Advance the program counter by the number of bytes consumed. @@ -523,18 +530,21 @@ public static EvmExceptionType InstructionPush(VirtualMa /// /// Executes a DUP operation which duplicates the nth stack element. /// + /// The gas policy implementation. /// The duplicate operation implementation that defines which element to duplicate. + /// The tracing flag. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// The gas state which is reduced by the operation's cost. /// Reference to the program counter. /// on success or if insufficient stack elements. [SkipLocalsInit] - public static EvmExceptionType InstructionDup(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) - where TOpCount : IOpCount + public static EvmExceptionType InstructionDup(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy + where TOpCount : struct, IOpCount where TTracingInst : struct, IFlag { - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); return stack.Dup(TOpCount.Count); } @@ -542,18 +552,21 @@ public static EvmExceptionType InstructionDup(VirtualMac /// /// Executes a SWAP operation which swaps the top element with the (n+1)th element. /// + /// The gas policy implementation. /// The swap operation implementation that defines the swap depth. + /// The tracing flag. /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// The gas state which is reduced by the operation's cost. /// Reference to the program counter. /// on success or if insufficient elements. [SkipLocalsInit] - public static EvmExceptionType InstructionSwap(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) - where TOpCount : IOpCount + public static EvmExceptionType InstructionSwap(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy + where TOpCount : struct, IOpCount where TTracingInst : struct, IFlag { - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); // Swap the top element with the (n+1)th element; ensure adequate stack depth. return stack.Swap(TOpCount.Count + 1); } @@ -563,20 +576,22 @@ public static EvmExceptionType InstructionSwap(VirtualMa /// Pops data offset and length, then pops a fixed number of topics from the stack. /// Validates memory expansion and deducts gas accordingly. /// + /// The gas policy implementation. /// Specifies the number of log topics (as defined by its Count property). /// The virtual machine instance. /// The execution stack. - /// The available gas which is reduced by the operation's cost. + /// The gas state which is reduced by the operation's cost. /// Reference to the program counter. /// /// if the log is successfully recorded; otherwise, an appropriate exception type such as /// , , or . /// [SkipLocalsInit] - public static EvmExceptionType InstructionLog(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionLog(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TOpCount : struct, IOpCount { - EvmState vmState = vm.EvmState; + VmState vmState = vm.VmState; // Logging is not permitted in static call contexts. if (vmState.IsStatic) goto StaticCallViolation; @@ -587,11 +602,10 @@ public static EvmExceptionType InstructionLog(VirtualMachine vm, ref E long topicsCount = TOpCount.Count; // Ensure that the memory expansion for the log data is accounted for. - if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in position, length)) goto OutOfGas; + if (!TGasPolicy.UpdateMemoryCost(ref gas, in position, length, vmState)) goto OutOfGas; // Deduct gas for the log entry itself, including per-topic and per-byte data costs. - if (!EvmCalculations.UpdateGas( - GasCostOf.Log + topicsCount * GasCostOf.LogTopic + - (long)length * GasCostOf.LogData, ref gasAvailable)) goto OutOfGas; + long dataSize = (long)length; + if (!TGasPolicy.ConsumeLogEmission(ref gas, topicsCount, dataSize)) goto OutOfGas; // Load the log data from memory. if (!vmState.Memory.TryLoad(in position, length, out ReadOnlyMemory data)) @@ -627,4 +641,3 @@ public static EvmExceptionType InstructionLog(VirtualMachine vm, ref E return EvmExceptionType.OutOfGas; } } - diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Storage.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Storage.cs index dd8abad4ee6..1cd5b0f56ec 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Storage.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Storage.cs @@ -6,7 +6,8 @@ using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; -using static Nethermind.Evm.VirtualMachine; +using Nethermind.Evm.GasPolicy; +using static Nethermind.Evm.VirtualMachineStatics; namespace Nethermind.Evm; @@ -27,24 +28,25 @@ internal static partial class EvmInstructions /// /// The virtual machine instance executing the instruction. /// The EVM stack. - /// The available gas, which is reduced by the gas cost of the operation. + /// The gas state, updated by the operation's cost. /// The program counter. /// An indicating the result of the operation. [SkipLocalsInit] - public static EvmExceptionType InstructionTLoad(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionTLoad(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Increment the opcode metric for TLOAD. Metrics.TloadOpcode++; // Deduct the fixed gas cost for TLOAD. - gasAvailable -= GasCostOf.TLoad; + TGasPolicy.Consume(ref gas, GasCostOf.TLoad); // Attempt to pop the key (offset) from the stack; if unavailable, signal a stack underflow. if (!stack.PopUInt256(out UInt256 result)) goto StackUnderflow; // Construct a transient storage cell using the executing account and the provided offset. - StorageCell storageCell = new(vm.EvmState.Env.ExecutingAccount, in result); + StorageCell storageCell = new(vm.VmState.Env.ExecutingAccount, in result); // Retrieve the value from transient storage. ReadOnlySpan value = vm.WorldState.GetTransientState(in storageCell); @@ -52,10 +54,10 @@ public static EvmExceptionType InstructionTLoad(VirtualMachine vm, // Push the retrieved value onto the stack. stack.PushBytes(value); - // If storage tracing is enabled, record the operation (ensuring gas remains non-negative). + // If storage tracing is enabled, record the operation. if (vm.TxTracer.IsTracingStorage) { - if (gasAvailable < 0) goto OutOfGas; + if (TGasPolicy.GetRemainingGas(in gas) < 0) goto OutOfGas; vm.TxTracer.LoadOperationTransientStorage(storageCell.Address, result, value); } @@ -76,22 +78,23 @@ public static EvmExceptionType InstructionTLoad(VirtualMachine vm, /// /// The virtual machine instance executing the instruction. /// The EVM stack. - /// The available gas, reduced by the cost of TSTORE. + /// The gas state, updated by the operation's cost. /// The program counter. /// An indicating success or failure. [SkipLocalsInit] - public static EvmExceptionType InstructionTStore(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionTStore(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy { // Increment the opcode metric for TSTORE. Metrics.TstoreOpcode++; - EvmState vmState = vm.EvmState; + VmState vmState = vm.VmState; // Disallow storage modification during static calls. if (vmState.IsStatic) goto StaticCallViolation; // Deduct the gas cost for TSTORE. - gasAvailable -= GasCostOf.TStore; + TGasPolicy.Consume(ref gas, GasCostOf.TStore); // Pop the key (offset) from the stack; if unavailable, signal a stack underflow. if (!stack.PopUInt256(out UInt256 result)) goto StackUnderflow; @@ -108,7 +111,7 @@ public static EvmExceptionType InstructionTStore(VirtualMachine vm, ref EvmStack // If storage tracing is enabled, retrieve the current stored value and log the operation. if (vm.TxTracer.IsTracingStorage) { - if (gasAvailable < 0) goto OutOfGas; + if (TGasPolicy.GetRemainingGas(in gas) < 0) goto OutOfGas; ReadOnlySpan currentValue = vm.WorldState.GetTransientState(in storageCell); vm.TxTracer.SetOperationTransientStorage(storageCell.Address, result, bytes, currentValue); } @@ -137,10 +140,11 @@ public static EvmExceptionType InstructionTStore(VirtualMachine vm, ref EvmStack /// The program counter. /// An result. [SkipLocalsInit] - public static EvmExceptionType InstructionMStore(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionMStore(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); // Pop the memory offset; if not available, signal a stack underflow. if (!stack.PopUInt256(out UInt256 result)) goto StackUnderflow; @@ -148,11 +152,10 @@ public static EvmExceptionType InstructionMStore(VirtualMachine vm // Retrieve the 32-byte word to be stored. Span bytes = stack.PopWord256(); - EvmState vmState = vm.EvmState; + VmState vmState = vm.VmState; // Update the memory cost for a 32-byte store; if insufficient gas, signal out-of-gas. - if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in result, in BigInt32) || - !vmState.Memory.TrySaveWord(in result, bytes)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in result, in BigInt32, vmState) || !vmState.Memory.TrySaveWord(in result, bytes)) { goto OutOfGas; } @@ -183,10 +186,11 @@ public static EvmExceptionType InstructionMStore(VirtualMachine vm /// The program counter. /// An result. [SkipLocalsInit] - public static EvmExceptionType InstructionMStore8(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionMStore8(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); // Pop the memory offset from the stack; if missing, signal a stack underflow. if (!stack.PopUInt256(out UInt256 result)) goto StackUnderflow; @@ -194,11 +198,11 @@ public static EvmExceptionType InstructionMStore8(VirtualMachine v // Pop a single byte from the stack. byte data = stack.PopByte(); - EvmState vmState = vm.EvmState; + VmState vmState = vm.VmState; // Update the memory cost for a single-byte extension; if insufficient, signal out-of-gas. - if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in result, in UInt256.One) || - !vmState.Memory.TrySaveByte(in result, data)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in result, in UInt256.One, vmState) || + !vmState.Memory.TrySaveByte(in result, data)) { goto OutOfGas; } @@ -229,19 +233,20 @@ public static EvmExceptionType InstructionMStore8(VirtualMachine v /// The program counter. /// An result. [SkipLocalsInit] - public static EvmExceptionType InstructionMLoad(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionMLoad(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); // Pop the memory offset; if missing, signal a stack underflow. if (!stack.PopUInt256(out UInt256 result)) goto StackUnderflow; - EvmState vmState = vm.EvmState; + VmState vmState = vm.VmState; // Update memory cost for a 32-byte load. - if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, in result, in BigInt32) || - !vmState.Memory.TryLoadSpan(in result, out Span bytes)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in result, in BigInt32, vmState) || + !vmState.Memory.TryLoadSpan(in result, out Span bytes)) { goto OutOfGas; } @@ -275,7 +280,8 @@ public static EvmExceptionType InstructionMLoad(VirtualMachine vm, /// The program counter. /// An result. [SkipLocalsInit] - public static EvmExceptionType InstructionMCopy(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionMCopy(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Increment the opcode metric for MCOPY. @@ -285,13 +291,13 @@ public static EvmExceptionType InstructionMCopy(VirtualMachine vm, if (!stack.PopUInt256(out UInt256 a) || !stack.PopUInt256(out UInt256 b) || !stack.PopUInt256(out UInt256 c)) goto StackUnderflow; // Calculate additional gas cost based on the length (using a division rounding-up method) and deduct the total cost. - gasAvailable -= GasCostOf.VeryLow + GasCostOf.VeryLow * EvmCalculations.Div32Ceiling(c, out bool outOfGas); + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow + GasCostOf.VeryLow * EvmCalculations.Div32Ceiling(c, out bool outOfGas)); if (outOfGas) goto OutOfGas; - EvmState vmState = vm.EvmState; + VmState vmState = vm.VmState; // Update memory cost for the destination area (largest offset among source and destination) over the specified length. - if (!EvmCalculations.UpdateMemoryCost(vmState, ref gasAvailable, UInt256.Max(b, a), c) || + if (!TGasPolicy.UpdateMemoryCost(ref gas, UInt256.Max(b, a), c, vmState) || !vmState.Memory.TryLoadSpan(in b, c, out Span bytes)) { goto OutOfGas; @@ -323,27 +329,29 @@ public static EvmExceptionType InstructionMCopy(VirtualMachine vm, /// and updates persistent storage for the executing account. This method handles legacy gas calculations. /// /// + /// The gas policy used for gas accounting. /// A flag type indicating whether detailed tracing is enabled. /// The virtual machine instance. /// The EVM stack. - /// The available gas, which is decremented by multiple cost adjustments during storage modification. + /// The gas state, updated by the operation's cost. /// The program counter. /// An indicating the outcome. [SkipLocalsInit] - internal static EvmExceptionType InstructionSStoreUnmetered(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + internal static EvmExceptionType InstructionSStoreUnmetered(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Increment the SSTORE opcode metric. Metrics.IncrementSStoreOpcode(); - EvmState vmState = vm.EvmState; + VmState vmState = vm.VmState; // Disallow storage modifications in static calls. if (vmState.IsStatic) goto StaticCallViolation; IReleaseSpec spec = vm.Spec; // For legacy metering: ensure there is enough gas for the SSTORE reset cost before reading storage. - if (!EvmCalculations.UpdateGas(spec.GetSStoreResetCost(), ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, spec.GetSStoreResetCost())) goto OutOfGas; // Pop the key and then the new value for storage; signal underflow if unavailable. @@ -358,7 +366,7 @@ internal static EvmExceptionType InstructionSStoreUnmetered(Virtua StorageCell storageCell = new(vmState.Env.ExecutingAccount, in result); // Charge gas based on whether this is a cold or warm storage access. - if (!EvmCalculations.ChargeStorageAccessGas(ref gasAvailable, vm, in storageCell, StorageAccessType.SSTORE, spec)) + if (!TGasPolicy.ConsumeStorageAccessGas(ref gas, in vmState.AccessTracker, vm.TxTracer.IsTracingAccess, in storageCell, StorageAccessType.SSTORE, spec)) goto OutOfGas; // Retrieve the current value from persistent storage. @@ -384,7 +392,7 @@ internal static EvmExceptionType InstructionSStoreUnmetered(Virtua // When setting a non-zero value over an existing zero, apply the difference in gas costs. else if (currentIsZero) { - if (!EvmCalculations.UpdateGas(GasCostOf.SSet - GasCostOf.SReset, ref gasAvailable)) + if (!TGasPolicy.UpdateGas(ref gas, GasCostOf.SSet - GasCostOf.SReset)) goto OutOfGas; } @@ -422,22 +430,24 @@ internal static EvmExceptionType InstructionSStoreUnmetered(Virtua /// and updates persistent storage for the executing account. This method handles net metered gas calculations. /// /// + /// The gas policy used for gas accounting. /// A flag type indicating whether detailed tracing is enabled. /// A flag type indicating whether stipend fix is enabled. /// The virtual machine instance. /// The EVM stack. - /// The available gas, which is decremented by multiple cost adjustments during storage modification. + /// The gas state, updated by the operation's cost. /// The program counter. /// An indicating the outcome. [SkipLocalsInit] - internal static EvmExceptionType InstructionSStoreMetered(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + internal static EvmExceptionType InstructionSStoreMetered(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag where TUseNetGasStipendFix : struct, IFlag { // Increment the SSTORE opcode metric. Metrics.IncrementSStoreOpcode(); - EvmState vmState = vm.EvmState; + VmState vmState = vm.VmState; // Disallow storage modifications in static calls. if (vmState.IsStatic) goto StaticCallViolation; @@ -448,7 +458,7 @@ internal static EvmExceptionType InstructionSStoreMetered bytes) + private static void TraceSstore(VirtualMachine vm, bool newIsZero, in StorageCell storageCell, ReadOnlySpan bytes) + where TGasPolicy : struct, IGasPolicy { ReadOnlySpan valueToStore = newIsZero ? BytesZero.AsSpan() : bytes; byte[] storageBytes = new byte[32]; // Allocated on the heap to avoid stack allocation. @@ -593,11 +604,12 @@ private static void TraceSstore(VirtualMachine vm, bool newIsZero, in StorageCel /// /// The virtual machine instance. /// The EVM stack. - /// The remaining gas, reduced by the SLOAD cost and any storage access gas adjustments. + /// The gas state, updated by the operation's cost. /// The program counter (unused in this instruction). /// An indicating the result of the operation. [SkipLocalsInit] - internal static EvmExceptionType InstructionSLoad(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + internal static EvmExceptionType InstructionSLoad(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { IReleaseSpec spec = vm.Spec; @@ -606,20 +618,18 @@ internal static EvmExceptionType InstructionSLoad(VirtualMachine v Metrics.IncrementSLoadOpcode(); // Deduct the gas cost for performing an SLOAD. - gasAvailable -= spec.GetSLoadCost(); + TGasPolicy.Consume(ref gas, spec.GetSLoadCost()); // Pop the key from the stack; if unavailable, signal a stack underflow. if (!stack.PopUInt256(out UInt256 result)) goto StackUnderflow; // Construct the storage cell for the executing account. - Address executingAccount = vm.EvmState.Env.ExecutingAccount; + Address executingAccount = vm.VmState.Env.ExecutingAccount; StorageCell storageCell = new(executingAccount, in result); // Charge additional gas based on whether the storage cell is hot or cold. - if (!EvmCalculations.ChargeStorageAccessGas(ref gasAvailable, vm, in storageCell, StorageAccessType.SLOAD, spec)) - { + if (!TGasPolicy.ConsumeStorageAccessGas(ref gas, in vm.VmState.AccessTracker, vm.TxTracer.IsTracingAccess, in storageCell, StorageAccessType.SLOAD, spec)) goto OutOfGas; - } // Retrieve the persistent storage value and push it onto the stack. ReadOnlySpan value = vm.WorldState.Get(in storageCell); @@ -645,16 +655,17 @@ internal static EvmExceptionType InstructionSLoad(VirtualMachine v /// zero-padding if necessary. /// [SkipLocalsInit] - public static EvmExceptionType InstructionCallDataLoad(VirtualMachine vm, ref EvmStack stack, ref long gasAvailable, ref int programCounter) + public static EvmExceptionType InstructionCallDataLoad(VirtualMachine vm, ref EvmStack stack, ref TGasPolicy gas, ref int programCounter) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { - gasAvailable -= GasCostOf.VeryLow; + TGasPolicy.Consume(ref gas, GasCostOf.VeryLow); // Pop the offset from which to load call data. if (!stack.PopUInt256(out UInt256 result)) goto StackUnderflow; // Load 32 bytes from input data, applying zero padding as needed. - stack.PushBytes(vm.EvmState.Env.InputData.SliceWithZeroPadding(result, 32)); + stack.PushBytes(vm.VmState.Env.InputData.SliceWithZeroPadding(result, 32)); return EvmExceptionType.None; // Jump forward to be unpredicted by the branch predictor. diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.cs index e3b6646cda9..cd1d55436d8 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.cs @@ -1,15 +1,15 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Runtime.CompilerServices; using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Evm.GasPolicy; [assembly: InternalsVisibleTo("Nethermind.Evm.Precompiles")] namespace Nethermind.Evm; -using unsafe OpCode = delegate*; - internal static unsafe partial class EvmInstructions { /// @@ -17,14 +17,16 @@ internal static unsafe partial class EvmInstructions /// Each of the 256 entries in the returned array corresponds to an EVM instruction, /// with unassigned opcodes defaulting to a bad instruction handler. /// + /// The gas policy type used for gas accounting. /// A struct implementing IFlag used for tracing purposes. /// The release specification containing enabled features and opcode flags. /// An array of function pointers (opcode handlers) indexed by opcode value. - public static OpCode[] GenerateOpCodes(IReleaseSpec spec) + public static delegate*, ref EvmStack, ref TGasPolicy, ref int, EvmExceptionType>[] GenerateOpCodes(IReleaseSpec spec) + where TGasPolicy : struct, IGasPolicy where TTracingInst : struct, IFlag { // Allocate lookup table for all possible opcodes. - OpCode[] lookup = new OpCode[byte.MaxValue + 1]; + var lookup = new delegate*, ref EvmStack, ref TGasPolicy, ref int, EvmExceptionType>[byte.MaxValue + 1]; for (int i = 0; i < lookup.Length; i++) { @@ -33,275 +35,277 @@ public static OpCode[] GenerateOpCodes(IReleaseSpec spec) // Set basic control and arithmetic opcodes. lookup[(int)Instruction.STOP] = &InstructionStop; - lookup[(int)Instruction.ADD] = &InstructionMath2Param; - lookup[(int)Instruction.MUL] = &InstructionMath2Param; - lookup[(int)Instruction.SUB] = &InstructionMath2Param; - lookup[(int)Instruction.DIV] = &InstructionMath2Param; - lookup[(int)Instruction.SDIV] = &InstructionMath2Param; - lookup[(int)Instruction.MOD] = &InstructionMath2Param; - lookup[(int)Instruction.SMOD] = &InstructionMath2Param; - lookup[(int)Instruction.ADDMOD] = &InstructionMath3Param; - lookup[(int)Instruction.MULMOD] = &InstructionMath3Param; - lookup[(int)Instruction.EXP] = &InstructionExp; - lookup[(int)Instruction.SIGNEXTEND] = &InstructionSignExtend; + lookup[(int)Instruction.ADD] = &InstructionMath2Param; + lookup[(int)Instruction.MUL] = &InstructionMath2Param; + lookup[(int)Instruction.SUB] = &InstructionMath2Param; + lookup[(int)Instruction.DIV] = &InstructionMath2Param; + lookup[(int)Instruction.SDIV] = &InstructionMath2Param; + lookup[(int)Instruction.MOD] = &InstructionMath2Param; + lookup[(int)Instruction.SMOD] = &InstructionMath2Param; + lookup[(int)Instruction.ADDMOD] = &InstructionMath3Param; + lookup[(int)Instruction.MULMOD] = &InstructionMath3Param; + lookup[(int)Instruction.EXP] = &InstructionExp; + lookup[(int)Instruction.SIGNEXTEND] = &InstructionSignExtend; // Comparison and bitwise opcodes. - lookup[(int)Instruction.LT] = &InstructionMath2Param; - lookup[(int)Instruction.GT] = &InstructionMath2Param; - lookup[(int)Instruction.SLT] = &InstructionMath2Param; - lookup[(int)Instruction.SGT] = &InstructionMath2Param; - lookup[(int)Instruction.EQ] = &InstructionBitwise; - lookup[(int)Instruction.ISZERO] = &InstructionMath1Param; - lookup[(int)Instruction.AND] = &InstructionBitwise; - lookup[(int)Instruction.OR] = &InstructionBitwise; - lookup[(int)Instruction.XOR] = &InstructionBitwise; - lookup[(int)Instruction.NOT] = &InstructionMath1Param; - lookup[(int)Instruction.BYTE] = &InstructionByte; + lookup[(int)Instruction.LT] = &InstructionMath2Param; + lookup[(int)Instruction.GT] = &InstructionMath2Param; + lookup[(int)Instruction.SLT] = &InstructionMath2Param; + lookup[(int)Instruction.SGT] = &InstructionMath2Param; + lookup[(int)Instruction.EQ] = &InstructionBitwise; + lookup[(int)Instruction.ISZERO] = &InstructionMath1Param; + lookup[(int)Instruction.AND] = &InstructionBitwise; + lookup[(int)Instruction.OR] = &InstructionBitwise; + lookup[(int)Instruction.XOR] = &InstructionBitwise; + lookup[(int)Instruction.NOT] = &InstructionMath1Param; + lookup[(int)Instruction.BYTE] = &InstructionByte; // Conditional: enable shift opcodes if the spec allows. if (spec.ShiftOpcodesEnabled) { - lookup[(int)Instruction.SHL] = &InstructionShift; - lookup[(int)Instruction.SHR] = &InstructionShift; - lookup[(int)Instruction.SAR] = &InstructionSar; + lookup[(int)Instruction.SHL] = &InstructionShift; + lookup[(int)Instruction.SHR] = &InstructionShift; + lookup[(int)Instruction.SAR] = &InstructionSar; } if (spec.CLZEnabled) { - lookup[(int)Instruction.CLZ] = &InstructionMath1Param; + lookup[(int)Instruction.CLZ] = &InstructionMath1Param; } // Cryptographic hash opcode. - lookup[(int)Instruction.KECCAK256] = &InstructionKeccak256; + lookup[(int)Instruction.KECCAK256] = &InstructionKeccak256; // Environment opcodes. - lookup[(int)Instruction.ADDRESS] = &InstructionEnvAddress; - lookup[(int)Instruction.BALANCE] = &InstructionBalance; - lookup[(int)Instruction.ORIGIN] = &InstructionEnv32Bytes; - lookup[(int)Instruction.CALLER] = &InstructionEnvAddress; - lookup[(int)Instruction.CALLVALUE] = &InstructionEnvUInt256; - lookup[(int)Instruction.CALLDATALOAD] = &InstructionCallDataLoad; - lookup[(int)Instruction.CALLDATASIZE] = &InstructionEnvUInt32; - lookup[(int)Instruction.CALLDATACOPY] = &InstructionCodeCopy; - lookup[(int)Instruction.CODESIZE] = &InstructionEnvUInt32; - lookup[(int)Instruction.CODECOPY] = &InstructionCodeCopy; - lookup[(int)Instruction.GASPRICE] = &InstructionBlkUInt256; - - lookup[(int)Instruction.EXTCODESIZE] = &InstructionExtCodeSize; - lookup[(int)Instruction.EXTCODECOPY] = &InstructionExtCodeCopy; + lookup[(int)Instruction.ADDRESS] = &InstructionEnvAddress, TTracingInst>; + lookup[(int)Instruction.BALANCE] = &InstructionBalance; + lookup[(int)Instruction.ORIGIN] = &InstructionEnv32Bytes, TTracingInst>; + lookup[(int)Instruction.CALLER] = &InstructionEnvAddress, TTracingInst>; + lookup[(int)Instruction.CALLVALUE] = &InstructionEnvUInt256, TTracingInst>; + lookup[(int)Instruction.CALLDATALOAD] = &InstructionCallDataLoad; + lookup[(int)Instruction.CALLDATASIZE] = &InstructionEnvUInt32, TTracingInst>; + lookup[(int)Instruction.CALLDATACOPY] = + &InstructionCodeCopy, TTracingInst>; + lookup[(int)Instruction.CODESIZE] = &InstructionEnvUInt32, TTracingInst>; + lookup[(int)Instruction.CODECOPY] = &InstructionCodeCopy, TTracingInst>; + lookup[(int)Instruction.GASPRICE] = &InstructionBlkUInt256, TTracingInst>; + + lookup[(int)Instruction.EXTCODESIZE] = &InstructionExtCodeSize; + lookup[(int)Instruction.EXTCODECOPY] = &InstructionExtCodeCopy; // Return data opcodes (if enabled). if (spec.ReturnDataOpcodesEnabled) { - lookup[(int)Instruction.RETURNDATASIZE] = &InstructionReturnDataSize; - lookup[(int)Instruction.RETURNDATACOPY] = &InstructionReturnDataCopy; + lookup[(int)Instruction.RETURNDATASIZE] = &InstructionReturnDataSize; + lookup[(int)Instruction.RETURNDATACOPY] = &InstructionReturnDataCopy; } // Extended code hash opcode handling. if (spec.ExtCodeHashOpcodeEnabled) { lookup[(int)Instruction.EXTCODEHASH] = spec.IsEofEnabled ? - &InstructionExtCodeHashEof : - &InstructionExtCodeHash; + &InstructionExtCodeHashEof : + &InstructionExtCodeHash; } - lookup[(int)Instruction.BLOCKHASH] = &InstructionBlockHash; + lookup[(int)Instruction.BLOCKHASH] = &InstructionBlockHash; // More environment opcodes. - lookup[(int)Instruction.COINBASE] = &InstructionBlkAddress; - lookup[(int)Instruction.TIMESTAMP] = &InstructionBlkUInt64; - lookup[(int)Instruction.NUMBER] = &InstructionBlkUInt64; - lookup[(int)Instruction.PREVRANDAO] = &InstructionPrevRandao; - lookup[(int)Instruction.GASLIMIT] = &InstructionBlkUInt64; + lookup[(int)Instruction.COINBASE] = &InstructionBlkAddress, TTracingInst>; + lookup[(int)Instruction.TIMESTAMP] = &InstructionBlkUInt64, TTracingInst>; + lookup[(int)Instruction.NUMBER] = &InstructionBlkUInt64, TTracingInst>; + lookup[(int)Instruction.PREVRANDAO] = &InstructionPrevRandao; + lookup[(int)Instruction.GASLIMIT] = &InstructionBlkUInt64, TTracingInst>; if (spec.ChainIdOpcodeEnabled) { - lookup[(int)Instruction.CHAINID] = &InstructionEnv32Bytes; + lookup[(int)Instruction.CHAINID] = &InstructionEnv32Bytes, TTracingInst>; } if (spec.SelfBalanceOpcodeEnabled) { - lookup[(int)Instruction.SELFBALANCE] = &InstructionSelfBalance; + lookup[(int)Instruction.SELFBALANCE] = &InstructionSelfBalance; } if (spec.BaseFeeEnabled) { - lookup[(int)Instruction.BASEFEE] = &InstructionBlkUInt256; + lookup[(int)Instruction.BASEFEE] = &InstructionBlkUInt256, TTracingInst>; } if (spec.IsEip4844Enabled) { - lookup[(int)Instruction.BLOBHASH] = &InstructionBlobHash; + lookup[(int)Instruction.BLOBHASH] = &InstructionBlobHash; } if (spec.BlobBaseFeeEnabled) { - lookup[(int)Instruction.BLOBBASEFEE] = &InstructionBlobBaseFee; + lookup[(int)Instruction.BLOBBASEFEE] = &InstructionBlobBaseFee; } // Gap: opcodes 0x4b to 0x4f are unassigned. // Memory and storage instructions. lookup[(int)Instruction.POP] = &InstructionPop; - lookup[(int)Instruction.MLOAD] = &InstructionMLoad; - lookup[(int)Instruction.MSTORE] = &InstructionMStore; - lookup[(int)Instruction.MSTORE8] = &InstructionMStore8; - lookup[(int)Instruction.SLOAD] = &InstructionSLoad; + lookup[(int)Instruction.MLOAD] = &InstructionMLoad; + lookup[(int)Instruction.MSTORE] = &InstructionMStore; + lookup[(int)Instruction.MSTORE8] = &InstructionMStore8; + lookup[(int)Instruction.SLOAD] = &InstructionSLoad; lookup[(int)Instruction.SSTORE] = spec.UseNetGasMetering ? (spec.UseNetGasMeteringWithAStipendFix ? - &InstructionSStoreMetered : - &InstructionSStoreMetered + &InstructionSStoreMetered : + &InstructionSStoreMetered ) : - &InstructionSStoreUnmetered; + &InstructionSStoreUnmetered; // Jump instructions. lookup[(int)Instruction.JUMP] = &InstructionJump; lookup[(int)Instruction.JUMPI] = &InstructionJumpIf; - lookup[(int)Instruction.PC] = &InstructionProgramCounter; - lookup[(int)Instruction.MSIZE] = &InstructionEnvUInt64; - lookup[(int)Instruction.GAS] = &InstructionGas; + lookup[(int)Instruction.PC] = &InstructionProgramCounter; + lookup[(int)Instruction.MSIZE] = &InstructionEnvUInt64, TTracingInst>; + lookup[(int)Instruction.GAS] = &InstructionGas; lookup[(int)Instruction.JUMPDEST] = &InstructionJumpDest; // Transient storage opcodes. if (spec.TransientStorageEnabled) { - lookup[(int)Instruction.TLOAD] = &InstructionTLoad; + lookup[(int)Instruction.TLOAD] = &InstructionTLoad; lookup[(int)Instruction.TSTORE] = &InstructionTStore; } if (spec.MCopyIncluded) { - lookup[(int)Instruction.MCOPY] = &InstructionMCopy; + lookup[(int)Instruction.MCOPY] = &InstructionMCopy; } // Optional PUSH0 instruction. if (spec.IncludePush0Instruction) { - lookup[(int)Instruction.PUSH0] = &InstructionPush0; + lookup[(int)Instruction.PUSH0] = &InstructionPush0; } // PUSH opcodes (PUSH1 to PUSH32). - lookup[(int)Instruction.PUSH1] = &InstructionPush; - lookup[(int)Instruction.PUSH2] = &InstructionPush2; - lookup[(int)Instruction.PUSH3] = &InstructionPush; - lookup[(int)Instruction.PUSH4] = &InstructionPush; - lookup[(int)Instruction.PUSH5] = &InstructionPush; - lookup[(int)Instruction.PUSH6] = &InstructionPush; - lookup[(int)Instruction.PUSH7] = &InstructionPush; - lookup[(int)Instruction.PUSH8] = &InstructionPush; - lookup[(int)Instruction.PUSH9] = &InstructionPush; - lookup[(int)Instruction.PUSH10] = &InstructionPush; - lookup[(int)Instruction.PUSH11] = &InstructionPush; - lookup[(int)Instruction.PUSH12] = &InstructionPush; - lookup[(int)Instruction.PUSH13] = &InstructionPush; - lookup[(int)Instruction.PUSH14] = &InstructionPush; - lookup[(int)Instruction.PUSH15] = &InstructionPush; - lookup[(int)Instruction.PUSH16] = &InstructionPush; - lookup[(int)Instruction.PUSH17] = &InstructionPush; - lookup[(int)Instruction.PUSH18] = &InstructionPush; - lookup[(int)Instruction.PUSH19] = &InstructionPush; - lookup[(int)Instruction.PUSH20] = &InstructionPush; - lookup[(int)Instruction.PUSH21] = &InstructionPush; - lookup[(int)Instruction.PUSH22] = &InstructionPush; - lookup[(int)Instruction.PUSH23] = &InstructionPush; - lookup[(int)Instruction.PUSH24] = &InstructionPush; - lookup[(int)Instruction.PUSH25] = &InstructionPush; - lookup[(int)Instruction.PUSH26] = &InstructionPush; - lookup[(int)Instruction.PUSH27] = &InstructionPush; - lookup[(int)Instruction.PUSH28] = &InstructionPush; - lookup[(int)Instruction.PUSH29] = &InstructionPush; - lookup[(int)Instruction.PUSH30] = &InstructionPush; - lookup[(int)Instruction.PUSH31] = &InstructionPush; - lookup[(int)Instruction.PUSH32] = &InstructionPush; + lookup[(int)Instruction.PUSH1] = &InstructionPush; + lookup[(int)Instruction.PUSH2] = &InstructionPush2; + lookup[(int)Instruction.PUSH3] = &InstructionPush; + lookup[(int)Instruction.PUSH4] = &InstructionPush; + lookup[(int)Instruction.PUSH5] = &InstructionPush; + lookup[(int)Instruction.PUSH6] = &InstructionPush; + lookup[(int)Instruction.PUSH7] = &InstructionPush; + lookup[(int)Instruction.PUSH8] = &InstructionPush; + lookup[(int)Instruction.PUSH9] = &InstructionPush; + lookup[(int)Instruction.PUSH10] = &InstructionPush; + lookup[(int)Instruction.PUSH11] = &InstructionPush; + lookup[(int)Instruction.PUSH12] = &InstructionPush; + lookup[(int)Instruction.PUSH13] = &InstructionPush; + lookup[(int)Instruction.PUSH14] = &InstructionPush; + lookup[(int)Instruction.PUSH15] = &InstructionPush; + lookup[(int)Instruction.PUSH16] = &InstructionPush; + lookup[(int)Instruction.PUSH17] = &InstructionPush; + lookup[(int)Instruction.PUSH18] = &InstructionPush; + lookup[(int)Instruction.PUSH19] = &InstructionPush; + lookup[(int)Instruction.PUSH20] = &InstructionPush; + lookup[(int)Instruction.PUSH21] = &InstructionPush; + lookup[(int)Instruction.PUSH22] = &InstructionPush; + lookup[(int)Instruction.PUSH23] = &InstructionPush; + lookup[(int)Instruction.PUSH24] = &InstructionPush; + lookup[(int)Instruction.PUSH25] = &InstructionPush; + lookup[(int)Instruction.PUSH26] = &InstructionPush; + lookup[(int)Instruction.PUSH27] = &InstructionPush; + lookup[(int)Instruction.PUSH28] = &InstructionPush; + lookup[(int)Instruction.PUSH29] = &InstructionPush; + lookup[(int)Instruction.PUSH30] = &InstructionPush; + lookup[(int)Instruction.PUSH31] = &InstructionPush; + lookup[(int)Instruction.PUSH32] = &InstructionPush; // DUP opcodes (DUP1 to DUP16). - lookup[(int)Instruction.DUP1] = &InstructionDup; - lookup[(int)Instruction.DUP2] = &InstructionDup; - lookup[(int)Instruction.DUP3] = &InstructionDup; - lookup[(int)Instruction.DUP4] = &InstructionDup; - lookup[(int)Instruction.DUP5] = &InstructionDup; - lookup[(int)Instruction.DUP6] = &InstructionDup; - lookup[(int)Instruction.DUP7] = &InstructionDup; - lookup[(int)Instruction.DUP8] = &InstructionDup; - lookup[(int)Instruction.DUP9] = &InstructionDup; - lookup[(int)Instruction.DUP10] = &InstructionDup; - lookup[(int)Instruction.DUP11] = &InstructionDup; - lookup[(int)Instruction.DUP12] = &InstructionDup; - lookup[(int)Instruction.DUP13] = &InstructionDup; - lookup[(int)Instruction.DUP14] = &InstructionDup; - lookup[(int)Instruction.DUP15] = &InstructionDup; - lookup[(int)Instruction.DUP16] = &InstructionDup; + lookup[(int)Instruction.DUP1] = &InstructionDup; + lookup[(int)Instruction.DUP2] = &InstructionDup; + lookup[(int)Instruction.DUP3] = &InstructionDup; + lookup[(int)Instruction.DUP4] = &InstructionDup; + lookup[(int)Instruction.DUP5] = &InstructionDup; + lookup[(int)Instruction.DUP6] = &InstructionDup; + lookup[(int)Instruction.DUP7] = &InstructionDup; + lookup[(int)Instruction.DUP8] = &InstructionDup; + lookup[(int)Instruction.DUP9] = &InstructionDup; + lookup[(int)Instruction.DUP10] = &InstructionDup; + lookup[(int)Instruction.DUP11] = &InstructionDup; + lookup[(int)Instruction.DUP12] = &InstructionDup; + lookup[(int)Instruction.DUP13] = &InstructionDup; + lookup[(int)Instruction.DUP14] = &InstructionDup; + lookup[(int)Instruction.DUP15] = &InstructionDup; + lookup[(int)Instruction.DUP16] = &InstructionDup; // SWAP opcodes (SWAP1 to SWAP16). - lookup[(int)Instruction.SWAP1] = &InstructionSwap; - lookup[(int)Instruction.SWAP2] = &InstructionSwap; - lookup[(int)Instruction.SWAP3] = &InstructionSwap; - lookup[(int)Instruction.SWAP4] = &InstructionSwap; - lookup[(int)Instruction.SWAP5] = &InstructionSwap; - lookup[(int)Instruction.SWAP6] = &InstructionSwap; - lookup[(int)Instruction.SWAP7] = &InstructionSwap; - lookup[(int)Instruction.SWAP8] = &InstructionSwap; - lookup[(int)Instruction.SWAP9] = &InstructionSwap; - lookup[(int)Instruction.SWAP10] = &InstructionSwap; - lookup[(int)Instruction.SWAP11] = &InstructionSwap; - lookup[(int)Instruction.SWAP12] = &InstructionSwap; - lookup[(int)Instruction.SWAP13] = &InstructionSwap; - lookup[(int)Instruction.SWAP14] = &InstructionSwap; - lookup[(int)Instruction.SWAP15] = &InstructionSwap; - lookup[(int)Instruction.SWAP16] = &InstructionSwap; + lookup[(int)Instruction.SWAP1] = &InstructionSwap; + lookup[(int)Instruction.SWAP2] = &InstructionSwap; + lookup[(int)Instruction.SWAP3] = &InstructionSwap; + lookup[(int)Instruction.SWAP4] = &InstructionSwap; + lookup[(int)Instruction.SWAP5] = &InstructionSwap; + lookup[(int)Instruction.SWAP6] = &InstructionSwap; + lookup[(int)Instruction.SWAP7] = &InstructionSwap; + lookup[(int)Instruction.SWAP8] = &InstructionSwap; + lookup[(int)Instruction.SWAP9] = &InstructionSwap; + lookup[(int)Instruction.SWAP10] = &InstructionSwap; + lookup[(int)Instruction.SWAP11] = &InstructionSwap; + lookup[(int)Instruction.SWAP12] = &InstructionSwap; + lookup[(int)Instruction.SWAP13] = &InstructionSwap; + lookup[(int)Instruction.SWAP14] = &InstructionSwap; + lookup[(int)Instruction.SWAP15] = &InstructionSwap; + lookup[(int)Instruction.SWAP16] = &InstructionSwap; // LOG opcodes. - lookup[(int)Instruction.LOG0] = &InstructionLog; - lookup[(int)Instruction.LOG1] = &InstructionLog; - lookup[(int)Instruction.LOG2] = &InstructionLog; - lookup[(int)Instruction.LOG3] = &InstructionLog; - lookup[(int)Instruction.LOG4] = &InstructionLog; + lookup[(int)Instruction.LOG0] = &InstructionLog; + lookup[(int)Instruction.LOG1] = &InstructionLog; + lookup[(int)Instruction.LOG2] = &InstructionLog; + lookup[(int)Instruction.LOG3] = &InstructionLog; + lookup[(int)Instruction.LOG4] = &InstructionLog; // Extended opcodes for EO (EoF) mode. if (spec.IsEofEnabled) { - lookup[(int)Instruction.DATALOAD] = &InstructionDataLoad; - lookup[(int)Instruction.DATALOADN] = &InstructionDataLoadN; - lookup[(int)Instruction.DATASIZE] = &InstructionDataSize; - lookup[(int)Instruction.DATACOPY] = &InstructionDataCopy; + lookup[(int)Instruction.DATALOAD] = &InstructionDataLoad; + lookup[(int)Instruction.DATALOADN] = &InstructionDataLoadN; + lookup[(int)Instruction.DATASIZE] = &InstructionDataSize; + lookup[(int)Instruction.DATACOPY] = &InstructionDataCopy; lookup[(int)Instruction.RJUMP] = &InstructionRelativeJump; lookup[(int)Instruction.RJUMPI] = &InstructionRelativeJumpIf; lookup[(int)Instruction.RJUMPV] = &InstructionJumpTable; lookup[(int)Instruction.CALLF] = &InstructionCallFunction; lookup[(int)Instruction.RETF] = &InstructionReturnFunction; lookup[(int)Instruction.JUMPF] = &InstructionJumpFunction; - lookup[(int)Instruction.DUPN] = &InstructionDupN; - lookup[(int)Instruction.SWAPN] = &InstructionSwapN; - lookup[(int)Instruction.EXCHANGE] = &InstructionExchange; - lookup[(int)Instruction.EOFCREATE] = &InstructionEofCreate; + lookup[(int)Instruction.DUPN] = &InstructionDupN; + lookup[(int)Instruction.SWAPN] = &InstructionSwapN; + lookup[(int)Instruction.EXCHANGE] = &InstructionExchange; + lookup[(int)Instruction.EOFCREATE] = &InstructionEofCreate; lookup[(int)Instruction.RETURNCODE] = &InstructionReturnCode; } // Contract creation and call opcodes. - lookup[(int)Instruction.CREATE] = &InstructionCreate; - lookup[(int)Instruction.CALL] = &InstructionCall; - lookup[(int)Instruction.CALLCODE] = &InstructionCall; + lookup[(int)Instruction.CREATE] = &InstructionCreate; + lookup[(int)Instruction.CALL] = &InstructionCall; + lookup[(int)Instruction.CALLCODE] = &InstructionCall; lookup[(int)Instruction.RETURN] = &InstructionReturn; if (spec.DelegateCallEnabled) { - lookup[(int)Instruction.DELEGATECALL] = &InstructionCall; + lookup[(int)Instruction.DELEGATECALL] = &InstructionCall; } if (spec.Create2OpcodeEnabled) { - lookup[(int)Instruction.CREATE2] = &InstructionCreate; + lookup[(int)Instruction.CREATE2] = &InstructionCreate; } - lookup[(int)Instruction.RETURNDATALOAD] = &InstructionReturnDataLoad; + lookup[(int)Instruction.RETURNDATALOAD] = &InstructionReturnDataLoad; if (spec.StaticCallEnabled) { - lookup[(int)Instruction.STATICCALL] = &InstructionCall; + lookup[(int)Instruction.STATICCALL] = &InstructionCall; } // Extended call opcodes in EO mode. if (spec.IsEofEnabled) { - lookup[(int)Instruction.EXTCALL] = &InstructionEofCall; + lookup[(int)Instruction.EXTCALL] = &InstructionEofCall; if (spec.DelegateCallEnabled) { - lookup[(int)Instruction.EXTDELEGATECALL] = &InstructionEofCall; + lookup[(int)Instruction.EXTDELEGATECALL] = + &InstructionEofCall; } if (spec.StaticCallEnabled) { - lookup[(int)Instruction.EXTSTATICCALL] = &InstructionEofCall; + lookup[(int)Instruction.EXTSTATICCALL] = &InstructionEofCall; } } diff --git a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs index bdb4935fed1..5f483bb2c8c 100644 --- a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs @@ -9,28 +9,56 @@ using Nethermind.Core.Eip2930; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Evm.GasPolicy; using Nethermind.Int256; namespace Nethermind.Evm; +/// +/// Generic intrinsic gas result with TGasPolicy-typed Standard and FloorGas. +/// +public readonly record struct IntrinsicGas(TGasPolicy Standard, TGasPolicy FloorGas) + where TGasPolicy : struct, IGasPolicy +{ + public TGasPolicy MinimalGas { get; } = TGasPolicy.Max(Standard, FloorGas); + public static explicit operator TGasPolicy(IntrinsicGas gas) => gas.MinimalGas; +} -public readonly record struct IntrinsicGas(long Standard, long FloorGas) +/// +/// Non-generic intrinsic gas result for backward compatibility. +/// +public readonly record struct EthereumIntrinsicGas(long Standard, long FloorGas) { public long MinimalGas { get; } = Math.Max(Standard, FloorGas); - public static explicit operator long(IntrinsicGas gas) => gas.MinimalGas; + public static explicit operator long(EthereumIntrinsicGas gas) => gas.MinimalGas; } public static class IntrinsicGasCalculator { - public static IntrinsicGas Calculate(Transaction transaction, IReleaseSpec releaseSpec) + /// + /// Calculates intrinsic gas with TGasPolicy type, allowing MultiGas breakdown for Arbitrum. + /// + public static IntrinsicGas Calculate(Transaction transaction, IReleaseSpec releaseSpec) + where TGasPolicy : struct, IGasPolicy + { + TGasPolicy standard = TGasPolicy.CalculateIntrinsicGas(transaction, releaseSpec); + long floorCost = CalculateFloorCost(transaction, releaseSpec); + TGasPolicy floorGas = TGasPolicy.FromLong(floorCost); + return new IntrinsicGas(standard, floorGas); + } + + /// + /// Non-generic backward-compatible Calculate method. + /// + public static EthereumIntrinsicGas Calculate(Transaction transaction, IReleaseSpec releaseSpec) { - var intrinsicGas = GasCostOf.Transaction + long intrinsicGas = GasCostOf.Transaction + DataCost(transaction, releaseSpec) + CreateCost(transaction, releaseSpec) + AccessListCost(transaction, releaseSpec) + AuthorizationListCost(transaction, releaseSpec); - var floorGas = CalculateFloorCost(transaction, releaseSpec); - return new IntrinsicGas(intrinsicGas, floorGas); + long floorGas = CalculateFloorCost(transaction, releaseSpec); + return new EthereumIntrinsicGas(intrinsicGas, floorGas); } private static long CreateCost(Transaction transaction, IReleaseSpec releaseSpec) => diff --git a/src/Nethermind/Nethermind.Evm/StackPool.cs b/src/Nethermind/Nethermind.Evm/StackPool.cs index 2be787ee0b2..3c5a1309388 100644 --- a/src/Nethermind/Nethermind.Evm/StackPool.cs +++ b/src/Nethermind/Nethermind.Evm/StackPool.cs @@ -6,14 +6,14 @@ using System.Runtime.Intrinsics; using System.Threading; -using static Nethermind.Evm.EvmState; +using static Nethermind.Evm.VirtualMachineStatics; namespace Nethermind.Evm; internal sealed class StackPool { // Also have parallel prewarming and Rpc calls - private const int MaxStacksPooled = VirtualMachine.MaxCallDepth * 2; + private const int MaxStacksPooled = MaxCallDepth * 2; private readonly struct StackItem(byte[] dataStack, ReturnState[] returnStack) { public readonly byte[] DataStack = dataStack; diff --git a/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs index c95c4576e8a..ec77b92b666 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs @@ -7,18 +7,20 @@ using System.Threading; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; namespace Nethermind.Evm.Tracing.Debugger; -public class DebugTracer : ITxTracer, ITxTracerWrapper, IDisposable +public class DebugTracer : ITxTracer, ITxTracerWrapper, IDisposable + where TGasPolicy : struct, IGasPolicy { public enum DebugPhase { Starting, Blocked, Running, Aborted } private readonly AutoResetEvent _autoResetEvent = new(false); - private readonly Dictionary<(int depth, int pc), Func> _breakPoints = new(); - private Func? _globalBreakCondition; + private readonly Dictionary<(int depth, int pc), Func, bool>> _breakPoints = new(); + private Func, bool>? _globalBreakCondition; private readonly object _lock = new(); public DebugTracer(ITxTracer tracer) @@ -32,7 +34,7 @@ public DebugTracer(ITxTracer tracer) public DebugPhase CurrentPhase { get; private set; } = DebugPhase.Starting; public bool CanReadState => CurrentPhase is DebugPhase.Blocked; public bool IsStepByStepModeOn { get; set; } - public EvmState? CurrentState { get; set; } + public VmState? CurrentState { get; set; } public bool IsTracingReceipt => InnerTracer.IsTracingReceipt; @@ -64,7 +66,7 @@ public DebugTracer(ITxTracer tracer) public bool IsBreakpoitnSet(int depth, int programCounter) => _breakPoints.ContainsKey((depth, programCounter)); - public void SetBreakPoint((int depth, int pc) point, Func condition = null) + public void SetBreakPoint((int depth, int pc) point, Func, bool> condition = null) { if (CurrentPhase is DebugPhase.Blocked or DebugPhase.Starting) { @@ -79,12 +81,12 @@ public void UnsetBreakPoint(int depth, int programCounter) } } - public void SetCondition(Func? condition = null) + public void SetCondition(Func, bool>? condition = null) { if (CurrentPhase is DebugPhase.Blocked or DebugPhase.Starting) _globalBreakCondition = condition; } - public void TryWait(ref EvmState evmState, ref int programCounter, ref long gasAvailable, ref int stackHead) + public void TryWait(ref VmState vmState, ref int programCounter, ref TGasPolicy gas, ref int stackHead) { if (CurrentPhase is DebugPhase.Aborted) { @@ -93,10 +95,10 @@ public void TryWait(ref EvmState evmState, ref int programCounter, ref long gasA lock (_lock) { - evmState.ProgramCounter = programCounter; - evmState.GasAvailable = gasAvailable; - evmState.DataStackHead = stackHead; - CurrentState = evmState; + vmState.ProgramCounter = programCounter; + vmState.Gas = gas; + vmState.DataStackHead = stackHead; + CurrentState = vmState; } if (IsStepByStepModeOn) @@ -112,7 +114,7 @@ public void TryWait(ref EvmState evmState, ref int programCounter, ref long gasA lock (_lock) { stackHead = CurrentState.DataStackHead; - gasAvailable = CurrentState.GasAvailable; + gas = CurrentState.Gas; programCounter = CurrentState.ProgramCounter; } } @@ -163,7 +165,7 @@ public void CheckBreakPoint() { (int CallDepth, int ProgramCounter) breakpoint = (CurrentState!.Env.CallDepth, CurrentState.ProgramCounter); - if (_breakPoints.TryGetValue(breakpoint, out Func? point)) + if (_breakPoints.TryGetValue(breakpoint, out Func, bool>? point)) { bool conditionResults = point?.Invoke(CurrentState) ?? true; if (conditionResults) @@ -292,4 +294,12 @@ public void Dispose() _autoResetEvent.Dispose(); } } + +/// +/// Non-generic DebugTracer for backward compatibility with EthereumGasPolicy. +/// +public class DebugTracer : DebugTracer +{ + public DebugTracer(ITxTracer tracer) : base(tracer) { } +} #endif diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/SystemTransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/SystemTransactionProcessor.cs index a4bd99c0758..cac2907385e 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/SystemTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/SystemTransactionProcessor.cs @@ -3,6 +3,7 @@ using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.Tracing; using Nethermind.Int256; using Nethermind.Logging; @@ -11,7 +12,8 @@ namespace Nethermind.Evm.TransactionProcessing; -public sealed class SystemTransactionProcessor : TransactionProcessorBase +public sealed class SystemTransactionProcessor : TransactionProcessorBase + where TGasPolicy : struct, IGasPolicy { private readonly bool _isAura; @@ -25,7 +27,7 @@ public SystemTransactionProcessor( ITransactionProcessor.IBlobBaseFeeCalculator blobBaseFeeCalculator, ISpecProvider? specProvider, IWorldState? worldState, - IVirtualMachine? virtualMachine, + IVirtualMachine? virtualMachine, ICodeInfoRepository? codeInfoRepository, ILogManager? logManager) : base(blobBaseFeeCalculator, specProvider, worldState, virtualMachine, codeInfoRepository, logManager) @@ -73,7 +75,7 @@ protected override void PayValue(Transaction tx, IReleaseSpec spec, ExecutionOpt } } - protected override IntrinsicGas CalculateIntrinsicGas(Transaction tx, IReleaseSpec spec) => tx is SystemCall ? default : base.CalculateIntrinsicGas(tx, spec); + protected override IntrinsicGas CalculateIntrinsicGas(Transaction tx, IReleaseSpec spec) => tx is SystemCall ? default : base.CalculateIntrinsicGas(tx, spec); protected override bool RecoverSenderIfNeeded(Transaction tx, IReleaseSpec spec, ExecutionOptions opts, in UInt256 effectiveGasPrice) { diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 1513feecd3c..ce337d50f1c 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -13,6 +13,7 @@ using Nethermind.Crypto; using Nethermind.Evm.CodeAnalysis; using Nethermind.Evm.EvmObjectFormat.Handlers; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.Tracing; using Nethermind.Int256; using Nethermind.Logging; @@ -22,14 +23,27 @@ namespace Nethermind.Evm.TransactionProcessing { - public sealed class TransactionProcessor( + public sealed class TransactionProcessor( + ITransactionProcessor.IBlobBaseFeeCalculator blobBaseFeeCalculator, + ISpecProvider? specProvider, + IWorldState? worldState, + IVirtualMachine? virtualMachine, + ICodeInfoRepository? codeInfoRepository, + ILogManager? logManager) + : TransactionProcessorBase(blobBaseFeeCalculator, specProvider, worldState, virtualMachine, codeInfoRepository, logManager) + where TGasPolicy : struct, IGasPolicy; + + /// + /// Non-generic TransactionProcessor for backward compatibility with EthereumGasPolicy. + /// + public sealed class EthereumTransactionProcessor( ITransactionProcessor.IBlobBaseFeeCalculator blobBaseFeeCalculator, ISpecProvider? specProvider, IWorldState? worldState, IVirtualMachine? virtualMachine, ICodeInfoRepository? codeInfoRepository, ILogManager? logManager) - : TransactionProcessorBase(blobBaseFeeCalculator, specProvider, worldState, virtualMachine, codeInfoRepository, logManager); + : EthereumTransactionProcessorBase(blobBaseFeeCalculator, specProvider, worldState, virtualMachine, codeInfoRepository, logManager); public class BlobBaseFeeCalculator : ITransactionProcessor.IBlobBaseFeeCalculator { @@ -40,15 +54,16 @@ public bool TryCalculateBlobBaseFee(BlockHeader header, Transaction transaction, BlobGasCalculator.TryCalculateBlobBaseFee(header, transaction, blobGasPriceUpdateFraction, out blobBaseFee); } - public abstract class TransactionProcessorBase : ITransactionProcessor + public abstract class TransactionProcessorBase : ITransactionProcessor + where TGasPolicy : struct, IGasPolicy { protected EthereumEcdsa Ecdsa { get; } protected ILogger Logger { get; } protected ISpecProvider SpecProvider { get; } protected IWorldState WorldState { get; } - protected IVirtualMachine VirtualMachine { get; } + protected IVirtualMachine VirtualMachine { get; } private readonly ICodeInfoRepository _codeInfoRepository; - private SystemTransactionProcessor? _systemTransactionProcessor; + private SystemTransactionProcessor? _systemTransactionProcessor; private readonly ITransactionProcessor.IBlobBaseFeeCalculator _blobBaseFeeCalculator; private readonly ILogManager _logManager; @@ -90,7 +105,7 @@ protected TransactionProcessorBase( ITransactionProcessor.IBlobBaseFeeCalculator? blobBaseFeeCalculator, ISpecProvider? specProvider, IWorldState? worldState, - IVirtualMachine? virtualMachine, + IVirtualMachine? virtualMachine, ICodeInfoRepository? codeInfoRepository, ILogManager? logManager) { @@ -147,7 +162,7 @@ private TransactionResult ExecuteCore(Transaction tx, ITxTracer tracer, Executio if (Logger.IsTrace) Logger.Trace($"Executing tx {tx.Hash}"); if (tx.IsSystem() || opts == ExecutionOptions.SkipValidation) { - _systemTransactionProcessor ??= new SystemTransactionProcessor(_blobBaseFeeCalculator, SpecProvider, WorldState, VirtualMachine, _codeInfoRepository, _logManager); + _systemTransactionProcessor ??= new SystemTransactionProcessor(_blobBaseFeeCalculator, SpecProvider, WorldState, VirtualMachine, _codeInfoRepository, _logManager); return _systemTransactionProcessor.Execute(tx, tracer, opts); } @@ -169,7 +184,7 @@ protected virtual TransactionResult Execute(Transaction tx, ITxTracer tracer, Ex bool commit = opts.HasFlag(ExecutionOptions.Commit) || (!opts.HasFlag(ExecutionOptions.SkipValidation) && !spec.IsEip658Enabled); TransactionResult result; - IntrinsicGas intrinsicGas = CalculateIntrinsicGas(tx, spec); + IntrinsicGas intrinsicGas = CalculateIntrinsicGas(tx, spec); if (!(result = ValidateStatic(tx, header, spec, opts, in intrinsicGas))) return result; UInt256 effectiveGasPrice = CalculateEffectiveGasPrice(tx, spec.IsEip1559Enabled, header.BaseFeePerGas, out UInt256 opcodeGasPrice); @@ -198,7 +213,7 @@ protected virtual TransactionResult Execute(Transaction tx, ITxTracer tracer, Ex int delegationRefunds = (!spec.IsEip7702Enabled || !tx.HasAuthorizationList) ? 0 : ProcessDelegations(tx, spec, accessTracker); - if (!(result = CalculateAvailableGas(tx, intrinsicGas, out long gasAvailable))) return result; + if (!(result = CalculateAvailableGas(tx, in intrinsicGas, out TGasPolicy gasAvailable))) return result; if (!(result = BuildExecutionEnvironment(tx, spec, _codeInfoRepository, accessTracker, out ExecutionEnvironment e))) return result; using ExecutionEnvironment env = e; @@ -261,9 +276,9 @@ protected virtual TransactionResult Execute(Transaction tx, ITxTracer tracer, Ex : TransactionResult.Ok; } - protected virtual TransactionResult CalculateAvailableGas(Transaction tx, IntrinsicGas intrinsicGas, out long gasAvailable) + protected virtual TransactionResult CalculateAvailableGas(Transaction tx, in IntrinsicGas intrinsicGas, out TGasPolicy gasAvailable) { - gasAvailable = tx.GasLimit - intrinsicGas.Standard; + gasAvailable = TGasPolicy.CreateAvailableFromIntrinsic(tx.GasLimit, intrinsicGas.Standard); return TransactionResult.Ok; } @@ -380,7 +395,7 @@ protected virtual TransactionResult ValidateStatic( BlockHeader header, IReleaseSpec spec, ExecutionOptions opts, - in IntrinsicGas intrinsicGas) + in IntrinsicGas intrinsicGas) { bool validate = !opts.HasFlag(ExecutionOptions.SkipValidation); @@ -408,7 +423,7 @@ protected virtual TransactionResult ValidateStatic( return TransactionResult.TransactionSizeOverMaxInitCodeSize; } - return ValidateGas(tx, header, intrinsicGas.MinimalGas); + return ValidateGas(tx, header, TGasPolicy.GetRemainingGas(intrinsicGas.MinimalGas)); } protected virtual TransactionResult ValidateGas(Transaction tx, BlockHeader header, long minGasRequired) @@ -468,8 +483,8 @@ protected virtual bool RecoverSenderIfNeeded(Transaction tx, IReleaseSpec spec, return deleteCallerAccount; } - protected virtual IntrinsicGas CalculateIntrinsicGas(Transaction tx, IReleaseSpec spec) - => IntrinsicGasCalculator.Calculate(tx, spec); + protected virtual IntrinsicGas CalculateIntrinsicGas(Transaction tx, IReleaseSpec spec) + => IntrinsicGasCalculator.Calculate(tx, spec); protected virtual UInt256 CalculateEffectiveGasPrice(Transaction tx, bool eip1559Enabled, in UInt256 baseFee, out UInt256 opcodeGasPrice) { @@ -643,9 +658,9 @@ private int ExecuteEvmCall( ITxTracer tracer, ExecutionOptions opts, int delegationRefunds, - IntrinsicGas gas, + IntrinsicGas gas, in StackAccessTracker accessedItems, - long gasAvailable, + TGasPolicy gasAvailable, ExecutionEnvironment env, out TransactionSubstate substate, out GasConsumed gasConsumed) @@ -674,20 +689,21 @@ private int ExecuteEvmCall( { // If EOF header parsing or full container validation fails, transaction is considered valid and failing. // Gas for initcode execution is not consumed, only intrinsic creation transaction costs are charged. - gasConsumed = gas.MinimalGas; + long minimalGasLong = TGasPolicy.GetRemainingGas(gas.MinimalGas); + gasConsumed = minimalGasLong; // If noValidation we didn't charge for gas, so do not refund; otherwise return unspent gas if (!opts.HasFlag(ExecutionOptions.SkipValidation)) - WorldState.AddToBalance(tx.SenderAddress!, (ulong)(tx.GasLimit - gas.MinimalGas) * VirtualMachine.TxExecutionContext.GasPrice, spec); + WorldState.AddToBalance(tx.SenderAddress!, (ulong)(tx.GasLimit - minimalGasLong) * VirtualMachine.TxExecutionContext.GasPrice, spec); goto Complete; } ExecutionType executionType = tx.IsContractCreation ? ((spec.IsEofEnabled && tx.IsEofContractCreation) ? ExecutionType.TXCREATE : ExecutionType.CREATE) : ExecutionType.TRANSACTION; - using (EvmState state = EvmState.RentTopLevel(gasAvailable, executionType, env, in accessedItems, in snapshot)) + using (VmState state = VmState.RentTopLevel(gasAvailable, executionType, env, in accessedItems, in snapshot)) { substate = VirtualMachine.ExecuteTransaction(state, WorldState, tracer); Metrics.IncrementOpCodes(VirtualMachine.OpCodeCount); - gasAvailable = state.GasAvailable; + gasAvailable = state.Gas; if (tracer.IsTracingAccess) { @@ -755,10 +771,10 @@ protected virtual GasConsumed RefundOnFailContractCreation(Transaction tx, Block return tx.GasLimit; } - protected virtual bool DeployLegacyContract(IReleaseSpec spec, Address codeOwner, in TransactionSubstate substate, in StackAccessTracker accessedItems, ref long unspentGas) + protected virtual bool DeployLegacyContract(IReleaseSpec spec, Address codeOwner, in TransactionSubstate substate, in StackAccessTracker accessedItems, ref TGasPolicy unspentGas) { long codeDepositGasCost = CodeDepositHandler.CalculateCost(spec, substate.Output.Bytes.Length); - if (unspentGas < codeDepositGasCost && spec.ChargeForTopLevelCreate) + if (TGasPolicy.GetRemainingGas(unspentGas) < codeDepositGasCost && spec.ChargeForTopLevelCreate) { return false; } @@ -768,7 +784,7 @@ protected virtual bool DeployLegacyContract(IReleaseSpec spec, Address codeOwner return false; } - if (unspentGas >= codeDepositGasCost) + if (TGasPolicy.GetRemainingGas(unspentGas) >= codeDepositGasCost) { // Copy the bytes so it's not live memory that will be used in another tx byte[] code = substate.Output.Bytes.ToArray(); @@ -778,20 +794,20 @@ protected virtual bool DeployLegacyContract(IReleaseSpec spec, Address codeOwner accessedItems.WarmUpLargeContract(codeOwner); } - unspentGas -= codeDepositGasCost; + TGasPolicy.Consume(ref unspentGas, codeDepositGasCost); } return true; } - private bool DeployEofContract(IReleaseSpec spec, Address codeOwner, in TransactionSubstate substate, in StackAccessTracker accessedItems, ref long unspentGas) + private bool DeployEofContract(IReleaseSpec spec, Address codeOwner, in TransactionSubstate substate, in StackAccessTracker accessedItems, ref TGasPolicy unspentGas) { // 1 - load deploy EOF subContainer at deploy_container_index in the container from which RETURNCODE is executed ReadOnlySpan auxExtraData = substate.Output.Bytes.Span; EofCodeInfo deployCodeInfo = (EofCodeInfo)substate.Output.DeployCode; long codeDepositGasCost = CodeDepositHandler.CalculateCost(spec, deployCodeInfo.Code.Length + auxExtraData.Length); - if (unspentGas < codeDepositGasCost && spec.ChargeForTopLevelCreate) + if (TGasPolicy.GetRemainingGas(unspentGas) < codeDepositGasCost && spec.ChargeForTopLevelCreate) { return false; } @@ -820,7 +836,7 @@ private bool DeployEofContract(IReleaseSpec spec, Address codeOwner, in Transact bytecodeResult[dataSubHeaderSectionStart + 1] = (byte)(dataSize >> 8); bytecodeResult[dataSubHeaderSectionStart + 2] = (byte)(dataSize & 0xFF); - if (unspentGas >= codeDepositGasCost) + if (TGasPolicy.GetRemainingGas(unspentGas) >= codeDepositGasCost) { // 4 - set state[new_address].code to the updated deploy container // push new_address onto the stack (already done before the ifs) @@ -829,7 +845,7 @@ private bool DeployEofContract(IReleaseSpec spec, Address codeOwner, in Transact { accessedItems.WarmUpLargeContract(codeOwner); } - unspentGas -= codeDepositGasCost; + TGasPolicy.Consume(ref unspentGas, codeDepositGasCost); } return true; @@ -889,14 +905,14 @@ protected void TraceLogInvalidTx(Transaction transaction, string reason) } protected virtual GasConsumed Refund(Transaction tx, BlockHeader header, IReleaseSpec spec, ExecutionOptions opts, - in TransactionSubstate substate, in long unspentGas, in UInt256 gasPrice, int codeInsertRefunds, long floorGas) + in TransactionSubstate substate, in TGasPolicy unspentGas, in UInt256 gasPrice, int codeInsertRefunds, TGasPolicy floorGas) { long spentGas = tx.GasLimit; var codeInsertRefund = (GasCostOf.NewAccount - GasCostOf.PerAuthBaseCost) * codeInsertRefunds; if (!substate.IsError) { - spentGas -= unspentGas; + spentGas -= TGasPolicy.GetRemainingGas(unspentGas); long totalToRefund = codeInsertRefund; if (!substate.ShouldRevert) @@ -904,7 +920,7 @@ protected virtual GasConsumed Refund(Transaction tx, BlockHeader header, IReleas long actualRefund = CalculateClaimableRefund(spentGas, totalToRefund, spec); if (Logger.IsTrace) - Logger.Trace("Refunding unused gas of " + unspentGas + " and refund of " + actualRefund); + Logger.Trace("Refunding unused gas of " + TGasPolicy.GetRemainingGas(unspentGas) + " and refund of " + actualRefund); spentGas -= actualRefund; } else if (codeInsertRefund > 0) @@ -917,7 +933,7 @@ protected virtual GasConsumed Refund(Transaction tx, BlockHeader header, IReleas } long operationGas = spentGas; - spentGas = Math.Max(spentGas, floorGas); + spentGas = Math.Max(spentGas, TGasPolicy.GetRemainingGas(floorGas)); UInt256 refundAmount = (ulong)(tx.GasLimit - spentGas) * gasPrice; PayRefund(tx, refundAmount, spec); @@ -938,6 +954,18 @@ protected virtual long CalculateClaimableRefund(long spentGas, long totalRefund, private static void ThrowInvalidDataException(string message) => throw new InvalidDataException(message); } + /// + /// Non-generic TransactionProcessorBase for backward compatibility with EthereumGasPolicy. + /// + public abstract class EthereumTransactionProcessorBase( + ITransactionProcessor.IBlobBaseFeeCalculator? blobBaseFeeCalculator, + ISpecProvider? specProvider, + IWorldState? worldState, + IVirtualMachine? virtualMachine, + ICodeInfoRepository? codeInfoRepository, + ILogManager? logManager) + : TransactionProcessorBase(blobBaseFeeCalculator, specProvider, worldState, virtualMachine, codeInfoRepository, logManager); + public readonly struct TransactionResult : IEquatable { private TransactionResult(ErrorType error = ErrorType.None, EvmExceptionType evmException = EvmExceptionType.None) diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.Warmup.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.Warmup.cs index c86f1b39aa8..8d50611b3f7 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.Warmup.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.Warmup.cs @@ -10,6 +10,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Evm.CodeAnalysis; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.State; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; @@ -20,15 +21,14 @@ namespace Nethermind.Evm; -using unsafe OpCode = delegate*; - -public unsafe partial class VirtualMachine +public unsafe partial class VirtualMachine + where TGasPolicy : struct, IGasPolicy { public static void WarmUpEvmInstructions(IWorldState state, ICodeInfoRepository codeInfoRepository) { IReleaseSpec spec = Fork.GetLatest(); IBlockhashProvider hashProvider = new WarmupBlockhashProvider(MainnetSpecProvider.Instance); - VirtualMachine vm = new(hashProvider, MainnetSpecProvider.Instance, LimboLogs.Instance); + VirtualMachine vm = new(hashProvider, MainnetSpecProvider.Instance, LimboLogs.Instance); ILogManager lm = new OneLoggerLogManager(NullLogger.Instance); byte[] bytecode = new byte[64]; @@ -54,24 +54,24 @@ public static void WarmUpEvmInstructions(IWorldState state, ICodeInfoRepository value: 0, inputData: default); - using (EvmState evmState = EvmState.RentTopLevel(long.MaxValue, ExecutionType.TRANSACTION, env, new StackAccessTracker(), state.TakeSnapshot())) + using (VmState vmState = VmState.RentTopLevel(TGasPolicy.FromLong(long.MaxValue), ExecutionType.TRANSACTION, env, new StackAccessTracker(), state.TakeSnapshot())) { - vm.EvmState = evmState; + vm.VmState = vmState; vm._worldState = state; vm._codeInfoRepository = codeInfoRepository; - evmState.InitializeStacks(); + vmState.InitializeStacks(); - RunOpCodes(vm, state, evmState, spec); - RunOpCodes(vm, state, evmState, spec); + RunOpCodes(vm, state, vmState, spec); + RunOpCodes(vm, state, vmState, spec); } - TransactionProcessor processor = new(BlobBaseFeeCalculator.Instance, MainnetSpecProvider.Instance, state, vm, codeInfoRepository, lm); + TransactionProcessor processor = new(BlobBaseFeeCalculator.Instance, MainnetSpecProvider.Instance, state, vm, codeInfoRepository, lm); processor.SetBlockExecutionContext(new BlockExecutionContext(header, spec)); RunTransactions(processor, state, spec); } - private static void RunTransactions(TransactionProcessor processor, IWorldState state, IReleaseSpec spec) + private static void RunTransactions(TransactionProcessor processor, IWorldState state, IReleaseSpec spec) { const int WarmUpIterations = 40; @@ -147,16 +147,16 @@ static void AddPrecompileCall(List codeToDeploy) codeToDeploy.Add((byte)Instruction.POP); } - private static void RunOpCodes(VirtualMachine vm, IWorldState state, EvmState evmState, IReleaseSpec spec) + private static void RunOpCodes(VirtualMachine vm, IWorldState state, VmState vmState, IReleaseSpec spec) where TTracingInst : struct, IFlag { const int WarmUpIterations = 40; - OpCode[] opcodes = vm.GenerateOpCodes(spec); + var opcodes = vm.GenerateOpCodes(spec); ITxTracer txTracer = new FeesTracer(); vm._txTracer = txTracer; - EvmStack stack = new(0, txTracer, evmState.DataStack); - long gas = long.MaxValue; + EvmStack stack = new(0, txTracer, vmState.DataStack); + TGasPolicy gas = TGasPolicy.FromLong(long.MaxValue); int pc = 0; for (int repeat = 0; repeat < WarmUpIterations; repeat++) @@ -172,15 +172,15 @@ private static void RunOpCodes(VirtualMachine vm, IWorldState stat stack.PushOne(); opcodes[i](vm, ref stack, ref gas, ref pc); - if (vm.ReturnData is EvmState returnState) + if (vm.ReturnData is VmState returnState) { returnState.Dispose(); vm.ReturnData = null!; } state.Reset(resetBlockChanges: true); - stack = new(0, txTracer, evmState.DataStack); - gas = long.MaxValue; + stack = new(0, txTracer, vmState.DataStack); + gas = TGasPolicy.FromLong(long.MaxValue); pc = 0; } } diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index ceef34f926c..f4d8202ec38 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -15,12 +15,14 @@ using Nethermind.Core.Specs; using Nethermind.Evm.CodeAnalysis; using Nethermind.Evm.EvmObjectFormat.Handlers; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.Precompiles; using Nethermind.Evm.Tracing; using Nethermind.Logging; using Nethermind.Evm.State; using static Nethermind.Evm.EvmObjectFormat.EofValidator; +using static Nethermind.Evm.VirtualMachineStatics; #if DEBUG using Nethermind.Evm.Tracing.Debugger; @@ -29,32 +31,33 @@ [assembly: InternalsVisibleTo("Nethermind.Evm.Test")] namespace Nethermind.Evm; -using unsafe OpCode = delegate*; using Int256; public sealed class EthereumVirtualMachine( IBlockhashProvider? blockHashProvider, ISpecProvider? specProvider, ILogManager? logManager -) : VirtualMachine(blockHashProvider, specProvider, logManager) +) : VirtualMachine(blockHashProvider, specProvider, logManager), IVirtualMachine { } -public unsafe partial class VirtualMachine( - IBlockhashProvider? blockHashProvider, - ISpecProvider? specProvider, - ILogManager? logManager) : IVirtualMachine +/// +/// Static fields shared across all VirtualMachine generic instantiations. +/// Moved out of the generic class to avoid duplication per type parameter. +/// +public static class VirtualMachineStatics { public const int MaxCallDepth = Eof1.RETURN_STACK_MAX_HEIGHT; - private static readonly UInt256 P255Int = (UInt256)BigInteger.Pow(2, 255); - internal static readonly byte[] EofHash256 = KeccakHash.ComputeHashBytes(MAGIC); - internal static ref readonly UInt256 P255 => ref P255Int; - internal static readonly UInt256 BigInt256 = 256; - internal static readonly UInt256 BigInt32 = 32; - internal static readonly byte[] BytesZero = [0]; + public static readonly UInt256 P255Int = (UInt256)BigInteger.Pow(2, 255); + public static readonly byte[] EofHash256 = KeccakHash.ComputeHashBytes(EvmObjectFormat.EofValidator.MAGIC); + public static ref readonly UInt256 P255 => ref P255Int; + public static readonly UInt256 BigInt256 = 256; + public static readonly UInt256 BigInt32 = 32; + + public static readonly byte[] BytesZero = [0]; - internal static readonly byte[] BytesZero32 = + public static readonly byte[] BytesZero32 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -62,7 +65,7 @@ public unsafe partial class VirtualMachine( 0, 0, 0, 0, 0, 0, 0, 0 }; - internal static readonly byte[] BytesMax32 = + public static readonly byte[] BytesMax32 = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, @@ -70,15 +73,22 @@ public unsafe partial class VirtualMachine( 255, 255, 255, 255, 255, 255, 255, 255 }; - internal static readonly PrecompileExecutionFailureException PrecompileExecutionFailureException = new(); - internal static readonly OutOfGasException PrecompileOutOfGasException = new(); + public static readonly PrecompileExecutionFailureException PrecompileExecutionFailureException = new(); + public static readonly OutOfGasException PrecompileOutOfGasException = new(); +} +public unsafe partial class VirtualMachine( + IBlockhashProvider? blockHashProvider, + ISpecProvider? specProvider, + ILogManager? logManager) : IVirtualMachine + where TGasPolicy : struct, IGasPolicy +{ private readonly ValueHash256 _chainId = ((UInt256)specProvider.ChainId).ToValueHash(); private readonly IBlockhashProvider _blockHashProvider = blockHashProvider ?? throw new ArgumentNullException(nameof(blockHashProvider)); protected readonly ISpecProvider _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); protected readonly ILogger _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - protected readonly Stack _stateStack = new(); + protected readonly Stack> _stateStack = new(); protected IWorldState _worldState; private (Address Address, bool ShouldDelete) _parityTouchBugAccount = (Address.FromNumber(3), false); @@ -87,11 +97,11 @@ public unsafe partial class VirtualMachine( private ICodeInfoRepository _codeInfoRepository; - private OpCode[] _opcodeMethods; + private delegate*, ref EvmStack, ref TGasPolicy, ref int, EvmExceptionType>[] _opcodeMethods; private static long _txCount; private ReadOnlyMemory _returnDataBuffer = Array.Empty(); - protected EvmState _currentState; + protected VmState _currentState; protected ReadOnlyMemory? _previousCallResult; protected UInt256 _previousCallOutputDestination; @@ -104,7 +114,7 @@ public unsafe partial class VirtualMachine( public ref ReadOnlyMemory ReturnDataBuffer => ref _returnDataBuffer; public object ReturnData { get; set; } public IBlockhashProvider BlockHashProvider => _blockHashProvider; - protected Stack StateStack => _stateStack; + protected Stack> StateStack => _stateStack; private BlockExecutionContext _blockExecutionContext; public void SetBlockExecutionContext(in BlockExecutionContext blockExecutionContext) => _blockExecutionContext = blockExecutionContext; @@ -117,7 +127,7 @@ public unsafe partial class VirtualMachine( /// public void SetTxExecutionContext(in TxExecutionContext txExecutionContext) => _txExecutionContext = txExecutionContext; - public EvmState EvmState { get => _currentState; protected set => _currentState = value; } + public VmState VmState { get => _currentState; protected set => _currentState = value; } public int SectionIndex { get; set; } public int OpCodeCount { get; set; } @@ -129,7 +139,7 @@ public unsafe partial class VirtualMachine( /// /// The type of tracing instructions flag used to conditionally trace execution actions. /// - /// The initial EVM state to begin transaction execution. + /// The initial EVM state to begin transaction execution. /// The current world state that may be modified during execution. /// An object used to record execution details and trace transaction actions. /// @@ -139,7 +149,7 @@ public unsafe partial class VirtualMachine( /// Thrown when an EVM-specific error occurs during execution. /// public virtual TransactionSubstate ExecuteTransaction( - EvmState evmState, + VmState vmState, IWorldState worldState, ITxTracer txTracer) where TTracingInst : struct, IFlag @@ -154,7 +164,7 @@ public virtual TransactionSubstate ExecuteTransaction( OpCodeCount = 0; // Initialize the code repository and set up the initial execution state. _codeInfoRepository = TxExecutionContext.CodeInfoRepository; - _currentState = evmState; + _currentState = vmState; _previousCallResult = null; _previousCallOutputDestination = UInt256.Zero; ZeroPaddedSpan previousCallOutput = ZeroPaddedSpan.Empty; @@ -239,18 +249,18 @@ public virtual TransactionSubstate ExecuteTransaction( } // For nested call frames, merge the results and restore the previous execution state. - using (EvmState previousState = _currentState) + using (VmState previousState = _currentState) { // Restore the previous state from the stack and mark it as a continuation. _currentState = _stateStack.Pop(); _currentState.IsContinuation = true; // Refund the remaining gas from the completed call frame. - _currentState.GasAvailable += previousState.GasAvailable; + TGasPolicy.Refund(ref _currentState.Gas, in previousState.Gas); bool previousStateSucceeded = true; if (!callResult.ShouldRevert) { - long gasAvailableForCodeDeposit = previousState.GasAvailable; + long gasAvailableForCodeDeposit = TGasPolicy.GetRemainingGas(previousState.Gas); // Process contract creation calls differently from regular calls. if (previousState.ExecutionType.IsAnyCreate()) @@ -314,7 +324,7 @@ public virtual TransactionSubstate ExecuteTransaction( } } - protected void PrepareCreateData(EvmState previousState, ref ZeroPaddedSpan previousCallOutput) + protected void PrepareCreateData(VmState previousState, ref ZeroPaddedSpan previousCallOutput) { _previousCallResult = previousState.Env.ExecutingAccount.Bytes; _previousCallOutputDestination = UInt256.Zero; @@ -322,7 +332,7 @@ protected void PrepareCreateData(EvmState previousState, ref ZeroPaddedSpan prev previousCallOutput = ZeroPaddedSpan.Empty; } - protected ZeroPaddedSpan HandleRegularReturn(scoped in CallResult callResult, EvmState previousState) + protected ZeroPaddedSpan HandleRegularReturn(scoped in CallResult callResult, VmState previousState) where TTracingInst : struct, IFlag { ZeroPaddedSpan previousCallOutput; @@ -344,13 +354,13 @@ protected ZeroPaddedSpan HandleRegularReturn(scoped in CallResult if (_txTracer.IsTracingActions) { - _txTracer.ReportActionEnd(previousState.GasAvailable, ReturnDataBuffer); + _txTracer.ReportActionEnd(TGasPolicy.GetRemainingGas(previousState.Gas), ReturnDataBuffer); } return previousCallOutput; } - protected void HandleEofCreate(in CallResult callResult, EvmState previousState, long gasAvailableForCodeDeposit, ref bool previousStateSucceeded) + protected void HandleEofCreate(in CallResult callResult, VmState previousState, long gasAvailableForCodeDeposit, ref bool previousStateSucceeded) { Address callCodeOwner = previousState.Env.ExecutingAccount; // ReturnCode was called with a container index and auxdata @@ -399,16 +409,16 @@ protected void HandleEofCreate(in CallResult callResult, EvmState previousState, // 4 - set state[new_address].code to the updated deploy container // push new_address onto the stack (already done before the ifs) _codeInfoRepository.InsertCode(bytecodeResultArray, callCodeOwner, spec); - _currentState.GasAvailable -= codeDepositGasCost; + TGasPolicy.Consume(ref _currentState.Gas, codeDepositGasCost); if (_txTracer.IsTracingActions) { - _txTracer.ReportActionEnd(previousState.GasAvailable - codeDepositGasCost, callCodeOwner, bytecodeResultArray); + _txTracer.ReportActionEnd(TGasPolicy.GetRemainingGas(previousState.Gas) - codeDepositGasCost, callCodeOwner, bytecodeResultArray); } } else if (spec.FailOnOutOfGasCodeDeposit || invalidCode) { - _currentState.GasAvailable -= gasAvailableForCodeDeposit; + TGasPolicy.Consume(ref _currentState.Gas, gasAvailableForCodeDeposit); _worldState.Restore(previousState.Snapshot); if (!previousState.IsCreateOnPreExistingAccount) { @@ -452,7 +462,7 @@ protected void HandleEofCreate(in CallResult callResult, EvmState previousState, /// protected void HandleLegacyCreate( in CallResult callResult, - EvmState previousState, + VmState previousState, long gasAvailableForCodeDeposit, ref bool previousStateSucceeded) { @@ -477,19 +487,19 @@ protected void HandleLegacyCreate( _codeInfoRepository.InsertCode(code, callCodeOwner, spec); // Deduct the gas cost for the code deposit from the current state's available gas. - _currentState.GasAvailable -= codeDepositGasCost; + TGasPolicy.Consume(ref _currentState.Gas, codeDepositGasCost); // If tracing is enabled, report the successful code deposit operation. if (isTracing) { - _txTracer.ReportActionEnd(previousState.GasAvailable - codeDepositGasCost, callCodeOwner, callResult.Output.Bytes); + _txTracer.ReportActionEnd(TGasPolicy.GetRemainingGas(previousState.Gas) - codeDepositGasCost, callCodeOwner, callResult.Output.Bytes); } } // If the code deposit should fail due to out-of-gas or invalid code conditions... else if (spec.FailOnOutOfGasCodeDeposit || invalidCode) { // Consume all remaining gas allocated for the code deposit. - _currentState.GasAvailable -= gasAvailableForCodeDeposit; + TGasPolicy.Consume(ref _currentState.Gas, gasAvailableForCodeDeposit); // Roll back the world state to its snapshot from before the creation attempt. _worldState.Restore(previousState.Snapshot); @@ -516,7 +526,7 @@ protected void HandleLegacyCreate( // report the end of the action if tracing is enabled. else if (isTracing) { - _txTracer.ReportActionEnd(previousState.GasAvailable - codeDepositGasCost, callCodeOwner, callResult.Output.Bytes); + _txTracer.ReportActionEnd(TGasPolicy.GetRemainingGas(previousState.Gas) - codeDepositGasCost, callCodeOwner, callResult.Output.Bytes); } } @@ -550,7 +560,7 @@ protected TransactionSubstate PrepareTopLevelSubstate(scoped in CallResult callR /// A reference to the output data buffer that will be updated with the reverted call's output, /// padded to match the expected length. /// - protected void HandleRevert(EvmState previousState, in CallResult callResult, ref ZeroPaddedSpan previousCallOutput) + protected void HandleRevert(VmState previousState, in CallResult callResult, ref ZeroPaddedSpan previousCallOutput) { // Restore the world state to the snapshot taken before the execution of the call. _worldState.Restore(previousState.Snapshot); @@ -580,7 +590,7 @@ protected void HandleRevert(EvmState previousState, in CallResult callResult, re // If transaction tracing is enabled, report the revert action along with the available gas and output bytes. if (_txTracer.IsTracingActions) { - _txTracer.ReportActionRevert(previousState.GasAvailable, outputBytes); + _txTracer.ReportActionRevert(TGasPolicy.GetRemainingGas(previousState.Gas), outputBytes); } } @@ -770,13 +780,13 @@ protected TransactionSubstate HandleException(scoped in CallResult callResult, s /// A containing the results of the precompile execution. In case of a failure, /// returns the default value of . /// - protected virtual CallResult ExecutePrecompile(EvmState currentState, bool isTracingActions, out Exception? failure, out string? substateError) + protected virtual CallResult ExecutePrecompile(VmState currentState, bool isTracingActions, out Exception? failure, out string? substateError) { // Report the precompile action if tracing is enabled. if (isTracingActions) { _txTracer.ReportAction( - currentState.GasAvailable, + TGasPolicy.GetRemainingGas(currentState.Gas), currentState.Env.Value, currentState.From, currentState.To, @@ -803,12 +813,12 @@ protected virtual CallResult ExecutePrecompile(EvmState currentState, bool isTra // If running a precompile on a top-level call frame, and it fails, assign a general execution failure. if (currentState.IsPrecompile && currentState.IsTopLevel) { - failure = PrecompileExecutionFailureException; + failure = VirtualMachineStatics.PrecompileExecutionFailureException; goto Failure; } // Otherwise, if no exception but precompile did not succeed, exhaust the remaining gas. - currentState.GasAvailable = 0; + TGasPolicy.SetOutOfGas(ref currentState.Gas); } // If execution reaches here, the precompile operation is considered successful. @@ -822,9 +832,9 @@ protected virtual CallResult ExecutePrecompile(EvmState currentState, bool isTra } - protected void TraceTransactionActionStart(EvmState currentState) + protected void TraceTransactionActionStart(VmState currentState) { - _txTracer.ReportAction(currentState.GasAvailable, + _txTracer.ReportAction(TGasPolicy.GetRemainingGas(currentState.Gas), currentState.Env.Value, currentState.From, currentState.To, @@ -868,18 +878,18 @@ private void PrepareOpcodes(IReleaseSpec spec) spec.EvmInstructionsNoTrace = GenerateOpCodes(spec); } // Ensure the non-traced opcode set is generated and assign it to the _opcodeMethods field. - _opcodeMethods = (OpCode[])(spec.EvmInstructionsNoTrace ??= GenerateOpCodes(spec)); + _opcodeMethods = (delegate*, ref EvmStack, ref TGasPolicy, ref int, EvmExceptionType>[])(spec.EvmInstructionsNoTrace ??= GenerateOpCodes(spec)); } else { // For tracing-enabled execution, generate (if necessary) and cache the traced opcode set. - _opcodeMethods = (OpCode[])(spec.EvmInstructionsTraced ??= GenerateOpCodes(spec)); + _opcodeMethods = (delegate*, ref EvmStack, ref TGasPolicy, ref int, EvmExceptionType>[])(spec.EvmInstructionsTraced ??= GenerateOpCodes(spec)); } } - protected virtual OpCode[] GenerateOpCodes(IReleaseSpec spec) + protected virtual delegate*, ref EvmStack, ref TGasPolicy, ref int, EvmExceptionType>[] GenerateOpCodes(IReleaseSpec spec) where TTracingInst : struct, IFlag - => EvmInstructions.GenerateOpCodes(spec); + => EvmInstructions.GenerateOpCodes(spec); /// /// Reports the final outcome of a transaction action to the transaction tracer, taking into account @@ -895,7 +905,7 @@ protected virtual OpCode[] GenerateOpCodes(IReleaseSpec spec) /// /// The result of the executed call, including output bytes, exception and revert flags, and additional metadata. /// - protected void TraceTransactionActionEnd(EvmState currentState, in CallResult callResult) + protected void TraceTransactionActionEnd(VmState currentState, in CallResult callResult) { IReleaseSpec spec = BlockExecutionContext.Spec; // Calculate the gas cost required for depositing the contract code based on the length of the output. @@ -913,14 +923,16 @@ protected void TraceTransactionActionEnd(EvmState currentState, in CallResult ca else if (callResult.ShouldRevert) { // For creation operations, subtract the code deposit cost from the available gas; otherwise, use full gas. - long reportedGas = currentState.ExecutionType.IsAnyCreate() ? currentState.GasAvailable - codeDepositGasCost : currentState.GasAvailable; + long gasAvailable = TGasPolicy.GetRemainingGas(currentState.Gas); + long reportedGas = currentState.ExecutionType.IsAnyCreate() ? gasAvailable - codeDepositGasCost : gasAvailable; _txTracer.ReportActionRevert(reportedGas, outputBytes); } // Process contract creation flows. else if (currentState.ExecutionType.IsAnyCreate()) { + long gasAvailable = TGasPolicy.GetRemainingGas(currentState.Gas); // If available gas is insufficient to cover the code deposit cost... - if (currentState.GasAvailable < codeDepositGasCost) + if (gasAvailable < codeDepositGasCost) { // When the spec mandates charging for top-level creation, report an out-of-gas error. if (spec.ChargeForTopLevelCreate) @@ -930,7 +942,7 @@ protected void TraceTransactionActionEnd(EvmState currentState, in CallResult ca // Otherwise, report a successful action end with the remaining gas. else { - _txTracer.ReportActionEnd(currentState.GasAvailable, currentState.To, outputBytes); + _txTracer.ReportActionEnd(gasAvailable, currentState.To, outputBytes); } } // If the generated code is invalid (e.g., violates EIP-3541 by starting with 0xEF), report an invalid code error. @@ -941,13 +953,13 @@ protected void TraceTransactionActionEnd(EvmState currentState, in CallResult ca // In the successful contract creation case, deduct the code deposit gas cost and report a normal action end. else { - _txTracer.ReportActionEnd(currentState.GasAvailable - codeDepositGasCost, currentState.To, outputBytes); + _txTracer.ReportActionEnd(gasAvailable - codeDepositGasCost, currentState.To, outputBytes); } } // For non-creation calls, report the action end using the current available gas and the standard return data. else { - _txTracer.ReportActionEnd(currentState.GasAvailable, ReturnDataBuffer); + _txTracer.ReportActionEnd(TGasPolicy.GetRemainingGas(currentState.Gas), ReturnDataBuffer); } } @@ -964,22 +976,11 @@ private void RevertParityTouchBugAccount() } } - protected static bool UpdateGas(long gasCost, ref long gasAvailable) - { - if (gasAvailable < gasCost) - { - return false; - } - - gasAvailable -= gasCost; - return true; - } - - private CallResult RunPrecompile(EvmState state) + private CallResult RunPrecompile(VmState state) { ReadOnlyMemory callData = state.Env.InputData; - ref readonly UInt256 transferValue = ref state.Env.TransferValue; - long gasAvailable = state.GasAvailable; + UInt256 transferValue = state.Env.TransferValue; + TGasPolicy gas = state.Gas; IPrecompile precompile = state.Env.CodeInfo.Precompile!; @@ -1006,12 +1007,12 @@ private CallResult RunPrecompile(EvmState state) } if ((ulong)baseGasCost + (ulong)dataGasCost > (ulong)long.MaxValue || - !UpdateGas(baseGasCost + dataGasCost, ref gasAvailable)) + !TGasPolicy.UpdateGas(ref gas, baseGasCost + dataGasCost)) { return new(output: default, precompileSuccess: false, fromVersion: 0, shouldRevert: true, EvmExceptionType.OutOfGas); } - state.GasAvailable = gasAvailable; + state.Gas = gas; try { @@ -1090,7 +1091,7 @@ protected CallResult ExecuteCall( scoped in UInt256 previousCallOutputDestination) where TTracingInst : struct, IFlag { - EvmState vmState = _currentState; + VmState vmState = _currentState; // Obtain a reference to the execution environment for convenience. ExecutionEnvironment env = vmState.Env; @@ -1126,7 +1127,7 @@ protected CallResult ExecuteCall( EvmStack stack = new(vmState.DataStackHead, _txTracer, AsAlignedSpan(vmState.DataStack, alignment: EvmStack.WordSize, size: StackPool.StackLength)); // Cache the available gas from the state for local use. - long gasAvailable = vmState.GasAvailable; + TGasPolicy gas = vmState.Gas; // If a previous call result exists, push its bytes onto the stack. if (previousCallResult is not null) @@ -1136,7 +1137,7 @@ protected CallResult ExecuteCall( // Report the remaining gas if tracing instructions are enabled. if (TTracingInst.IsActive) { - _txTracer.ReportOperationRemainingGas(vmState.GasAvailable); + _txTracer.ReportOperationRemainingGas(TGasPolicy.GetRemainingGas(vmState.Gas)); } } @@ -1147,7 +1148,7 @@ protected CallResult ExecuteCall( UInt256 localPreviousDest = previousCallOutputDestination; // Attempt to update the memory cost; if insufficient gas is available, jump to the out-of-gas handler. - if (!UpdateMemoryCost(vmState, ref gasAvailable, in localPreviousDest, (ulong)previousCallOutput.Length)) + if (!TGasPolicy.UpdateMemoryCost(ref gas, in localPreviousDest, (ulong)previousCallOutput.Length, vmState)) { goto OutOfGas; } @@ -1163,8 +1164,8 @@ protected CallResult ExecuteCall( // This leverages the compile-time evaluation of TTracingInst to optimize away runtime checks. return _txTracer.IsCancelable switch { - false => RunByteCode(ref stack, gasAvailable), - true => RunByteCode(ref stack, gasAvailable), + false => RunByteCode(ref stack, ref gas), + true => RunByteCode(ref stack, ref gas), }; Empty: @@ -1189,10 +1190,10 @@ protected CallResult ExecuteCall( /// A struct implementing that indicates at compile time whether cancellation support is enabled. /// /// - /// A reference to the current EVM stack used for execution. + /// A reference to the current EVM stack used for execution. /// - /// - /// The amount of gas available for executing the bytecode. + /// + /// The gas state to update /// /// /// A that encapsulates the outcome of the execution, which can be a successful result, @@ -1205,32 +1206,33 @@ protected CallResult ExecuteCall( [SkipLocalsInit] protected virtual unsafe CallResult RunByteCode( scoped ref EvmStack stack, - long gasAvailable) + scoped ref TGasPolicy gas) where TTracingInst : struct, IFlag where TCancelable : struct, IFlag { // Reset return data and set the current section index from the VM state. ReturnData = null; - SectionIndex = EvmState.FunctionIndex; + SectionIndex = VmState.FunctionIndex; // Retrieve the code information and create a read-only span of instructions. - ICodeInfo codeInfo = EvmState.Env.CodeInfo; + ICodeInfo codeInfo = VmState.Env.CodeInfo; ReadOnlySpan codeSection = GetInstructions(codeInfo); // Initialize the exception type to "None". EvmExceptionType exceptionType = EvmExceptionType.None; #if DEBUG // In debug mode, retrieve a tracer for interactive debugging. - DebugTracer? debugger = _txTracer.GetTracer(); + DebugTracer? debugger = _txTracer.GetTracer>(); #endif // Set the program counter from the current VM state; it may not be zero if resuming after a call. - int programCounter = EvmState.ProgramCounter; + int programCounter = VmState.ProgramCounter; - // Pin the opcode methods array to obtain a fixed pointer, avoiding repeated bounds checks and casts. - // If we don't use a pointer we have to cast for each call (delegate*<...> can't be used as a generic arg) - // Or have bounds checks (however only 256 opcodes and opcode is a byte so know always in bounds). - fixed (OpCode* opcodeMethods = &_opcodeMethods[0]) + // Pin the opcode methods array to obtain a fixed pointer, avoiding repeated bounds checks. + // If we don't use a pointer we have bounds checks (however only 256 opcodes and opcode is a byte so know always in bounds). + var opcodeArray = _opcodeMethods; + fixed (delegate*, ref EvmStack, ref TGasPolicy, ref int, EvmExceptionType>* + opcodeMethods = &opcodeArray[0]) { int opCodeCount = 0; ref Instruction code = ref MemoryMarshal.GetReference(codeSection); @@ -1239,7 +1241,7 @@ protected virtual unsafe CallResult RunByteCode( { #if DEBUG // Allow the debugger to inspect and possibly pause execution for debugging purposes. - debugger?.TryWait(ref _currentState, ref programCounter, ref gasAvailable, ref stack.Head); + debugger?.TryWait(ref _currentState, ref programCounter, ref gas, ref stack.Head); #endif // Fetch the current instruction from the code section. Instruction instruction = Unsafe.Add(ref code, programCounter); @@ -1250,7 +1252,7 @@ protected virtual unsafe CallResult RunByteCode( // If tracing is enabled, start an instruction trace. if (TTracingInst.IsActive) - StartInstructionTrace(instruction, gasAvailable, programCounter, in stack); + StartInstructionTrace(instruction, TGasPolicy.GetRemainingGas(in gas), programCounter, in stack); // Advance the program counter to point to the next instruction. programCounter++; @@ -1259,19 +1261,19 @@ protected virtual unsafe CallResult RunByteCode( // For the very common POP opcode, use an inlined implementation to reduce overhead. if (Instruction.POP == instruction) { - exceptionType = EvmInstructions.InstructionPop(this, ref stack, ref gasAvailable, ref programCounter); + exceptionType = EvmInstructions.InstructionPop(this, ref stack, ref gas, ref programCounter); } else { // Retrieve the opcode function pointer corresponding to the current instruction. - OpCode opcodeMethod = opcodeMethods[(int)instruction]; + var opcodeMethod = opcodeMethods[(int)instruction]; // Invoke the opcode method, which may modify the stack, gas, and program counter. // Is executed using fast delegate* via calli (see: C# function pointers https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/unsafe-code#function-pointers) - exceptionType = opcodeMethod(this, ref stack, ref gasAvailable, ref programCounter); + exceptionType = opcodeMethod(this, ref stack, ref gas, ref programCounter); } // If gas is exhausted, jump to the out-of-gas handler. - if (gasAvailable < 0) + if (TGasPolicy.GetRemainingGas(in gas) < 0) { OpCodeCount += opCodeCount; goto OutOfGas; @@ -1282,7 +1284,7 @@ protected virtual unsafe CallResult RunByteCode( // If tracing is enabled, complete the trace for the current instruction. if (TTracingInst.IsActive) - EndInstructionTrace(gasAvailable); + EndInstructionTrace(TGasPolicy.GetRemainingGas(in gas)); // If return data has been set, exit the loop to process the returned value. if (ReturnData is not null) @@ -1296,8 +1298,8 @@ protected virtual unsafe CallResult RunByteCode( { // If tracing is enabled, complete the trace for the current instruction. if (TTracingInst.IsActive) - EndInstructionTrace(gasAvailable); - UpdateCurrentState(programCounter, gasAvailable, stack.Head); + EndInstructionTrace(TGasPolicy.GetRemainingGas(in gas)); + UpdateCurrentState(programCounter, in gas, stack.Head); } else { @@ -1318,10 +1320,10 @@ protected virtual unsafe CallResult RunByteCode( DataReturn: #if DEBUG // Allow debugging before processing the return data. - debugger?.TryWait(ref _currentState, ref programCounter, ref gasAvailable, ref stack.Head); + debugger?.TryWait(ref _currentState, ref programCounter, ref gas, ref stack.Head); #endif // Process the return data based on its runtime type. - if (ReturnData is EvmState state) + if (ReturnData is VmState state) { return new CallResult(state); } @@ -1337,12 +1339,12 @@ protected virtual unsafe CallResult RunByteCode( return new CallResult(null, (byte[])ReturnData, null, codeInfo.Version, shouldRevert: true, exceptionType); OutOfGas: - gasAvailable = 0; + TGasPolicy.SetOutOfGas(ref gas); // Set the exception type to OutOfGas if gas has been exhausted. exceptionType = EvmExceptionType.OutOfGas; ReturnFailure: // Return a failure CallResult based on the remaining gas and the exception type. - return GetFailureReturn(gasAvailable, exceptionType); + return GetFailureReturn(TGasPolicy.GetRemainingGas(in gas), exceptionType); // Converts the code section bytes into a read-only span of instructions. // Lightest weight conversion as mostly just helpful when debugging to see what the opcodes are. @@ -1378,27 +1380,20 @@ private CallResult GetFailureReturn(long gasAvailable, EvmExceptionType exceptio }; } - private void UpdateCurrentState(int pc, long gas, int stackHead) + private void UpdateCurrentState(int pc, in TGasPolicy gas, int stackHead) { - EvmState state = EvmState; + VmState state = VmState; state.ProgramCounter = pc; - state.GasAvailable = gas; + state.Gas = gas; state.DataStackHead = stackHead; state.FunctionIndex = SectionIndex; } - private static bool UpdateMemoryCost(EvmState vmState, ref long gasAvailable, in UInt256 position, in UInt256 length) - { - long memoryCost = vmState.Memory.CalculateMemoryCost(in position, length, out bool outOfGas); - if (outOfGas) return false; - return memoryCost == 0L || UpdateGas(memoryCost, ref gasAvailable); - } - [MethodImpl(MethodImplOptions.NoInlining)] private void StartInstructionTrace(Instruction instruction, long gasAvailable, int programCounter, in EvmStack stackValue) { - EvmState vmState = EvmState; + VmState vmState = VmState; int sectionIndex = SectionIndex; bool isEofFrame = vmState.Env.CodeInfo.Version > 0; @@ -1458,3 +1453,11 @@ private void EndInstructionTraceError(long gasAvailable, EvmExceptionType evmExc _txTracer.ReportOperationError(evmExceptionType); } } + +/// +/// Non-generic VirtualMachine for backward compatibility with EthereumGasPolicy. +/// +public sealed class VirtualMachine( + IBlockhashProvider? blockHashProvider, + ISpecProvider? specProvider, + ILogManager? logManager) : VirtualMachine(blockHashProvider, specProvider, logManager), IVirtualMachine; diff --git a/src/Nethermind/Nethermind.Evm/EvmState.cs b/src/Nethermind/Nethermind.Evm/VmState.cs similarity index 88% rename from src/Nethermind/Nethermind.Evm/EvmState.cs rename to src/Nethermind/Nethermind.Evm/VmState.cs index b3459da4540..0636d957ba7 100644 --- a/src/Nethermind/Nethermind.Evm/EvmState.cs +++ b/src/Nethermind/Nethermind.Evm/VmState.cs @@ -7,6 +7,7 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Nethermind.Core; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.State; namespace Nethermind.Evm; @@ -15,9 +16,10 @@ namespace Nethermind.Evm; /// State for EVM Calls /// [DebuggerDisplay("{ExecutionType} to {Env.ExecutingAccount}, G {GasAvailable} R {Refund} PC {ProgramCounter} OUT {OutputDestination}:{OutputLength}")] -public sealed class EvmState : IDisposable // TODO: rename to CallState +public class VmState : IDisposable + where TGasPolicy : struct, IGasPolicy { - private static readonly ConcurrentQueue _statePool = new(); + private static readonly ConcurrentQueue> _statePool = new(); private static readonly StackPool _stackPool = new(); /* @@ -78,7 +80,7 @@ public sealed class EvmState : IDisposable // TODO: rename to CallState public byte[]? DataStack; public ReturnState[]? ReturnStack; - public long GasAvailable { get; set; } + public TGasPolicy Gas; internal long OutputDestination { get; private set; } // TODO: move to CallEnv internal long OutputLength { get; private set; } // TODO: move to CallEnv public long Refund { get; set; } @@ -101,18 +103,18 @@ public sealed class EvmState : IDisposable // TODO: rename to CallState private Snapshot _snapshot; /// - /// Rent a top level . + /// Rent a top level . /// - public static EvmState RentTopLevel( - long gasAvailable, + public static VmState RentTopLevel( + TGasPolicy gas, ExecutionType executionType, ExecutionEnvironment env, in StackAccessTracker accessedItems, in Snapshot snapshot) { - EvmState state = Rent(); + VmState state = Rent(); state.Initialize( - gasAvailable, + gas, outputDestination: 0L, outputLength: 0L, executionType: executionType, @@ -126,10 +128,10 @@ public static EvmState RentTopLevel( } /// - /// Constructor for a frame beneath top level. + /// Constructor for a frame beneath top level. /// - public static EvmState RentFrame( - long gasAvailable, + public static VmState RentFrame( + TGasPolicy gas, long outputDestination, long outputLength, ExecutionType executionType, @@ -140,9 +142,9 @@ public static EvmState RentFrame( in Snapshot snapshot, bool isTopLevel = false) { - EvmState state = Rent(); + VmState state = Rent(); state.Initialize( - gasAvailable, + gas, outputDestination, outputLength, executionType, @@ -155,12 +157,12 @@ public static EvmState RentFrame( return state; } - private static EvmState Rent() - => _statePool.TryDequeue(out EvmState state) ? state : new EvmState(); + private static VmState Rent() + => _statePool.TryDequeue(out VmState? state) ? state : new VmState(); [SkipLocalsInit] private void Initialize( - long gasAvailable, + TGasPolicy gas, long outputDestination, long outputLength, ExecutionType executionType, @@ -179,7 +181,7 @@ private void Initialize( _accessTracker.WasCreated(env.ExecutingAccount); } _accessTracker.TakeSnapshot(); - GasAvailable = gasAvailable; + Gas = gas; OutputDestination = outputDestination; OutputLength = outputLength; Refund = 0; @@ -223,8 +225,8 @@ ExecutionType.STATICCALL or ExecutionType.CALL or ExecutionType.CALLCODE or Exec public ref readonly StackAccessTracker AccessTracker => ref _accessTracker; public ExecutionEnvironment Env => _env!; - public ref EvmPooledMemory Memory => ref _memory; // TODO: move to CallEnv - public ref readonly Snapshot Snapshot => ref _snapshot; // TODO: move to CallEnv + public ref EvmPooledMemory Memory => ref _memory; + public ref readonly Snapshot Snapshot => ref _snapshot; public void Dispose() { @@ -266,11 +268,11 @@ public void Dispose() private StackTrace? _creationStackTrace; - ~EvmState() + ~VmState() { if (!_isDisposed) { - Console.Error.WriteLine($"Warning: {nameof(EvmState)} was not disposed. Created at: {_creationStackTrace}"); + Console.Error.WriteLine($"Warning: {nameof(VmState)} was not disposed. Created at: {_creationStackTrace}"); } } #endif @@ -284,17 +286,21 @@ public void InitializeStacks() } } - public void CommitToParent(EvmState parentState) + public void CommitToParent(VmState parentState) { ObjectDisposedException.ThrowIf(_isDisposed, this); parentState.Refund += Refund; _canRestore = false; // we can't restore if we committed } +} - public struct ReturnState - { - public int Index; - public int Offset; - public int Height; - } +/// +/// Return state for EVM call stack management. +/// +public struct ReturnState +{ + public int Index; + public int Offset; + public int Height; } + diff --git a/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs b/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs index b52ee357924..232d3d24c96 100644 --- a/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs @@ -46,10 +46,10 @@ protected override void Load(ContainerBuilder builder) // Block processing components common between rpc, validation and production .AddScoped() - .AddScoped() + .AddScoped() .AddScoped() .AddSingleton() - .AddScoped() + .AddScoped() .AddScoped() .AddSingleton() .AddScoped() diff --git a/src/Nethermind/Nethermind.Init/Steps/EvmWarmer.cs b/src/Nethermind/Nethermind.Init/Steps/EvmWarmer.cs index 41518e7914b..1256f090c0e 100644 --- a/src/Nethermind/Nethermind.Init/Steps/EvmWarmer.cs +++ b/src/Nethermind/Nethermind.Init/Steps/EvmWarmer.cs @@ -26,7 +26,7 @@ public Task Execute(CancellationToken cancellationToken) builder.AddModule(env); }); - VirtualMachine.WarmUpEvmInstructions(childContainerScope.Resolve(), childContainerScope.Resolve()); + EthereumVirtualMachine.WarmUpEvmInstructions(childContainerScope.Resolve(), childContainerScope.Resolve()); return Task.CompletedTask; } diff --git a/src/Nethermind/Nethermind.Optimism/OptimismBlockReceiptTracer.cs b/src/Nethermind/Nethermind.Optimism/OptimismBlockReceiptTracer.cs index 4d93eb4bf0a..ca828e25490 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismBlockReceiptTracer.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismBlockReceiptTracer.cs @@ -7,6 +7,7 @@ using Nethermind.Core.Crypto; using Nethermind.Evm.State; using Nethermind.Evm.Tracing; +using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Optimism; diff --git a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs index fef3c326ff7..2538b74c1ef 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs @@ -4,6 +4,7 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Evm; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.State; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; @@ -21,7 +22,7 @@ public class OptimismTransactionProcessor( ICostHelper costHelper, IOptimismSpecHelper opSpecHelper, ICodeInfoRepository? codeInfoRepository - ) : TransactionProcessorBase(blobBaseFeeCalculator, specProvider, worldState, virtualMachine, codeInfoRepository, logManager) + ) : EthereumTransactionProcessorBase(blobBaseFeeCalculator, specProvider, worldState, virtualMachine, codeInfoRepository, logManager) { private UInt256? _currentTxL1Cost; @@ -172,7 +173,7 @@ protected override void PayFees(Transaction tx, BlockHeader header, IReleaseSpec } protected override GasConsumed Refund(Transaction tx, BlockHeader header, IReleaseSpec spec, ExecutionOptions opts, - in TransactionSubstate substate, in long unspentGas, in UInt256 gasPrice, int codeInsertRefunds, long floorGas) + in TransactionSubstate substate, in EthereumGasPolicy unspentGas, in UInt256 gasPrice, int codeInsertRefunds, EthereumGasPolicy floorGas) { // if deposit: skip refunds, skip tipping coinbase // Regolith changes this behaviour to report the actual gasUsed instead of always reporting all gas used. diff --git a/src/Nethermind/Nethermind.Taiko.Test/TransactionProcessorTests.cs b/src/Nethermind/Nethermind.Taiko.Test/TransactionProcessorTests.cs index 2bb09f03b45..4272e260745 100644 --- a/src/Nethermind/Nethermind.Taiko.Test/TransactionProcessorTests.cs +++ b/src/Nethermind/Nethermind.Taiko.Test/TransactionProcessorTests.cs @@ -51,7 +51,7 @@ public void Setup() _stateProvider.CommitTree(0); EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); - VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); + EthereumVirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); _transactionProcessor = new TaikoTransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs b/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs index 1803ccf25fc..11b6fa4962f 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs @@ -5,6 +5,7 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Evm; +using Nethermind.Evm.GasPolicy; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; @@ -21,10 +22,10 @@ public class TaikoTransactionProcessor( IVirtualMachine virtualMachine, ICodeInfoRepository? codeInfoRepository, ILogManager? logManager - ) : TransactionProcessorBase(blobBaseFeeCalculator, specProvider, worldState, virtualMachine, codeInfoRepository, logManager) + ) : EthereumTransactionProcessorBase(blobBaseFeeCalculator, specProvider, worldState, virtualMachine, codeInfoRepository, logManager) { protected override TransactionResult ValidateStatic(Transaction tx, BlockHeader header, IReleaseSpec spec, ExecutionOptions opts, - in IntrinsicGas intrinsicGas) + in IntrinsicGas intrinsicGas) => base.ValidateStatic(tx, header, spec, tx.IsAnchorTx ? opts | ExecutionOptions.SkipValidationAndCommit : opts, in intrinsicGas); protected override TransactionResult BuyGas(Transaction tx, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs index 23c2095a6a7..fd9801cfef6 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs @@ -66,8 +66,8 @@ public void GetCandidatesAndStake_GenesisSetup_CanReadExpectedCandidates() } EthereumCodeInfoRepository codeInfoRepository = new(stateProvider); - VirtualMachine virtualMachine = new(new TestBlockhashProvider(specProvider), specProvider, LimboLogs.Instance); - TransactionProcessor transactionProcessor = new(BlobBaseFeeCalculator.Instance, specProvider, stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + EthereumVirtualMachine virtualMachine = new(new TestBlockhashProvider(specProvider), specProvider, LimboLogs.Instance); + EthereumTransactionProcessor transactionProcessor = new(BlobBaseFeeCalculator.Instance, specProvider, stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); MasternodeVotingContract masterVoting = new(stateProvider, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(transactionProcessor, stateProvider, Substitute.For())); diff --git a/tools/Evm/T8n/T8nExecutor.cs b/tools/Evm/T8n/T8nExecutor.cs index 95780e5c8e1..15081c34a07 100644 --- a/tools/Evm/T8n/T8nExecutor.cs +++ b/tools/Evm/T8n/T8nExecutor.cs @@ -39,11 +39,11 @@ public static T8nExecutionResult Execute(T8nCommandArguments arguments) EthereumCodeInfoRepository codeInfoRepository = new(stateProvider); IBlockhashProvider blockhashProvider = ConstructBlockHashProvider(test); - IVirtualMachine virtualMachine = new VirtualMachine( + IVirtualMachine virtualMachine = new EthereumVirtualMachine( blockhashProvider, test.SpecProvider, _logManager); - TransactionProcessor transactionProcessor = new( + EthereumTransactionProcessor transactionProcessor = new( BlobBaseFeeCalculator.Instance, test.SpecProvider, stateProvider, From 1b1d03e666a0bf2e5ac3f9c3539f3a0372d5c11a Mon Sep 17 00:00:00 2001 From: alex017 Date: Mon, 22 Dec 2025 10:55:06 +0100 Subject: [PATCH 099/255] refactor: Remove redundant try-catch in SszProperty.StaticLength (#9976) * Update SszProperty.cs * Update src/Nethermind/Nethermind.Serialization.SszGenerator/SszProperty.cs --------- Co-authored-by: Lukasz Rozmej --- .../SszProperty.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Nethermind/Nethermind.Serialization.SszGenerator/SszProperty.cs b/src/Nethermind/Nethermind.Serialization.SszGenerator/SszProperty.cs index 8d27fec8e31..64b4b9bf726 100644 --- a/src/Nethermind/Nethermind.Serialization.SszGenerator/SszProperty.cs +++ b/src/Nethermind/Nethermind.Serialization.SszGenerator/SszProperty.cs @@ -81,16 +81,13 @@ public int StaticLength { return 4; } - try + + return Kind switch { - return Kind switch - { - Kind.Vector => Length!.Value * Type.StaticLength, - Kind.BitVector => (Length!.Value + 7) / 8, - _ => Type.StaticLength, - }; - } - catch { throw; } + Kind.Vector => Length!.Value * Type.StaticLength, + Kind.BitVector => (Length!.Value + 7) / 8, + _ => Type.StaticLength, + }; } } From b047c67c9ea9795b29659f37bbf3213e54e6cdfa Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 22 Dec 2025 10:55:24 +0100 Subject: [PATCH 100/255] fix: correct NSubstitute argument types in AuraWithdrawalProcessorTests (#9966) Update AuraWithdrawalProcessorTests.cs --- .../AuraWithdrawalProcessorTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuraWithdrawalProcessorTests.cs b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuraWithdrawalProcessorTests.cs index fc3851d358c..e7a563cc98b 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuraWithdrawalProcessorTests.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuraWithdrawalProcessorTests.cs @@ -79,7 +79,7 @@ public void Should_not_invoke_contract_before_Shanghai() .ExecuteWithdrawals( Arg.Any(), Arg.Any(), - Arg.Any(), - Arg.Any()); + Arg.Any>(), + Arg.Any>()); } } From 0b74566ce7ad411fa7930ae84f2396409a8d0621 Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 11:13:04 +0100 Subject: [PATCH 101/255] Auto-update fast sync settings (#9989) Co-authored-by: rubo --- src/Nethermind/Nethermind.Runner/configs/base-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/base-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/chiado.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/gnosis.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/joc-testnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sepolia.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-mainnet.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-sepolia.json | 4 ++-- 14 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index 1409e9e1e44..ce54754e2b7 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 39620000, - "PivotHash": "0x11d162aaef5cd230f283abe65b55adeac1f9c287b13b286c257a4e0423fe2ba9" + "PivotNumber": 39730000, + "PivotHash": "0x31ba2c3f57ac39d1a0db01a7235cbadab5c27f9a53428ed1019f1a9833617895" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index c8c2117e48e..fb0359cea53 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 35130000, - "PivotHash": "0xf15b14c3e63b1e81aa3123bec4028b4dc39374ddec42dcee6ac0280c2142ac90" + "PivotNumber": 35240000, + "PivotHash": "0xa5b10f28961e206d30c6e4d49f69b601d1f59949847d25e61706a92dbbe94813" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.json b/src/Nethermind/Nethermind.Runner/configs/chiado.json index 386570d5a5d..2743d08630b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.json +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.json @@ -18,8 +18,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 19290000, - "PivotHash": "0x566186d34021566f4b7ffb9b4a69d17388c8c6deb12e661b2a52ff84da41ca46", + "PivotNumber": 19330000, + "PivotHash": "0x9d5e94c722999f8d24f5540d24314fb50298788ce3b9584130b4f90d0b741409", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": 10000000000, "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.json b/src/Nethermind/Nethermind.Runner/configs/gnosis.json index 78c0d137c26..c5742788e0f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.json +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.json @@ -14,8 +14,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 43700000, - "PivotHash": "0x11d61ff1fad7e3d718e7dc2cb8d1c92002de4c1b8bf84c91ced85ac6c160797a", + "PivotNumber": 43740000, + "PivotHash": "0xd2e0891cd60dec73ced28f67d16a0d8dd7f0e5e0278e44ff32d450e358c9f930", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000, diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json index 5d129dd23c2..51cbc2f03d2 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 21280000, - "PivotHash": "0xfb02d595da52ec9b0786e49aedb95fa3e951610bac60d1c4f7e82b64914a5c5f", - "PivotTotalDifficulty": "38417974" + "PivotNumber": 21320000, + "PivotHash": "0x481e4c8d23f9aecf95ec6513b3887aac0d1fde06f127fe39e5c60fb5aedb2861", + "PivotTotalDifficulty": "38477426" }, "Metrics": { "NodeName": "JOC-Mainnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json index eb02506e5d7..384c1ba679d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 14880000, - "PivotHash": "0x0330ea0f3aabd4b3028160bd9a72537f19be3f882dbb21124dfdaa2eba897e4e", - "PivotTotalDifficulty": "24793747" + "PivotNumber": 14930000, + "PivotHash": "0x445d340047d192588c9869d7564fb31884631181fcaacea2f9acb6cea98ccfec", + "PivotTotalDifficulty": "24871865" }, "Metrics": { "NodeName": "JOC-Testnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json index fa74ec60d2a..19b0cc9e644 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 26810000, - "PivotHash": "0xd167ec6b9abec18e0177e653eb820e4f01e76f74771ca85ffe4c0a7e601295f5", + "PivotNumber": 26900000, + "PivotHash": "0x440a8e2cc7670a094acbd1f0ee8a59bfdcc6a7e66712ca4dd5c17e1e7a9296bc", "PivotTotalDifficulty": "0", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json index 1974130d56a..062590c2c5d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 22170000, - "PivotHash": "0xc59438af96822433eecaecbe039d4c8fc1c39f40a08147b30007511dac2bebee", + "PivotNumber": 22280000, + "PivotHash": "0x84d6fa98aac973d62c1a3bfc7ea9ff6e5b3d7118fe906592e624548750761051", "PivotTotalDifficulty": "37331807", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index 3063dde0b2b..7656ce8e73d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -10,8 +10,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 24038000, - "PivotHash": "0xb4a0f7ea2cdbf38eccd02e9886c84b54f46e19c47f211331b50d37457591b4cb", + "PivotNumber": 24056000, + "PivotHash": "0x55ef3495449858196d13149bee4a61c95a139fea674cecc262a1313f37f45f25", "PivotTotalDifficulty": "58750003716598352816469", "FastSyncCatchUpHeightDelta": "10000000000", "AncientReceiptsBarrier": 15537394, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index cde07f1ce99..6e934a1e057 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -15,8 +15,8 @@ "FastSyncCatchUpHeightDelta": "10000000000", "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, - "PivotNumber": 145220000, - "PivotHash": "0x98023a4c5642b838ff8ddd30599e41677fbf390239922c3500e97652d4457f25" + "PivotNumber": 145330000, + "PivotHash": "0x65bcb7297272faf0198968b40890ba8aa59764982ff7099e3ae00ebffe0b317e" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index 99129734a1b..42a3b15f36f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 37110000, - "PivotHash": "0xd42d26ed6ba04979fdb91ec8f5fecd8107bd22e2bb5ced0fe6da1f385bfaa710" + "PivotNumber": 37220000, + "PivotHash": "0x8f5f71dc3c7bd02b93b08c6967e72920edf25a4e44202f1a30063b6e607dec98" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index 7a55dc6d32e..1e55080c2fc 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -17,8 +17,8 @@ "FastSync": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 9865000, - "PivotHash": "0x9968e7b98d7356e1d04c5622ca7bb5690cb9ff125756739cee12825c6d1ea76e", + "PivotNumber": 9881000, + "PivotHash": "0x4ee04d56b4218d5034a10541b1221477009ff50ec4c2a875143f50afeec821d3", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 1450409, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index 6c1dd05d974..d78f7685831 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 23350000, - "PivotHash": "0x2a465940100d53df2bfd56ed499ffdf166fa8ef48d7917c04bc87cdb14deea7e" + "PivotNumber": 23460000, + "PivotHash": "0xad968bde1f46ad7f27e0442f141bd3bbee3efb36c8da93c7cf17d59002e8cdbe" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index 7d9ba964a49..973e6a71866 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 22740000, - "PivotHash": "0xf1bf98478bdb00ff8b5201917cb67c4eeffa238b8de28af92f9a5fb73aaf276c" + "PivotNumber": 22850000, + "PivotHash": "0x0a7087f1c90fc7a7c7c72c64d3aba17f35ea78075933eede4e376daec43fd632" }, "Discovery": { "DiscoveryVersion": "V5" From d64ccf9acbc5776ee73cf3c8a6c9aa833cb5f0c2 Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 11:13:18 +0100 Subject: [PATCH 102/255] Update OP Superchain chains (#9988) Co-authored-by: emlautarom1 --- src/Nethermind/Chains/cyber-mainnet.json.zst | Bin 72235 -> 72230 bytes src/Nethermind/Chains/funki-mainnet.json.zst | Bin 78345 -> 78337 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/Nethermind/Chains/cyber-mainnet.json.zst b/src/Nethermind/Chains/cyber-mainnet.json.zst index 3ffc99ef56d1033b9b03b580f9f1cab67d4394f0..ca178a08100ec2071325b6f64cce0862369c2a01 100644 GIT binary patch delta 64274 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 j%EIUYi0YAUOmN!Yt delta 69111 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�V#-t||8#{O%My=(^Cd49o-p?IZ@`jc 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 TejIXo+gGUI?w`+l<)Q8p?2Gu^ From f548ec6102b2cd5742b95f6b6e08bc29206531e1 Mon Sep 17 00:00:00 2001 From: VolodymyrBg Date: Mon, 22 Dec 2025 12:49:57 +0200 Subject: [PATCH 103/255] perf: avoid LINQ allocations in GetStorageRangesMessageSerializer (#9951) --- .../Messages/GetStorageRangesMessageSerializer.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs index 5275e5f95c1..2a898746dbd 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs @@ -16,7 +16,14 @@ public override void Serialize(IByteBuffer byteBuffer, GetStorageRangeMessage me rlpStream.Encode(message.RequestId); rlpStream.Encode(message.StorageRange.RootHash); - rlpStream.Encode(message.StorageRange.Accounts.Select(static a => a.Path).ToArray()); // TODO: optimize this + var accounts = message.StorageRange.Accounts; + int accountsCount = accounts.Count; + int accountsPathsContentLength = accountsCount * Rlp.LengthOfKeccakRlp; + rlpStream.StartSequence(accountsPathsContentLength); + for (int i = 0; i < accountsCount; i++) + { + rlpStream.Encode(accounts[i].Path); + } rlpStream.Encode(message.StorageRange.StartingHash); rlpStream.Encode(message.StorageRange.LimitHash); rlpStream.Encode(message.ResponseBytes); @@ -48,7 +55,9 @@ public override int GetLength(GetStorageRangeMessage message, out int contentLen { contentLength = Rlp.LengthOf(message.RequestId); contentLength += Rlp.LengthOf(message.StorageRange.RootHash); - contentLength += Rlp.LengthOf(message.StorageRange.Accounts.Select(static a => a.Path).ToArray(), true); // TODO: optimize this + int accountsCount = message.StorageRange.Accounts.Count; + int accountsPathsContentLength = accountsCount * Rlp.LengthOfKeccakRlp; + contentLength += Rlp.LengthOfSequence(accountsPathsContentLength); contentLength += Rlp.LengthOf(message.StorageRange.StartingHash); contentLength += Rlp.LengthOf(message.StorageRange.LimitHash); contentLength += Rlp.LengthOf(message.ResponseBytes); From 79db2cd037de1497569fca95ff627a3b423fc36e Mon Sep 17 00:00:00 2001 From: marukai67 Date: Mon, 22 Dec 2025 12:34:53 +0100 Subject: [PATCH 104/255] refactor: cache blob and proof counts in BlobProofsManagerV1 (#9983) * Update BlobProofsManagerV1.cs * Update src/Nethermind/Nethermind.Crypto/BlobProofsManagerV1.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Lukasz Rozmej Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Nethermind.Crypto/BlobProofsManagerV1.cs | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Nethermind/Nethermind.Crypto/BlobProofsManagerV1.cs b/src/Nethermind/Nethermind.Crypto/BlobProofsManagerV1.cs index 50b6465d9dd..f6c222a7924 100644 --- a/src/Nethermind/Nethermind.Crypto/BlobProofsManagerV1.cs +++ b/src/Nethermind/Nethermind.Crypto/BlobProofsManagerV1.cs @@ -15,9 +15,12 @@ internal class BlobProofsManagerV1 : IBlobProofsManager public ShardBlobNetworkWrapper AllocateWrapper(params ReadOnlySpan blobs) { - ShardBlobNetworkWrapper result = new(blobs.ToArray(), new byte[blobs.Length][], new byte[blobs.Length * Ckzg.CellsPerExtBlob][], ProofVersion.V1); + int blobCount = blobs.Length; + int proofCount = blobCount * Ckzg.CellsPerExtBlob; - for (int i = 0; i < blobs.Length; i++) + ShardBlobNetworkWrapper result = new(blobs.ToArray(), new byte[blobCount][], new byte[proofCount][], ProofVersion.V1); + + for (int i = 0; i < blobCount; i++) { result.Commitments[i] = new byte[Ckzg.BytesPerCommitment]; for (int j = 0; j < Ckzg.CellsPerExtBlob; j++) @@ -48,12 +51,15 @@ public void ComputeProofsAndCommitments(ShardBlobNetworkWrapper wrapper) public bool ValidateLengths(ShardBlobNetworkWrapper wrapper) { - if (wrapper.Blobs.Length != wrapper.Commitments.Length || wrapper.Blobs.Length * Ckzg.CellsPerExtBlob != wrapper.Proofs.Length) + int blobCount = wrapper.Blobs.Length; + int proofCount = blobCount * Ckzg.CellsPerExtBlob; + + if (blobCount != wrapper.Commitments.Length || proofCount != wrapper.Proofs.Length) { return false; } - for (int i = 0; i < wrapper.Blobs.Length; i++) + for (int i = 0; i < blobCount; i++) { if (wrapper.Blobs[i].Length != Ckzg.BytesPerBlob || wrapper.Commitments[i].Length != Ckzg.BytesPerCommitment) { @@ -61,7 +67,7 @@ public bool ValidateLengths(ShardBlobNetworkWrapper wrapper) } } - for (int i = 0; i < wrapper.Proofs.Length; i++) + for (int i = 0; i < proofCount; i++) { if (wrapper.Proofs[i].Length != Ckzg.BytesPerProof) { @@ -80,14 +86,17 @@ public bool ValidateProofs(ShardBlobNetworkWrapper wrapper) return false; } - using ArrayPoolSpan cells = new(wrapper.Blobs.Length * Ckzg.BytesPerBlob * 2); - using ArrayPoolSpan flatCommitments = new(wrapper.Blobs.Length * Ckzg.BytesPerCommitment * Ckzg.CellsPerExtBlob); - using ArrayPoolSpan flatProofs = new(wrapper.Blobs.Length * Ckzg.BytesPerProof * Ckzg.CellsPerExtBlob); - using ArrayPoolSpan indices = new(wrapper.Blobs.Length * Ckzg.CellsPerExtBlob); + int blobCount = wrapper.Blobs.Length; + int cellCount = blobCount * Ckzg.CellsPerExtBlob; + + using ArrayPoolSpan cells = new(blobCount * Ckzg.BytesPerBlob * 2); + using ArrayPoolSpan flatCommitments = new(cellCount * Ckzg.BytesPerCommitment); + using ArrayPoolSpan flatProofs = new(cellCount * Ckzg.BytesPerProof); + using ArrayPoolSpan indices = new(cellCount); try { - for (int i = 0; i < wrapper.Blobs.Length; i++) + for (int i = 0; i < blobCount; i++) { Ckzg.ComputeCells(cells.Slice(i * Ckzg.BytesPerCell * Ckzg.CellsPerExtBlob, Ckzg.BytesPerCell * Ckzg.CellsPerExtBlob), wrapper.Blobs[i], KzgPolynomialCommitments.CkzgSetup); @@ -103,7 +112,7 @@ public bool ValidateProofs(ShardBlobNetworkWrapper wrapper) } return Ckzg.VerifyCellKzgProofBatch(flatCommitments, indices, cells, - flatProofs, wrapper.Blobs.Length * Ckzg.CellsPerExtBlob, KzgPolynomialCommitments.CkzgSetup); + flatProofs, cellCount, KzgPolynomialCommitments.CkzgSetup); } catch (Exception e) when (e is ArgumentException or ApplicationException or InsufficientMemoryException) { From f7eb580524566f7b01b5185982723da553b42989 Mon Sep 17 00:00:00 2001 From: Gengar Date: Mon, 22 Dec 2025 14:38:36 +0200 Subject: [PATCH 105/255] fix: replace unused mock logger with LimboTraceLogger in EnrDiscoveryTests (#9993) Replace EnrTreeCrawler logger with LimboTraceLogger --- src/Nethermind/Nethermind.Network.Dns.Test/EnrDiscoveryTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Network.Dns.Test/EnrDiscoveryTests.cs b/src/Nethermind/Nethermind.Network.Dns.Test/EnrDiscoveryTests.cs index b8e72b938f5..36285381432 100644 --- a/src/Nethermind/Nethermind.Network.Dns.Test/EnrDiscoveryTests.cs +++ b/src/Nethermind/Nethermind.Network.Dns.Test/EnrDiscoveryTests.cs @@ -48,7 +48,7 @@ public async Task Test_enr_discovery2() NodeRecordSigner singer = new(new Ecdsa(), TestItem.PrivateKeyA); EnrRecordParser parser = new(singer); - EnrTreeCrawler crawler = new(new(Substitute.For())); + EnrTreeCrawler crawler = new(LimboTraceLogger.Instance); int verified = 0; await foreach (string record in crawler.SearchTree("all.mainnet.ethdisco.net", default)) { From b5ddc8afed8c75bb254d28adbfed296c4d4d9921 Mon Sep 17 00:00:00 2001 From: Matthew Vauxhall Date: Mon, 22 Dec 2025 14:43:13 +0200 Subject: [PATCH 106/255] fix: replace empty exception with informative BlockchainException in ExtractSigners (#9986) perf: avoid unnecessary block clone in block_to_payload_v3 Replace generic Exception with empty message in ExtractSigners method with BlockchainException containing descriptive error message. This aligns with project's exception handling patterns and improves debuggability. --- .../Nethermind.Consensus.Clique/BlockHeaderExtensions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Consensus.Clique/BlockHeaderExtensions.cs b/src/Nethermind/Nethermind.Consensus.Clique/BlockHeaderExtensions.cs index b71813d8461..6c1bf551641 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/BlockHeaderExtensions.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/BlockHeaderExtensions.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Blockchain; using Nethermind.Core; namespace Nethermind.Consensus.Clique @@ -17,7 +18,7 @@ internal static Address[] ExtractSigners(BlockHeader blockHeader) { if (blockHeader.ExtraData is null) { - throw new Exception(string.Empty); + throw new BlockchainException("Block header ExtraData cannot be null when extracting signers"); } Span signersData = blockHeader.ExtraData.AsSpan(Clique.ExtraVanityLength, (blockHeader.ExtraData.Length - Clique.ExtraSealLength)); From 52a6b3a9d9fc826cda258be86f714fa6799c12cf Mon Sep 17 00:00:00 2001 From: 0xFloki Date: Mon, 22 Dec 2025 13:45:18 +0100 Subject: [PATCH 107/255] perf(tests): Remove redundant ToList() calls in PatriciaTreeBulkSetterTests (#9981) Update PatriciaTreeBulkSetterTests.cs --- .../Nethermind.State.Test/PatriciaTreeBulkSetterTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.State.Test/PatriciaTreeBulkSetterTests.cs b/src/Nethermind/Nethermind.State.Test/PatriciaTreeBulkSetterTests.cs index fa1940a9b1b..54e6827808c 100644 --- a/src/Nethermind/Nethermind.State.Test/PatriciaTreeBulkSetterTests.cs +++ b/src/Nethermind/Nethermind.State.Test/PatriciaTreeBulkSetterTests.cs @@ -676,17 +676,17 @@ public void TestBucketSort(int nibIndex, List paths, List buffer = new ArrayPoolList(paths.Count, paths.Count); int resultMask = PatriciaTree.BucketSort16Small(items.AsSpan(), buffer.AsSpan(), nibIndex, result); - buffer.Select((it) => it.Path).ToList().Should().BeEquivalentTo(expectedPaths); + buffer.Select((it) => it.Path).Should().BeEquivalentTo(expectedPaths); result.ToArray().Should().BeEquivalentTo(expectedResult); resultMask.Should().Be(expectedMask); resultMask = PatriciaTree.BucketSort16Large(items.AsSpan(), buffer.AsSpan(), nibIndex, result); - buffer.Select((it) => it.Path).ToList().Should().BeEquivalentTo(expectedPaths); + buffer.Select((it) => it.Path).Should().BeEquivalentTo(expectedPaths); result.ToArray().Should().BeEquivalentTo(expectedResult); resultMask.Should().Be(expectedMask); resultMask = PatriciaTree.BucketSort16(items.AsSpan(), buffer.AsSpan(), nibIndex, result); - buffer.Select((it) => it.Path).ToList().Should().BeEquivalentTo(expectedPaths); + buffer.Select((it) => it.Path).Should().BeEquivalentTo(expectedPaths); result.ToArray().Should().BeEquivalentTo(expectedResult); resultMask.Should().Be(expectedMask); } From 0277e738fa6d70213a8e36b15801cbf8dc23fb1d Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Mon, 22 Dec 2025 14:14:18 -0500 Subject: [PATCH 108/255] Use correct HardwareAcceleration checks for Vector (#10007) * Use correct HardwareAcceleration checks for Vector * Update src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpDestinationAnalyzer.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Vector512 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Nethermind.Core/Crypto/KeccakHash.cs | 6 +++--- .../Nethermind.Core/Extensions/Bytes.Vector.cs | 14 +++++++------- .../Nethermind.Evm.Precompiles/ModExpPrecompile.cs | 8 ++++---- .../CodeAnalysis/JumpDestinationAnalyzer.cs | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Crypto/KeccakHash.cs b/src/Nethermind/Nethermind.Core/Crypto/KeccakHash.cs index 972f96a92ca..35673cec481 100644 --- a/src/Nethermind/Nethermind.Core/Crypto/KeccakHash.cs +++ b/src/Nethermind/Nethermind.Core/Crypto/KeccakHash.cs @@ -422,7 +422,7 @@ public static void ComputeHash(ReadOnlySpan input, Span output) private static unsafe void XorVectors(Span state, ReadOnlySpan input) { ref byte stateRef = ref MemoryMarshal.GetReference(state); - if (Vector512.IsSupported && input.Length >= Vector512.Count) + if (Vector512.IsHardwareAccelerated && input.Length >= Vector512.Count) { // Convert to uint for the mod else the Jit does a more complicated signed mod // whereas as uint it just does an And @@ -441,7 +441,7 @@ private static unsafe void XorVectors(Span state, ReadOnlySpan input stateRef = ref Unsafe.Add(ref stateRef, vectorLength); } - if (Vector256.IsSupported && input.Length >= Vector256.Count) + if (Vector256.IsHardwareAccelerated && input.Length >= Vector256.Count) { // Convert to uint for the mod else the Jit does a more complicated signed mod // whereas as uint it just does an And @@ -460,7 +460,7 @@ private static unsafe void XorVectors(Span state, ReadOnlySpan input stateRef = ref Unsafe.Add(ref stateRef, vectorLength); } - if (Vector128.IsSupported && input.Length >= Vector128.Count) + if (Vector128.IsHardwareAccelerated && input.Length >= Vector128.Count) { int vectorLength = input.Length - (int)((uint)input.Length % (uint)Vector128.Count); ref byte inputRef = ref MemoryMarshal.GetReference(input); diff --git a/src/Nethermind/Nethermind.Core/Extensions/Bytes.Vector.cs b/src/Nethermind/Nethermind.Core/Extensions/Bytes.Vector.cs index 4527b52a94f..573d658ef22 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/Bytes.Vector.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/Bytes.Vector.cs @@ -51,7 +51,7 @@ public static void Or(this Span thisSpan, ReadOnlySpan valueSpan) ref byte thisRef = ref MemoryMarshal.GetReference(thisSpan); ref byte valueRef = ref MemoryMarshal.GetReference(valueSpan); - if (Vector512.IsSupported && thisSpan.Length >= Vector512.Count) + if (Vector512.IsHardwareAccelerated && thisSpan.Length >= Vector512.Count) { for (int i = 0; i < thisSpan.Length - Vector512.Count; i += Vector512.Count) { @@ -66,7 +66,7 @@ public static void Or(this Span thisSpan, ReadOnlySpan valueSpan) Vector512 b2 = Vector512.LoadUnsafe(ref Unsafe.Add(ref valueRef, offset)); Vector512.BitwiseOr(b1, b2).StoreUnsafe(ref Unsafe.Add(ref thisRef, offset)); } - else if (Vector256.IsSupported && thisSpan.Length >= Vector256.Count) + else if (Vector256.IsHardwareAccelerated && thisSpan.Length >= Vector256.Count) { for (int i = 0; i < thisSpan.Length - Vector256.Count; i += Vector256.Count) { @@ -81,7 +81,7 @@ public static void Or(this Span thisSpan, ReadOnlySpan valueSpan) Vector256 b2 = Vector256.LoadUnsafe(ref Unsafe.Add(ref valueRef, offset)); Vector256.BitwiseOr(b1, b2).StoreUnsafe(ref Unsafe.Add(ref thisRef, offset)); } - else if (Vector128.IsSupported && thisSpan.Length >= Vector128.Count) + else if (Vector128.IsHardwareAccelerated && thisSpan.Length >= Vector128.Count) { for (int i = 0; i < thisSpan.Length - Vector128.Count; i += Vector128.Count) { @@ -118,7 +118,7 @@ public static void Xor(this Span thisSpan, ReadOnlySpan valueSpan) int i = 0; // We can't do the fold back technique for xor so need to fall though each size - if (Vector512.IsSupported) + if (Vector512.IsHardwareAccelerated) { for (; i <= thisSpan.Length - Vector512.Count; i += Vector512.Count) { @@ -131,7 +131,7 @@ public static void Xor(this Span thisSpan, ReadOnlySpan valueSpan) if (i == thisSpan.Length) return; } - if (Vector256.IsSupported) + if (Vector256.IsHardwareAccelerated) { for (; i <= thisSpan.Length - Vector256.Count; i += Vector256.Count) { @@ -144,7 +144,7 @@ public static void Xor(this Span thisSpan, ReadOnlySpan valueSpan) if (i == thisSpan.Length) return; } - if (Vector128.IsSupported) + if (Vector128.IsHardwareAccelerated) { for (; i <= thisSpan.Length - Vector128.Count; i += Vector128.Count) { @@ -192,7 +192,7 @@ public static uint CountBits(this Span thisSpan) public static int CountLeadingZeroBits(this in Vector256 v) { - if (Vector256.IsSupported) + if (Vector256.IsHardwareAccelerated) { var cmp = Vector256.Equals(v, Vector256.Zero); uint nonZeroMask = ~cmp.ExtractMostSignificantBits(); diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/ModExpPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/ModExpPrecompile.cs index 44bb8bc15fc..8d8e1ec92b8 100644 --- a/src/Nethermind/Nethermind.Evm.Precompiles/ModExpPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm.Precompiles/ModExpPrecompile.cs @@ -130,7 +130,7 @@ private static bool ExceedsMaxInputSize(IReleaseSpec releaseSpec, uint baseLengt private static (uint baseLength, uint expLength, uint modulusLength) GetInputLengths(ReadOnlySpan inputData) { // Test if too high - if (Vector256.IsSupported) + if (Vector256.IsHardwareAccelerated) { ref var firstByte = ref MemoryMarshal.GetReference(inputData); Vector256 mask = ~Vector256.Create(0, 0, 0, 0, 0, 0, 0, uint.MaxValue).AsByte(); @@ -145,7 +145,7 @@ private static (uint baseLength, uint expLength, uint modulusLength) GetInputLen return GetInputLengthsMayOverflow(inputData); } } - else if (Vector128.IsSupported) + else if (Vector128.IsHardwareAccelerated) { ref var firstByte = ref MemoryMarshal.GetReference(inputData); Vector128 mask = ~Vector128.Create(0, 0, 0, uint.MaxValue).AsByte(); @@ -184,7 +184,7 @@ private static (uint baseLength, uint expLength, uint modulusLength) GetInputLen private static (uint baseLength, uint expLength, uint modulusLength) GetInputLengthsMayOverflow(ReadOnlySpan inputData) { // Only valid if baseLength and modulusLength are zero; when expLength doesn't matter - if (Vector256.IsSupported) + if (Vector256.IsHardwareAccelerated) { ref var firstByte = ref MemoryMarshal.GetReference(inputData); if (Vector256.BitwiseOr( @@ -196,7 +196,7 @@ private static (uint baseLength, uint expLength, uint modulusLength) GetInputLen return (uint.MaxValue, uint.MaxValue, uint.MaxValue); } } - else if (Vector128.IsSupported) + else if (Vector128.IsHardwareAccelerated) { ref var firstByte = ref MemoryMarshal.GetReference(inputData); if (Vector128.BitwiseOr( diff --git a/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpDestinationAnalyzer.cs b/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpDestinationAnalyzer.cs index f5fb43269de..118595a3d99 100644 --- a/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpDestinationAnalyzer.cs +++ b/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpDestinationAnalyzer.cs @@ -113,9 +113,9 @@ private long[] CreateJumpDestinationBitmap() long[] bitmap = CreateBitmap(code.Length); - return Vector512.IsSupported && code.Length >= Vector512.Count ? + return Vector512.IsHardwareAccelerated && code.Length >= Vector512.Count ? PopulateJumpDestinationBitmap_Vector512(bitmap, code) : - Vector128.IsSupported && code.Length >= Vector128.Count ? + Vector128.IsHardwareAccelerated && code.Length >= Vector128.Count ? PopulateJumpDestinationBitmap_Vector128(bitmap, code) : PopulateJumpDestinationBitmap_Scalar(bitmap, code); } @@ -266,7 +266,7 @@ internal static long[] PopulateJumpDestinationBitmap_Vector128(long[] bitmap, Re int move = 1; // We use 128bit rather than Avx or Avx-512 as is optimization for stretch of code without PUSHes. // As the vector size increases the chance of there being a PUSH increases which will disable this optimization. - if (Vector128.IsSupported && + if (Vector128.IsHardwareAccelerated && // Check not going to read passed end of code. programCounter <= code.Length - Vector128.Count && // Are we on an short stride, one quarter of the long flags? From 6898f30bf1a7751f1ebdcb13dd26ae10752ddc1c Mon Sep 17 00:00:00 2001 From: 0xFloki Date: Mon, 22 Dec 2025 20:36:03 +0100 Subject: [PATCH 109/255] Optimize ColumnDb MultiGet allocations (#9908) * Update ColumnDb.cs * Update ColumnDb.cs --- src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs index 34713b992b7..91879eeea77 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using Nethermind.Core; using Nethermind.Core.Crypto; using RocksDbSharp; @@ -62,8 +61,15 @@ public void Merge(ReadOnlySpan key, ReadOnlySpan value, WriteFlags w _mainDb.MergeWithColumnFamily(key, _columnFamily, value, writeFlags); } - public KeyValuePair[] this[byte[][] keys] => - _rocksDb.MultiGet(keys, keys.Select(k => _columnFamily).ToArray()); + public KeyValuePair[] this[byte[][] keys] + { + get + { + ColumnFamilyHandle[] columnFamilies = new ColumnFamilyHandle[keys.Length]; + Array.Fill(columnFamilies, _columnFamily); + return _rocksDb.MultiGet(keys, columnFamilies); + } + } public IEnumerable> GetAll(bool ordered = false) { From 9c0bbb35ab36ff8fd3f7bf50cafb23ec08907538 Mon Sep 17 00:00:00 2001 From: Micke <155267459+reallesee@users.noreply.github.com> Date: Mon, 22 Dec 2025 20:37:02 +0100 Subject: [PATCH 110/255] fix: correct type name in TimeoutDecoder error message (#9948) Co-authored-by: ak88 --- src/Nethermind/Nethermind.Xdc/RLP/TimeoutDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Xdc/RLP/TimeoutDecoder.cs b/src/Nethermind/Nethermind.Xdc/RLP/TimeoutDecoder.cs index 546b5b2c2d3..762b6749d6b 100644 --- a/src/Nethermind/Nethermind.Xdc/RLP/TimeoutDecoder.cs +++ b/src/Nethermind/Nethermind.Xdc/RLP/TimeoutDecoder.cs @@ -49,7 +49,7 @@ protected override Timeout DecodeInternal(RlpStream rlpStream, RlpBehaviors rlpB if ((rlpBehaviors & RlpBehaviors.ForSealing) != RlpBehaviors.ForSealing) { if (rlpStream.PeekNextRlpLength() != Signature.Size) - throw new RlpException($"Invalid signature length in {nameof(Vote)}"); + throw new RlpException($"Invalid signature length in {nameof(Timeout)}"); signature = new(rlpStream.DecodeByteArray()); } From 720a83671884aa0b568987f59a944f2c0fb67569 Mon Sep 17 00:00:00 2001 From: 0xFloki Date: Mon, 22 Dec 2025 20:37:21 +0100 Subject: [PATCH 111/255] perf: reduce allocations in TypeExtensions (#9994) * Update TypeExtensions.cs * Update TypeExtensions.cs * Update TypeExtensions.cs --- .../Extensions/TypeExtensions.cs | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Extensions/TypeExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/TypeExtensions.cs index 04a82b79e46..20e6ab5de76 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/TypeExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/TypeExtensions.cs @@ -5,6 +5,7 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using Nethermind.Core.Collections; namespace Nethermind.Core.Extensions; @@ -22,9 +23,16 @@ public static Type GetDirectInterfaceImplementation(this Type interfaceType) foreach (Type implementation in implementations) { - List interfaces = implementation.GetInterfaces().ToList(); + Type[] allInterfaces = implementation.GetInterfaces(); + using ArrayPoolListRef interfaces = new(allInterfaces.Length); - interfaces.RemoveAll(i => baseInterfaces.Contains(i)); + foreach (Type iface in allInterfaces) + { + if (!baseInterfaces.Contains(iface)) + { + interfaces.Add(iface); + } + } if (interfaces.Contains(interfaceType)) { @@ -35,18 +43,17 @@ public static Type GetDirectInterfaceImplementation(this Type interfaceType) throw new InvalidOperationException($"Couldn't find direct implementation of {interfaceType} interface"); } - private static readonly HashSet _valueTupleTypes = new HashSet( - new Type[] { - typeof(ValueTuple<>), - typeof(ValueTuple<,>), - typeof(ValueTuple<,,>), - typeof(ValueTuple<,,,>), - typeof(ValueTuple<,,,,>), - typeof(ValueTuple<,,,,,>), - typeof(ValueTuple<,,,,,,>), - typeof(ValueTuple<,,,,,,,>) - } - ); + private static readonly HashSet _valueTupleTypes = + [ + typeof(ValueTuple<>), + typeof(ValueTuple<,>), + typeof(ValueTuple<,,>), + typeof(ValueTuple<,,,>), + typeof(ValueTuple<,,,,>), + typeof(ValueTuple<,,,,,>), + typeof(ValueTuple<,,,,,,>), + typeof(ValueTuple<,,,,,,,>) + ]; public static bool IsValueTuple(this Type type) => type.IsGenericType && _valueTupleTypes.Contains(type.GetGenericTypeDefinition()); @@ -54,8 +61,7 @@ public static bool IsValueTuple(this Type type) => public static bool CanBeAssignedNull(this Type type) => !type.IsValueType || Nullable.GetUnderlyingType(type) is not null; - public static bool CannotBeAssignedNull(this Type type) => - type.IsValueType && Nullable.GetUnderlyingType(type) is null; + public static bool CannotBeAssignedNull(this Type type) => !CanBeAssignedNull(type); ///

/// Returns the type name. If this is a generic type, appends From 06b8fd4e791c1d792c0d8ae9e4ba03e74ed647ca Mon Sep 17 00:00:00 2001 From: lupin17 <59-quanta.middle@icloud.com> Date: Mon, 22 Dec 2025 20:38:55 +0100 Subject: [PATCH 112/255] refactor(trie): remove redundant condition check in IsValidWithOneNodeLess (#9982) * Update TrieNode.cs * Update src/Nethermind/Nethermind.Trie/TrieNode.cs * Update src/Nethermind/Nethermind.Trie/TrieNode.cs --------- Co-authored-by: Lukasz Rozmej Co-authored-by: Ben {chmark} Adams --- src/Nethermind/Nethermind.Trie/TrieNode.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Trie/TrieNode.cs b/src/Nethermind/Nethermind.Trie/TrieNode.cs index 7225f0ab073..09d62723325 100644 --- a/src/Nethermind/Nethermind.Trie/TrieNode.cs +++ b/src/Nethermind/Nethermind.Trie/TrieNode.cs @@ -241,7 +241,7 @@ public bool IsValidWithOneNodeLess } } - return nonEmptyNodes > 2; + return false; } } From 33397b20c68be7bc2f2d508e6ff8a57fb9ff7903 Mon Sep 17 00:00:00 2001 From: Fallengirl <155266340+Fallengirl@users.noreply.github.com> Date: Mon, 22 Dec 2025 20:39:22 +0100 Subject: [PATCH 113/255] fix: return correct count when no peer was dropped in DropWorstPeer (#10001) --- .../Nethermind.Synchronization/Peers/SyncPeerPool.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs index d0bbb7e0ba3..99adcbd3eeb 100644 --- a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs +++ b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs @@ -539,7 +539,12 @@ currentPeer.TotalDifficulty is not null && } } - worstPeer?.SyncPeer.Disconnect(DisconnectReason.DropWorstPeer, $"PEER REVIEW / {worstReason}"); + if (worstPeer is null) + { + return 0; + } + + worstPeer.SyncPeer.Disconnect(DisconnectReason.DropWorstPeer, $"PEER REVIEW / {worstReason}"); return 1; } From 4200facfb96d3a8cf1a23edcda8d4a5996f47afa Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Tue, 23 Dec 2025 00:36:30 +0300 Subject: [PATCH 114/255] Consider type boundaries (#10000) --- .../Extensions/ByteArrayExtensions.cs | 30 +++++++++++++++++-- .../ModExpPrecompile.cs | 14 +++++++-- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Extensions/ByteArrayExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/ByteArrayExtensions.cs index 94c1c12f86a..362afa9809e 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/ByteArrayExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/ByteArrayExtensions.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System; @@ -45,6 +45,7 @@ public static byte[] Slice(this byte[] bytes, int startIndex, int length) public static byte[] SliceWithZeroPaddingEmptyOnError(this byte[] bytes, int startIndex, int length) { int copiedFragmentLength = Math.Min(bytes.Length - startIndex, length); + if (copiedFragmentLength <= 0) { return []; @@ -59,21 +60,44 @@ public static byte[] SliceWithZeroPaddingEmptyOnError(this byte[] bytes, int sta public static ReadOnlySpan SliceWithZeroPaddingEmptyOnError(this ReadOnlySpan bytes, int startIndex, int length) { int copiedFragmentLength = Math.Min(bytes.Length - startIndex, length); + if (copiedFragmentLength <= 0) { return default; } + return SafeSliceWithZeroPadding(bytes, startIndex, length, copiedFragmentLength); + } + + public static ReadOnlySpan SliceWithZeroPaddingEmptyOnError(this ReadOnlySpan bytes, uint startIndex, uint length) + { + if (bytes.Length < startIndex) + { + return default; + } + + long copiedFragmentLength = Math.Min((uint)bytes.Length - startIndex, length); + + if (bytes.Length < startIndex + copiedFragmentLength) + { + return default; + } + + return SafeSliceWithZeroPadding(bytes, (int)startIndex, (int)length, (int)copiedFragmentLength); + } + + private static ReadOnlySpan SafeSliceWithZeroPadding(ReadOnlySpan bytes, int startIndex, int length, int copiedFragmentLength) + { ReadOnlySpan sliced = bytes.Slice(startIndex, copiedFragmentLength); + if (copiedFragmentLength < length) { byte[] extended = new byte[length]; sliced.CopyTo(extended); - sliced = extended; + return extended; } return sliced; } - } } diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/ModExpPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/ModExpPrecompile.cs index 8d8e1ec92b8..9cc89cc3a33 100644 --- a/src/Nethermind/Nethermind.Evm.Precompiles/ModExpPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm.Precompiles/ModExpPrecompile.cs @@ -93,8 +93,16 @@ private static long DataGasCostInternal(ReadOnlySpan inputData, IReleaseSp ulong complexity = MultComplexity(baseLength, modulusLength, releaseSpec.IsEip7883Enabled); uint expLengthUpTo32 = Math.Min(LengthSize, expLength); - uint startIndex = LengthsLengths + baseLength; //+ expLength - expLengthUpTo32; // Geth takes head here, why? - UInt256 exp = new(inputData.SliceWithZeroPaddingEmptyOnError((int)startIndex, (int)expLengthUpTo32), isBigEndian: true); + + ReadOnlySpan data = []; + + if (baseLength < uint.MaxValue - LengthsLengths) + { + uint startIndex = LengthsLengths + baseLength; //+ expLength - expLengthUpTo32; // Geth takes head here, why? + data = inputData.SliceWithZeroPaddingEmptyOnError(startIndex, expLengthUpTo32); + } + + UInt256 exp = new(data, isBigEndian: true); UInt256 iterationCount = CalculateIterationCount(expLength, exp, releaseSpec.IsEip7883Enabled); bool overflow = UInt256.MultiplyOverflow(complexity, iterationCount, out UInt256 result); @@ -113,7 +121,7 @@ private static bool ExceedsMaxInputSize(IReleaseSpec releaseSpec, uint baseLengt { return releaseSpec.IsEip7823Enabled ? (baseLength > ModExpMaxInputSizeEip7823 | expLength > ModExpMaxInputSizeEip7823 | modulusLength > ModExpMaxInputSizeEip7823) - : (baseLength | modulusLength) > int.MaxValue; + : (baseLength | modulusLength) >= uint.MaxValue; } [MethodImpl(MethodImplOptions.NoInlining)] From e120de1e140c49b6e1de993ee52db8186f4c87b0 Mon Sep 17 00:00:00 2001 From: Diptanshu Kakwani Date: Tue, 23 Dec 2025 16:51:08 +0530 Subject: [PATCH 115/255] Taiko Shasta Changes - II (#9998) * taiko-geth changes * potential fix for 'main chain predecessor cannot be found' error * address comments & add goldentouch account filter --- .../Handlers/ForkchoiceUpdatedHandler.cs | 2 +- .../Rpc/TaikoEngineRpcModule.cs | 5 +- .../Rpc/TaikoForkchoiceUpdatedHandler.cs | 12 +++ .../Nethermind.Taiko/TaikoBlockValidator.cs | 23 +++-- .../Nethermind.Taiko/TaikoHeaderHelper.cs | 4 +- .../Nethermind.Taiko/TaikoHeaderValidator.cs | 86 +++++++++++++++++-- .../TaikoPayloadPreparationService.cs | 15 ++++ 7 files changed, 131 insertions(+), 16 deletions(-) diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs index 017a0dc5486..65e3eb831d9 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs @@ -400,7 +400,7 @@ private void StartNewBeaconHeaderSync(ForkchoiceStateV1 forkchoiceState, BlockHe } - private bool TryGetBranch(Block newHeadBlock, out Block[] blocks) + protected virtual bool TryGetBranch(Block newHeadBlock, out Block[] blocks) { List blocksList = new() { newHeadBlock }; Block? predecessor = newHeadBlock; diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs index 6bda82d9b35..a5f9452aca7 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs @@ -11,7 +11,6 @@ using Nethermind.Api; using Nethermind.Blockchain; using Nethermind.Blockchain.Find; -using Nethermind.Consensus.Processing; using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Crypto; @@ -111,7 +110,9 @@ public Task> engine_newPayloadV3(TaikoExecutionPa public ResultWrapper taikoAuth_txPoolContentWithMinTip(Address beneficiary, UInt256 baseFee, ulong blockMaxGasLimit, ulong maxBytesPerTxList, Address[]? localAccounts, int maxTransactionsLists, ulong minTip) { - IEnumerable> pendingTxs = txPool.GetPendingTransactionsBySender(); + // Fetch all the pending transactions except transactions from the GoldenTouchAccount + IEnumerable> pendingTxs = txPool.GetPendingTransactionsBySender() + .Where(txs => !txs.Key.Value.Equals(TaikoBlockValidator.GoldenTouchAccount)); if (localAccounts is not null) { diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoForkchoiceUpdatedHandler.cs b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoForkchoiceUpdatedHandler.cs index e03907f6a88..f8e6e0cef02 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoForkchoiceUpdatedHandler.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoForkchoiceUpdatedHandler.cs @@ -90,4 +90,16 @@ protected override bool IsPayloadAttributesTimestampValid(Block newHeadBlock, Fo return blockHeader; } + + protected override bool TryGetBranch(Block newHeadBlock, out Block[] blocks) + { + // Allow resetting to any block already on the main chain (including genesis) + if (_blockTree.IsMainChain(newHeadBlock.Header)) + { + blocks = [newHeadBlock]; + return true; + } + + return base.TryGetBranch(newHeadBlock, out blocks); + } } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs b/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs index 47e0ee2d8d7..4b2331e60d3 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs @@ -24,7 +24,8 @@ public class TaikoBlockValidator( private static readonly byte[] AnchorSelector = Keccak.Compute("anchor(bytes32,bytes32,uint64,uint32)").Bytes[..4].ToArray(); private static readonly byte[] AnchorV2Selector = Keccak.Compute("anchorV2(uint64,bytes32,uint32,(uint8,uint8,uint32,uint64,uint32))").Bytes[..4].ToArray(); private static readonly byte[] AnchorV3Selector = Keccak.Compute("anchorV3(uint64,bytes32,uint32,(uint8,uint8,uint32,uint64,uint32),bytes32[])").Bytes[..4].ToArray(); - public static readonly byte[] AnchorV4Selector = Keccak.Compute("anchorV4((uint48,address,bytes,bytes32,(uint48,uint8,address,address)[]),(uint48,bytes32,bytes32))").Bytes[..4].ToArray(); + public static readonly byte[] AnchorV4Selector = Keccak.Compute("anchorV4((uint48,address,bytes),(uint48,bytes32,bytes32))").Bytes[..4].ToArray(); + public static readonly Address GoldenTouchAccount = new("0x0000777735367b36bC9B61C50022d9D0700dB4Ec"); @@ -63,13 +64,9 @@ private bool ValidateAnchorTransaction(Transaction tx, Block block, ITaikoReleas return false; } - if (tx.Data.Length == 0 - || (!AnchorSelector.AsSpan().SequenceEqual(tx.Data.Span[..4]) - && !AnchorV2Selector.AsSpan().SequenceEqual(tx.Data.Span[..4]) - && !AnchorV3Selector.AsSpan().SequenceEqual(tx.Data.Span[..4]) - && !AnchorV4Selector.AsSpan().SequenceEqual(tx.Data.Span[..4]))) + if (tx.Data.Length < 4 || !IsValidAnchorSelector(tx.Data.Span[..4], spec)) { - errorMessage = "Anchor transaction must have valid selector"; + errorMessage = "Anchor transaction must have valid selector for the current fork"; return false; } @@ -110,4 +107,16 @@ private bool ValidateAnchorTransaction(Transaction tx, Block block, ITaikoReleas errorMessage = null; return true; } + + private static bool IsValidAnchorSelector(ReadOnlySpan selector, ITaikoReleaseSpec spec) + { + if (spec.IsShastaEnabled) + return AnchorV4Selector.AsSpan().SequenceEqual(selector); + + if (spec.IsPacayaEnabled) + return AnchorV3Selector.AsSpan().SequenceEqual(selector); + + return AnchorSelector.AsSpan().SequenceEqual(selector) + || AnchorV2Selector.AsSpan().SequenceEqual(selector); + } } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs b/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs index 7afbdbeeb35..1f73b6a20a6 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs @@ -8,11 +8,13 @@ namespace Nethermind.Taiko; internal static class TaikoHeaderHelper { + public const int ShastaExtraDataMinLen = 2; + public static byte? DecodeOntakeExtraData(this BlockHeader header) => header.ExtraData is { Length: >= 32 } ? Math.Min(header.ExtraData[31], (byte)100) : null; // Two bytes encoded in the extra data for Shasta // - First byte: basefeeSharingPctg // - Second byte: isLowBondProposal (lowest bit) // Returns only the basefeeSharingPctg - public static byte? DecodeShastaExtraData(this BlockHeader header) => header.ExtraData is not { Length: >= 2 } ? null : header.ExtraData[0]; + public static byte? DecodeShastaExtraData(this BlockHeader header) => header.ExtraData is { Length: < ShastaExtraDataMinLen } ? null : header.ExtraData[0]; } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs b/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs index 0b0cbdab48d..abbc1d4648c 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs @@ -6,6 +6,7 @@ using Nethermind.Consensus; using Nethermind.Consensus.Validators; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Messages; using Nethermind.Core.Specs; using Nethermind.Int256; @@ -18,9 +19,14 @@ public class TaikoHeaderValidator( IBlockTree? blockTree, ISealValidator? sealValidator, ISpecProvider? specProvider, + IL1OriginStore l1OriginStore, + ITimestamper? timestamper, ILogManager? logManager) : HeaderValidator(blockTree, sealValidator, specProvider, logManager) { + private readonly IL1OriginStore _l1OriginStore = l1OriginStore ?? throw new ArgumentNullException(nameof(l1OriginStore)); + private readonly ITimestamper _timestamper = timestamper ?? Timestamper.Default; + // EIP-4396 calculation parameters. private const ulong BlockTimeTarget = 2; private const ulong MaxGasTargetPercentage = 95; @@ -31,6 +37,39 @@ public class TaikoHeaderValidator( protected override bool ValidateGasLimitRange(BlockHeader header, BlockHeader parent, IReleaseSpec spec, ref string? error) => true; + protected override bool Validate(BlockHeader header, BlockHeader? parent, bool isUncle, out string? error) + { + if (header.UnclesHash != Keccak.OfAnEmptySequenceRlp) + { + error = "Uncles must be empty"; + if (_logger.IsWarn) _logger.Warn($"Invalid block header ({header.Hash}) - uncles not empty"); + return false; + } + + if (header.WithdrawalsRoot is null) + { + error = "WithdrawalsRoot is missing"; + if (_logger.IsWarn) _logger.Warn($"Invalid block header ({header.Hash}) - withdrawals root is null"); + return false; + } + + return base.Validate(header, parent, isUncle, out error); + } + + protected override bool ValidateExtraData(BlockHeader header, IReleaseSpec spec, bool isUncle, ref string? error) + { + var taikoSpec = (ITaikoReleaseSpec)spec; + + if (taikoSpec.IsShastaEnabled && header.ExtraData is { Length: < TaikoHeaderHelper.ShastaExtraDataMinLen }) + { + error = $"ExtraData must be at least {TaikoHeaderHelper.ShastaExtraDataMinLen} bytes for Shasta, but got {header.ExtraData.Length}"; + if (_logger.IsWarn) _logger.Warn($"Invalid block header ({header.Hash}) - {error}"); + return false; + } + + return base.ValidateExtraData(header, spec, isUncle, ref error); + } + protected override bool Validate1559(BlockHeader header, BlockHeader parent, IReleaseSpec spec, ref string? error) { if (header.BaseFeePerGas.IsZero) @@ -140,13 +179,50 @@ private static UInt256 ClampEip4396BaseFeeShasta(UInt256 baseFee) protected override bool ValidateTimestamp(BlockHeader header, BlockHeader parent, ref string? error) { - if (header.Timestamp < parent.Timestamp) + var taikoSpec = (ITaikoReleaseSpec)_specProvider.GetSpec(header); + + // Shasta fork enforces a strict timestamp increase, while other forks allow equal timestamps + // (multiple L2 blocks per L1 block scenario). + if (taikoSpec.IsShastaEnabled) { - error = BlockErrorMessages.InvalidTimestamp; - if (_logger.IsWarn) _logger.Warn($"Invalid block header ({header.Hash}) - timestamp before parent"); - return false; + if (header.Timestamp <= parent.Timestamp) + { + error = BlockErrorMessages.InvalidTimestamp; + + if (_logger.IsWarn) + { + _logger.Warn($"Invalid block header ({header.Hash}) - timestamp must be greater than parent for Shasta"); + } + + return false; + } } - return true; + else + { + if (header.Timestamp < parent.Timestamp) + { + error = BlockErrorMessages.InvalidTimestamp; + if (_logger.IsWarn) _logger.Warn($"Invalid block header ({header.Hash}) - timestamp before parent"); + return false; + } + } + + // If not a preconfirmation block, check that timestamp is not in the future + L1Origin? l1Origin = _l1OriginStore.ReadL1Origin((UInt256)header.Number); + if (l1Origin is null || l1Origin.IsPreconfBlock) + { + return true; + } + + ulong currentTime = _timestamper.UnixTime.Seconds; + if (header.Timestamp <= currentTime) + { + return true; + } + + error = $"Block timestamp {header.Timestamp} is in the future (current time: {currentTime})"; + if (_logger.IsWarn) _logger.Warn($"Invalid block header ({header.Hash}) - {error}"); + return false; } protected override bool ValidateTotalDifficulty(BlockHeader header, BlockHeader parent, ref string? error) diff --git a/src/Nethermind/Nethermind.Taiko/TaikoPayloadPreparationService.cs b/src/Nethermind/Nethermind.Taiko/TaikoPayloadPreparationService.cs index 15fbe045831..fd6a32086e4 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoPayloadPreparationService.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoPayloadPreparationService.cs @@ -73,6 +73,21 @@ public class TaikoPayloadPreparationService( (payloadId, existing) => { if (_logger.IsInfo) _logger.Info($"Payload with the same parameters has already started. PayloadId: {payloadId}"); + + // Write L1Origin and HeadL1Origin even if the payload is already in the cache. + L1Origin l1Origin = attrs.L1Origin ?? throw new InvalidOperationException("L1Origin is required"); + l1OriginStore.WriteL1Origin(l1Origin.BlockId, l1Origin); + + if (!l1Origin.IsPreconfBlock) + { + l1OriginStore.WriteHeadL1Origin(l1Origin.BlockId); + + if (attrs.BlockMetadata?.BatchID is not null) + { + l1OriginStore.WriteBatchToLastBlockID(attrs.BlockMetadata.BatchID.Value, l1Origin.BlockId); + } + } + return existing; }); From 1e76bc17462079ce63cf1711caa8f59b6782da4e Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Tue, 23 Dec 2025 13:40:13 +0100 Subject: [PATCH 116/255] Set release target commit explicitly (#10009) --- .github/workflows/release.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4690a16497b..1bb9a671b73 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -149,7 +149,7 @@ jobs: rm -rf $PACKAGE_DIR/*/ echo "Publishing packages to GitHub" prerelease=${{ needs.build.outputs.prerelease && '1' || '' }} - if gh release view $GIT_TAG >/dev/null 2>&1; then publish=1; else publish=0; fi + if gh release view "$GIT_TAG" >/dev/null 2>&1; then publish=1; else publish=0; fi if (( !publish )); then echo "Drafting release $GIT_TAG" @@ -163,16 +163,17 @@ jobs: The packages are signed with the following OpenPGP key: `AD12 7976 5093 C675 9CD8 A400 24A7 7461 6F1E 617E` EOF ) - gh release create $GIT_TAG -t v$GIT_TAG -d ${prerelease:+-p} -F <(printf '%s' "$relnotes") + gh release create "$GIT_TAG" --target "$GITHUB_SHA" -t "v$GIT_TAG" -d ${prerelease:+-p} -F <(printf '%s' "$relnotes") fi cd $PACKAGE_DIR echo "Uploading assets" - gh release upload $GIT_TAG *.zip *.zip.asc + gh release upload "$GIT_TAG" *.zip *.zip.asc --clobber if (( publish )); then echo "Publishing release $GIT_TAG" - gh release edit $GIT_TAG --verify-tag -t v$GIT_TAG ${prerelease:+-p} ${prerelease:---latest} + if [[ -n "$prerelease" ]]; then flag="--prerelease"; else flag="--latest"; fi + gh release edit "$GIT_TAG" --verify-tag --target "$GITHUB_SHA" -t "v$GIT_TAG" --draft=false $flag fi echo "Publishing completed" From 392944d04395aee0153c74885d0d0e561b5e7ffe Mon Sep 17 00:00:00 2001 From: Galoretka Date: Tue, 23 Dec 2025 15:13:26 +0200 Subject: [PATCH 117/255] Fix/json converters exception type (#9984) * fix: use JsonException in boolean and BigInteger converters * fix: use JsonException in boolean and BigInteger converters * Update src/Nethermind/Nethermind.Serialization.Json/BigIntegerConverter.cs Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.Serialization.Json/BooleanConverter.cs Co-authored-by: Lukasz Rozmej * fix ci * Update BooleanConverter.cs --------- Co-authored-by: Lukasz Rozmej --- .../Nethermind.Serialization.Json/BigIntegerConverter.cs | 2 +- .../Nethermind.Serialization.Json/BooleanConverter.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Serialization.Json/BigIntegerConverter.cs b/src/Nethermind/Nethermind.Serialization.Json/BigIntegerConverter.cs index bc00e5e9d94..a7518b3d49d 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/BigIntegerConverter.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/BigIntegerConverter.cs @@ -17,7 +17,7 @@ public override BigInteger Read(ref Utf8JsonReader reader, Type typeToConvert, J { JsonTokenType.Number => new BigInteger(reader.GetInt64()), JsonTokenType.String => BigInteger.Parse(reader.GetString()), - _ => throw new InvalidOperationException() + _ => throw new JsonException($"Cannot convert {reader.TokenType} to {nameof(BigInteger)}") }; } diff --git a/src/Nethermind/Nethermind.Serialization.Json/BooleanConverter.cs b/src/Nethermind/Nethermind.Serialization.Json/BooleanConverter.cs index 77f5825ba96..d164de5da09 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/BooleanConverter.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/BooleanConverter.cs @@ -44,7 +44,7 @@ public override bool Read( } } - throw new InvalidOperationException(); + throw new JsonException($"Cannot convert {reader.TokenType} to {nameof(Boolean)}"); } [SkipLocalsInit] From 92f310bbb0f159459a37f0ee60a5402e49b65fe4 Mon Sep 17 00:00:00 2001 From: marukai67 Date: Tue, 23 Dec 2025 14:13:54 +0100 Subject: [PATCH 118/255] refactor(tests): Remove unused variables in Enode exception tests (#9991) * Update PeerManagerTests.cs * Update PeerManagerTests.cs * Update src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs * Update PeerManagerTests.cs * Update PeerManagerTests.cs --------- Co-authored-by: Lukasz Rozmej --- .../PeerManagerTests.cs | 55 ++++--------------- 1 file changed, 12 insertions(+), 43 deletions(-) diff --git a/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs b/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs index 2330957538e..e75041eec31 100644 --- a/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs @@ -119,31 +119,16 @@ public async Task Will_discard_a_duplicate_incoming_session() } [Test] - public void Will_return_exception_in_port() - { - Assert.Throws(static delegate - { - Enode unused = new(enode3String); - }); - } + public void Will_return_exception_in_port() => + Assert.Throws(static () => new Enode(enode3String)); [Test] - public void Will_return_exception_in_dns() - { - Assert.Throws(static delegate - { - Enode unused = new(enode4String); - }); - } + public void Will_return_exception_in_dns() => + Assert.Throws(static () => new Enode(enode4String)); [Test] - public void Will_return_exception_when_there_is_no_port() - { - Assert.Throws(static delegate - { - Enode unused = new(enode5String); - }); - } + public void Will_return_exception_when_there_is_no_port() => + Assert.Throws(static () => new Enode(enode5String)); [Test] public void Will_parse_ports_correctly_when_there_are_two_different_ports() @@ -162,32 +147,16 @@ public void Will_parse_port_correctly_when_there_is_only_one() } [Test] - public void Will_return_exception_on_wrong_ports_part() - { - Assert.Throws(static delegate - { - Enode unused = new(enode8String); - }); - } + public void Will_return_exception_on_wrong_ports_part() => + Assert.Throws(static () => new Enode(enode8String)); [Test] - public void Will_return_exception_on_duplicated_discovery_port_part() - { - Assert.Throws(static delegate - { - Enode unused = new(enode9String); - }); - } + public void Will_return_exception_on_duplicated_discovery_port_part() => + Assert.Throws(static () => new Enode(enode9String)); [Test] - public void Will_return_exception_on_wrong_form_of_discovery_port_part() - { - Assert.Throws(static delegate - { - Enode unused = new(enode10String); - }); - } - + public void Will_return_exception_on_wrong_form_of_discovery_port_part() => + Assert.Throws(static () => new Enode(enode10String)); [Test] public async Task Will_accept_static_connection() { From 2b53941be95fdae992af2f17f95e5982031f93f8 Mon Sep 17 00:00:00 2001 From: forkfury Date: Tue, 23 Dec 2025 14:14:12 +0100 Subject: [PATCH 119/255] test: replace Task.Delay with After() in ContractDataStoreTests (#9985) * Update ContractDataStoreTests.cs * Update ContractDataStoreTests.cs * Update ContractDataStoreWithLocalDataTests.cs --- .../Contract/ContractDataStoreTests.cs | 40 +++++++++---------- .../ContractDataStoreWithLocalDataTests.cs | 4 +- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreTests.cs index f88647fade1..a9669604116 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreTests.cs @@ -5,7 +5,6 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using FluentAssertions; using Nethermind.Abi; using Nethermind.Blockchain; @@ -91,7 +90,7 @@ public void returns_data_from_getAll_on_non_consecutive_receipts_with_incrementa } [Test] - public async Task returns_data_from_receipts_on_non_consecutive_with_not_incremental_changes() + public void returns_data_from_receipts_on_non_consecutive_with_not_incremental_changes() { TestCase
testCase = BuildTestCase
(); testCase.DataContract.IncrementalChanges.Returns(false); @@ -109,9 +108,10 @@ public async Task returns_data_from_receipts_on_non_consecutive_with_not_increme testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); - await Task.Delay(10); // delay for refresh from contract as its async - - testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(expected.Cast()); + Assert.That( + () => testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header), + Is.EquivalentTo(expected.Cast()).After(200, 20) + ); } [Test] @@ -127,7 +127,7 @@ public void returns_data_from_getAll_on_non_consecutive_with_not_incremental_cha } [Test] - public async Task returns_data_from_receipts_on_consecutive_with_not_incremental_changes() + public void returns_data_from_receipts_on_consecutive_with_not_incremental_changes() { TestCase
testCase = BuildTestCase
(); testCase.DataContract.IncrementalChanges.Returns(false); @@ -145,13 +145,14 @@ public async Task returns_data_from_receipts_on_consecutive_with_not_incremental testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); - await Task.Delay(10); // delay for refresh from contract as its async - - testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(expected.Cast()); + Assert.That( + () => testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header), + Is.EquivalentTo(expected.Cast()).After(200, 20) + ); } [Test] - public async Task returns_data_from_receipts_on_consecutive_with_incremental_changes() + public void returns_data_from_receipts_on_consecutive_with_incremental_changes() { TestCase
testCase = BuildTestCase
(); BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; @@ -167,16 +168,14 @@ public async Task returns_data_from_receipts_on_consecutive_with_incremental_cha testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); - await Task.Delay(50); // delay for refresh from contract as its async - Assert.That( () => testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).ToList(), - Is.EquivalentTo(new ArrayList() { TestItem.AddressA, TestItem.AddressB }).After(1000, 100) + Is.EquivalentTo(new ArrayList() { TestItem.AddressA, TestItem.AddressB }).After(200, 20) ); } [Test] - public async Task returns_unmodified_data_from_empty_receipts_on_consecutive_with_incremental_changes() + public void returns_unmodified_data_from_empty_receipts_on_consecutive_with_incremental_changes() { TestCase
testCase = BuildTestCase
(); BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; @@ -192,13 +191,14 @@ public async Task returns_unmodified_data_from_empty_receipts_on_consecutive_wit testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); - await Task.Delay(10); // delay for refresh from contract as its async - - testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(TestItem.AddressA, TestItem.AddressC); + Assert.That( + () => testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header), + Is.EquivalentTo(new[] { TestItem.AddressA, TestItem.AddressC }).After(200, 20) + ); } [Test] - public async Task returns_data_from_receipts_on_consecutive_with_incremental_changes_with_identity() + public void returns_data_from_receipts_on_consecutive_with_incremental_changes_with_identity() { TestCase testCase = BuildTestCase( TxPriorityContract.DistinctDestinationMethodComparer.Instance, @@ -227,11 +227,9 @@ public async Task returns_data_from_receipts_on_consecutive_with_incremental_cha testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); - await Task.Delay(10); // delay for refresh from contract as its async - Assert.That( () => testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Count(), - Is.EqualTo(3).After(1000, 100) + Is.EqualTo(3).After(200, 20) ); testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(new[] diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs index 735267cdbb6..9d1f68f7092 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs @@ -86,7 +86,7 @@ public void combines_contract_and_local_data_correctly() Assert.That( () => testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header), - Is.EquivalentTo(expected.Cast()).After(1000, 100) + Is.EquivalentTo(expected.Cast()).After(200, 20) ); localDataSource.Data.Returns(new[] { TestItem.AddressC, TestItem.AddressD }); @@ -95,7 +95,7 @@ public void combines_contract_and_local_data_correctly() Assert.That( () => testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header), - Is.EquivalentTo(expected.Cast()).After(1000, 100) + Is.EquivalentTo(expected.Cast()).After(200, 20) ); } From 04a460412913c7c336e5a185d51651a4e3fd0f83 Mon Sep 17 00:00:00 2001 From: ANtutov Date: Tue, 23 Dec 2025 15:14:47 +0200 Subject: [PATCH 120/255] fix: delegate raw converters read to base converters (#10006) * fix: delegate raw converters read to base converters * fix: delegate raw converters read to base converters * fix --- .../LongConverter.cs | 13 +++++++++---- .../LongRawJsonConverter.cs | 18 +----------------- .../ULongConverter.cs | 13 +++++++++---- .../ULongRawJsonConverter.cs | 18 +----------------- 4 files changed, 20 insertions(+), 42 deletions(-) diff --git a/src/Nethermind/Nethermind.Serialization.Json/LongConverter.cs b/src/Nethermind/Nethermind.Serialization.Json/LongConverter.cs index 37756065e77..7b46c9e2dc3 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/LongConverter.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/LongConverter.cs @@ -79,10 +79,7 @@ public static long FromString(ReadOnlySpan s) throw new JsonException("hex to long"); } - public override long Read( - ref Utf8JsonReader reader, - Type typeToConvert, - JsonSerializerOptions options) + internal static long ReadCore(ref Utf8JsonReader reader) { if (reader.TokenType == JsonTokenType.Number) { @@ -103,6 +100,14 @@ public override long Read( throw new JsonException(); } + public override long Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options) + { + return ReadCore(ref reader); + } + [SkipLocalsInit] public override void Write( Utf8JsonWriter writer, diff --git a/src/Nethermind/Nethermind.Serialization.Json/LongRawJsonConverter.cs b/src/Nethermind/Nethermind.Serialization.Json/LongRawJsonConverter.cs index df81b47e6be..aec0b06c5d7 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/LongRawJsonConverter.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/LongRawJsonConverter.cs @@ -15,23 +15,7 @@ public override long Read( Type typeToConvert, JsonSerializerOptions options) { - if (reader.TokenType == JsonTokenType.Number) - { - return reader.GetInt64(); - } - else if (reader.TokenType == JsonTokenType.String) - { - if (!reader.HasValueSequence) - { - return LongConverter.FromString(reader.ValueSpan); - } - else - { - return LongConverter.FromString(reader.ValueSequence.ToArray()); - } - } - - throw new JsonException(); + return LongConverter.ReadCore(ref reader); } public override void Write( diff --git a/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs b/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs index a2637fb085c..e0fb0988f5e 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs @@ -78,10 +78,7 @@ public override void Write( } } - public override ulong Read( - ref Utf8JsonReader reader, - Type typeToConvert, - JsonSerializerOptions options) + internal static ulong ReadCore(ref Utf8JsonReader reader) { if (reader.TokenType == JsonTokenType.Number) { @@ -101,5 +98,13 @@ public override ulong Read( throw new JsonException(); } + + public override ulong Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options) + { + return ReadCore(ref reader); + } } } diff --git a/src/Nethermind/Nethermind.Serialization.Json/ULongRawJsonConverter.cs b/src/Nethermind/Nethermind.Serialization.Json/ULongRawJsonConverter.cs index fa172ac039c..bb1d6b92e8f 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/ULongRawJsonConverter.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/ULongRawJsonConverter.cs @@ -15,23 +15,7 @@ public override ulong Read( Type typeToConvert, JsonSerializerOptions options) { - if (reader.TokenType == JsonTokenType.Number) - { - return reader.GetUInt64(); - } - else if (reader.TokenType == JsonTokenType.String) - { - if (!reader.HasValueSequence) - { - return ULongConverter.FromString(reader.ValueSpan); - } - else - { - return ULongConverter.FromString(reader.ValueSequence.ToArray()); - } - } - - throw new JsonException(); + return ULongConverter.ReadCore(ref reader); } public override void Write( From 5412d22f67a4d7e987b2e25982c2d96f5953a20c Mon Sep 17 00:00:00 2001 From: Bashmunta Date: Tue, 23 Dec 2025 15:37:09 +0200 Subject: [PATCH 121/255] fix: remove duplicate HasSignedRecently checks in sealer clique (#10011) --- .../Nethermind.Consensus.Clique/CliqueSealer.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus.Clique/CliqueSealer.cs b/src/Nethermind/Nethermind.Consensus.Clique/CliqueSealer.cs index f7f8ffed645..c2553622c2b 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/CliqueSealer.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/CliqueSealer.cs @@ -101,15 +101,6 @@ public bool CanSeal(long blockNumber, Hash256 parentHash) return false; } - if (_snapshotManager.HasSignedRecently(snapshot, blockNumber, _signer.Address)) - { - if (_snapshotManager.HasSignedRecently(snapshot, blockNumber, _signer.Address)) - { - if (_logger.IsTrace) _logger.Trace("Signed recently"); - return false; - } - } - // If we're amongst the recent signers, wait for the next block if (_snapshotManager.HasSignedRecently(snapshot, blockNumber, _signer.Address)) { From 06e12cf5a5829785f9cd5a8b9ffd05a1f65b317d Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Tue, 23 Dec 2025 15:53:09 +0100 Subject: [PATCH 122/255] Make Nethermind UI SSE endpoint relative (#10008) --- .../Nethermind.Runner/Monitoring/DataFeedExtensions.cs | 2 +- src/Nethermind/Nethermind.Runner/wwwroot/js/bundle.js | 2 +- src/Nethermind/Nethermind.UI/scripts/app.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/Monitoring/DataFeedExtensions.cs b/src/Nethermind/Nethermind.Runner/Monitoring/DataFeedExtensions.cs index c5f8dd28d08..cb3a27d243f 100644 --- a/src/Nethermind/Nethermind.Runner/Monitoring/DataFeedExtensions.cs +++ b/src/Nethermind/Nethermind.Runner/Monitoring/DataFeedExtensions.cs @@ -36,6 +36,6 @@ public static void MapDataFeeds(this IEndpointRouteBuilder endpoints, Applicatio _dataFeed = new DataFeed(txPool, specProvider, receiptFinder, blockTree, syncPeerPool, mainProcessingContext, logManager, lifetime.ApplicationStopped); - endpoints.MapGet("/data/events", _dataFeed.ProcessingFeedAsync); + endpoints.MapGet("data/events", _dataFeed.ProcessingFeedAsync); } } diff --git a/src/Nethermind/Nethermind.Runner/wwwroot/js/bundle.js b/src/Nethermind/Nethermind.Runner/wwwroot/js/bundle.js index 2bcc888ebfe..4c493e6bdf5 100644 --- a/src/Nethermind/Nethermind.Runner/wwwroot/js/bundle.js +++ b/src/Nethermind/Nethermind.Runner/wwwroot/js/bundle.js @@ -1,6 +1,6 @@ (()=>{var Ct=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var ai=Ct((KS,mh)=>{mh.exports={Aacute:"\xC1",aacute:"\xE1",Abreve:"\u0102",abreve:"\u0103",ac:"\u223E",acd:"\u223F",acE:"\u223E\u0333",Acirc:"\xC2",acirc:"\xE2",acute:"\xB4",Acy:"\u0410",acy:"\u0430",AElig:"\xC6",aelig:"\xE6",af:"\u2061",Afr:"\u{1D504}",afr:"\u{1D51E}",Agrave:"\xC0",agrave:"\xE0",alefsym:"\u2135",aleph:"\u2135",Alpha:"\u0391",alpha:"\u03B1",Amacr:"\u0100",amacr:"\u0101",amalg:"\u2A3F",amp:"&",AMP:"&",andand:"\u2A55",And:"\u2A53",and:"\u2227",andd:"\u2A5C",andslope:"\u2A58",andv:"\u2A5A",ang:"\u2220",ange:"\u29A4",angle:"\u2220",angmsdaa:"\u29A8",angmsdab:"\u29A9",angmsdac:"\u29AA",angmsdad:"\u29AB",angmsdae:"\u29AC",angmsdaf:"\u29AD",angmsdag:"\u29AE",angmsdah:"\u29AF",angmsd:"\u2221",angrt:"\u221F",angrtvb:"\u22BE",angrtvbd:"\u299D",angsph:"\u2222",angst:"\xC5",angzarr:"\u237C",Aogon:"\u0104",aogon:"\u0105",Aopf:"\u{1D538}",aopf:"\u{1D552}",apacir:"\u2A6F",ap:"\u2248",apE:"\u2A70",ape:"\u224A",apid:"\u224B",apos:"'",ApplyFunction:"\u2061",approx:"\u2248",approxeq:"\u224A",Aring:"\xC5",aring:"\xE5",Ascr:"\u{1D49C}",ascr:"\u{1D4B6}",Assign:"\u2254",ast:"*",asymp:"\u2248",asympeq:"\u224D",Atilde:"\xC3",atilde:"\xE3",Auml:"\xC4",auml:"\xE4",awconint:"\u2233",awint:"\u2A11",backcong:"\u224C",backepsilon:"\u03F6",backprime:"\u2035",backsim:"\u223D",backsimeq:"\u22CD",Backslash:"\u2216",Barv:"\u2AE7",barvee:"\u22BD",barwed:"\u2305",Barwed:"\u2306",barwedge:"\u2305",bbrk:"\u23B5",bbrktbrk:"\u23B6",bcong:"\u224C",Bcy:"\u0411",bcy:"\u0431",bdquo:"\u201E",becaus:"\u2235",because:"\u2235",Because:"\u2235",bemptyv:"\u29B0",bepsi:"\u03F6",bernou:"\u212C",Bernoullis:"\u212C",Beta:"\u0392",beta:"\u03B2",beth:"\u2136",between:"\u226C",Bfr:"\u{1D505}",bfr:"\u{1D51F}",bigcap:"\u22C2",bigcirc:"\u25EF",bigcup:"\u22C3",bigodot:"\u2A00",bigoplus:"\u2A01",bigotimes:"\u2A02",bigsqcup:"\u2A06",bigstar:"\u2605",bigtriangledown:"\u25BD",bigtriangleup:"\u25B3",biguplus:"\u2A04",bigvee:"\u22C1",bigwedge:"\u22C0",bkarow:"\u290D",blacklozenge:"\u29EB",blacksquare:"\u25AA",blacktriangle:"\u25B4",blacktriangledown:"\u25BE",blacktriangleleft:"\u25C2",blacktriangleright:"\u25B8",blank:"\u2423",blk12:"\u2592",blk14:"\u2591",blk34:"\u2593",block:"\u2588",bne:"=\u20E5",bnequiv:"\u2261\u20E5",bNot:"\u2AED",bnot:"\u2310",Bopf:"\u{1D539}",bopf:"\u{1D553}",bot:"\u22A5",bottom:"\u22A5",bowtie:"\u22C8",boxbox:"\u29C9",boxdl:"\u2510",boxdL:"\u2555",boxDl:"\u2556",boxDL:"\u2557",boxdr:"\u250C",boxdR:"\u2552",boxDr:"\u2553",boxDR:"\u2554",boxh:"\u2500",boxH:"\u2550",boxhd:"\u252C",boxHd:"\u2564",boxhD:"\u2565",boxHD:"\u2566",boxhu:"\u2534",boxHu:"\u2567",boxhU:"\u2568",boxHU:"\u2569",boxminus:"\u229F",boxplus:"\u229E",boxtimes:"\u22A0",boxul:"\u2518",boxuL:"\u255B",boxUl:"\u255C",boxUL:"\u255D",boxur:"\u2514",boxuR:"\u2558",boxUr:"\u2559",boxUR:"\u255A",boxv:"\u2502",boxV:"\u2551",boxvh:"\u253C",boxvH:"\u256A",boxVh:"\u256B",boxVH:"\u256C",boxvl:"\u2524",boxvL:"\u2561",boxVl:"\u2562",boxVL:"\u2563",boxvr:"\u251C",boxvR:"\u255E",boxVr:"\u255F",boxVR:"\u2560",bprime:"\u2035",breve:"\u02D8",Breve:"\u02D8",brvbar:"\xA6",bscr:"\u{1D4B7}",Bscr:"\u212C",bsemi:"\u204F",bsim:"\u223D",bsime:"\u22CD",bsolb:"\u29C5",bsol:"\\",bsolhsub:"\u27C8",bull:"\u2022",bullet:"\u2022",bump:"\u224E",bumpE:"\u2AAE",bumpe:"\u224F",Bumpeq:"\u224E",bumpeq:"\u224F",Cacute:"\u0106",cacute:"\u0107",capand:"\u2A44",capbrcup:"\u2A49",capcap:"\u2A4B",cap:"\u2229",Cap:"\u22D2",capcup:"\u2A47",capdot:"\u2A40",CapitalDifferentialD:"\u2145",caps:"\u2229\uFE00",caret:"\u2041",caron:"\u02C7",Cayleys:"\u212D",ccaps:"\u2A4D",Ccaron:"\u010C",ccaron:"\u010D",Ccedil:"\xC7",ccedil:"\xE7",Ccirc:"\u0108",ccirc:"\u0109",Cconint:"\u2230",ccups:"\u2A4C",ccupssm:"\u2A50",Cdot:"\u010A",cdot:"\u010B",cedil:"\xB8",Cedilla:"\xB8",cemptyv:"\u29B2",cent:"\xA2",centerdot:"\xB7",CenterDot:"\xB7",cfr:"\u{1D520}",Cfr:"\u212D",CHcy:"\u0427",chcy:"\u0447",check:"\u2713",checkmark:"\u2713",Chi:"\u03A7",chi:"\u03C7",circ:"\u02C6",circeq:"\u2257",circlearrowleft:"\u21BA",circlearrowright:"\u21BB",circledast:"\u229B",circledcirc:"\u229A",circleddash:"\u229D",CircleDot:"\u2299",circledR:"\xAE",circledS:"\u24C8",CircleMinus:"\u2296",CirclePlus:"\u2295",CircleTimes:"\u2297",cir:"\u25CB",cirE:"\u29C3",cire:"\u2257",cirfnint:"\u2A10",cirmid:"\u2AEF",cirscir:"\u29C2",ClockwiseContourIntegral:"\u2232",CloseCurlyDoubleQuote:"\u201D",CloseCurlyQuote:"\u2019",clubs:"\u2663",clubsuit:"\u2663",colon:":",Colon:"\u2237",Colone:"\u2A74",colone:"\u2254",coloneq:"\u2254",comma:",",commat:"@",comp:"\u2201",compfn:"\u2218",complement:"\u2201",complexes:"\u2102",cong:"\u2245",congdot:"\u2A6D",Congruent:"\u2261",conint:"\u222E",Conint:"\u222F",ContourIntegral:"\u222E",copf:"\u{1D554}",Copf:"\u2102",coprod:"\u2210",Coproduct:"\u2210",copy:"\xA9",COPY:"\xA9",copysr:"\u2117",CounterClockwiseContourIntegral:"\u2233",crarr:"\u21B5",cross:"\u2717",Cross:"\u2A2F",Cscr:"\u{1D49E}",cscr:"\u{1D4B8}",csub:"\u2ACF",csube:"\u2AD1",csup:"\u2AD0",csupe:"\u2AD2",ctdot:"\u22EF",cudarrl:"\u2938",cudarrr:"\u2935",cuepr:"\u22DE",cuesc:"\u22DF",cularr:"\u21B6",cularrp:"\u293D",cupbrcap:"\u2A48",cupcap:"\u2A46",CupCap:"\u224D",cup:"\u222A",Cup:"\u22D3",cupcup:"\u2A4A",cupdot:"\u228D",cupor:"\u2A45",cups:"\u222A\uFE00",curarr:"\u21B7",curarrm:"\u293C",curlyeqprec:"\u22DE",curlyeqsucc:"\u22DF",curlyvee:"\u22CE",curlywedge:"\u22CF",curren:"\xA4",curvearrowleft:"\u21B6",curvearrowright:"\u21B7",cuvee:"\u22CE",cuwed:"\u22CF",cwconint:"\u2232",cwint:"\u2231",cylcty:"\u232D",dagger:"\u2020",Dagger:"\u2021",daleth:"\u2138",darr:"\u2193",Darr:"\u21A1",dArr:"\u21D3",dash:"\u2010",Dashv:"\u2AE4",dashv:"\u22A3",dbkarow:"\u290F",dblac:"\u02DD",Dcaron:"\u010E",dcaron:"\u010F",Dcy:"\u0414",dcy:"\u0434",ddagger:"\u2021",ddarr:"\u21CA",DD:"\u2145",dd:"\u2146",DDotrahd:"\u2911",ddotseq:"\u2A77",deg:"\xB0",Del:"\u2207",Delta:"\u0394",delta:"\u03B4",demptyv:"\u29B1",dfisht:"\u297F",Dfr:"\u{1D507}",dfr:"\u{1D521}",dHar:"\u2965",dharl:"\u21C3",dharr:"\u21C2",DiacriticalAcute:"\xB4",DiacriticalDot:"\u02D9",DiacriticalDoubleAcute:"\u02DD",DiacriticalGrave:"`",DiacriticalTilde:"\u02DC",diam:"\u22C4",diamond:"\u22C4",Diamond:"\u22C4",diamondsuit:"\u2666",diams:"\u2666",die:"\xA8",DifferentialD:"\u2146",digamma:"\u03DD",disin:"\u22F2",div:"\xF7",divide:"\xF7",divideontimes:"\u22C7",divonx:"\u22C7",DJcy:"\u0402",djcy:"\u0452",dlcorn:"\u231E",dlcrop:"\u230D",dollar:"$",Dopf:"\u{1D53B}",dopf:"\u{1D555}",Dot:"\xA8",dot:"\u02D9",DotDot:"\u20DC",doteq:"\u2250",doteqdot:"\u2251",DotEqual:"\u2250",dotminus:"\u2238",dotplus:"\u2214",dotsquare:"\u22A1",doublebarwedge:"\u2306",DoubleContourIntegral:"\u222F",DoubleDot:"\xA8",DoubleDownArrow:"\u21D3",DoubleLeftArrow:"\u21D0",DoubleLeftRightArrow:"\u21D4",DoubleLeftTee:"\u2AE4",DoubleLongLeftArrow:"\u27F8",DoubleLongLeftRightArrow:"\u27FA",DoubleLongRightArrow:"\u27F9",DoubleRightArrow:"\u21D2",DoubleRightTee:"\u22A8",DoubleUpArrow:"\u21D1",DoubleUpDownArrow:"\u21D5",DoubleVerticalBar:"\u2225",DownArrowBar:"\u2913",downarrow:"\u2193",DownArrow:"\u2193",Downarrow:"\u21D3",DownArrowUpArrow:"\u21F5",DownBreve:"\u0311",downdownarrows:"\u21CA",downharpoonleft:"\u21C3",downharpoonright:"\u21C2",DownLeftRightVector:"\u2950",DownLeftTeeVector:"\u295E",DownLeftVectorBar:"\u2956",DownLeftVector:"\u21BD",DownRightTeeVector:"\u295F",DownRightVectorBar:"\u2957",DownRightVector:"\u21C1",DownTeeArrow:"\u21A7",DownTee:"\u22A4",drbkarow:"\u2910",drcorn:"\u231F",drcrop:"\u230C",Dscr:"\u{1D49F}",dscr:"\u{1D4B9}",DScy:"\u0405",dscy:"\u0455",dsol:"\u29F6",Dstrok:"\u0110",dstrok:"\u0111",dtdot:"\u22F1",dtri:"\u25BF",dtrif:"\u25BE",duarr:"\u21F5",duhar:"\u296F",dwangle:"\u29A6",DZcy:"\u040F",dzcy:"\u045F",dzigrarr:"\u27FF",Eacute:"\xC9",eacute:"\xE9",easter:"\u2A6E",Ecaron:"\u011A",ecaron:"\u011B",Ecirc:"\xCA",ecirc:"\xEA",ecir:"\u2256",ecolon:"\u2255",Ecy:"\u042D",ecy:"\u044D",eDDot:"\u2A77",Edot:"\u0116",edot:"\u0117",eDot:"\u2251",ee:"\u2147",efDot:"\u2252",Efr:"\u{1D508}",efr:"\u{1D522}",eg:"\u2A9A",Egrave:"\xC8",egrave:"\xE8",egs:"\u2A96",egsdot:"\u2A98",el:"\u2A99",Element:"\u2208",elinters:"\u23E7",ell:"\u2113",els:"\u2A95",elsdot:"\u2A97",Emacr:"\u0112",emacr:"\u0113",empty:"\u2205",emptyset:"\u2205",EmptySmallSquare:"\u25FB",emptyv:"\u2205",EmptyVerySmallSquare:"\u25AB",emsp13:"\u2004",emsp14:"\u2005",emsp:"\u2003",ENG:"\u014A",eng:"\u014B",ensp:"\u2002",Eogon:"\u0118",eogon:"\u0119",Eopf:"\u{1D53C}",eopf:"\u{1D556}",epar:"\u22D5",eparsl:"\u29E3",eplus:"\u2A71",epsi:"\u03B5",Epsilon:"\u0395",epsilon:"\u03B5",epsiv:"\u03F5",eqcirc:"\u2256",eqcolon:"\u2255",eqsim:"\u2242",eqslantgtr:"\u2A96",eqslantless:"\u2A95",Equal:"\u2A75",equals:"=",EqualTilde:"\u2242",equest:"\u225F",Equilibrium:"\u21CC",equiv:"\u2261",equivDD:"\u2A78",eqvparsl:"\u29E5",erarr:"\u2971",erDot:"\u2253",escr:"\u212F",Escr:"\u2130",esdot:"\u2250",Esim:"\u2A73",esim:"\u2242",Eta:"\u0397",eta:"\u03B7",ETH:"\xD0",eth:"\xF0",Euml:"\xCB",euml:"\xEB",euro:"\u20AC",excl:"!",exist:"\u2203",Exists:"\u2203",expectation:"\u2130",exponentiale:"\u2147",ExponentialE:"\u2147",fallingdotseq:"\u2252",Fcy:"\u0424",fcy:"\u0444",female:"\u2640",ffilig:"\uFB03",fflig:"\uFB00",ffllig:"\uFB04",Ffr:"\u{1D509}",ffr:"\u{1D523}",filig:"\uFB01",FilledSmallSquare:"\u25FC",FilledVerySmallSquare:"\u25AA",fjlig:"fj",flat:"\u266D",fllig:"\uFB02",fltns:"\u25B1",fnof:"\u0192",Fopf:"\u{1D53D}",fopf:"\u{1D557}",forall:"\u2200",ForAll:"\u2200",fork:"\u22D4",forkv:"\u2AD9",Fouriertrf:"\u2131",fpartint:"\u2A0D",frac12:"\xBD",frac13:"\u2153",frac14:"\xBC",frac15:"\u2155",frac16:"\u2159",frac18:"\u215B",frac23:"\u2154",frac25:"\u2156",frac34:"\xBE",frac35:"\u2157",frac38:"\u215C",frac45:"\u2158",frac56:"\u215A",frac58:"\u215D",frac78:"\u215E",frasl:"\u2044",frown:"\u2322",fscr:"\u{1D4BB}",Fscr:"\u2131",gacute:"\u01F5",Gamma:"\u0393",gamma:"\u03B3",Gammad:"\u03DC",gammad:"\u03DD",gap:"\u2A86",Gbreve:"\u011E",gbreve:"\u011F",Gcedil:"\u0122",Gcirc:"\u011C",gcirc:"\u011D",Gcy:"\u0413",gcy:"\u0433",Gdot:"\u0120",gdot:"\u0121",ge:"\u2265",gE:"\u2267",gEl:"\u2A8C",gel:"\u22DB",geq:"\u2265",geqq:"\u2267",geqslant:"\u2A7E",gescc:"\u2AA9",ges:"\u2A7E",gesdot:"\u2A80",gesdoto:"\u2A82",gesdotol:"\u2A84",gesl:"\u22DB\uFE00",gesles:"\u2A94",Gfr:"\u{1D50A}",gfr:"\u{1D524}",gg:"\u226B",Gg:"\u22D9",ggg:"\u22D9",gimel:"\u2137",GJcy:"\u0403",gjcy:"\u0453",gla:"\u2AA5",gl:"\u2277",glE:"\u2A92",glj:"\u2AA4",gnap:"\u2A8A",gnapprox:"\u2A8A",gne:"\u2A88",gnE:"\u2269",gneq:"\u2A88",gneqq:"\u2269",gnsim:"\u22E7",Gopf:"\u{1D53E}",gopf:"\u{1D558}",grave:"`",GreaterEqual:"\u2265",GreaterEqualLess:"\u22DB",GreaterFullEqual:"\u2267",GreaterGreater:"\u2AA2",GreaterLess:"\u2277",GreaterSlantEqual:"\u2A7E",GreaterTilde:"\u2273",Gscr:"\u{1D4A2}",gscr:"\u210A",gsim:"\u2273",gsime:"\u2A8E",gsiml:"\u2A90",gtcc:"\u2AA7",gtcir:"\u2A7A",gt:">",GT:">",Gt:"\u226B",gtdot:"\u22D7",gtlPar:"\u2995",gtquest:"\u2A7C",gtrapprox:"\u2A86",gtrarr:"\u2978",gtrdot:"\u22D7",gtreqless:"\u22DB",gtreqqless:"\u2A8C",gtrless:"\u2277",gtrsim:"\u2273",gvertneqq:"\u2269\uFE00",gvnE:"\u2269\uFE00",Hacek:"\u02C7",hairsp:"\u200A",half:"\xBD",hamilt:"\u210B",HARDcy:"\u042A",hardcy:"\u044A",harrcir:"\u2948",harr:"\u2194",hArr:"\u21D4",harrw:"\u21AD",Hat:"^",hbar:"\u210F",Hcirc:"\u0124",hcirc:"\u0125",hearts:"\u2665",heartsuit:"\u2665",hellip:"\u2026",hercon:"\u22B9",hfr:"\u{1D525}",Hfr:"\u210C",HilbertSpace:"\u210B",hksearow:"\u2925",hkswarow:"\u2926",hoarr:"\u21FF",homtht:"\u223B",hookleftarrow:"\u21A9",hookrightarrow:"\u21AA",hopf:"\u{1D559}",Hopf:"\u210D",horbar:"\u2015",HorizontalLine:"\u2500",hscr:"\u{1D4BD}",Hscr:"\u210B",hslash:"\u210F",Hstrok:"\u0126",hstrok:"\u0127",HumpDownHump:"\u224E",HumpEqual:"\u224F",hybull:"\u2043",hyphen:"\u2010",Iacute:"\xCD",iacute:"\xED",ic:"\u2063",Icirc:"\xCE",icirc:"\xEE",Icy:"\u0418",icy:"\u0438",Idot:"\u0130",IEcy:"\u0415",iecy:"\u0435",iexcl:"\xA1",iff:"\u21D4",ifr:"\u{1D526}",Ifr:"\u2111",Igrave:"\xCC",igrave:"\xEC",ii:"\u2148",iiiint:"\u2A0C",iiint:"\u222D",iinfin:"\u29DC",iiota:"\u2129",IJlig:"\u0132",ijlig:"\u0133",Imacr:"\u012A",imacr:"\u012B",image:"\u2111",ImaginaryI:"\u2148",imagline:"\u2110",imagpart:"\u2111",imath:"\u0131",Im:"\u2111",imof:"\u22B7",imped:"\u01B5",Implies:"\u21D2",incare:"\u2105",in:"\u2208",infin:"\u221E",infintie:"\u29DD",inodot:"\u0131",intcal:"\u22BA",int:"\u222B",Int:"\u222C",integers:"\u2124",Integral:"\u222B",intercal:"\u22BA",Intersection:"\u22C2",intlarhk:"\u2A17",intprod:"\u2A3C",InvisibleComma:"\u2063",InvisibleTimes:"\u2062",IOcy:"\u0401",iocy:"\u0451",Iogon:"\u012E",iogon:"\u012F",Iopf:"\u{1D540}",iopf:"\u{1D55A}",Iota:"\u0399",iota:"\u03B9",iprod:"\u2A3C",iquest:"\xBF",iscr:"\u{1D4BE}",Iscr:"\u2110",isin:"\u2208",isindot:"\u22F5",isinE:"\u22F9",isins:"\u22F4",isinsv:"\u22F3",isinv:"\u2208",it:"\u2062",Itilde:"\u0128",itilde:"\u0129",Iukcy:"\u0406",iukcy:"\u0456",Iuml:"\xCF",iuml:"\xEF",Jcirc:"\u0134",jcirc:"\u0135",Jcy:"\u0419",jcy:"\u0439",Jfr:"\u{1D50D}",jfr:"\u{1D527}",jmath:"\u0237",Jopf:"\u{1D541}",jopf:"\u{1D55B}",Jscr:"\u{1D4A5}",jscr:"\u{1D4BF}",Jsercy:"\u0408",jsercy:"\u0458",Jukcy:"\u0404",jukcy:"\u0454",Kappa:"\u039A",kappa:"\u03BA",kappav:"\u03F0",Kcedil:"\u0136",kcedil:"\u0137",Kcy:"\u041A",kcy:"\u043A",Kfr:"\u{1D50E}",kfr:"\u{1D528}",kgreen:"\u0138",KHcy:"\u0425",khcy:"\u0445",KJcy:"\u040C",kjcy:"\u045C",Kopf:"\u{1D542}",kopf:"\u{1D55C}",Kscr:"\u{1D4A6}",kscr:"\u{1D4C0}",lAarr:"\u21DA",Lacute:"\u0139",lacute:"\u013A",laemptyv:"\u29B4",lagran:"\u2112",Lambda:"\u039B",lambda:"\u03BB",lang:"\u27E8",Lang:"\u27EA",langd:"\u2991",langle:"\u27E8",lap:"\u2A85",Laplacetrf:"\u2112",laquo:"\xAB",larrb:"\u21E4",larrbfs:"\u291F",larr:"\u2190",Larr:"\u219E",lArr:"\u21D0",larrfs:"\u291D",larrhk:"\u21A9",larrlp:"\u21AB",larrpl:"\u2939",larrsim:"\u2973",larrtl:"\u21A2",latail:"\u2919",lAtail:"\u291B",lat:"\u2AAB",late:"\u2AAD",lates:"\u2AAD\uFE00",lbarr:"\u290C",lBarr:"\u290E",lbbrk:"\u2772",lbrace:"{",lbrack:"[",lbrke:"\u298B",lbrksld:"\u298F",lbrkslu:"\u298D",Lcaron:"\u013D",lcaron:"\u013E",Lcedil:"\u013B",lcedil:"\u013C",lceil:"\u2308",lcub:"{",Lcy:"\u041B",lcy:"\u043B",ldca:"\u2936",ldquo:"\u201C",ldquor:"\u201E",ldrdhar:"\u2967",ldrushar:"\u294B",ldsh:"\u21B2",le:"\u2264",lE:"\u2266",LeftAngleBracket:"\u27E8",LeftArrowBar:"\u21E4",leftarrow:"\u2190",LeftArrow:"\u2190",Leftarrow:"\u21D0",LeftArrowRightArrow:"\u21C6",leftarrowtail:"\u21A2",LeftCeiling:"\u2308",LeftDoubleBracket:"\u27E6",LeftDownTeeVector:"\u2961",LeftDownVectorBar:"\u2959",LeftDownVector:"\u21C3",LeftFloor:"\u230A",leftharpoondown:"\u21BD",leftharpoonup:"\u21BC",leftleftarrows:"\u21C7",leftrightarrow:"\u2194",LeftRightArrow:"\u2194",Leftrightarrow:"\u21D4",leftrightarrows:"\u21C6",leftrightharpoons:"\u21CB",leftrightsquigarrow:"\u21AD",LeftRightVector:"\u294E",LeftTeeArrow:"\u21A4",LeftTee:"\u22A3",LeftTeeVector:"\u295A",leftthreetimes:"\u22CB",LeftTriangleBar:"\u29CF",LeftTriangle:"\u22B2",LeftTriangleEqual:"\u22B4",LeftUpDownVector:"\u2951",LeftUpTeeVector:"\u2960",LeftUpVectorBar:"\u2958",LeftUpVector:"\u21BF",LeftVectorBar:"\u2952",LeftVector:"\u21BC",lEg:"\u2A8B",leg:"\u22DA",leq:"\u2264",leqq:"\u2266",leqslant:"\u2A7D",lescc:"\u2AA8",les:"\u2A7D",lesdot:"\u2A7F",lesdoto:"\u2A81",lesdotor:"\u2A83",lesg:"\u22DA\uFE00",lesges:"\u2A93",lessapprox:"\u2A85",lessdot:"\u22D6",lesseqgtr:"\u22DA",lesseqqgtr:"\u2A8B",LessEqualGreater:"\u22DA",LessFullEqual:"\u2266",LessGreater:"\u2276",lessgtr:"\u2276",LessLess:"\u2AA1",lesssim:"\u2272",LessSlantEqual:"\u2A7D",LessTilde:"\u2272",lfisht:"\u297C",lfloor:"\u230A",Lfr:"\u{1D50F}",lfr:"\u{1D529}",lg:"\u2276",lgE:"\u2A91",lHar:"\u2962",lhard:"\u21BD",lharu:"\u21BC",lharul:"\u296A",lhblk:"\u2584",LJcy:"\u0409",ljcy:"\u0459",llarr:"\u21C7",ll:"\u226A",Ll:"\u22D8",llcorner:"\u231E",Lleftarrow:"\u21DA",llhard:"\u296B",lltri:"\u25FA",Lmidot:"\u013F",lmidot:"\u0140",lmoustache:"\u23B0",lmoust:"\u23B0",lnap:"\u2A89",lnapprox:"\u2A89",lne:"\u2A87",lnE:"\u2268",lneq:"\u2A87",lneqq:"\u2268",lnsim:"\u22E6",loang:"\u27EC",loarr:"\u21FD",lobrk:"\u27E6",longleftarrow:"\u27F5",LongLeftArrow:"\u27F5",Longleftarrow:"\u27F8",longleftrightarrow:"\u27F7",LongLeftRightArrow:"\u27F7",Longleftrightarrow:"\u27FA",longmapsto:"\u27FC",longrightarrow:"\u27F6",LongRightArrow:"\u27F6",Longrightarrow:"\u27F9",looparrowleft:"\u21AB",looparrowright:"\u21AC",lopar:"\u2985",Lopf:"\u{1D543}",lopf:"\u{1D55D}",loplus:"\u2A2D",lotimes:"\u2A34",lowast:"\u2217",lowbar:"_",LowerLeftArrow:"\u2199",LowerRightArrow:"\u2198",loz:"\u25CA",lozenge:"\u25CA",lozf:"\u29EB",lpar:"(",lparlt:"\u2993",lrarr:"\u21C6",lrcorner:"\u231F",lrhar:"\u21CB",lrhard:"\u296D",lrm:"\u200E",lrtri:"\u22BF",lsaquo:"\u2039",lscr:"\u{1D4C1}",Lscr:"\u2112",lsh:"\u21B0",Lsh:"\u21B0",lsim:"\u2272",lsime:"\u2A8D",lsimg:"\u2A8F",lsqb:"[",lsquo:"\u2018",lsquor:"\u201A",Lstrok:"\u0141",lstrok:"\u0142",ltcc:"\u2AA6",ltcir:"\u2A79",lt:"<",LT:"<",Lt:"\u226A",ltdot:"\u22D6",lthree:"\u22CB",ltimes:"\u22C9",ltlarr:"\u2976",ltquest:"\u2A7B",ltri:"\u25C3",ltrie:"\u22B4",ltrif:"\u25C2",ltrPar:"\u2996",lurdshar:"\u294A",luruhar:"\u2966",lvertneqq:"\u2268\uFE00",lvnE:"\u2268\uFE00",macr:"\xAF",male:"\u2642",malt:"\u2720",maltese:"\u2720",Map:"\u2905",map:"\u21A6",mapsto:"\u21A6",mapstodown:"\u21A7",mapstoleft:"\u21A4",mapstoup:"\u21A5",marker:"\u25AE",mcomma:"\u2A29",Mcy:"\u041C",mcy:"\u043C",mdash:"\u2014",mDDot:"\u223A",measuredangle:"\u2221",MediumSpace:"\u205F",Mellintrf:"\u2133",Mfr:"\u{1D510}",mfr:"\u{1D52A}",mho:"\u2127",micro:"\xB5",midast:"*",midcir:"\u2AF0",mid:"\u2223",middot:"\xB7",minusb:"\u229F",minus:"\u2212",minusd:"\u2238",minusdu:"\u2A2A",MinusPlus:"\u2213",mlcp:"\u2ADB",mldr:"\u2026",mnplus:"\u2213",models:"\u22A7",Mopf:"\u{1D544}",mopf:"\u{1D55E}",mp:"\u2213",mscr:"\u{1D4C2}",Mscr:"\u2133",mstpos:"\u223E",Mu:"\u039C",mu:"\u03BC",multimap:"\u22B8",mumap:"\u22B8",nabla:"\u2207",Nacute:"\u0143",nacute:"\u0144",nang:"\u2220\u20D2",nap:"\u2249",napE:"\u2A70\u0338",napid:"\u224B\u0338",napos:"\u0149",napprox:"\u2249",natural:"\u266E",naturals:"\u2115",natur:"\u266E",nbsp:"\xA0",nbump:"\u224E\u0338",nbumpe:"\u224F\u0338",ncap:"\u2A43",Ncaron:"\u0147",ncaron:"\u0148",Ncedil:"\u0145",ncedil:"\u0146",ncong:"\u2247",ncongdot:"\u2A6D\u0338",ncup:"\u2A42",Ncy:"\u041D",ncy:"\u043D",ndash:"\u2013",nearhk:"\u2924",nearr:"\u2197",neArr:"\u21D7",nearrow:"\u2197",ne:"\u2260",nedot:"\u2250\u0338",NegativeMediumSpace:"\u200B",NegativeThickSpace:"\u200B",NegativeThinSpace:"\u200B",NegativeVeryThinSpace:"\u200B",nequiv:"\u2262",nesear:"\u2928",nesim:"\u2242\u0338",NestedGreaterGreater:"\u226B",NestedLessLess:"\u226A",NewLine:` `,nexist:"\u2204",nexists:"\u2204",Nfr:"\u{1D511}",nfr:"\u{1D52B}",ngE:"\u2267\u0338",nge:"\u2271",ngeq:"\u2271",ngeqq:"\u2267\u0338",ngeqslant:"\u2A7E\u0338",nges:"\u2A7E\u0338",nGg:"\u22D9\u0338",ngsim:"\u2275",nGt:"\u226B\u20D2",ngt:"\u226F",ngtr:"\u226F",nGtv:"\u226B\u0338",nharr:"\u21AE",nhArr:"\u21CE",nhpar:"\u2AF2",ni:"\u220B",nis:"\u22FC",nisd:"\u22FA",niv:"\u220B",NJcy:"\u040A",njcy:"\u045A",nlarr:"\u219A",nlArr:"\u21CD",nldr:"\u2025",nlE:"\u2266\u0338",nle:"\u2270",nleftarrow:"\u219A",nLeftarrow:"\u21CD",nleftrightarrow:"\u21AE",nLeftrightarrow:"\u21CE",nleq:"\u2270",nleqq:"\u2266\u0338",nleqslant:"\u2A7D\u0338",nles:"\u2A7D\u0338",nless:"\u226E",nLl:"\u22D8\u0338",nlsim:"\u2274",nLt:"\u226A\u20D2",nlt:"\u226E",nltri:"\u22EA",nltrie:"\u22EC",nLtv:"\u226A\u0338",nmid:"\u2224",NoBreak:"\u2060",NonBreakingSpace:"\xA0",nopf:"\u{1D55F}",Nopf:"\u2115",Not:"\u2AEC",not:"\xAC",NotCongruent:"\u2262",NotCupCap:"\u226D",NotDoubleVerticalBar:"\u2226",NotElement:"\u2209",NotEqual:"\u2260",NotEqualTilde:"\u2242\u0338",NotExists:"\u2204",NotGreater:"\u226F",NotGreaterEqual:"\u2271",NotGreaterFullEqual:"\u2267\u0338",NotGreaterGreater:"\u226B\u0338",NotGreaterLess:"\u2279",NotGreaterSlantEqual:"\u2A7E\u0338",NotGreaterTilde:"\u2275",NotHumpDownHump:"\u224E\u0338",NotHumpEqual:"\u224F\u0338",notin:"\u2209",notindot:"\u22F5\u0338",notinE:"\u22F9\u0338",notinva:"\u2209",notinvb:"\u22F7",notinvc:"\u22F6",NotLeftTriangleBar:"\u29CF\u0338",NotLeftTriangle:"\u22EA",NotLeftTriangleEqual:"\u22EC",NotLess:"\u226E",NotLessEqual:"\u2270",NotLessGreater:"\u2278",NotLessLess:"\u226A\u0338",NotLessSlantEqual:"\u2A7D\u0338",NotLessTilde:"\u2274",NotNestedGreaterGreater:"\u2AA2\u0338",NotNestedLessLess:"\u2AA1\u0338",notni:"\u220C",notniva:"\u220C",notnivb:"\u22FE",notnivc:"\u22FD",NotPrecedes:"\u2280",NotPrecedesEqual:"\u2AAF\u0338",NotPrecedesSlantEqual:"\u22E0",NotReverseElement:"\u220C",NotRightTriangleBar:"\u29D0\u0338",NotRightTriangle:"\u22EB",NotRightTriangleEqual:"\u22ED",NotSquareSubset:"\u228F\u0338",NotSquareSubsetEqual:"\u22E2",NotSquareSuperset:"\u2290\u0338",NotSquareSupersetEqual:"\u22E3",NotSubset:"\u2282\u20D2",NotSubsetEqual:"\u2288",NotSucceeds:"\u2281",NotSucceedsEqual:"\u2AB0\u0338",NotSucceedsSlantEqual:"\u22E1",NotSucceedsTilde:"\u227F\u0338",NotSuperset:"\u2283\u20D2",NotSupersetEqual:"\u2289",NotTilde:"\u2241",NotTildeEqual:"\u2244",NotTildeFullEqual:"\u2247",NotTildeTilde:"\u2249",NotVerticalBar:"\u2224",nparallel:"\u2226",npar:"\u2226",nparsl:"\u2AFD\u20E5",npart:"\u2202\u0338",npolint:"\u2A14",npr:"\u2280",nprcue:"\u22E0",nprec:"\u2280",npreceq:"\u2AAF\u0338",npre:"\u2AAF\u0338",nrarrc:"\u2933\u0338",nrarr:"\u219B",nrArr:"\u21CF",nrarrw:"\u219D\u0338",nrightarrow:"\u219B",nRightarrow:"\u21CF",nrtri:"\u22EB",nrtrie:"\u22ED",nsc:"\u2281",nsccue:"\u22E1",nsce:"\u2AB0\u0338",Nscr:"\u{1D4A9}",nscr:"\u{1D4C3}",nshortmid:"\u2224",nshortparallel:"\u2226",nsim:"\u2241",nsime:"\u2244",nsimeq:"\u2244",nsmid:"\u2224",nspar:"\u2226",nsqsube:"\u22E2",nsqsupe:"\u22E3",nsub:"\u2284",nsubE:"\u2AC5\u0338",nsube:"\u2288",nsubset:"\u2282\u20D2",nsubseteq:"\u2288",nsubseteqq:"\u2AC5\u0338",nsucc:"\u2281",nsucceq:"\u2AB0\u0338",nsup:"\u2285",nsupE:"\u2AC6\u0338",nsupe:"\u2289",nsupset:"\u2283\u20D2",nsupseteq:"\u2289",nsupseteqq:"\u2AC6\u0338",ntgl:"\u2279",Ntilde:"\xD1",ntilde:"\xF1",ntlg:"\u2278",ntriangleleft:"\u22EA",ntrianglelefteq:"\u22EC",ntriangleright:"\u22EB",ntrianglerighteq:"\u22ED",Nu:"\u039D",nu:"\u03BD",num:"#",numero:"\u2116",numsp:"\u2007",nvap:"\u224D\u20D2",nvdash:"\u22AC",nvDash:"\u22AD",nVdash:"\u22AE",nVDash:"\u22AF",nvge:"\u2265\u20D2",nvgt:">\u20D2",nvHarr:"\u2904",nvinfin:"\u29DE",nvlArr:"\u2902",nvle:"\u2264\u20D2",nvlt:"<\u20D2",nvltrie:"\u22B4\u20D2",nvrArr:"\u2903",nvrtrie:"\u22B5\u20D2",nvsim:"\u223C\u20D2",nwarhk:"\u2923",nwarr:"\u2196",nwArr:"\u21D6",nwarrow:"\u2196",nwnear:"\u2927",Oacute:"\xD3",oacute:"\xF3",oast:"\u229B",Ocirc:"\xD4",ocirc:"\xF4",ocir:"\u229A",Ocy:"\u041E",ocy:"\u043E",odash:"\u229D",Odblac:"\u0150",odblac:"\u0151",odiv:"\u2A38",odot:"\u2299",odsold:"\u29BC",OElig:"\u0152",oelig:"\u0153",ofcir:"\u29BF",Ofr:"\u{1D512}",ofr:"\u{1D52C}",ogon:"\u02DB",Ograve:"\xD2",ograve:"\xF2",ogt:"\u29C1",ohbar:"\u29B5",ohm:"\u03A9",oint:"\u222E",olarr:"\u21BA",olcir:"\u29BE",olcross:"\u29BB",oline:"\u203E",olt:"\u29C0",Omacr:"\u014C",omacr:"\u014D",Omega:"\u03A9",omega:"\u03C9",Omicron:"\u039F",omicron:"\u03BF",omid:"\u29B6",ominus:"\u2296",Oopf:"\u{1D546}",oopf:"\u{1D560}",opar:"\u29B7",OpenCurlyDoubleQuote:"\u201C",OpenCurlyQuote:"\u2018",operp:"\u29B9",oplus:"\u2295",orarr:"\u21BB",Or:"\u2A54",or:"\u2228",ord:"\u2A5D",order:"\u2134",orderof:"\u2134",ordf:"\xAA",ordm:"\xBA",origof:"\u22B6",oror:"\u2A56",orslope:"\u2A57",orv:"\u2A5B",oS:"\u24C8",Oscr:"\u{1D4AA}",oscr:"\u2134",Oslash:"\xD8",oslash:"\xF8",osol:"\u2298",Otilde:"\xD5",otilde:"\xF5",otimesas:"\u2A36",Otimes:"\u2A37",otimes:"\u2297",Ouml:"\xD6",ouml:"\xF6",ovbar:"\u233D",OverBar:"\u203E",OverBrace:"\u23DE",OverBracket:"\u23B4",OverParenthesis:"\u23DC",para:"\xB6",parallel:"\u2225",par:"\u2225",parsim:"\u2AF3",parsl:"\u2AFD",part:"\u2202",PartialD:"\u2202",Pcy:"\u041F",pcy:"\u043F",percnt:"%",period:".",permil:"\u2030",perp:"\u22A5",pertenk:"\u2031",Pfr:"\u{1D513}",pfr:"\u{1D52D}",Phi:"\u03A6",phi:"\u03C6",phiv:"\u03D5",phmmat:"\u2133",phone:"\u260E",Pi:"\u03A0",pi:"\u03C0",pitchfork:"\u22D4",piv:"\u03D6",planck:"\u210F",planckh:"\u210E",plankv:"\u210F",plusacir:"\u2A23",plusb:"\u229E",pluscir:"\u2A22",plus:"+",plusdo:"\u2214",plusdu:"\u2A25",pluse:"\u2A72",PlusMinus:"\xB1",plusmn:"\xB1",plussim:"\u2A26",plustwo:"\u2A27",pm:"\xB1",Poincareplane:"\u210C",pointint:"\u2A15",popf:"\u{1D561}",Popf:"\u2119",pound:"\xA3",prap:"\u2AB7",Pr:"\u2ABB",pr:"\u227A",prcue:"\u227C",precapprox:"\u2AB7",prec:"\u227A",preccurlyeq:"\u227C",Precedes:"\u227A",PrecedesEqual:"\u2AAF",PrecedesSlantEqual:"\u227C",PrecedesTilde:"\u227E",preceq:"\u2AAF",precnapprox:"\u2AB9",precneqq:"\u2AB5",precnsim:"\u22E8",pre:"\u2AAF",prE:"\u2AB3",precsim:"\u227E",prime:"\u2032",Prime:"\u2033",primes:"\u2119",prnap:"\u2AB9",prnE:"\u2AB5",prnsim:"\u22E8",prod:"\u220F",Product:"\u220F",profalar:"\u232E",profline:"\u2312",profsurf:"\u2313",prop:"\u221D",Proportional:"\u221D",Proportion:"\u2237",propto:"\u221D",prsim:"\u227E",prurel:"\u22B0",Pscr:"\u{1D4AB}",pscr:"\u{1D4C5}",Psi:"\u03A8",psi:"\u03C8",puncsp:"\u2008",Qfr:"\u{1D514}",qfr:"\u{1D52E}",qint:"\u2A0C",qopf:"\u{1D562}",Qopf:"\u211A",qprime:"\u2057",Qscr:"\u{1D4AC}",qscr:"\u{1D4C6}",quaternions:"\u210D",quatint:"\u2A16",quest:"?",questeq:"\u225F",quot:'"',QUOT:'"',rAarr:"\u21DB",race:"\u223D\u0331",Racute:"\u0154",racute:"\u0155",radic:"\u221A",raemptyv:"\u29B3",rang:"\u27E9",Rang:"\u27EB",rangd:"\u2992",range:"\u29A5",rangle:"\u27E9",raquo:"\xBB",rarrap:"\u2975",rarrb:"\u21E5",rarrbfs:"\u2920",rarrc:"\u2933",rarr:"\u2192",Rarr:"\u21A0",rArr:"\u21D2",rarrfs:"\u291E",rarrhk:"\u21AA",rarrlp:"\u21AC",rarrpl:"\u2945",rarrsim:"\u2974",Rarrtl:"\u2916",rarrtl:"\u21A3",rarrw:"\u219D",ratail:"\u291A",rAtail:"\u291C",ratio:"\u2236",rationals:"\u211A",rbarr:"\u290D",rBarr:"\u290F",RBarr:"\u2910",rbbrk:"\u2773",rbrace:"}",rbrack:"]",rbrke:"\u298C",rbrksld:"\u298E",rbrkslu:"\u2990",Rcaron:"\u0158",rcaron:"\u0159",Rcedil:"\u0156",rcedil:"\u0157",rceil:"\u2309",rcub:"}",Rcy:"\u0420",rcy:"\u0440",rdca:"\u2937",rdldhar:"\u2969",rdquo:"\u201D",rdquor:"\u201D",rdsh:"\u21B3",real:"\u211C",realine:"\u211B",realpart:"\u211C",reals:"\u211D",Re:"\u211C",rect:"\u25AD",reg:"\xAE",REG:"\xAE",ReverseElement:"\u220B",ReverseEquilibrium:"\u21CB",ReverseUpEquilibrium:"\u296F",rfisht:"\u297D",rfloor:"\u230B",rfr:"\u{1D52F}",Rfr:"\u211C",rHar:"\u2964",rhard:"\u21C1",rharu:"\u21C0",rharul:"\u296C",Rho:"\u03A1",rho:"\u03C1",rhov:"\u03F1",RightAngleBracket:"\u27E9",RightArrowBar:"\u21E5",rightarrow:"\u2192",RightArrow:"\u2192",Rightarrow:"\u21D2",RightArrowLeftArrow:"\u21C4",rightarrowtail:"\u21A3",RightCeiling:"\u2309",RightDoubleBracket:"\u27E7",RightDownTeeVector:"\u295D",RightDownVectorBar:"\u2955",RightDownVector:"\u21C2",RightFloor:"\u230B",rightharpoondown:"\u21C1",rightharpoonup:"\u21C0",rightleftarrows:"\u21C4",rightleftharpoons:"\u21CC",rightrightarrows:"\u21C9",rightsquigarrow:"\u219D",RightTeeArrow:"\u21A6",RightTee:"\u22A2",RightTeeVector:"\u295B",rightthreetimes:"\u22CC",RightTriangleBar:"\u29D0",RightTriangle:"\u22B3",RightTriangleEqual:"\u22B5",RightUpDownVector:"\u294F",RightUpTeeVector:"\u295C",RightUpVectorBar:"\u2954",RightUpVector:"\u21BE",RightVectorBar:"\u2953",RightVector:"\u21C0",ring:"\u02DA",risingdotseq:"\u2253",rlarr:"\u21C4",rlhar:"\u21CC",rlm:"\u200F",rmoustache:"\u23B1",rmoust:"\u23B1",rnmid:"\u2AEE",roang:"\u27ED",roarr:"\u21FE",robrk:"\u27E7",ropar:"\u2986",ropf:"\u{1D563}",Ropf:"\u211D",roplus:"\u2A2E",rotimes:"\u2A35",RoundImplies:"\u2970",rpar:")",rpargt:"\u2994",rppolint:"\u2A12",rrarr:"\u21C9",Rrightarrow:"\u21DB",rsaquo:"\u203A",rscr:"\u{1D4C7}",Rscr:"\u211B",rsh:"\u21B1",Rsh:"\u21B1",rsqb:"]",rsquo:"\u2019",rsquor:"\u2019",rthree:"\u22CC",rtimes:"\u22CA",rtri:"\u25B9",rtrie:"\u22B5",rtrif:"\u25B8",rtriltri:"\u29CE",RuleDelayed:"\u29F4",ruluhar:"\u2968",rx:"\u211E",Sacute:"\u015A",sacute:"\u015B",sbquo:"\u201A",scap:"\u2AB8",Scaron:"\u0160",scaron:"\u0161",Sc:"\u2ABC",sc:"\u227B",sccue:"\u227D",sce:"\u2AB0",scE:"\u2AB4",Scedil:"\u015E",scedil:"\u015F",Scirc:"\u015C",scirc:"\u015D",scnap:"\u2ABA",scnE:"\u2AB6",scnsim:"\u22E9",scpolint:"\u2A13",scsim:"\u227F",Scy:"\u0421",scy:"\u0441",sdotb:"\u22A1",sdot:"\u22C5",sdote:"\u2A66",searhk:"\u2925",searr:"\u2198",seArr:"\u21D8",searrow:"\u2198",sect:"\xA7",semi:";",seswar:"\u2929",setminus:"\u2216",setmn:"\u2216",sext:"\u2736",Sfr:"\u{1D516}",sfr:"\u{1D530}",sfrown:"\u2322",sharp:"\u266F",SHCHcy:"\u0429",shchcy:"\u0449",SHcy:"\u0428",shcy:"\u0448",ShortDownArrow:"\u2193",ShortLeftArrow:"\u2190",shortmid:"\u2223",shortparallel:"\u2225",ShortRightArrow:"\u2192",ShortUpArrow:"\u2191",shy:"\xAD",Sigma:"\u03A3",sigma:"\u03C3",sigmaf:"\u03C2",sigmav:"\u03C2",sim:"\u223C",simdot:"\u2A6A",sime:"\u2243",simeq:"\u2243",simg:"\u2A9E",simgE:"\u2AA0",siml:"\u2A9D",simlE:"\u2A9F",simne:"\u2246",simplus:"\u2A24",simrarr:"\u2972",slarr:"\u2190",SmallCircle:"\u2218",smallsetminus:"\u2216",smashp:"\u2A33",smeparsl:"\u29E4",smid:"\u2223",smile:"\u2323",smt:"\u2AAA",smte:"\u2AAC",smtes:"\u2AAC\uFE00",SOFTcy:"\u042C",softcy:"\u044C",solbar:"\u233F",solb:"\u29C4",sol:"/",Sopf:"\u{1D54A}",sopf:"\u{1D564}",spades:"\u2660",spadesuit:"\u2660",spar:"\u2225",sqcap:"\u2293",sqcaps:"\u2293\uFE00",sqcup:"\u2294",sqcups:"\u2294\uFE00",Sqrt:"\u221A",sqsub:"\u228F",sqsube:"\u2291",sqsubset:"\u228F",sqsubseteq:"\u2291",sqsup:"\u2290",sqsupe:"\u2292",sqsupset:"\u2290",sqsupseteq:"\u2292",square:"\u25A1",Square:"\u25A1",SquareIntersection:"\u2293",SquareSubset:"\u228F",SquareSubsetEqual:"\u2291",SquareSuperset:"\u2290",SquareSupersetEqual:"\u2292",SquareUnion:"\u2294",squarf:"\u25AA",squ:"\u25A1",squf:"\u25AA",srarr:"\u2192",Sscr:"\u{1D4AE}",sscr:"\u{1D4C8}",ssetmn:"\u2216",ssmile:"\u2323",sstarf:"\u22C6",Star:"\u22C6",star:"\u2606",starf:"\u2605",straightepsilon:"\u03F5",straightphi:"\u03D5",strns:"\xAF",sub:"\u2282",Sub:"\u22D0",subdot:"\u2ABD",subE:"\u2AC5",sube:"\u2286",subedot:"\u2AC3",submult:"\u2AC1",subnE:"\u2ACB",subne:"\u228A",subplus:"\u2ABF",subrarr:"\u2979",subset:"\u2282",Subset:"\u22D0",subseteq:"\u2286",subseteqq:"\u2AC5",SubsetEqual:"\u2286",subsetneq:"\u228A",subsetneqq:"\u2ACB",subsim:"\u2AC7",subsub:"\u2AD5",subsup:"\u2AD3",succapprox:"\u2AB8",succ:"\u227B",succcurlyeq:"\u227D",Succeeds:"\u227B",SucceedsEqual:"\u2AB0",SucceedsSlantEqual:"\u227D",SucceedsTilde:"\u227F",succeq:"\u2AB0",succnapprox:"\u2ABA",succneqq:"\u2AB6",succnsim:"\u22E9",succsim:"\u227F",SuchThat:"\u220B",sum:"\u2211",Sum:"\u2211",sung:"\u266A",sup1:"\xB9",sup2:"\xB2",sup3:"\xB3",sup:"\u2283",Sup:"\u22D1",supdot:"\u2ABE",supdsub:"\u2AD8",supE:"\u2AC6",supe:"\u2287",supedot:"\u2AC4",Superset:"\u2283",SupersetEqual:"\u2287",suphsol:"\u27C9",suphsub:"\u2AD7",suplarr:"\u297B",supmult:"\u2AC2",supnE:"\u2ACC",supne:"\u228B",supplus:"\u2AC0",supset:"\u2283",Supset:"\u22D1",supseteq:"\u2287",supseteqq:"\u2AC6",supsetneq:"\u228B",supsetneqq:"\u2ACC",supsim:"\u2AC8",supsub:"\u2AD4",supsup:"\u2AD6",swarhk:"\u2926",swarr:"\u2199",swArr:"\u21D9",swarrow:"\u2199",swnwar:"\u292A",szlig:"\xDF",Tab:" ",target:"\u2316",Tau:"\u03A4",tau:"\u03C4",tbrk:"\u23B4",Tcaron:"\u0164",tcaron:"\u0165",Tcedil:"\u0162",tcedil:"\u0163",Tcy:"\u0422",tcy:"\u0442",tdot:"\u20DB",telrec:"\u2315",Tfr:"\u{1D517}",tfr:"\u{1D531}",there4:"\u2234",therefore:"\u2234",Therefore:"\u2234",Theta:"\u0398",theta:"\u03B8",thetasym:"\u03D1",thetav:"\u03D1",thickapprox:"\u2248",thicksim:"\u223C",ThickSpace:"\u205F\u200A",ThinSpace:"\u2009",thinsp:"\u2009",thkap:"\u2248",thksim:"\u223C",THORN:"\xDE",thorn:"\xFE",tilde:"\u02DC",Tilde:"\u223C",TildeEqual:"\u2243",TildeFullEqual:"\u2245",TildeTilde:"\u2248",timesbar:"\u2A31",timesb:"\u22A0",times:"\xD7",timesd:"\u2A30",tint:"\u222D",toea:"\u2928",topbot:"\u2336",topcir:"\u2AF1",top:"\u22A4",Topf:"\u{1D54B}",topf:"\u{1D565}",topfork:"\u2ADA",tosa:"\u2929",tprime:"\u2034",trade:"\u2122",TRADE:"\u2122",triangle:"\u25B5",triangledown:"\u25BF",triangleleft:"\u25C3",trianglelefteq:"\u22B4",triangleq:"\u225C",triangleright:"\u25B9",trianglerighteq:"\u22B5",tridot:"\u25EC",trie:"\u225C",triminus:"\u2A3A",TripleDot:"\u20DB",triplus:"\u2A39",trisb:"\u29CD",tritime:"\u2A3B",trpezium:"\u23E2",Tscr:"\u{1D4AF}",tscr:"\u{1D4C9}",TScy:"\u0426",tscy:"\u0446",TSHcy:"\u040B",tshcy:"\u045B",Tstrok:"\u0166",tstrok:"\u0167",twixt:"\u226C",twoheadleftarrow:"\u219E",twoheadrightarrow:"\u21A0",Uacute:"\xDA",uacute:"\xFA",uarr:"\u2191",Uarr:"\u219F",uArr:"\u21D1",Uarrocir:"\u2949",Ubrcy:"\u040E",ubrcy:"\u045E",Ubreve:"\u016C",ubreve:"\u016D",Ucirc:"\xDB",ucirc:"\xFB",Ucy:"\u0423",ucy:"\u0443",udarr:"\u21C5",Udblac:"\u0170",udblac:"\u0171",udhar:"\u296E",ufisht:"\u297E",Ufr:"\u{1D518}",ufr:"\u{1D532}",Ugrave:"\xD9",ugrave:"\xF9",uHar:"\u2963",uharl:"\u21BF",uharr:"\u21BE",uhblk:"\u2580",ulcorn:"\u231C",ulcorner:"\u231C",ulcrop:"\u230F",ultri:"\u25F8",Umacr:"\u016A",umacr:"\u016B",uml:"\xA8",UnderBar:"_",UnderBrace:"\u23DF",UnderBracket:"\u23B5",UnderParenthesis:"\u23DD",Union:"\u22C3",UnionPlus:"\u228E",Uogon:"\u0172",uogon:"\u0173",Uopf:"\u{1D54C}",uopf:"\u{1D566}",UpArrowBar:"\u2912",uparrow:"\u2191",UpArrow:"\u2191",Uparrow:"\u21D1",UpArrowDownArrow:"\u21C5",updownarrow:"\u2195",UpDownArrow:"\u2195",Updownarrow:"\u21D5",UpEquilibrium:"\u296E",upharpoonleft:"\u21BF",upharpoonright:"\u21BE",uplus:"\u228E",UpperLeftArrow:"\u2196",UpperRightArrow:"\u2197",upsi:"\u03C5",Upsi:"\u03D2",upsih:"\u03D2",Upsilon:"\u03A5",upsilon:"\u03C5",UpTeeArrow:"\u21A5",UpTee:"\u22A5",upuparrows:"\u21C8",urcorn:"\u231D",urcorner:"\u231D",urcrop:"\u230E",Uring:"\u016E",uring:"\u016F",urtri:"\u25F9",Uscr:"\u{1D4B0}",uscr:"\u{1D4CA}",utdot:"\u22F0",Utilde:"\u0168",utilde:"\u0169",utri:"\u25B5",utrif:"\u25B4",uuarr:"\u21C8",Uuml:"\xDC",uuml:"\xFC",uwangle:"\u29A7",vangrt:"\u299C",varepsilon:"\u03F5",varkappa:"\u03F0",varnothing:"\u2205",varphi:"\u03D5",varpi:"\u03D6",varpropto:"\u221D",varr:"\u2195",vArr:"\u21D5",varrho:"\u03F1",varsigma:"\u03C2",varsubsetneq:"\u228A\uFE00",varsubsetneqq:"\u2ACB\uFE00",varsupsetneq:"\u228B\uFE00",varsupsetneqq:"\u2ACC\uFE00",vartheta:"\u03D1",vartriangleleft:"\u22B2",vartriangleright:"\u22B3",vBar:"\u2AE8",Vbar:"\u2AEB",vBarv:"\u2AE9",Vcy:"\u0412",vcy:"\u0432",vdash:"\u22A2",vDash:"\u22A8",Vdash:"\u22A9",VDash:"\u22AB",Vdashl:"\u2AE6",veebar:"\u22BB",vee:"\u2228",Vee:"\u22C1",veeeq:"\u225A",vellip:"\u22EE",verbar:"|",Verbar:"\u2016",vert:"|",Vert:"\u2016",VerticalBar:"\u2223",VerticalLine:"|",VerticalSeparator:"\u2758",VerticalTilde:"\u2240",VeryThinSpace:"\u200A",Vfr:"\u{1D519}",vfr:"\u{1D533}",vltri:"\u22B2",vnsub:"\u2282\u20D2",vnsup:"\u2283\u20D2",Vopf:"\u{1D54D}",vopf:"\u{1D567}",vprop:"\u221D",vrtri:"\u22B3",Vscr:"\u{1D4B1}",vscr:"\u{1D4CB}",vsubnE:"\u2ACB\uFE00",vsubne:"\u228A\uFE00",vsupnE:"\u2ACC\uFE00",vsupne:"\u228B\uFE00",Vvdash:"\u22AA",vzigzag:"\u299A",Wcirc:"\u0174",wcirc:"\u0175",wedbar:"\u2A5F",wedge:"\u2227",Wedge:"\u22C0",wedgeq:"\u2259",weierp:"\u2118",Wfr:"\u{1D51A}",wfr:"\u{1D534}",Wopf:"\u{1D54E}",wopf:"\u{1D568}",wp:"\u2118",wr:"\u2240",wreath:"\u2240",Wscr:"\u{1D4B2}",wscr:"\u{1D4CC}",xcap:"\u22C2",xcirc:"\u25EF",xcup:"\u22C3",xdtri:"\u25BD",Xfr:"\u{1D51B}",xfr:"\u{1D535}",xharr:"\u27F7",xhArr:"\u27FA",Xi:"\u039E",xi:"\u03BE",xlarr:"\u27F5",xlArr:"\u27F8",xmap:"\u27FC",xnis:"\u22FB",xodot:"\u2A00",Xopf:"\u{1D54F}",xopf:"\u{1D569}",xoplus:"\u2A01",xotime:"\u2A02",xrarr:"\u27F6",xrArr:"\u27F9",Xscr:"\u{1D4B3}",xscr:"\u{1D4CD}",xsqcup:"\u2A06",xuplus:"\u2A04",xutri:"\u25B3",xvee:"\u22C1",xwedge:"\u22C0",Yacute:"\xDD",yacute:"\xFD",YAcy:"\u042F",yacy:"\u044F",Ycirc:"\u0176",ycirc:"\u0177",Ycy:"\u042B",ycy:"\u044B",yen:"\xA5",Yfr:"\u{1D51C}",yfr:"\u{1D536}",YIcy:"\u0407",yicy:"\u0457",Yopf:"\u{1D550}",yopf:"\u{1D56A}",Yscr:"\u{1D4B4}",yscr:"\u{1D4CE}",YUcy:"\u042E",yucy:"\u044E",yuml:"\xFF",Yuml:"\u0178",Zacute:"\u0179",zacute:"\u017A",Zcaron:"\u017D",zcaron:"\u017E",Zcy:"\u0417",zcy:"\u0437",Zdot:"\u017B",zdot:"\u017C",zeetrf:"\u2128",ZeroWidthSpace:"\u200B",Zeta:"\u0396",zeta:"\u03B6",zfr:"\u{1D537}",Zfr:"\u2128",ZHcy:"\u0416",zhcy:"\u0436",zigrarr:"\u21DD",zopf:"\u{1D56B}",Zopf:"\u2124",Zscr:"\u{1D4B5}",zscr:"\u{1D4CF}",zwj:"\u200D",zwnj:"\u200C"}});var Sl=Ct((t2,dh)=>{dh.exports={Aacute:"\xC1",aacute:"\xE1",Acirc:"\xC2",acirc:"\xE2",acute:"\xB4",AElig:"\xC6",aelig:"\xE6",Agrave:"\xC0",agrave:"\xE0",amp:"&",AMP:"&",Aring:"\xC5",aring:"\xE5",Atilde:"\xC3",atilde:"\xE3",Auml:"\xC4",auml:"\xE4",brvbar:"\xA6",Ccedil:"\xC7",ccedil:"\xE7",cedil:"\xB8",cent:"\xA2",copy:"\xA9",COPY:"\xA9",curren:"\xA4",deg:"\xB0",divide:"\xF7",Eacute:"\xC9",eacute:"\xE9",Ecirc:"\xCA",ecirc:"\xEA",Egrave:"\xC8",egrave:"\xE8",ETH:"\xD0",eth:"\xF0",Euml:"\xCB",euml:"\xEB",frac12:"\xBD",frac14:"\xBC",frac34:"\xBE",gt:">",GT:">",Iacute:"\xCD",iacute:"\xED",Icirc:"\xCE",icirc:"\xEE",iexcl:"\xA1",Igrave:"\xCC",igrave:"\xEC",iquest:"\xBF",Iuml:"\xCF",iuml:"\xEF",laquo:"\xAB",lt:"<",LT:"<",macr:"\xAF",micro:"\xB5",middot:"\xB7",nbsp:"\xA0",not:"\xAC",Ntilde:"\xD1",ntilde:"\xF1",Oacute:"\xD3",oacute:"\xF3",Ocirc:"\xD4",ocirc:"\xF4",Ograve:"\xD2",ograve:"\xF2",ordf:"\xAA",ordm:"\xBA",Oslash:"\xD8",oslash:"\xF8",Otilde:"\xD5",otilde:"\xF5",Ouml:"\xD6",ouml:"\xF6",para:"\xB6",plusmn:"\xB1",pound:"\xA3",quot:'"',QUOT:'"',raquo:"\xBB",reg:"\xAE",REG:"\xAE",sect:"\xA7",shy:"\xAD",sup1:"\xB9",sup2:"\xB2",sup3:"\xB3",szlig:"\xDF",THORN:"\xDE",thorn:"\xFE",times:"\xD7",Uacute:"\xDA",uacute:"\xFA",Ucirc:"\xDB",ucirc:"\xFB",Ugrave:"\xD9",ugrave:"\xF9",uml:"\xA8",Uuml:"\xDC",uuml:"\xFC",Yacute:"\xDD",yacute:"\xFD",yen:"\xA5",yuml:"\xFF"}});var si=Ct((e2,hh)=>{hh.exports={amp:"&",apos:"'",gt:">",lt:"<",quot:'"'}});var Ll=Ct((r2,gh)=>{gh.exports={"0":65533,"128":8364,"130":8218,"131":402,"132":8222,"133":8230,"134":8224,"135":8225,"136":710,"137":8240,"138":352,"139":8249,"140":338,"142":381,"145":8216,"146":8217,"147":8220,"148":8221,"149":8226,"150":8211,"151":8212,"152":732,"153":8482,"154":353,"155":8250,"156":339,"158":382,"159":376}});var Al=Ct(Ir=>{"use strict";var xh=Ir&&Ir.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Ir,"__esModule",{value:!0});var El=xh(Ll()),yh=String.fromCodePoint||function(t){var e="";return t>65535&&(t-=65536,e+=String.fromCharCode(t>>>10&1023|55296),t=56320|t&1023),e+=String.fromCharCode(t),e};function vh(t){return t>=55296&&t<=57343||t>1114111?"\uFFFD":(t in El.default&&(t=El.default[t]),yh(t))}Ir.default=vh});var li=Ct(At=>{"use strict";var In=At&&At.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(At,"__esModule",{value:!0});At.decodeHTML=At.decodeHTMLStrict=At.decodeXML=void 0;var ui=In(ai()),bh=In(Sl()),wh=In(si()),Dl=In(Al()),kh=/&(?:[a-zA-Z0-9]+|#[xX][\da-fA-F]+|#\d+);/g;At.decodeXML=ql(wh.default);At.decodeHTMLStrict=ql(ui.default);function ql(t){var e=Il(t);return function(r){return String(r).replace(kh,e)}}var Cl=function(t,e){return t{"use strict";var Nl=ut&&ut.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(ut,"__esModule",{value:!0});ut.escapeUTF8=ut.escape=ut.encodeNonAsciiHTML=ut.encodeHTML=ut.encodeXML=void 0;var _h=Nl(si()),Bl=Hl(_h.default),Rl=Fl(Bl);ut.encodeXML=$l(Bl);var Th=Nl(ai()),ci=Hl(Th.default),Mh=Fl(ci);ut.encodeHTML=Lh(ci,Mh);ut.encodeNonAsciiHTML=$l(ci);function Hl(t){return Object.keys(t).sort().reduce(function(e,r){return e[t[r]]="&"+r+";",e},{})}function Fl(t){for(var e=[],r=[],n=0,o=Object.keys(t);n1?Sh(t):t.charCodeAt(0)).toString(16).toUpperCase()+";"}function Lh(t,e){return function(r){return r.replace(e,function(n){return t[n]}).replace(Ol,Nn)}}var Pl=new RegExp(Rl.source+"|"+Ol.source,"g");function Eh(t){return t.replace(Pl,Nn)}ut.escape=Eh;function Ah(t){return t.replace(Rl,Nn)}ut.escapeUTF8=Ah;function $l(t){return function(e){return e.replace(Pl,function(r){return t[r]||Nn(r)})}}});var Gl=Ct(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.decodeXMLStrict=O.decodeHTML5Strict=O.decodeHTML4Strict=O.decodeHTML5=O.decodeHTML4=O.decodeHTMLStrict=O.decodeHTML=O.decodeXML=O.encodeHTML5=O.encodeHTML4=O.escapeUTF8=O.escape=O.encodeNonAsciiHTML=O.encodeHTML=O.encodeXML=O.encode=O.decodeStrict=O.decode=void 0;var Bn=li(),Ul=fi();function Dh(t,e){return(!e||e<=0?Bn.decodeXML:Bn.decodeHTML)(t)}O.decode=Dh;function Ch(t,e){return(!e||e<=0?Bn.decodeXML:Bn.decodeHTMLStrict)(t)}O.decodeStrict=Ch;function qh(t,e){return(!e||e<=0?Ul.encodeXML:Ul.encodeHTML)(t)}O.encode=qh;var _e=fi();Object.defineProperty(O,"encodeXML",{enumerable:!0,get:function(){return _e.encodeXML}});Object.defineProperty(O,"encodeHTML",{enumerable:!0,get:function(){return _e.encodeHTML}});Object.defineProperty(O,"encodeNonAsciiHTML",{enumerable:!0,get:function(){return _e.encodeNonAsciiHTML}});Object.defineProperty(O,"escape",{enumerable:!0,get:function(){return _e.escape}});Object.defineProperty(O,"escapeUTF8",{enumerable:!0,get:function(){return _e.escapeUTF8}});Object.defineProperty(O,"encodeHTML4",{enumerable:!0,get:function(){return _e.encodeHTML}});Object.defineProperty(O,"encodeHTML5",{enumerable:!0,get:function(){return _e.encodeHTML}});var jt=li();Object.defineProperty(O,"decodeXML",{enumerable:!0,get:function(){return jt.decodeXML}});Object.defineProperty(O,"decodeHTML",{enumerable:!0,get:function(){return jt.decodeHTML}});Object.defineProperty(O,"decodeHTMLStrict",{enumerable:!0,get:function(){return jt.decodeHTMLStrict}});Object.defineProperty(O,"decodeHTML4",{enumerable:!0,get:function(){return jt.decodeHTML}});Object.defineProperty(O,"decodeHTML5",{enumerable:!0,get:function(){return jt.decodeHTML}});Object.defineProperty(O,"decodeHTML4Strict",{enumerable:!0,get:function(){return jt.decodeHTMLStrict}});Object.defineProperty(O,"decodeHTML5Strict",{enumerable:!0,get:function(){return jt.decodeHTMLStrict}});Object.defineProperty(O,"decodeXMLStrict",{enumerable:!0,get:function(){return jt.decodeXML}})});var tc=Ct((s2,Kl)=>{"use strict";function Ih(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function Vl(t,e){for(var r=0;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(c){throw c},f:o}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var i=!0,a=!1,s;return{s:function(){r=r.call(t)},n:function(){var c=r.next();return i=c.done,c},e:function(c){a=!0,s=c},f:function(){try{!i&&r.return!=null&&r.return()}finally{if(a)throw s}}}}function Bh(t,e){if(t){if(typeof t=="string")return zl(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if(r==="Object"&&t.constructor&&(r=t.constructor.name),r==="Map"||r==="Set")return Array.from(t);if(r==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return zl(t,e)}}function zl(t,e){(e==null||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r0?t*40+55:0,a=e>0?e*40+55:0,s=r>0?r*40+55:0;n[o]=Oh([i,a,s])}function Jl(t){for(var e=t.toString(16);e.length<2;)e="0"+e;return e}function Oh(t){var e=[],r=Zl(t),n;try{for(r.s();!(n=r.n()).done;){var o=n.value;e.push(Jl(o))}}catch(i){r.e(i)}finally{r.f()}return"#"+e.join("")}function Wl(t,e,r,n){var o;return e==="text"?o=Gh(r,n):e==="display"?o=$h(t,r,n):e==="xterm256Foreground"?o=Fn(t,n.colors[r]):e==="xterm256Background"?o=On(t,n.colors[r]):e==="rgb"&&(o=Ph(t,r)),o}function Ph(t,e){e=e.substring(2).slice(0,-1);var r=+e.substr(0,2),n=e.substring(5).split(";"),o=n.map(function(i){return("0"+Number(i).toString(16)).substr(-2)}).join("");return Hn(t,(r===38?"color:#":"background-color:#")+o)}function $h(t,e,r){e=parseInt(e,10);var n={"-1":function(){return"
"},0:function(){return t.length&&Ql(t)},1:function(){return Zt(t,"b")},3:function(){return Zt(t,"i")},4:function(){return Zt(t,"u")},8:function(){return Hn(t,"display:none")},9:function(){return Zt(t,"strike")},22:function(){return Hn(t,"font-weight:normal;text-decoration:none;font-style:normal")},23:function(){return jl(t,"i")},24:function(){return jl(t,"u")},39:function(){return Fn(t,r.fg)},49:function(){return On(t,r.bg)},53:function(){return Hn(t,"text-decoration:overline")}},o;return n[e]?o=n[e]():4"}).join("")}function Rn(t,e){for(var r=[],n=t;n<=e;n++)r.push(n);return r}function Uh(t){return function(e){return(t===null||e.category!==t)&&t!=="all"}}function Xl(t){t=parseInt(t,10);var e=null;return t===0?e="all":t===1?e="bold":2")}function Hn(t,e){return Zt(t,"span",e)}function Fn(t,e){return Zt(t,"span","color:"+e)}function On(t,e){return Zt(t,"span","background-color:"+e)}function jl(t,e){var r;if(t.slice(-1)[0]===e&&(r=t.pop()),r)return""}function Vh(t,e,r){var n=!1,o=3;function i(){return""}function a(L,b){return r("xterm256Foreground",b),""}function s(L,b){return r("xterm256Background",b),""}function u(L){return e.newline?r("display",-1):r("text",L),""}function c(L,b){n=!0,b.trim().length===0&&(b="0"),b=b.trimRight(";").split(";");var N=Zl(b),H;try{for(N.s();!(H=N.n()).done;){var P=H.value;r("display",P)}}catch(I){N.e(I)}finally{N.f()}return""}function l(L){return r("text",L),""}function p(L){return r("rgb",L),""}var f=[{pattern:/^\x08+/,sub:i},{pattern:/^\x1b\[[012]?K/,sub:i},{pattern:/^\x1b\[\(B/,sub:i},{pattern:/^\x1b\[[34]8;2;\d+;\d+;\d+m/,sub:p},{pattern:/^\x1b\[38;5;(\d+)m/,sub:a},{pattern:/^\x1b\[48;5;(\d+)m/,sub:s},{pattern:/^\n/,sub:u},{pattern:/^\r+\n/,sub:u},{pattern:/^\r/,sub:u},{pattern:/^\x1b\[((?:\d{1,3};?)+|)m/,sub:c},{pattern:/^\x1b\[\d?J/,sub:i},{pattern:/^\x1b\[\d{0,3};\d{0,3}f/,sub:i},{pattern:/^\x1b\[?[\d;]{0,3}/,sub:i},{pattern:/^(([^\x1b\x08\r\n])+)/,sub:l}];function m(L,b){b>o&&n||(n=!1,t=t.replace(L.pattern,L.sub))}var d=[],y=t,k=y.length;t:for(;k>0;){for(var _=0,q=0,A=f.length;qe?1:t>=e?0:NaN}function Gn(t,e){return t==null||e==null?NaN:et?1:e>=t?0:NaN}function Kt(t){let e,r,n;t.length!==2?(e=ft,r=(s,u)=>ft(t(s),u),n=(s,u)=>t(s)-u):(e=t===ft||t===Gn?t:yc,r=t,n=t);function o(s,u,c=0,l=s.length){if(c>>1;r(s[p],u)<0?c=p+1:l=p}while(c>>1;r(s[p],u)<=0?c=p+1:l=p}while(cc&&n(s[p-1],u)>-n(s[p],u)?p-1:p}return{left:o,center:a,right:i}}function yc(){return 0}function Nr(t){return t===null?NaN:+t}function*Si(t,e){if(e===void 0)for(let r of t)r!=null&&(r=+r)>=r&&(yield r);else{let r=-1;for(let n of t)(n=e(n,++r,t))!=null&&(n=+n)>=n&&(yield n)}}var Li=Kt(ft),Ei=Li.right,vc=Li.left,bc=Kt(Nr).center,Vn=Ei;function Me(t,e){let r,n;if(e===void 0)for(let o of t)o!=null&&(r===void 0?o>=o&&(r=n=o):(r>o&&(r=o),n=i&&(r=n=i):(r>i&&(r=i),n{let n=t(e,r);return n||n===0?n:(t(r,r)===0)-(t(e,e)===0)}}function zn(t,e){return(t==null||!(t>=t))-(e==null||!(e>=e))||(te?1:0)}var Tc=Math.sqrt(50),Mc=Math.sqrt(10),Sc=Math.sqrt(2);function Br(t,e,r){let n=(e-t)/Math.max(0,r),o=Math.floor(Math.log10(n)),i=n/Math.pow(10,o),a=i>=Tc?10:i>=Mc?5:i>=Sc?2:1,s,u,c;return o<0?(c=Math.pow(10,-o)/a,s=Math.round(t*c),u=Math.round(e*c),s/ce&&--u,c=-c):(c=Math.pow(10,o)*a,s=Math.round(t/c),u=Math.round(e/c),s*ce&&--u),u0))return[];if(t===e)return[t];let n=e=o))return[];let s=i-o+1,u=new Array(s);if(n)if(a<0)for(let c=0;c=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r=o)&&(r=o)}return r}function Rr(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r>n||r===void 0&&n>=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r>o||r===void 0&&o>=o)&&(r=o)}return r}function Hr(t,e,r=0,n=1/0,o){if(e=Math.floor(e),r=Math.floor(Math.max(0,r)),n=Math.floor(Math.min(t.length-1,n)),!(r<=e&&e<=n))return t;for(o=o===void 0?zn:Di(o);n>r;){if(n-r>600){let u=n-r+1,c=e-r+1,l=Math.log(u),p=.5*Math.exp(2*l/3),f=.5*Math.sqrt(l*p*(u-p)/u)*(c-u/2<0?-1:1),m=Math.max(r,Math.floor(e-c*p/u+f)),d=Math.min(n,Math.floor(e+(u-c)*p/u+f));Hr(t,e,m,d,o)}let i=t[e],a=r,s=n;for(Ke(t,r,e),o(t[n],i)>0&&Ke(t,r,n);a0;)--s}o(t[r],i)===0?Ke(t,r,s):(++s,Ke(t,s,n)),s<=e&&(r=s+1),e<=s&&(n=s-1)}return t}function Ke(t,e,r){let n=t[e];t[e]=t[r],t[r]=n}function Ee(t,e,r){if(t=Float64Array.from(Si(t,r)),!(!(n=t.length)||isNaN(e=+e))){if(e<=0||n<2)return Rr(t);if(e>=1)return ee(t);var n,o=(n-1)*e,i=Math.floor(o),a=ee(Hr(t,i).subarray(0,i+1)),s=Rr(t.subarray(i+1));return a+(s-a)*(o-i)}}function Ae(t,e,r){t=+t,e=+e,r=(o=arguments.length)<2?(e=t,t=0,1):o<3?1:+r;for(var n=-1,o=Math.max(0,Math.ceil((e-t)/r))|0,i=new Array(o);++n+t(e)}function Dc(t,e){return e=Math.max(0,t.bandwidth()-e*2)/2,t.round()&&(e=Math.round(e)),r=>+t(r)+e}function Cc(){return!this.__axis}function Ii(t,e){var r=[],n=null,o=null,i=6,a=6,s=3,u=typeof window<"u"&&window.devicePixelRatio>1?0:.5,c=t===Yn||t===tr?-1:1,l=t===tr||t===Wn?"x":"y",p=t===Yn||t===Xn?Lc:Ec;function f(m){var d=n??(e.ticks?e.ticks.apply(e,r):e.domain()),y=o??(e.tickFormat?e.tickFormat.apply(e,r):Ci),k=Math.max(i,0)+s,_=e.range(),q=+_[0]+u,A=+_[_.length-1]+u,D=(e.bandwidth?Dc:Ac)(e.copy(),u),L=m.selection?m.selection():m,b=L.selectAll(".domain").data([null]),N=L.selectAll(".tick").data(d,e).order(),H=N.exit(),P=N.enter().append("g").attr("class","tick"),I=N.select("line"),h=N.select("text");b=b.merge(b.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),N=N.merge(P),I=I.merge(P.append("line").attr("stroke","currentColor").attr(l+"2",c*i)),h=h.merge(P.append("text").attr("fill","currentColor").attr(l,c*k).attr("dy",t===Yn?"0em":t===Xn?"0.71em":"0.32em")),m!==L&&(b=b.transition(m),N=N.transition(m),I=I.transition(m),h=h.transition(m),H=H.transition(m).attr("opacity",qi).attr("transform",function(T){return isFinite(T=D(T))?p(T+u):this.getAttribute("transform")}),P.attr("opacity",qi).attr("transform",function(T){var E=this.parentNode.__axis;return p((E&&isFinite(E=E(T))?E:D(T))+u)})),H.remove(),b.attr("d",t===tr||t===Wn?a?"M"+c*a+","+q+"H"+u+"V"+A+"H"+c*a:"M"+u+","+q+"V"+A:a?"M"+q+","+c*a+"V"+u+"H"+A+"V"+c*a:"M"+q+","+u+"H"+A),N.attr("opacity",1).attr("transform",function(T){return p(D(T)+u)}),I.attr(l+"2",c*i),h.attr(l,c*k).text(y),L.filter(Cc).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===Wn?"start":t===tr?"end":"middle"),L.each(function(){this.__axis=D})}return f.scale=function(m){return arguments.length?(e=m,f):e},f.ticks=function(){return r=Array.from(arguments),f},f.tickArguments=function(m){return arguments.length?(r=m==null?[]:Array.from(m),f):r.slice()},f.tickValues=function(m){return arguments.length?(n=m==null?null:Array.from(m),f):n&&n.slice()},f.tickFormat=function(m){return arguments.length?(o=m,f):o},f.tickSize=function(m){return arguments.length?(i=a=+m,f):i},f.tickSizeInner=function(m){return arguments.length?(i=+m,f):i},f.tickSizeOuter=function(m){return arguments.length?(a=+m,f):a},f.tickPadding=function(m){return arguments.length?(s=+m,f):s},f.offset=function(m){return arguments.length?(u=+m,f):u},f}function Fr(t){return Ii(Xn,t)}function Or(t){return Ii(tr,t)}var qc={value:()=>{}};function Bi(){for(var t=0,e=arguments.length,r={},n;t=0&&(n=r.slice(o+1),r=r.slice(0,o)),r&&!e.hasOwnProperty(r))throw new Error("unknown type: "+r);return{type:r,name:n}})}Pr.prototype=Bi.prototype={constructor:Pr,on:function(t,e){var r=this._,n=Ic(t+"",r),o,i=-1,a=n.length;if(arguments.length<2){for(;++i0)for(var r=new Array(o),n=0,o,i;n=0&&(e=t.slice(0,r))!=="xmlns"&&(t=t.slice(r+1)),Zn.hasOwnProperty(e)?{space:Zn[e],local:t}:t}function Bc(t){return function(){var e=this.ownerDocument,r=this.namespaceURI;return r===$r&&e.documentElement.namespaceURI===$r?e.createElement(t):e.createElementNS(r,t)}}function Rc(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Ur(t){var e=qt(t);return(e.local?Rc:Bc)(e)}function Hc(){}function re(t){return t==null?Hc:function(){return this.querySelector(t)}}function Ri(t){typeof t!="function"&&(t=re(t));for(var e=this._groups,r=e.length,n=new Array(r),o=0;o=A&&(A=q+1);!(L=k[A])&&++A=0;)(a=n[o])&&(i&&a.compareDocumentPosition(i)^4&&i.parentNode.insertBefore(a,i),i=a);return this}function Xi(t){t||(t=Zc);function e(p,f){return p&&f?t(p.__data__,f.__data__):!p-!f}for(var r=this._groups,n=r.length,o=new Array(n),i=0;ie?1:t>=e?0:NaN}function ji(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function Zi(){return Array.from(this)}function Ji(){for(var t=this._groups,e=0,r=t.length;e1?this.each((e==null?nf:typeof e=="function"?af:of)(t,e,r??"")):Ft(this.node(),t)}function Ft(t,e){return t.style.getPropertyValue(e)||zr(t).getComputedStyle(t,null).getPropertyValue(e)}function sf(t){return function(){delete this[t]}}function uf(t,e){return function(){this[t]=e}}function lf(t,e){return function(){var r=e.apply(this,arguments);r==null?delete this[t]:this[t]=r}}function na(t,e){return arguments.length>1?this.each((e==null?sf:typeof e=="function"?lf:uf)(t,e)):this.node()[t]}function oa(t){return t.trim().split(/^|\s+/)}function Qn(t){return t.classList||new ia(t)}function ia(t){this._node=t,this._names=oa(t.getAttribute("class")||"")}ia.prototype={add:function(t){var e=this._names.indexOf(t);e<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var e=this._names.indexOf(t);e>=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function aa(t,e){for(var r=Qn(t),n=-1,o=e.length;++n=0&&(r=e.slice(n+1),e=e.slice(0,n)),{type:e,name:r}})}function Lf(t){return function(){var e=this.__on;if(e){for(var r=0,n=-1,o=e.length,i;r>8&15|e>>4&240,e>>4&15|e&240,(e&15)<<4|e&15,1):r===8?Yr(e>>24&255,e>>16&255,e>>8&255,(e&255)/255):r===4?Yr(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|e&240,((e&15)<<4|e&15)/255):null):(e=If.exec(t))?new et(e[1],e[2],e[3],1):(e=Nf.exec(t))?new et(e[1]*255/100,e[2]*255/100,e[3]*255/100,1):(e=Bf.exec(t))?Yr(e[1],e[2],e[3],e[4]):(e=Rf.exec(t))?Yr(e[1]*255/100,e[2]*255/100,e[3]*255/100,e[4]):(e=Hf.exec(t))?Aa(e[1],e[2]/100,e[3]/100,1):(e=Ff.exec(t))?Aa(e[1],e[2]/100,e[3]/100,e[4]):_a.hasOwnProperty(t)?Sa(_a[t]):t==="transparent"?new et(NaN,NaN,NaN,0):null}function Sa(t){return new et(t>>16&255,t>>8&255,t&255,1)}function Yr(t,e,r,n){return n<=0&&(t=e=r=NaN),new et(t,e,r,n)}function eo(t){return t instanceof ae||(t=yt(t)),t?(t=t.rgb(),new et(t.r,t.g,t.b,t.opacity)):new et}function qe(t,e,r,n){return arguments.length===1?eo(t):new et(t,e,r,n??1)}function et(t,e,r,n){this.r=+t,this.g=+e,this.b=+r,this.opacity=+n}De(et,qe,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new et(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new et(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new et(oe(this.r),oe(this.g),oe(this.b),Xr(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:La,formatHex:La,formatHex8:$f,formatRgb:Ea,toString:Ea}));function La(){return`#${ne(this.r)}${ne(this.g)}${ne(this.b)}`}function $f(){return`#${ne(this.r)}${ne(this.g)}${ne(this.b)}${ne((isNaN(this.opacity)?1:this.opacity)*255)}`}function Ea(){let t=Xr(this.opacity);return`${t===1?"rgb(":"rgba("}${oe(this.r)}, ${oe(this.g)}, ${oe(this.b)}${t===1?")":`, ${t})`}`}function Xr(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function oe(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function ne(t){return t=oe(t),(t<16?"0":"")+t.toString(16)}function Aa(t,e,r,n){return n<=0?t=e=r=NaN:r<=0||r>=1?t=e=NaN:e<=0&&(t=NaN),new xt(t,e,r,n)}function Ca(t){if(t instanceof xt)return new xt(t.h,t.s,t.l,t.opacity);if(t instanceof ae||(t=yt(t)),!t)return new xt;if(t instanceof xt)return t;t=t.rgb();var e=t.r/255,r=t.g/255,n=t.b/255,o=Math.min(e,r,n),i=Math.max(e,r,n),a=NaN,s=i-o,u=(i+o)/2;return s?(e===i?a=(r-n)/s+(r0&&u<1?0:a,new xt(a,s,u,t.opacity)}function qa(t,e,r,n){return arguments.length===1?Ca(t):new xt(t,e,r,n??1)}function xt(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}De(xt,qa,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new xt(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new xt(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,e=isNaN(t)||isNaN(this.s)?0:this.s,r=this.l,n=r+(r<.5?r:1-r)*e,o=2*r-n;return new et(to(t>=240?t-240:t+120,o,n),to(t,o,n),to(t<120?t+240:t-120,o,n),this.opacity)},clamp(){return new xt(Da(this.h),Wr(this.s),Wr(this.l),Xr(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){let t=Xr(this.opacity);return`${t===1?"hsl(":"hsla("}${Da(this.h)}, ${Wr(this.s)*100}%, ${Wr(this.l)*100}%${t===1?")":`, ${t})`}`}}));function Da(t){return t=(t||0)%360,t<0?t+360:t}function Wr(t){return Math.max(0,Math.min(1,t||0))}function to(t,e,r){return(t<60?e+(r-e)*t/60:t<180?r:t<240?e+(r-e)*(240-t)/60:e)*255}var Ia=Math.PI/180,Na=180/Math.PI;var Fa=-.14861,ro=1.78277,no=-.29227,jr=-.90649,ar=1.97294,Ba=ar*jr,Ra=ar*ro,Ha=ro*no-jr*Fa;function Uf(t){if(t instanceof se)return new se(t.h,t.s,t.l,t.opacity);t instanceof et||(t=eo(t));var e=t.r/255,r=t.g/255,n=t.b/255,o=(Ha*n+Ba*e-Ra*r)/(Ha+Ba-Ra),i=n-o,a=(ar*(r-o)-no*i)/jr,s=Math.sqrt(a*a+i*i)/(ar*o*(1-o)),u=s?Math.atan2(a,i)*Na-120:NaN;return new se(u<0?u+360:u,s,o,t.opacity)}function mt(t,e,r,n){return arguments.length===1?Uf(t):new se(t,e,r,n??1)}function se(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}De(se,mt,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new se(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new se(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=isNaN(this.h)?0:(this.h+120)*Ia,e=+this.l,r=isNaN(this.s)?0:this.s*e*(1-e),n=Math.cos(t),o=Math.sin(t);return new et(255*(e+r*(Fa*n+ro*o)),255*(e+r*(no*n+jr*o)),255*(e+r*(ar*n)),this.opacity)}}));function oo(t,e,r,n,o){var i=t*t,a=i*t;return((1-3*t+3*i-a)*e+(4-6*i+3*a)*r+(1+3*t+3*i-3*a)*n+a*o)/6}function Oa(t){var e=t.length-1;return function(r){var n=r<=0?r=0:r>=1?(r=1,e-1):Math.floor(r*e),o=t[n],i=t[n+1],a=n>0?t[n-1]:2*o-i,s=n()=>t;function $a(t,e){return function(r){return t+r*e}}function Gf(t,e,r){return t=Math.pow(t,r),e=Math.pow(e,r)-t,r=1/r,function(n){return Math.pow(t+n*e,r)}}function Ua(t,e){var r=e-t;return r?$a(t,r>180||r<-180?r-360*Math.round(r/360):r):Ie(isNaN(t)?e:t)}function Ga(t){return(t=+t)==1?Nt:function(e,r){return r-e?Gf(e,r,t):Ie(isNaN(e)?r:e)}}function Nt(t,e){var r=e-t;return r?$a(t,r):Ie(isNaN(t)?e:t)}var ue=function t(e){var r=Ga(e);function n(o,i){var a=r((o=qe(o)).r,(i=qe(i)).r),s=r(o.g,i.g),u=r(o.b,i.b),c=Nt(o.opacity,i.opacity);return function(l){return o.r=a(l),o.g=s(l),o.b=u(l),o.opacity=c(l),o+""}}return n.gamma=t,n}(1);function Va(t){return function(e){var r=e.length,n=new Array(r),o=new Array(r),i=new Array(r),a,s;for(a=0;ar&&(i=e.slice(r,i),s[a]?s[a]+=i:s[++a]=i),(n=n[0])===(o=o[0])?s[a]?s[a]+=o:s[++a]=o:(s[++a]=null,u.push({i:a,x:Z(n,o)})),r=io.lastIndex;return r180?l+=360:l-c>180&&(c+=360),f.push({i:p.push(o(p)+"rotate(",null,n)-2,x:Z(c,l)})):l&&p.push(o(p)+"rotate("+l+n)}function s(c,l,p,f){c!==l?f.push({i:p.push(o(p)+"skewX(",null,n)-2,x:Z(c,l)}):l&&p.push(o(p)+"skewX("+l+n)}function u(c,l,p,f,m,d){if(c!==p||l!==f){var y=m.push(o(m)+"scale(",null,",",null,")");d.push({i:y-4,x:Z(c,p)},{i:y-2,x:Z(l,f)})}else(p!==1||f!==1)&&m.push(o(m)+"scale("+p+","+f+")")}return function(c,l){var p=[],f=[];return c=t(c),l=t(l),i(c.translateX,c.translateY,l.translateX,l.translateY,p,f),a(c.rotate,l.rotate,p,f),s(c.skewX,l.skewX,p,f),u(c.scaleX,c.scaleY,l.scaleX,l.scaleY,p,f),c=l=null,function(m){for(var d=-1,y=f.length,k;++d=0&&t._call.call(void 0,e),t=t._next;--Ne}function es(){le=(tn=pr.now())+en,Ne=cr=0;try{os()}finally{Ne=0,Jf(),le=0}}function Zf(){var t=pr.now(),e=t-tn;e>rs&&(en-=e,tn=t)}function Jf(){for(var t,e=Kr,r,n=1/0;e;)e._call?(n>e._time&&(n=e._time),t=e,e=e._next):(r=e._next,e._next=null,e=t?t._next=r:Kr=r);fr=t,co(n)}function co(t){if(!Ne){cr&&(cr=clearTimeout(cr));var e=t-le;e>24?(t<1/0&&(cr=setTimeout(es,t-pr.now()-en)),lr&&(lr=clearInterval(lr))):(lr||(tn=pr.now(),lr=setInterval(Zf,rs)),Ne=1,ns(es))}}function nn(t,e,r){var n=new mr;return e=e==null?0:+e,n.restart(o=>{n.stop(),t(o+e)},e,r),n}var Qf=jn("start","end","cancel","interrupt"),Kf=[],ss=0,is=1,an=2,on=3,as=4,sn=5,hr=6;function Pt(t,e,r,n,o,i){var a=t.__transition;if(!a)t.__transition={};else if(r in a)return;tp(t,r,{name:e,index:n,group:o,on:Qf,tween:Kf,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:ss})}function gr(t,e){var r=J(t,e);if(r.state>ss)throw new Error("too late; already scheduled");return r}function rt(t,e){var r=J(t,e);if(r.state>on)throw new Error("too late; already running");return r}function J(t,e){var r=t.__transition;if(!r||!(r=r[e]))throw new Error("transition not found");return r}function tp(t,e,r){var n=t.__transition,o;n[e]=r,r.timer=rn(i,0,r.time);function i(c){r.state=is,r.timer.restart(a,r.delay,r.time),r.delay<=c&&a(c-r.delay)}function a(c){var l,p,f,m;if(r.state!==is)return u();for(l in n)if(m=n[l],m.name===r.name){if(m.state===on)return nn(a);m.state===as?(m.state=hr,m.timer.stop(),m.on.call("interrupt",t,t.__data__,m.index,m.group),delete n[l]):+lan&&n.state=0&&(e=e.slice(0,r)),!e||e==="start"})}function bp(t,e,r){var n,o,i=vp(e)?gr:rt;return function(){var a=i(this,t),s=a.on;s!==n&&(o=(n=s).copy()).on(e,r),a.on=o}}function ys(t,e){var r=this._id;return arguments.length<2?J(this.node(),r).on.on(t):this.each(bp(r,t,e))}function wp(t){return function(){var e=this.parentNode;for(var r in this.__transition)if(+r!==t)return;e&&e.removeChild(this)}}function vs(){return this.on("end.remove",wp(this._id))}function bs(t){var e=this._name,r=this._id;typeof t!="function"&&(t=re(t));for(var n=this._groups,o=n.length,i=new Array(o),a=0;a=0))throw new Error(`invalid digits: ${t}`);if(e>15)return qs;let r=10**e;return function(n){this._+=n[0];for(let o=1,i=n.length;oce)if(!(Math.abs(p*u-c*l)>ce)||!i)this._append`L${this._x1=e},${this._y1=r}`;else{let m=n-a,d=o-s,y=u*u+c*c,k=m*m+d*d,_=Math.sqrt(y),q=Math.sqrt(f),A=i*Math.tan((po-Math.acos((y+f-k)/(2*_*q)))/2),D=A/q,L=A/_;Math.abs(D-1)>ce&&this._append`L${e+D*l},${r+D*p}`,this._append`A${i},${i},0,0,${+(p*m>l*d)},${this._x1=e+L*u},${this._y1=r+L*c}`}}arc(e,r,n,o,i,a){if(e=+e,r=+r,n=+n,a=!!a,n<0)throw new Error(`negative radius: ${n}`);let s=n*Math.cos(o),u=n*Math.sin(o),c=e+s,l=r+u,p=1^a,f=a?o-i:i-o;this._x1===null?this._append`M${c},${l}`:(Math.abs(this._x1-c)>ce||Math.abs(this._y1-l)>ce)&&this._append`L${c},${l}`,n&&(f<0&&(f=f%mo+mo),f>Hp?this._append`A${n},${n},0,1,${p},${e-s},${r-u}A${n},${n},0,1,${p},${this._x1=c},${this._y1=l}`:f>ce&&this._append`A${n},${n},0,${+(f>=po)},${p},${this._x1=e+n*Math.cos(i)},${this._y1=r+n*Math.sin(i)}`)}rect(e,r,n,o){this._append`M${this._x0=this._x1=+e},${this._y0=this._y1=+r}h${n=+n}v${+o}h${-n}Z`}toString(){return this._}};function Is(){return new fe}Is.prototype=fe.prototype;function Ns(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)}function pe(t,e){if((r=(t=e?t.toExponential(e-1):t.toExponential()).indexOf("e"))<0)return null;var r,n=t.slice(0,r);return[n.length>1?n[0]+n.slice(2):n,+t.slice(r+1)]}function Mt(t){return t=pe(Math.abs(t)),t?t[1]:NaN}function Bs(t,e){return function(r,n){for(var o=r.length,i=[],a=0,s=t[0],u=0;o>0&&s>0&&(u+s+1>n&&(s=Math.max(1,n-u)),i.push(r.substring(o-=s,o+s)),!((u+=s+1)>n));)s=t[a=(a+1)%t.length];return i.reverse().join(e)}}function Rs(t){return function(e){return e.replace(/[0-9]/g,function(r){return t[+r]})}}var Op=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function St(t){if(!(e=Op.exec(t)))throw new Error("invalid format: "+t);var e;return new pn({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}St.prototype=pn.prototype;function pn(t){this.fill=t.fill===void 0?" ":t.fill+"",this.align=t.align===void 0?">":t.align+"",this.sign=t.sign===void 0?"-":t.sign+"",this.symbol=t.symbol===void 0?"":t.symbol+"",this.zero=!!t.zero,this.width=t.width===void 0?void 0:+t.width,this.comma=!!t.comma,this.precision=t.precision===void 0?void 0:+t.precision,this.trim=!!t.trim,this.type=t.type===void 0?"":t.type+""}pn.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function Hs(t){t:for(var e=t.length,r=1,n=-1,o;r0&&(n=0);break}return n>0?t.slice(0,n)+t.slice(o+1):t}var ho;function Fs(t,e){var r=pe(t,e);if(!r)return t+"";var n=r[0],o=r[1],i=o-(ho=Math.max(-8,Math.min(8,Math.floor(o/3)))*3)+1,a=n.length;return i===a?n:i>a?n+new Array(i-a+1).join("0"):i>0?n.slice(0,i)+"."+n.slice(i):"0."+new Array(1-i).join("0")+pe(t,Math.max(0,e+i-1))[0]}function go(t,e){var r=pe(t,e);if(!r)return t+"";var n=r[0],o=r[1];return o<0?"0."+new Array(-o).join("0")+n:n.length>o+1?n.slice(0,o+1)+"."+n.slice(o+1):n+new Array(o-n.length+2).join("0")}var xo={"%":(t,e)=>(t*100).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:Ns,e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>go(t*100,e),r:go,s:Fs,X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function yo(t){return t}var Os=Array.prototype.map,Ps=["y","z","a","f","p","n","\xB5","m","","k","M","G","T","P","E","Z","Y"];function $s(t){var e=t.grouping===void 0||t.thousands===void 0?yo:Bs(Os.call(t.grouping,Number),t.thousands+""),r=t.currency===void 0?"":t.currency[0]+"",n=t.currency===void 0?"":t.currency[1]+"",o=t.decimal===void 0?".":t.decimal+"",i=t.numerals===void 0?yo:Rs(Os.call(t.numerals,String)),a=t.percent===void 0?"%":t.percent+"",s=t.minus===void 0?"\u2212":t.minus+"",u=t.nan===void 0?"NaN":t.nan+"";function c(p){p=St(p);var f=p.fill,m=p.align,d=p.sign,y=p.symbol,k=p.zero,_=p.width,q=p.comma,A=p.precision,D=p.trim,L=p.type;L==="n"?(q=!0,L="g"):xo[L]||(A===void 0&&(A=12),D=!0,L="g"),(k||f==="0"&&m==="=")&&(k=!0,f="0",m="=");var b=y==="$"?r:y==="#"&&/[boxX]/.test(L)?"0"+L.toLowerCase():"",N=y==="$"?n:/[%p]/.test(L)?a:"",H=xo[L],P=/[defgprs%]/.test(L);A=A===void 0?6:/[gprs]/.test(L)?Math.max(1,Math.min(21,A)):Math.max(0,Math.min(20,A));function I(h){var T=b,E=N,R,g,x;if(L==="c")E=H(h)+E,h="";else{h=+h;var M=h<0||1/h<0;if(h=isNaN(h)?u:H(Math.abs(h),A),D&&(h=Hs(h)),M&&+h==0&&d!=="+"&&(M=!1),T=(M?d==="("?d:s:d==="-"||d==="("?"":d)+T,E=(L==="s"?Ps[8+ho/3]:"")+E+(M&&d==="("?")":""),P){for(R=-1,g=h.length;++Rx||x>57){E=(x===46?o+h.slice(R+1):h.slice(R))+E,h=h.slice(0,R);break}}}q&&!k&&(h=e(h,1/0));var S=T.length+h.length+E.length,v=S<_?new Array(_-S+1).join(f):"";switch(q&&k&&(h=e(v+h,v.length?_-E.length:1/0),v=""),m){case"<":h=T+h+E+v;break;case"=":h=T+v+h+E;break;case"^":h=v.slice(0,S=v.length>>1)+T+h+E+v.slice(S);break;default:h=v+T+h+E;break}return i(h)}return I.toString=function(){return p+""},I}function l(p,f){var m=c((p=St(p),p.type="f",p)),d=Math.max(-8,Math.min(8,Math.floor(Mt(f)/3)))*3,y=Math.pow(10,-d),k=Ps[8+d/3];return function(_){return m(y*_)+k}}return{format:c,formatPrefix:l}}var mn,bt,dn;vo({thousands:",",grouping:[3],currency:["$",""]});function vo(t){return mn=$s(t),bt=mn.format,dn=mn.formatPrefix,mn}function bo(t){return Math.max(0,-Mt(Math.abs(t)))}function wo(t,e){return Math.max(0,Math.max(-8,Math.min(8,Math.floor(Mt(e)/3)))*3-Mt(Math.abs(t)))}function ko(t,e){return t=Math.abs(t),e=Math.abs(e)-t,Math.max(0,Mt(e)-Mt(t))+1}function Pp(t){var e=0,r=t.children,n=r&&r.length;if(!n)e=1;else for(;--n>=0;)e+=r[n].value;t.value=e}function Us(){return this.eachAfter(Pp)}function Gs(t,e){let r=-1;for(let n of this)t.call(e,n,++r,this);return this}function Vs(t,e){for(var r=this,n=[r],o,i,a=-1;r=n.pop();)if(t.call(e,r,++a,this),o=r.children)for(i=o.length-1;i>=0;--i)n.push(o[i]);return this}function zs(t,e){for(var r=this,n=[r],o=[],i,a,s,u=-1;r=n.pop();)if(o.push(r),i=r.children)for(a=0,s=i.length;a=0;)r+=n[o].value;e.value=r})}function Xs(t){return this.eachBefore(function(e){e.children&&e.children.sort(t)})}function js(t){for(var e=this,r=$p(e,t),n=[e];e!==r;)e=e.parent,n.push(e);for(var o=n.length;t!==r;)n.splice(o,0,t),t=t.parent;return n}function $p(t,e){if(t===e)return t;var r=t.ancestors(),n=e.ancestors(),o=null;for(t=r.pop(),e=n.pop();t===e;)o=t,t=r.pop(),e=n.pop();return o}function Zs(){for(var t=this,e=[t];t=t.parent;)e.push(t);return e}function Js(){return Array.from(this)}function Qs(){var t=[];return this.eachBefore(function(e){e.children||t.push(e)}),t}function Ks(){var t=this,e=[];return t.each(function(r){r!==t&&e.push({source:r.parent,target:r})}),e}function*tu(){var t=this,e,r=[t],n,o,i;do for(e=r.reverse(),r=[];t=e.pop();)if(yield t,n=t.children)for(o=0,i=n.length;o=0;--s)o.push(i=a[s]=new yr(a[s])),i.parent=n,i.depth=n.depth+1;return r.eachBefore(Yp)}function Up(){return Re(this).eachBefore(zp)}function Gp(t){return t.children}function Vp(t){return Array.isArray(t)?t[1]:null}function zp(t){t.data.value!==void 0&&(t.value=t.data.value),t.data=t.data.data}function Yp(t){var e=0;do t.height=e;while((t=t.parent)&&t.height<++e)}function yr(t){this.data=t,this.depth=this.height=0,this.parent=null}yr.prototype=Re.prototype={constructor:yr,count:Us,each:Gs,eachAfter:zs,eachBefore:Vs,find:Ys,sum:Ws,sort:Xs,path:js,ancestors:Zs,descendants:Js,leaves:Qs,links:Ks,copy:Up,[Symbol.iterator]:tu};function eu(t){if(typeof t!="function")throw new Error;return t}function He(){return 0}function Fe(t){return function(){return t}}function ru(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)}function nu(t,e,r,n,o){for(var i=t.children,a,s=-1,u=i.length,c=t.value&&(n-e)/t.value;++sq&&(q=c),b=k*k*L,A=Math.max(q/b,b/_),A>D){k-=c;break}D=A}a.push(u={value:k,dice:m1?n:1)},r}(Wp);function _o(){var t=vr,e=!1,r=1,n=1,o=[0],i=He,a=He,s=He,u=He,c=He;function l(f){return f.x0=f.y0=0,f.x1=r,f.y1=n,f.eachBefore(p),o=[0],e&&f.eachBefore(ru),f}function p(f){var m=o[f.depth],d=f.x0+m,y=f.y0+m,k=f.x1-m,_=f.y1-m;ke&&(r=t,t=e,e=r),function(n){return Math.max(t,Math.min(e,n))}}function Zp(t,e,r){var n=t[0],o=t[1],i=e[0],a=e[1];return o2?Jp:Zp,u=c=null,p}function p(f){return f==null||isNaN(f=+f)?i:(u||(u=s(t.map(n),e,r)))(n(a(f)))}return p.invert=function(f){return a(o((c||(c=s(e,t.map(n),Z)))(f)))},p.domain=function(f){return arguments.length?(t=Array.from(f,So),l()):t.slice()},p.range=function(f){return arguments.length?(e=Array.from(f),l()):e.slice()},p.rangeRound=function(f){return e=Array.from(f),r=ur,l()},p.clamp=function(f){return arguments.length?(a=f?!0:Ut,l()):a!==Ut},p.interpolate=function(f){return arguments.length?(r=f,l()):r},p.unknown=function(f){return arguments.length?(i=f,p):i},function(f,m){return n=f,o=m,l()}}function wr(){return Qp()(Ut,Ut)}function Eo(t,e,r,n){var o=Le(t,e,r),i;switch(n=St(n??",f"),n.type){case"s":{var a=Math.max(Math.abs(t),Math.abs(e));return n.precision==null&&!isNaN(i=wo(o,a))&&(n.precision=i),dn(n,a)}case"":case"e":case"g":case"p":case"r":{n.precision==null&&!isNaN(i=ko(o,Math.max(Math.abs(t),Math.abs(e))))&&(n.precision=i-(n.type==="e"));break}case"f":case"%":{n.precision==null&&!isNaN(i=bo(o))&&(n.precision=i-(n.type==="%")*2);break}}return bt(n)}function Kp(t){var e=t.domain;return t.ticks=function(r){var n=e();return te(n[0],n[n.length-1],r??10)},t.tickFormat=function(r,n){var o=e();return Eo(o[0],o[o.length-1],r??10,n)},t.nice=function(r){r==null&&(r=10);var n=e(),o=0,i=n.length-1,a=n[o],s=n[i],u,c,l=10;for(s0;){if(c=Qe(a,s,r),c===u)return n[o]=a,n[i]=s,e(n);if(c>0)a=Math.floor(a/c)*c,s=Math.ceil(s/c)*c;else if(c<0)a=Math.ceil(a*c)/c,s=Math.floor(s*c)/c;else break;u=c}return t},t}function de(){var t=wr();return t.copy=function(){return hn(t,de())},$t.apply(t,arguments),Kp(t)}function kr(t,e){t=t.slice();var r=0,n=t.length-1,o=t[r],i=t[n],a;return iMath.pow(t,e)}function om(t){return t===Math.E?Math.log:t===10&&Math.log10||t===2&&Math.log2||(t=Math.log(t),e=>Math.log(e)/t)}function lu(t){return(e,r)=>-t(-e,r)}function cu(t){let e=t(su,uu),r=e.domain,n=10,o,i;function a(){return o=om(n),i=nm(n),r()[0]<0?(o=lu(o),i=lu(i),t(tm,em)):t(su,uu),e}return e.base=function(s){return arguments.length?(n=+s,a()):n},e.domain=function(s){return arguments.length?(r(s),a()):r()},e.ticks=s=>{let u=r(),c=u[0],l=u[u.length-1],p=l0){for(;f<=m;++f)for(d=1;dl)break;_.push(y)}}else for(;f<=m;++f)for(d=n-1;d>=1;--d)if(y=f>0?d/i(-f):d*i(f),!(yl)break;_.push(y)}_.length*2{if(s==null&&(s=10),u==null&&(u=n===10?"s":","),typeof u!="function"&&(!(n%1)&&(u=St(u)).precision==null&&(u.trim=!0),u=bt(u)),s===1/0)return u;let c=Math.max(1,n*s/e.ticks().length);return l=>{let p=l/i(Math.round(o(l)));return p*nr(kr(r(),{floor:s=>i(Math.floor(o(s))),ceil:s=>i(Math.ceil(o(s)))})),e}var Ao=new Date,Do=new Date;function z(t,e,r,n){function o(i){return t(i=arguments.length===0?new Date:new Date(+i)),i}return o.floor=i=>(t(i=new Date(+i)),i),o.ceil=i=>(t(i=new Date(i-1)),e(i,1),t(i),i),o.round=i=>{let a=o(i),s=o.ceil(i);return i-a(e(i=new Date(+i),a==null?1:Math.floor(a)),i),o.range=(i,a,s)=>{let u=[];if(i=o.ceil(i),s=s==null?1:Math.floor(s),!(i0))return u;let c;do u.push(c=new Date(+i)),e(i,s),t(i);while(cz(a=>{if(a>=a)for(;t(a),!i(a);)a.setTime(a-1)},(a,s)=>{if(a>=a)if(s<0)for(;++s<=0;)for(;e(a,-1),!i(a););else for(;--s>=0;)for(;e(a,1),!i(a););}),r&&(o.count=(i,a)=>(Ao.setTime(+i),Do.setTime(+a),t(Ao),t(Do),Math.floor(r(Ao,Do))),o.every=i=>(i=Math.floor(i),!isFinite(i)||!(i>0)?null:i>1?o.filter(n?a=>n(a)%i===0:a=>o.count(0,a)%i===0):o)),o}var _r=z(()=>{},(t,e)=>{t.setTime(+t+e)},(t,e)=>e-t);_r.every=t=>(t=Math.floor(t),!isFinite(t)||!(t>0)?null:t>1?z(e=>{e.setTime(Math.floor(e/t)*t)},(e,r)=>{e.setTime(+e+r*t)},(e,r)=>(r-e)/t):_r);var m_=_r.range;var Lt=z(t=>{t.setTime(t-t.getMilliseconds())},(t,e)=>{t.setTime(+t+e*1e3)},(t,e)=>(e-t)/1e3,t=>t.getUTCSeconds()),fu=Lt.range;var Oe=z(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*1e3)},(t,e)=>{t.setTime(+t+e*6e4)},(t,e)=>(e-t)/6e4,t=>t.getMinutes()),im=Oe.range,gn=z(t=>{t.setUTCSeconds(0,0)},(t,e)=>{t.setTime(+t+e*6e4)},(t,e)=>(e-t)/6e4,t=>t.getUTCMinutes()),am=gn.range;var Pe=z(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*1e3-t.getMinutes()*6e4)},(t,e)=>{t.setTime(+t+e*36e5)},(t,e)=>(e-t)/36e5,t=>t.getHours()),sm=Pe.range,xn=z(t=>{t.setUTCMinutes(0,0,0)},(t,e)=>{t.setTime(+t+e*36e5)},(t,e)=>(e-t)/36e5,t=>t.getUTCHours()),um=xn.range;var Rt=z(t=>t.setHours(0,0,0,0),(t,e)=>t.setDate(t.getDate()+e),(t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*6e4)/864e5,t=>t.getDate()-1),lm=Rt.range,Mr=z(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>t.getUTCDate()-1),cm=Mr.range,yn=z(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>Math.floor(t/864e5)),fm=yn.range;function xe(t){return z(e=>{e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)},(e,r)=>{e.setDate(e.getDate()+r*7)},(e,r)=>(r-e-(r.getTimezoneOffset()-e.getTimezoneOffset())*6e4)/6048e5)}var Ht=xe(0),$e=xe(1),mu=xe(2),du=xe(3),Gt=xe(4),hu=xe(5),gu=xe(6),xu=Ht.range,pm=$e.range,mm=mu.range,dm=du.range,hm=Gt.range,gm=hu.range,xm=gu.range;function ye(t){return z(e=>{e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)},(e,r)=>{e.setUTCDate(e.getUTCDate()+r*7)},(e,r)=>(r-e)/6048e5)}var ve=ye(0),Ue=ye(1),yu=ye(2),vu=ye(3),Vt=ye(4),bu=ye(5),wu=ye(6),ku=ve.range,ym=Ue.range,vm=yu.range,bm=vu.range,wm=Vt.range,km=bu.range,_m=wu.range;var Ge=z(t=>{t.setDate(1),t.setHours(0,0,0,0)},(t,e)=>{t.setMonth(t.getMonth()+e)},(t,e)=>e.getMonth()-t.getMonth()+(e.getFullYear()-t.getFullYear())*12,t=>t.getMonth()),Tm=Ge.range,vn=z(t=>{t.setUTCDate(1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCMonth(t.getUTCMonth()+e)},(t,e)=>e.getUTCMonth()-t.getUTCMonth()+(e.getUTCFullYear()-t.getUTCFullYear())*12,t=>t.getUTCMonth()),Mm=vn.range;var pt=z(t=>{t.setMonth(0,1),t.setHours(0,0,0,0)},(t,e)=>{t.setFullYear(t.getFullYear()+e)},(t,e)=>e.getFullYear()-t.getFullYear(),t=>t.getFullYear());pt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:z(e=>{e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)},(e,r)=>{e.setFullYear(e.getFullYear()+r*t)});var Sm=pt.range,wt=z(t=>{t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCFullYear(t.getUTCFullYear()+e)},(t,e)=>e.getUTCFullYear()-t.getUTCFullYear(),t=>t.getUTCFullYear());wt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:z(e=>{e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)},(e,r)=>{e.setUTCFullYear(e.getUTCFullYear()+r*t)});var Lm=wt.range;function Tu(t,e,r,n,o,i){let a=[[Lt,1,1e3],[Lt,5,5*1e3],[Lt,15,15*1e3],[Lt,30,30*1e3],[i,1,6e4],[i,5,5*6e4],[i,15,15*6e4],[i,30,30*6e4],[o,1,36e5],[o,3,3*36e5],[o,6,6*36e5],[o,12,12*36e5],[n,1,864e5],[n,2,2*864e5],[r,1,6048e5],[e,1,2592e6],[e,3,3*2592e6],[t,1,31536e6]];function s(c,l,p){let f=lk).right(a,f);if(m===a.length)return t.every(Le(c/31536e6,l/31536e6,p));if(m===0)return _r.every(Math.max(Le(c,l,p),1));let[d,y]=a[f/a[m-1][2]53)return null;"w"in w||(w.w=1),"Z"in w?(Y=No(Sr(w.y,0,1)),lt=Y.getUTCDay(),Y=lt>4||lt===0?Ue.ceil(Y):Ue(Y),Y=Mr.offset(Y,(w.V-1)*7),w.y=Y.getUTCFullYear(),w.m=Y.getUTCMonth(),w.d=Y.getUTCDate()+(w.w+6)%7):(Y=Io(Sr(w.y,0,1)),lt=Y.getDay(),Y=lt>4||lt===0?$e.ceil(Y):$e(Y),Y=Rt.offset(Y,(w.V-1)*7),w.y=Y.getFullYear(),w.m=Y.getMonth(),w.d=Y.getDate()+(w.w+6)%7)}else("W"in w||"U"in w)&&("w"in w||(w.w="u"in w?w.u%7:"W"in w?1:0),lt="Z"in w?No(Sr(w.y,0,1)).getUTCDay():Io(Sr(w.y,0,1)).getDay(),w.m=0,w.d="W"in w?(w.w+6)%7+w.W*7-(lt+5)%7:w.w+w.U*7-(lt+6)%7);return"Z"in w?(w.H+=w.Z/100|0,w.M+=w.Z%100,No(w)):Io(w)}}function H(C,F,U,w){for(var st=0,Y=F.length,lt=U.length,ct,Qt;st=lt)return-1;if(ct=F.charCodeAt(st++),ct===37){if(ct=F.charAt(st++),Qt=L[ct in Mu?F.charAt(st++):ct],!Qt||(w=Qt(C,U,w))<0)return-1}else if(ct!=U.charCodeAt(w++))return-1}return w}function P(C,F,U){var w=c.exec(F.slice(U));return w?(C.p=l.get(w[0].toLowerCase()),U+w[0].length):-1}function I(C,F,U){var w=m.exec(F.slice(U));return w?(C.w=d.get(w[0].toLowerCase()),U+w[0].length):-1}function h(C,F,U){var w=p.exec(F.slice(U));return w?(C.w=f.get(w[0].toLowerCase()),U+w[0].length):-1}function T(C,F,U){var w=_.exec(F.slice(U));return w?(C.m=q.get(w[0].toLowerCase()),U+w[0].length):-1}function E(C,F,U){var w=y.exec(F.slice(U));return w?(C.m=k.get(w[0].toLowerCase()),U+w[0].length):-1}function R(C,F,U){return H(C,e,F,U)}function g(C,F,U){return H(C,r,F,U)}function x(C,F,U){return H(C,n,F,U)}function M(C){return a[C.getDay()]}function S(C){return i[C.getDay()]}function v(C){return u[C.getMonth()]}function B(C){return s[C.getMonth()]}function G(C){return o[+(C.getHours()>=12)]}function K(C){return 1+~~(C.getMonth()/3)}function ot(C){return a[C.getUTCDay()]}function ht(C){return i[C.getUTCDay()]}function tt(C){return u[C.getUTCMonth()]}function Dt(C){return s[C.getUTCMonth()]}function gt(C){return o[+(C.getUTCHours()>=12)]}function Je(C){return 1+~~(C.getUTCMonth()/3)}return{format:function(C){var F=b(C+="",A);return F.toString=function(){return C},F},parse:function(C){var F=N(C+="",!1);return F.toString=function(){return C},F},utcFormat:function(C){var F=b(C+="",D);return F.toString=function(){return C},F},utcParse:function(C){var F=N(C+="",!0);return F.toString=function(){return C},F}}}var Mu={"-":"",_:" ",0:"0"},Q=/^\s*\d+/,Cm=/^%/,qm=/[\\^$*+?|[\]().{}]/g;function V(t,e,r){var n=t<0?"-":"",o=(n?-t:t)+"",i=o.length;return n+(i[e.toLowerCase(),r]))}function Nm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.w=+n[0],r+n[0].length):-1}function Bm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.u=+n[0],r+n[0].length):-1}function Rm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.U=+n[0],r+n[0].length):-1}function Hm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.V=+n[0],r+n[0].length):-1}function Fm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.W=+n[0],r+n[0].length):-1}function Su(t,e,r){var n=Q.exec(e.slice(r,r+4));return n?(t.y=+n[0],r+n[0].length):-1}function Lu(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.y=+n[0]+(+n[0]>68?1900:2e3),r+n[0].length):-1}function Om(t,e,r){var n=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(r,r+6));return n?(t.Z=n[1]?0:-(n[2]+(n[3]||"00")),r+n[0].length):-1}function Pm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.q=n[0]*3-3,r+n[0].length):-1}function $m(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.m=n[0]-1,r+n[0].length):-1}function Eu(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.d=+n[0],r+n[0].length):-1}function Um(t,e,r){var n=Q.exec(e.slice(r,r+3));return n?(t.m=0,t.d=+n[0],r+n[0].length):-1}function Au(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.H=+n[0],r+n[0].length):-1}function Gm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.M=+n[0],r+n[0].length):-1}function Vm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.S=+n[0],r+n[0].length):-1}function zm(t,e,r){var n=Q.exec(e.slice(r,r+3));return n?(t.L=+n[0],r+n[0].length):-1}function Ym(t,e,r){var n=Q.exec(e.slice(r,r+6));return n?(t.L=Math.floor(n[0]/1e3),r+n[0].length):-1}function Wm(t,e,r){var n=Cm.exec(e.slice(r,r+1));return n?r+n[0].length:-1}function Xm(t,e,r){var n=Q.exec(e.slice(r));return n?(t.Q=+n[0],r+n[0].length):-1}function jm(t,e,r){var n=Q.exec(e.slice(r));return n?(t.s=+n[0],r+n[0].length):-1}function Du(t,e){return V(t.getDate(),e,2)}function Zm(t,e){return V(t.getHours(),e,2)}function Jm(t,e){return V(t.getHours()%12||12,e,2)}function Qm(t,e){return V(1+Rt.count(pt(t),t),e,3)}function Bu(t,e){return V(t.getMilliseconds(),e,3)}function Km(t,e){return Bu(t,e)+"000"}function td(t,e){return V(t.getMonth()+1,e,2)}function ed(t,e){return V(t.getMinutes(),e,2)}function rd(t,e){return V(t.getSeconds(),e,2)}function nd(t){var e=t.getDay();return e===0?7:e}function od(t,e){return V(Ht.count(pt(t)-1,t),e,2)}function Ru(t){var e=t.getDay();return e>=4||e===0?Gt(t):Gt.ceil(t)}function id(t,e){return t=Ru(t),V(Gt.count(pt(t),t)+(pt(t).getDay()===4),e,2)}function ad(t){return t.getDay()}function sd(t,e){return V($e.count(pt(t)-1,t),e,2)}function ud(t,e){return V(t.getFullYear()%100,e,2)}function ld(t,e){return t=Ru(t),V(t.getFullYear()%100,e,2)}function cd(t,e){return V(t.getFullYear()%1e4,e,4)}function fd(t,e){var r=t.getDay();return t=r>=4||r===0?Gt(t):Gt.ceil(t),V(t.getFullYear()%1e4,e,4)}function pd(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+V(e/60|0,"0",2)+V(e%60,"0",2)}function Cu(t,e){return V(t.getUTCDate(),e,2)}function md(t,e){return V(t.getUTCHours(),e,2)}function dd(t,e){return V(t.getUTCHours()%12||12,e,2)}function hd(t,e){return V(1+Mr.count(wt(t),t),e,3)}function Hu(t,e){return V(t.getUTCMilliseconds(),e,3)}function gd(t,e){return Hu(t,e)+"000"}function xd(t,e){return V(t.getUTCMonth()+1,e,2)}function yd(t,e){return V(t.getUTCMinutes(),e,2)}function vd(t,e){return V(t.getUTCSeconds(),e,2)}function bd(t){var e=t.getUTCDay();return e===0?7:e}function wd(t,e){return V(ve.count(wt(t)-1,t),e,2)}function Fu(t){var e=t.getUTCDay();return e>=4||e===0?Vt(t):Vt.ceil(t)}function kd(t,e){return t=Fu(t),V(Vt.count(wt(t),t)+(wt(t).getUTCDay()===4),e,2)}function _d(t){return t.getUTCDay()}function Td(t,e){return V(Ue.count(wt(t)-1,t),e,2)}function Md(t,e){return V(t.getUTCFullYear()%100,e,2)}function Sd(t,e){return t=Fu(t),V(t.getUTCFullYear()%100,e,2)}function Ld(t,e){return V(t.getUTCFullYear()%1e4,e,4)}function Ed(t,e){var r=t.getUTCDay();return t=r>=4||r===0?Vt(t):Vt.ceil(t),V(t.getUTCFullYear()%1e4,e,4)}function Ad(){return"+0000"}function qu(){return"%"}function Iu(t){return+t}function Nu(t){return Math.floor(+t/1e3)}var Ve,bn,Ou,Pu,$u;Ro({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function Ro(t){return Ve=Bo(t),bn=Ve.format,Ou=Ve.parse,Pu=Ve.utcFormat,$u=Ve.utcParse,Ve}function Dd(t){return new Date(t)}function Cd(t){return t instanceof Date?+t:+new Date(+t)}function Uu(t,e,r,n,o,i,a,s,u,c){var l=wr(),p=l.invert,f=l.domain,m=c(".%L"),d=c(":%S"),y=c("%I:%M"),k=c("%I %p"),_=c("%a %d"),q=c("%b %d"),A=c("%B"),D=c("%Y");function L(b){return(u(b)1?0:t<-1?ze:Math.acos(t)}function Po(t){return t>=1?Ar:t<=-1?-Ar:Math.asin(t)}function Tn(t){let e=3;return t.digits=function(r){if(!arguments.length)return e;if(r==null)e=null;else{let n=Math.floor(r);if(!(n>=0))throw new RangeError(`invalid digits: ${r}`);e=n}return t},()=>new fe(e)}function Bd(t){return t.innerRadius}function Rd(t){return t.outerRadius}function Hd(t){return t.startAngle}function Fd(t){return t.endAngle}function Od(t){return t&&t.padAngle}function Pd(t,e,r,n,o,i,a,s){var u=r-t,c=n-e,l=a-o,p=s-i,f=p*u-l*c;if(!(f*fR*R+g*g&&(H=I,P=h),{cx:H,cy:P,x01:-l,y01:-p,x11:H*(o/L-1),y11:P*(o/L-1)}}function $o(){var t=Bd,e=Rd,r=W(0),n=null,o=Hd,i=Fd,a=Od,s=null,u=Tn(c);function c(){var l,p,f=+t.apply(this,arguments),m=+e.apply(this,arguments),d=o.apply(this,arguments)-Ar,y=i.apply(this,arguments)-Ar,k=Oo(y-d),_=y>d;if(s||(s=l=u()),mat))s.moveTo(0,0);else if(k>Ye-at)s.moveTo(m*zt(d),m*kt(d)),s.arc(0,0,m,d,y,!_),f>at&&(s.moveTo(f*zt(y),f*kt(y)),s.arc(0,0,f,y,d,_));else{var q=d,A=y,D=d,L=y,b=k,N=k,H=a.apply(this,arguments)/2,P=H>at&&(n?+n.apply(this,arguments):be(f*f+m*m)),I=_n(Oo(m-f)/2,+r.apply(this,arguments)),h=I,T=I,E,R;if(P>at){var g=Po(P/f*kt(H)),x=Po(P/m*kt(H));(b-=g*2)>at?(g*=_?1:-1,D+=g,L-=g):(b=0,D=L=(d+y)/2),(N-=x*2)>at?(x*=_?1:-1,q+=x,A-=x):(N=0,q=A=(d+y)/2)}var M=m*zt(q),S=m*kt(q),v=f*zt(L),B=f*kt(L);if(I>at){var G=m*zt(A),K=m*kt(A),ot=f*zt(D),ht=f*kt(D),tt;if(kat?T>at?(E=Mn(ot,ht,M,S,m,T,_),R=Mn(G,K,v,B,m,T,_),s.moveTo(E.cx+E.x01,E.cy+E.y01),Tat)||!(b>at)?s.lineTo(v,B):h>at?(E=Mn(v,B,G,K,f,-h,_),R=Mn(M,S,ot,ht,f,-h,_),s.lineTo(E.cx+E.x01,E.cy+E.y01),ht?1:e>=t?0:NaN}function Ju(t){return t}function Uo(){var t=Ju,e=Zu,r=null,n=W(0),o=W(Ye),i=W(0);function a(s){var u,c=(s=Sn(s)).length,l,p,f=0,m=new Array(c),d=new Array(c),y=+n.apply(this,arguments),k=Math.min(Ye,Math.max(-Ye,o.apply(this,arguments)-y)),_,q=Math.min(Math.abs(k)/c,i.apply(this,arguments)),A=q*(k<0?-1:1),D;for(u=0;u0&&(f+=D);for(e!=null?m.sort(function(L,b){return e(d[L],d[b])}):r!=null&&m.sort(function(L,b){return r(s[L],s[b])}),u=0,p=f?(k-c*A)/f:0;u0?D*p:0)+A,d[l]={data:s[l],index:u,value:D,startAngle:y,endAngle:_,padAngle:q};return d}return a.value=function(s){return arguments.length?(t=typeof s=="function"?s:W(+s),a):t},a.sortValues=function(s){return arguments.length?(e=s,r=null,a):e},a.sort=function(s){return arguments.length?(r=s,e=null,a):r},a.startAngle=function(s){return arguments.length?(n=typeof s=="function"?s:W(+s),a):n},a.endAngle=function(s){return arguments.length?(o=typeof s=="function"?s:W(+s),a):o},a.padAngle=function(s){return arguments.length?(i=typeof s=="function"?s:W(+s),a):i},a}function Qu(t){return t<0?-1:1}function Ku(t,e,r){var n=t._x1-t._x0,o=e-t._x1,i=(t._y1-t._y0)/(n||o<0&&-0),a=(r-t._y1)/(o||n<0&&-0),s=(i*o+a*n)/(n+o);return(Qu(i)+Qu(a))*Math.min(Math.abs(i),Math.abs(a),.5*Math.abs(s))||0}function tl(t,e){var r=t._x1-t._x0;return r?(3*(t._y1-t._y0)/r-e)/2:e}function Go(t,e,r){var n=t._x0,o=t._y0,i=t._x1,a=t._y1,s=(i-n)/3;t._context.bezierCurveTo(n+s,o+s*e,i-s,a-s*r,i,a)}function Ln(t){this._context=t}Ln.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:Go(this,this._t0,tl(this,this._t0));break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){var r=NaN;if(t=+t,e=+e,!(t===this._x1&&e===this._y1)){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,Go(this,tl(this,r=Ku(this,t,e)),r);break;default:Go(this,this._t0,r=Ku(this,t,e));break}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e,this._t0=r}}};function $d(t){this._context=new el(t)}($d.prototype=Object.create(Ln.prototype)).point=function(t,e){Ln.prototype.point.call(this,e,t)};function el(t){this._context=t}el.prototype={moveTo:function(t,e){this._context.moveTo(e,t)},closePath:function(){this._context.closePath()},lineTo:function(t,e){this._context.lineTo(e,t)},bezierCurveTo:function(t,e,r,n,o,i){this._context.bezierCurveTo(e,t,n,r,i,o)}};function En(t){return new Ln(t)}function Yt(t,e,r){this.k=t,this.x=e,this.y=r}Yt.prototype={constructor:Yt,scale:function(t){return t===1?this:new Yt(this.k*t,this.x,this.y)},translate:function(t,e){return t===0&e===0?this:new Yt(this.k,this.x+this.k*t,this.y+this.k*e)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Vo=new Yt(1,0,0);zo.prototype=Yt.prototype;function zo(t){for(;!t.__zoom;)if(!(t=t.parentNode))return Vo;return t.__zoom}var dt=bt(",.0f"),Wt=bt(",.1f");function Wo(t){function e(c){return c.toString().padStart(2,"0")}let r=Math.floor(t/1e3),n=Math.floor(r/60),o=Math.floor(n/60),i=Math.floor(o/24),a=o%24,s=n%60,u=r%60;return i===0&&a===0&&s===0&&u===0?"0s":i>0?`${i}d ${e(a)}h ${e(s)}m ${e(u)}s`:a>0?`${a}h ${e(s)}m ${e(u)}s`:s>0?`${s}m ${e(u)}s`:`${u}s`}var Ud=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function nl(t){let e=new Date(t*1e3),r=String(e.getDate()).padStart(2,"0"),n=Ud[e.getMonth()],o=e.getFullYear(),i=String(e.getHours()).padStart(2,"0"),a=String(e.getMinutes()).padStart(2,"0"),s=String(e.getSeconds()).padStart(2,"0");return`${r} ${n} ${o} ${i}:${a}:${s}`}var Yo=["bytes","kB","MB","GB","TB","PB"];function ol(t){if(!Number.isFinite(t)||t<0)return"0 bytes";let e=0,r=t;for(;r>=1e3&&eGd(a.charCodeAt(0))).length>=o.length/2?`0x${e}`:o}function Gd(t){return t<32||t>=127&&t<160}function Vd(t){if(t.length===0||t.length%2!==0)return new Uint8Array;let e=new Uint8Array(t.length/2);for(let r=0;r=1e14){let o=t/1e18;n=`${rl(o,4)} ${ll}`}else if(t>=1e5){let o=t/1e9;n=`${rl(o,4)} gwei`}else n=`${t} wei`;return n}function An(t){return!t.startsWith("0x")||t.length<14?t:`${t.slice(0,8)}...${t.slice(-6)}`}function Xt(t,e,r=80,n=44,o=60){let i=e[e.length-1],a=i.t-o*1e3;e=e.filter(A=>A.t>=a);let s={top:2,right:2,bottom:2,left:2},u=r-s.left-s.right,c=n-s.top-s.bottom,l=j(t).select("svg");l.empty()&&(l=j(t).append("svg").attr("width",r).attr("height",n),l.append("g").attr("class","line-group").attr("transform",`translate(${s.left},${s.top})`).append("path").attr("class","sparkline-path").attr("fill","none").attr("stroke","#00bff2").attr("stroke-width",1.5),l.append("g").attr("class","y-axis").attr("transform",`translate(${s.left},${s.top})`)),l.attr("width",r).attr("height",n);let f=l.select("g.line-group").select("path.sparkline-path"),m=i.t,d=wn().domain([new Date(a),new Date(m)]).range([0,u]),[y,k]=Me(e,A=>A.v),_=de().domain([y,k]).range([c,0]).nice(),q=We().x(A=>d(new Date(A.t))).y(A=>_(A.v));if(f.datum(e).attr("d",q).attr("transform",null),e.length>1){let A=u/o;f.attr("transform",`translate(${A},0)`),f.transition().duration(300).attr("transform","translate(0,0)")}}function Cr(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r=o)&&(r=o)}return r}function Xe(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r>n||r===void 0&&n>=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r>o||r===void 0&&o>=o)&&(r=o)}return r}function je(t,e){let r=0;if(e===void 0)for(let n of t)(n=+n)&&(r+=n);else{let n=-1;for(let o of t)(o=+e(o,++n,t))&&(r+=o)}return r}function Xd(t){return t.target.depth}function Xo(t,e){return t.sourceLinks.length?t.depth:e-1}function jo(t){return t.targetLinks.length?t.depth:t.sourceLinks.length?Xe(t.sourceLinks,Xd)-1:0}function Ze(t){return function(){return t}}function fl(t,e){return Dn(t.source,e.source)||t.index-e.index}function pl(t,e){return Dn(t.target,e.target)||t.index-e.index}function Dn(t,e){return t.y0-e.y0}function Zo(t){return t.value}function jd(t){return t.index}function Zd(t){return t.nodes}function Jd(t){return t.links}function ml(t,e){let r=t.get(e);if(!r)throw new Error("missing: "+e);return r}function dl({nodes:t}){for(let e of t){let r=e.y0,n=r;for(let o of e.sourceLinks)o.y0=r+o.width/2,r+=o.width;for(let o of e.targetLinks)o.y1=n+o.width/2,n+=o.width}}function Cn(){let t=0,e=0,r=1,n=1,o=24,i=8,a,s=jd,u=Xo,c,l,p=Zd,f=Jd,m=6;function d(){let g={nodes:p.apply(null,arguments),links:f.apply(null,arguments)};return y(g),k(g),_(g),q(g),L(g),dl(g),g}d.update=function(g){return dl(g),g},d.nodeId=function(g){return arguments.length?(s=typeof g=="function"?g:Ze(g),d):s},d.nodeAlign=function(g){return arguments.length?(u=typeof g=="function"?g:Ze(g),d):u},d.nodeSort=function(g){return arguments.length?(c=g,d):c},d.nodeWidth=function(g){return arguments.length?(o=+g,d):o},d.nodePadding=function(g){return arguments.length?(i=a=+g,d):i},d.nodes=function(g){return arguments.length?(p=typeof g=="function"?g:Ze(g),d):p},d.links=function(g){return arguments.length?(f=typeof g=="function"?g:Ze(g),d):f},d.linkSort=function(g){return arguments.length?(l=g,d):l},d.size=function(g){return arguments.length?(t=e=0,r=+g[0],n=+g[1],d):[r-t,n-e]},d.extent=function(g){return arguments.length?(t=+g[0][0],r=+g[1][0],e=+g[0][1],n=+g[1][1],d):[[t,e],[r,n]]},d.iterations=function(g){return arguments.length?(m=+g,d):m};function y({nodes:g,links:x}){for(let[S,v]of g.entries())v.index=S,v.sourceLinks=[],v.targetLinks=[];let M=new Map(g.map((S,v)=>[s(S,v,g),S]));for(let[S,v]of x.entries()){v.index=S;let{source:B,target:G}=v;typeof B!="object"&&(B=v.source=ml(M,B)),typeof G!="object"&&(G=v.target=ml(M,G)),B.sourceLinks.push(v),G.targetLinks.push(v)}if(l!=null)for(let{sourceLinks:S,targetLinks:v}of g)S.sort(l),v.sort(l)}function k({nodes:g}){for(let x of g)x.value=x.fixedValue===void 0?Math.max(je(x.sourceLinks,Zo),je(x.targetLinks,Zo)):x.fixedValue}function _({nodes:g}){let x=g.length,M=new Set(g),S=new Set,v=0;for(;M.size;){for(let B of M){B.depth=v;for(let{target:G}of B.sourceLinks)S.add(G)}if(++v>x)throw new Error("circular link");M=S,S=new Set}}function q({nodes:g}){let x=g.length,M=new Set(g),S=new Set,v=0;for(;M.size;){for(let B of M){B.height=v;for(let{source:G}of B.targetLinks)S.add(G)}if(++v>x)throw new Error("circular link");M=S,S=new Set}}function A({nodes:g}){let x=Cr(g,v=>v.depth)+1,M=(r-t-o)/(x-1),S=new Array(x);for(let v of g){let B=Math.max(0,Math.min(x-1,Math.floor(u.call(null,v,x))));v.layer=B,v.x0=t+B*M,v.x1=v.x0+o,S[B]?S[B].push(v):S[B]=[v]}if(c)for(let v of S)v.sort(c);return S}function D(g){let x=Xe(g,M=>(n-e-(M.length-1)*a)/je(M,Zo));for(let M of g){let S=e;for(let v of M){v.y0=S,v.y1=S+v.value*x,S=v.y1+a;for(let B of v.sourceLinks)B.width=B.value*x}S=(n-S+a)/(M.length+1);for(let v=0;vM.length)-1)),D(x);for(let M=0;M0))continue;let ht=(K/ot-G.y0)*x;G.y0+=ht,G.y1+=ht,h(G)}c===void 0&&B.sort(Dn),H(B,M)}}function N(g,x,M){for(let S=g.length,v=S-2;v>=0;--v){let B=g[v];for(let G of B){let K=0,ot=0;for(let{target:tt,value:Dt}of G.sourceLinks){let gt=Dt*(tt.layer-G.layer);K+=R(G,tt)*gt,ot+=gt}if(!(ot>0))continue;let ht=(K/ot-G.y0)*x;G.y0+=ht,G.y1+=ht,h(G)}c===void 0&&B.sort(Dn),H(B,M)}}function H(g,x){let M=g.length>>1,S=g[M];I(g,S.y0-a,M-1,x),P(g,S.y1+a,M+1,x),I(g,n,g.length-1,x),P(g,e,0,x)}function P(g,x,M,S){for(;M1e-6&&(v.y0+=B,v.y1+=B),x=v.y1+a}}function I(g,x,M,S){for(;M>=0;--M){let v=g[M],B=(v.y1-x)*S;B>1e-6&&(v.y0-=B,v.y1-=B),x=v.y0-a}}function h({sourceLinks:g,targetLinks:x}){if(l===void 0){for(let{source:{sourceLinks:M}}of x)M.sort(pl);for(let{target:{targetLinks:M}}of g)M.sort(fl)}}function T(g){if(l===void 0)for(let{sourceLinks:x,targetLinks:M}of g)x.sort(pl),M.sort(fl)}function E(g,x){let M=g.y0-(g.sourceLinks.length-1)*a/2;for(let{target:S,width:v}of g.sourceLinks){if(S===x)break;M+=v+a}for(let{source:S,width:v}of x.targetLinks){if(S===g)break;M-=v}return M}function R(g,x){let M=x.y0-(x.targetLinks.length-1)*a/2;for(let{source:S,width:v}of x.targetLinks){if(S===g)break;M+=v+a}for(let{target:S,width:v}of g.sourceLinks){if(S===x)break;M-=v}return M}return d}var Jo=Math.PI,Qo=2*Jo,ke=1e-6,Qd=Qo-ke;function Ko(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function hl(){return new Ko}Ko.prototype=hl.prototype={constructor:Ko,moveTo:function(t,e){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)},closePath:function(){this._x1!==null&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,e){this._+="L"+(this._x1=+t)+","+(this._y1=+e)},quadraticCurveTo:function(t,e,r,n){this._+="Q"+ +t+","+ +e+","+(this._x1=+r)+","+(this._y1=+n)},bezierCurveTo:function(t,e,r,n,o,i){this._+="C"+ +t+","+ +e+","+ +r+","+ +n+","+(this._x1=+o)+","+(this._y1=+i)},arcTo:function(t,e,r,n,o){t=+t,e=+e,r=+r,n=+n,o=+o;var i=this._x1,a=this._y1,s=r-t,u=n-e,c=i-t,l=a-e,p=c*c+l*l;if(o<0)throw new Error("negative radius: "+o);if(this._x1===null)this._+="M"+(this._x1=t)+","+(this._y1=e);else if(p>ke)if(!(Math.abs(l*s-u*c)>ke)||!o)this._+="L"+(this._x1=t)+","+(this._y1=e);else{var f=r-i,m=n-a,d=s*s+u*u,y=f*f+m*m,k=Math.sqrt(d),_=Math.sqrt(p),q=o*Math.tan((Jo-Math.acos((d+p-y)/(2*k*_)))/2),A=q/_,D=q/k;Math.abs(A-1)>ke&&(this._+="L"+(t+A*c)+","+(e+A*l)),this._+="A"+o+","+o+",0,0,"+ +(l*f>c*m)+","+(this._x1=t+D*s)+","+(this._y1=e+D*u)}},arc:function(t,e,r,n,o,i){t=+t,e=+e,r=+r,i=!!i;var a=r*Math.cos(n),s=r*Math.sin(n),u=t+a,c=e+s,l=1^i,p=i?n-o:o-n;if(r<0)throw new Error("negative radius: "+r);this._x1===null?this._+="M"+u+","+c:(Math.abs(this._x1-u)>ke||Math.abs(this._y1-c)>ke)&&(this._+="L"+u+","+c),r&&(p<0&&(p=p%Qo+Qo),p>Qd?this._+="A"+r+","+r+",0,1,"+l+","+(t-a)+","+(e-s)+"A"+r+","+r+",0,1,"+l+","+(this._x1=u)+","+(this._y1=c):p>ke&&(this._+="A"+r+","+r+",0,"+ +(p>=Jo)+","+l+","+(this._x1=t+r*Math.cos(o))+","+(this._y1=e+r*Math.sin(o))))},rect:function(t,e,r,n){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +r+"v"+ +n+"h"+-r+"Z"},toString:function(){return this._}};var ti=hl;function ei(t){return function(){return t}}function gl(t){return t[0]}function xl(t){return t[1]}var yl=Array.prototype.slice;function Kd(t){return t.source}function th(t){return t.target}function eh(t){var e=Kd,r=th,n=gl,o=xl,i=null;function a(){var s,u=yl.call(arguments),c=e.apply(this,u),l=r.apply(this,u);if(i||(i=s=ti()),t(i,+n.apply(this,(u[0]=c,u)),+o.apply(this,u),+n.apply(this,(u[0]=l,u)),+o.apply(this,u)),s)return i=null,s+""||null}return a.source=function(s){return arguments.length?(e=s,a):e},a.target=function(s){return arguments.length?(r=s,a):r},a.x=function(s){return arguments.length?(n=typeof s=="function"?s:ei(+s),a):n},a.y=function(s){return arguments.length?(o=typeof s=="function"?s:ei(+s),a):o},a.context=function(s){return arguments.length?(i=s??null,a):i},a}function rh(t,e,r,n,o){t.moveTo(e,r),t.bezierCurveTo(e=(e+n)/2,r,e,o,n,o)}function ri(){return eh(rh)}function nh(t){return[t.source.x1,t.y0]}function oh(t){return[t.target.x0,t.y1]}function ni(){return ri().source(nh).target(oh)}var qn=class{svg;rectG;linkG;nodeG;sankeyGenerator;width=window.innerWidth;height=250;defs;blueColors=["#E1F5FE","#B3E5FC","#81D4FA","#4FC3F7","#29B6F6","#03A9F4","#039BE5","#0288D1","#0277BD","#01579B"];orangeColors=["#FFF5e1","#FFE0B2","#FFCC80","#FFB74D","#FFA726","#FF9800","#FB8C00","#F57C00","#EF6C00","#E65100"];constructor(e){this.svg=j(e).append("svg").attr("width",window.innerWidth).attr("height",this.height).attr("viewBox",[0,0,window.innerWidth,this.height]).style("max-width","100%").style("height","auto"),this.defs=this.svg.append("defs");let r=this.blueColors.slice(5,-1);r=[...r,...r,...r,...r],this.initGradient("blue-flow",r),this.rectG=this.svg.append("g").attr("stroke","#000"),this.linkG=this.svg.append("g").attr("fill","none").style("mix-blend-mode","normal"),this.nodeG=this.svg.append("g"),this.sankeyGenerator=Cn().nodeId(n=>n.name).nodeAlign(jo).nodeWidth(10).nodePadding(30).nodeSort((n,o)=>n.inclusion&&o.inclusion?n.namen.target.inclusion&&o.target.inclusion?n.source.namei/(r.length-1)).attr("stop-color",o=>o),n.append("animate").attr("attributeName","x1").attr("values","0%;200%").attr("dur","12s").attr("repeatCount","indefinite"),n.append("animate").attr("attributeName","x2").attr("values","100%;300%").attr("dur","12s").attr("repeatCount","indefinite")}isRightAligned(e){return!e.inclusion}update(e,r){this.sankeyGenerator.extent([[100,20],[window.innerWidth-100,this.height-25]]);let n=[],o={};this.width=window.innerWidth-56,this.svg.attr("width",this.width).attr("height",this.height).attr("viewBox",[0,0,this.width,this.height]);for(let l of r.links)l.value>0&&(n.push(l),o[l.source]=!0,o[l.target]=!0);let a={nodes:e.filter(l=>o[l.name]).map(l=>({...l})),links:n.map(l=>({...l}))},{nodes:s,links:u}=this.sankeyGenerator(a);this.rectG.selectAll("rect").data(s,l=>l.name).join("rect").attr("x",l=>l.x0).attr("y",l=>l.y0).attr("height",l=>l.y1-l.y0).attr("width",l=>l.x1-l.x0).attr("fill",l=>(l.name==="P2P Network"&&(l.value=r.hashesReceived),l.inclusion?l.name==="Tx Pool"||l.name==="Added To Block"?"#FFA726":"#00BFF2":"#555")),this.linkG.selectAll("path").data(u,l=>l.index).join("path").attr("d",ni()).attr("stroke",l=>l.target.inclusion?"url(#blue-flow)":"#333").attr("stroke-width",l=>Math.max(1,l.width??1));let c=this.nodeG.selectAll("text").data(s,l=>l.name).join(l=>l.append("text").attr("data-last","0"),l=>l,l=>l.remove());c.attr("data-last",function(l){return j(this).attr("data-current")||"0"}).attr("data-current",l=>(l.targetLinks||[]).reduce((f,m)=>f+(m.value||0),0)||l.value||0).attr("x",l=>this.isRightAligned(l)?l.x1+6:l.x0-6).attr("y",l=>(l.y0+l.y1)/2).attr("dy","-0.5em").attr("text-anchor",l=>this.isRightAligned(l)?"start":"end").text(l=>l.name).each(function(){j(this).selectAll("tspan.number").data([0]).join("tspan").attr("class","number").attr("x",()=>{let l=j(this).datum();return l&&l.inclusion?l.x1+6:l.x0-6}).attr("dy","1em")}),c.selectAll("tspan.number").transition().duration(500).tween("text",function(){let l=j(this),p=j(this.parentNode),f=p.empty()?0:parseFloat(p.attr("data-last")||"0"),m=p.empty()?0:parseFloat(p.attr("data-current")||"0"),d=Z(f,m);return function(y){l.text(bt(",.0f")(d(y)))}})}};function vl(t,e,r,n,o,i,a,s){let u=window.innerWidth-56,l={name:"root",children:[...n.map(h=>({name:o(h),item:h,size:a(h)}))]},p=Re(l).sum(h=>h.children?0:a(h.data?h.data.item:h.item)).sort(h=>h.children?0:i(h.data?h.data.item:h.item)),f=p.value??0,m=f>0?f/r:0,d=Math.min(u,u*m);_o().size([d,e-1]).round(!0).tile(vr.ratio(1)).paddingOuter(.5).paddingInner(2)(p);let[y,k]=Me(n,s),_=y&&y>0?y:1e-6,q=k||1,A=kn(Fo).domain([_,q]);function D(h){let T=s(h),E=T>0?T:1e-6;return A(E)}let L=j(t).select("svg");if(L.empty()){L=j(t).append("svg").attr("width",u).attr("height",e).attr("viewBox",[0,0,u,e]);let h=L.append("defs"),T=h.append("pattern").attr("id","unusedStripes").attr("patternUnits","userSpaceOnUse").attr("width",8).attr("height",8);T.append("rect").attr("class","pattern-bg").attr("width",8).attr("height",8).attr("fill","#444"),T.append("path").attr("d","M0,0 l8,8").attr("stroke","#000").attr("stroke-width",1),L.append("rect").attr("class","unused").attr("fill","url(#unusedStripes)").attr("opacity",1).attr("width",u).attr("height",e).attr("stroke","#fff").attr("stroke-width",1),h.append("marker").attr("id","arrowStart").attr("markerWidth",10).attr("markerHeight",10).attr("refX",5).attr("refY",5).attr("orient","auto").attr("markerUnits","strokeWidth").append("path").attr("d","M10,0 L0,5 L10,10").attr("fill","#ccc"),h.append("marker").attr("id","arrowEnd").attr("markerWidth",10).attr("markerHeight",10).attr("refX",5).attr("refY",5).attr("orient","auto").attr("markerUnits","strokeWidth").append("path").attr("d","M0,0 L10,5 L0,10").attr("fill","#ccc")}L.attr("width",u).attr("height",e).attr("viewBox",[0,0,u,e]),L.selectAll("rect.unused").attr("width",u);let b=p.leaves();L.selectAll("g.node").data(b,h=>h.data.name).join(h=>{let T=h.append("g").attr("class","node").attr("data-hash",E=>E.data.name).attr("transform",E=>`translate(${E.x0},${E.y0})`).attr("opacity",0);return T.append("rect").attr("stroke","#000").attr("stroke-width",.5).attr("width",0).attr("height",0).attr("fill",E=>D(E.data.item)),T.transition().duration(600).attr("opacity",1),T.select("rect").transition().duration(600).attr("width",E=>E.x1-E.x0).attr("height",E=>E.y1-E.y0),T},h=>(h.transition().duration(600).attr("transform",T=>`translate(${T.x0},${T.y0})`).attr("opacity",1),h.select("rect").transition().duration(600).attr("width",T=>T.x1-T.x0).attr("height",T=>T.y1-T.y0).attr("fill",T=>D(T.data.item)),h),h=>{h.transition().duration(600).attr("opacity",0).remove()});let H=(r-f)/r,I=H>=.1?[{key:"unused-label",x:d,w:u-d,ratio:H}]:[];L.selectAll("line.unused-arrow").data(I,h=>h.key).join(h=>h.append("line").attr("class","unused-arrow").attr("x1",T=>T.x+10).attr("x2",T=>T.x+T.w-10).attr("y1",145).attr("y2",145).attr("stroke","#ccc").attr("stroke-width",2).attr("marker-start","url(#arrowStart)").attr("marker-end","url(#arrowEnd)").attr("opacity",0).call(T=>T.transition().duration(600).attr("opacity",1)),h=>h.transition().duration(600).attr("x1",T=>T.x+10).attr("x2",T=>T.x+T.w-10),h=>h.transition().duration(600).attr("opacity",0).remove()),L.selectAll("text.unused-label").data(I,h=>h.key).join(h=>h.append("text").attr("class","unused-label").attr("x",T=>T.x+T.w/2).attr("y",135).attr("fill","#ccc").attr("font-size",14).attr("text-anchor","middle").attr("opacity",0).text(T=>`${(T.ratio*100).toFixed(1)}% available`).call(T=>T.transition().duration(600).attr("opacity",1)),h=>h.transition().duration(600).attr("x",T=>T.x+T.w/2).text(T=>`${(T.ratio*100).toFixed(1)}% available`),h=>h.transition().duration(600).attr("opacity",0).remove())}function bl(t,e,r=36){let n={top:4,right:4,bottom:20,left:20},o=t.getBoundingClientRect().width,i=100,a=j(t).append("svg").style("display","block").style("background","black").attr("width",o).attr("height",i),s=a.append("g").attr("transform",`translate(${n.left},${n.top})`);function u(){return o-n.left-n.right}let c=i-n.top-n.bottom,l=[],p,f=br().domain(Ae(r)).range([0,u()]).paddingInner(.3).paddingOuter(.1),m=de().range([c,0]);function d(){return xr().duration(750)}function y(A){if(!A.length)return{min:0,q1:0,median:0,q3:0,max:0,whiskerLow:0,whiskerHigh:0};let D=A.slice().sort(ft),L=D[0],b=D[D.length-1],N=Ee(D,.25),H=Ee(D,.5),P=Ee(D,.75),I=P-N,h=Math.max(L,N-1.5*I),T=Math.min(b,P+1.5*I);return{min:L,q1:N,median:H,q3:P,max:b,whiskerLow:h,whiskerHigh:T}}function k(A,D){let L=A.map(e).filter(x=>Number.isFinite(x)&&x>=0),b=y(L);if(l.length{x.xIndex-=1});l.length&&l[0].xIndex<0;){let x=l.shift();x&&(p=x.stats.median)}l.push({xIndex:r-1,blockNumber:D,stats:b,values:L})}let N=ee(l,x=>x.stats.whiskerHigh)||1;m.domain([0,N]);let H=s.selectAll(".box-group").data(l,x=>x.xIndex);H.exit().transition(d()).attr("transform",x=>`translate(${f(x.xIndex)||0},${c}) scale(0.001,0.001)`).remove();let P=H.enter().append("g").attr("class","box-group").attr("stroke-width",1).attr("transform",x=>`translate(${f(x.xIndex)||0}, ${c}) scale(0.001,0.001)`);P.append("line").attr("class","whisker-line").attr("stroke","#aaa"),P.append("rect").attr("class","box-rect").attr("stroke","white").attr("fill","gray"),P.append("line").attr("class","median-line").attr("stroke","#ccc").attr("stroke-width",1),P.append("line").attr("class","whisker-cap lower").attr("stroke","#aaa"),P.append("line").attr("class","whisker-cap upper").attr("stroke","#aaa"),P.append("g").attr("class","points-group"),H=P.merge(H),H.transition(d()).attr("transform",x=>`translate(${f(x.xIndex)||0},0) scale(1,1)`),H.each(function(x){let M=j(this),S=x.stats,v=f.bandwidth(),B,G=l.find(ot=>ot.xIndex===x.xIndex-1);G?B=G.stats.median:x.xIndex===0&&p!==void 0&&(B=p);let K="gray";B!==void 0&&(S.median>B?K="rgb(127, 63, 63)":S.median{x.selectAll("text").attr("fill","white"),x.selectAll("line,path").attr("stroke","white")});let h=Fr(f).tickFormat(x=>{let M=l.find(S=>S.xIndex===x);return M?String(M.blockNumber):""}),T=s.append("g").attr("class","x-axis").attr("transform",`translate(0,${c})`).call(h),E=f.bandwidth();E<25&&T.selectAll(".tick").each(function(x,M){M/2%2!==0&&j(this).remove()}),T.call(x=>{x.selectAll("text").attr("fill","white"),x.selectAll("line,path").attr("stroke","white")}),s.selectAll(".median-trend").remove();let R=l.filter(x=>x.xIndex>=0).sort((x,M)=>x.xIndex-M.xIndex),g=We().x(x=>(f(x.xIndex)??0)+E/2).y(x=>m(x.stats.median)).curve(En);s.append("path").attr("class","median-trend").datum(R).attr("fill","none").attr("stroke","#FFA726").attr("stroke-width",2).transition(d()).attr("d",g)}function _(){o=t.getBoundingClientRect().width,a.attr("width",o),f.range([0,u()]),q()}function q(){s.selectAll(".box-group").transition().duration(0).attr("transform",I=>`translate(${f(I.xIndex)||0},0)`),s.selectAll(".y-axis").remove(),s.selectAll(".x-axis").remove();let A=Or(m).ticks(3);s.append("g").attr("class","y-axis").call(A).call(I=>{I.selectAll("text").attr("fill","white"),I.selectAll("line,path").attr("stroke","white")});let D=Fr(f).tickFormat(I=>{let h=l.find(T=>T.xIndex===I);return h?String(h.blockNumber):""}),L=s.append("g").attr("class","x-axis").attr("transform",`translate(0,${c})`).call(D);f.bandwidth()<25&&L.selectAll(".tick").each(function(I,h){h%2!==0&&j(this).remove()}),L.call(I=>{I.selectAll("text").attr("fill","white"),I.selectAll("line,path").attr("stroke","white")}),s.selectAll(".median-trend").remove();let N=l.filter(I=>I.xIndex>=0).sort((I,h)=>I.xIndex-h.xIndex),H=f.bandwidth(),P=We().x(I=>(f(I.xIndex)??0)+H/2).y(I=>m(I.stats.median)).curve(En);s.append("path").attr("class","median-trend").datum(N).attr("fill","none").attr("stroke","#FFA726").attr("stroke-width",2).attr("d",P)}return{update:k,resize:_}}var qr=100,ih=120,ah=qr+ih,sh=qr,wl=qr/2,uh=j("#pie-chart").append("svg").attr("width",ah).attr("height",sh).attr("overflow","visible"),kl=uh.append("g").attr("transform",`translate(${qr/2}, ${qr/2})`),lh=me().range(Ho),ch=Uo().sort(null).value(t=>t.count),oi=$o().innerRadius(0).outerRadius(wl),fh=kl.append("g").attr("class","slice-layer"),ph=kl.append("g").attr("class","label-layer");function _l(t){let e=ch(t),r=e.map(m=>{let[d,y]=oi.centroid(m);return{...m,centroidY:y}}),n=r.slice().sort((m,d)=>m.centroidY-d.centroidY),o=18,i=-((n.length-1)*o)/2,a=wl+20,s={};n.forEach((m,d)=>{s[m.data.type]={x:a,y:i+d*o}});let u=fh.selectAll("path").data(e,m=>m.data.type);u.exit().remove(),u.enter().append("path").attr("stroke","#222").style("stroke-width","1px").attr("fill",m=>lh(m.data.type)).each(function(m){this._current=m}).merge(u).transition().duration(750).attrTween("d",function(m){let d=vt(this._current,m);return this._current=d(0),y=>oi(d(y))});let l=ph.selectAll("g.label").data(r,m=>m.data.type);l.exit().remove();let p=l.enter().append("g").attr("class","label").style("pointer-events","none");p.append("polyline").attr("fill","none").attr("stroke","#fff"),p.append("text").style("alignment-baseline","middle").style("text-anchor","start").style("fill","#fff");let f=p.merge(l);f.select("polyline").transition().duration(750).attr("points",m=>{let[d,y]=oi.centroid(m),{x:k,y:_}=s[m.data.type],q=k*.6;return`${d},${y} ${q},${_} ${k},${_}`}),f.select("text").transition().duration(750).attr("transform",m=>{let d=s[m.data.type];return`translate(${d.x},${d.y})`}).tween("label",function(m){return()=>{this.textContent=`${m.data.type} (${m.data.count})`}})}function Tl(t){switch(t){case 0:return"Legacy";case 1:return"AccessList";case 2:return"Eip1559";case 3:return"Blob";case 4:return"SetCode";case 5:return"TxCreate";default:return"Unknown"}}function ii(t){switch(t){case"0x095ea7b3":return"approve";case"0xa9059cbb":return"transfer";case"0x23b872dd":return"transferFrom";case"0xd0e30db0":return"deposit";case"0xe8e33700":case"0xf305d719":return"addLiquidity";case"0xbaa2abde":case"0x02751cec":case"0xaf2979eb":case"0xded9382a":case"0x5b0d5984":case"0x2195995c":return"removeLiquidity";case"0xfb3bdb41":case"0x7ff36ab5":case"0xb6f9de95":case"0x18cbafe5":case"0x791ac947":case"0x38ed1739":case"0x5c11d795":case"0x4a25d94a":case"0x5f575529":case"0x6b68764c":case"0x845a101f":case"0x8803dbee":return"swap";case"0x24856bc3":case"0x3593564c":return"dex";case"0x":return"ETH transfer";default:return t}}function Ml(t){switch(t){case"0xdac17f958d2ee523a2206206994597c13d831ec7":return"usdt";case"0x4ecaba5870353805a9f068101a40e0f32ed605c6":return"usdt";case"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48":return"usdc";case"0xddafbb505ad214d7b80b1f830fccc89b60fb7a83":return"usdc";case"0x6b175474e89094c44da98b954eedeac495271d0f":return"dai";case"0x44fa8e6f47987339850636f88629646662444217":return"dai";case"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2":return"weth";case"0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1":return"weth";case"0x7a250d5630b4cf539739df2c5dacb4c659f2488d":return"uniswap v2";case"0x66a9893cc07d91d95644aedd05d03f95e1dba8af":return"uniswap v4";case"0x2f848984984d6c3c036174ce627703edaf780479":return"xen minter";case"0x0a252663dbcc0b073063d6420a40319e438cfa59":return"xen";case"0x881d40237659c251811cec9c364ef91dc08d300c":return"metamask";default:return t}}var Wh=tc(),Pn=class{nodeLog;ansiConvert=new Wh;logs=[];constructor(e){this.nodeLog=document.getElementById(e)}receivedLog(e){let r=JSON.parse(e.data);for(let n of r){let o=this.ansiConvert.toHtml(n);this.logs.length>=100&&this.logs.shift(),this.logs.push(o)}}appendLogs(){if(this.logs.length>0){let e=!1;(this.nodeLog.scrollHeight<500||this.nodeLog.scrollTop250;)this.nodeLog.firstChild.remove(),n--;e&&window.setTimeout(()=>this.scrollLogs(),17)}}resize(){let e=document.body.getBoundingClientRect();var n=this.nodeLog.getBoundingClientRect().top-e.top,o=window.innerHeight-n-16;o>0&&(this.nodeLog.style.height=`${o}px`)}scrollLogs(){this.nodeLog.scrollTop=this.nodeLog.scrollHeight}};function $(t,e){t.innerText!==e&&(t.innerText=e)}var $n=class{lastGasLimit=36e6;minGas;medianGas;aveGas;maxGas;gasLimit;gasLimitDelta;constructor(e,r,n,o,i,a){this.minGas=document.getElementById(e),this.medianGas=document.getElementById(r),this.aveGas=document.getElementById(n),this.maxGas=document.getElementById(o),this.gasLimit=document.getElementById(i),this.gasLimitDelta=document.getElementById(a)}parseEvent(e){if(document.hidden)return;let r=JSON.parse(e.data);$(this.minGas,r.minGas.toFixed(2)),$(this.medianGas,r.medianGas.toFixed(2)),$(this.aveGas,r.aveGas.toFixed(2)),$(this.maxGas,r.maxGas.toFixed(2)),$(this.gasLimit,dt(r.gasLimit)),$(this.gasLimitDelta,r.gasLimit>this.lastGasLimit?"\u{1F446}":r.gasLimitparseInt(t.effectiveGasPrice,16)/1e9,36);function dc(t,e){do if(!(t.matches===void 0||!t.matches(e)))return t;while(t=t.parentElement);return null}function kg(t,e,r,n,o){t.addEventListener(e,function(i){try{let a=dc(i.target,r);a!==null&&n.apply(a,arguments)}catch{}},o)}var ec=[],rc=[],nc=[],oc=[],ic=[],ac=[],sc=[],pi=0,mi=0,di=0,hi=0,gi=0,Un=0;function Te(t,e){t.push(e),t.length>60&&t.shift()}var _g=new qn("#txPoolFlow"),bi=null,uc=!1;function Tg(t){if(!uc){if(t.pooledTx==0){document.getElementById("txPoolFlow").classList.add("not-active");return}setTimeout(Ti,10),document.getElementById("txPoolFlow").classList.remove("not-active"),uc=!0}let e=performance.now(),r=e/1e3,n=r-Un,o=0,i=0,a=0,s=0;for(let c of t.links)c.target==="Received Txs"&&(o+=c.value),c.target==="Tx Pool"&&(i+=c.value),c.target==="Added To Block"&&(a+=c.value),c.target==="Duplicate"&&(s+=c.value);let u=t.hashesReceived;if(Un!==0&&(Te(ec,{t:e,v:u-gi}),Te(rc,{t:e,v:o-pi}),Te(ic,{t:e,v:s-hi}),Te(nc,{t:e,v:i-mi}),Te(oc,{t:e,v:a-di})),!document.hidden){if(!bi)return;_g.update(bi,t),$(Xh,dt(t.pooledTx)),$(jh,dt(t.pooledBlobTx)),$(Zh,dt(t.pooledTx+t.pooledBlobTx)),Un!==0&&(Xt(document.getElementById("sparkHashesTps"),ec),Xt(document.getElementById("sparkReceivedTps"),rc),Xt(document.getElementById("sparkDuplicateTps"),ic),Xt(document.getElementById("sparkTxPoolTps"),nc),Xt(document.getElementById("sparkBlockTps"),oc),$(Jh,Wt((a-di)/n)),$(Qh,Wt((o-pi)/n)),$(Kh,Wt((i-mi)/n)),$(tg,Wt((s-hi)/n)),$(eg,Wt((u-gi)/n)))}Un=r,pi=o,mi=i,di=a,hi=s,gi=u}var _i=new Pn("nodeLog"),Mg=new $n("minGas","medianGas","aveGas","maxGas","gasLimit","gasLimitDelta"),Jt=new EventSource("/data/events");Jt.addEventListener("log",t=>_i.receivedLog(t));Jt.addEventListener("processed",t=>Mg.parseEvent(t));Jt.addEventListener("nodeData",t=>{let e=JSON.parse(t.data),r=al(e.network),n=`Nethermind [${r}]${e.instance?" - "+e.instance:""}`;document.title!=n&&(document.title=n),$(rg,e.version),$(ng,r),document.getElementById("network-logo").src=`logos/${sl(e.network)}`,$(pc,Wo(e.uptime)),cl(e.gasToken)});Jt.addEventListener("txNodes",t=>{bi=JSON.parse(t.data)});Jt.addEventListener("txLinks",t=>{if(document.hidden)return;let e=JSON.parse(t.data);Tg(e)});var wi=0,hc=0,lc=!1;Jt.addEventListener("forkChoice",t=>{let e=performance.now();if(hc=e-wi,wi=e,document.hidden)return;let r=JSON.parse(t.data),n=parseInt(r.head.number,16);!lc&&n!==0&&(lc=!0,document.getElementById("latestBlock").classList.remove("not-active"),setTimeout(Ti,10));let o=parseInt(r.safe,16),i=parseInt(r.finalized,16);$(og,n.toFixed(0)),$(ig,o.toFixed(0)),$(ag,i.toFixed(0)),$(sg,`(${(o-n).toFixed(0)})`),$(ug,`(${(i-n).toFixed(0)})`);let a=r.head;if(a.tx.length===0)return;let s=a.tx.map((u,c)=>{let l=a.receipts[c];return{block:a.number,order:c,...u,...l}});$(hg,il(a.extraData)),$(gg,dt(parseInt(a.gasUsed,16))),$(xg,dt(parseInt(a.gasLimit,16))),$(yg,ol(parseInt(a.size,16))),$(vg,nl(parseInt(a.timestamp,16))),$(bg,dt(a.tx.length)),$(wg,dt(a.tx.reduce((u,c)=>u+c.blobs,0))),vl(document.getElementById("block"),160,parseInt(r.head.gasLimit,16),s,u=>u.hash,u=>u.order,u=>parseInt(u.gasUsed,16),u=>parseInt(u.effectiveGasPrice,16)*parseInt(u.gasUsed,16)),mc.update(s,n),_t.push(...s),ki=_t.length,_t.length>25e4&&_t.slice(_t.length-25e3),gc=Lg(s)});var gc,Sg="";kg(document.getElementById("block"),"pointermove","g.node",t=>{let r=dc(t.target,"g.node").dataset.hash,n=gc[r];if(!n)return;let o=document.getElementById("txDetails");return Sg!==r&&(o.innerHTML=` +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var i=!0,a=!1,s;return{s:function(){r=r.call(t)},n:function(){var c=r.next();return i=c.done,c},e:function(c){a=!0,s=c},f:function(){try{!i&&r.return!=null&&r.return()}finally{if(a)throw s}}}}function Bh(t,e){if(t){if(typeof t=="string")return zl(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if(r==="Object"&&t.constructor&&(r=t.constructor.name),r==="Map"||r==="Set")return Array.from(t);if(r==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return zl(t,e)}}function zl(t,e){(e==null||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r0?t*40+55:0,a=e>0?e*40+55:0,s=r>0?r*40+55:0;n[o]=Oh([i,a,s])}function Jl(t){for(var e=t.toString(16);e.length<2;)e="0"+e;return e}function Oh(t){var e=[],r=Zl(t),n;try{for(r.s();!(n=r.n()).done;){var o=n.value;e.push(Jl(o))}}catch(i){r.e(i)}finally{r.f()}return"#"+e.join("")}function Wl(t,e,r,n){var o;return e==="text"?o=Gh(r,n):e==="display"?o=$h(t,r,n):e==="xterm256Foreground"?o=Fn(t,n.colors[r]):e==="xterm256Background"?o=On(t,n.colors[r]):e==="rgb"&&(o=Ph(t,r)),o}function Ph(t,e){e=e.substring(2).slice(0,-1);var r=+e.substr(0,2),n=e.substring(5).split(";"),o=n.map(function(i){return("0"+Number(i).toString(16)).substr(-2)}).join("");return Hn(t,(r===38?"color:#":"background-color:#")+o)}function $h(t,e,r){e=parseInt(e,10);var n={"-1":function(){return"
"},0:function(){return t.length&&Ql(t)},1:function(){return Zt(t,"b")},3:function(){return Zt(t,"i")},4:function(){return Zt(t,"u")},8:function(){return Hn(t,"display:none")},9:function(){return Zt(t,"strike")},22:function(){return Hn(t,"font-weight:normal;text-decoration:none;font-style:normal")},23:function(){return jl(t,"i")},24:function(){return jl(t,"u")},39:function(){return Fn(t,r.fg)},49:function(){return On(t,r.bg)},53:function(){return Hn(t,"text-decoration:overline")}},o;return n[e]?o=n[e]():4"}).join("")}function Rn(t,e){for(var r=[],n=t;n<=e;n++)r.push(n);return r}function Uh(t){return function(e){return(t===null||e.category!==t)&&t!=="all"}}function Xl(t){t=parseInt(t,10);var e=null;return t===0?e="all":t===1?e="bold":2")}function Hn(t,e){return Zt(t,"span",e)}function Fn(t,e){return Zt(t,"span","color:"+e)}function On(t,e){return Zt(t,"span","background-color:"+e)}function jl(t,e){var r;if(t.slice(-1)[0]===e&&(r=t.pop()),r)return""}function Vh(t,e,r){var n=!1,o=3;function i(){return""}function a(L,b){return r("xterm256Foreground",b),""}function s(L,b){return r("xterm256Background",b),""}function u(L){return e.newline?r("display",-1):r("text",L),""}function c(L,b){n=!0,b.trim().length===0&&(b="0"),b=b.trimRight(";").split(";");var N=Zl(b),H;try{for(N.s();!(H=N.n()).done;){var P=H.value;r("display",P)}}catch(I){N.e(I)}finally{N.f()}return""}function l(L){return r("text",L),""}function p(L){return r("rgb",L),""}var f=[{pattern:/^\x08+/,sub:i},{pattern:/^\x1b\[[012]?K/,sub:i},{pattern:/^\x1b\[\(B/,sub:i},{pattern:/^\x1b\[[34]8;2;\d+;\d+;\d+m/,sub:p},{pattern:/^\x1b\[38;5;(\d+)m/,sub:a},{pattern:/^\x1b\[48;5;(\d+)m/,sub:s},{pattern:/^\n/,sub:u},{pattern:/^\r+\n/,sub:u},{pattern:/^\r/,sub:u},{pattern:/^\x1b\[((?:\d{1,3};?)+|)m/,sub:c},{pattern:/^\x1b\[\d?J/,sub:i},{pattern:/^\x1b\[\d{0,3};\d{0,3}f/,sub:i},{pattern:/^\x1b\[?[\d;]{0,3}/,sub:i},{pattern:/^(([^\x1b\x08\r\n])+)/,sub:l}];function m(L,b){b>o&&n||(n=!1,t=t.replace(L.pattern,L.sub))}var d=[],y=t,k=y.length;t:for(;k>0;){for(var _=0,q=0,A=f.length;qe?1:t>=e?0:NaN}function Gn(t,e){return t==null||e==null?NaN:et?1:e>=t?0:NaN}function Kt(t){let e,r,n;t.length!==2?(e=ft,r=(s,u)=>ft(t(s),u),n=(s,u)=>t(s)-u):(e=t===ft||t===Gn?t:yc,r=t,n=t);function o(s,u,c=0,l=s.length){if(c>>1;r(s[p],u)<0?c=p+1:l=p}while(c>>1;r(s[p],u)<=0?c=p+1:l=p}while(cc&&n(s[p-1],u)>-n(s[p],u)?p-1:p}return{left:o,center:a,right:i}}function yc(){return 0}function Nr(t){return t===null?NaN:+t}function*Si(t,e){if(e===void 0)for(let r of t)r!=null&&(r=+r)>=r&&(yield r);else{let r=-1;for(let n of t)(n=e(n,++r,t))!=null&&(n=+n)>=n&&(yield n)}}var Li=Kt(ft),Ei=Li.right,vc=Li.left,bc=Kt(Nr).center,Vn=Ei;function Me(t,e){let r,n;if(e===void 0)for(let o of t)o!=null&&(r===void 0?o>=o&&(r=n=o):(r>o&&(r=o),n=i&&(r=n=i):(r>i&&(r=i),n{let n=t(e,r);return n||n===0?n:(t(r,r)===0)-(t(e,e)===0)}}function zn(t,e){return(t==null||!(t>=t))-(e==null||!(e>=e))||(te?1:0)}var Tc=Math.sqrt(50),Mc=Math.sqrt(10),Sc=Math.sqrt(2);function Br(t,e,r){let n=(e-t)/Math.max(0,r),o=Math.floor(Math.log10(n)),i=n/Math.pow(10,o),a=i>=Tc?10:i>=Mc?5:i>=Sc?2:1,s,u,c;return o<0?(c=Math.pow(10,-o)/a,s=Math.round(t*c),u=Math.round(e*c),s/ce&&--u,c=-c):(c=Math.pow(10,o)*a,s=Math.round(t/c),u=Math.round(e/c),s*ce&&--u),u0))return[];if(t===e)return[t];let n=e=o))return[];let s=i-o+1,u=new Array(s);if(n)if(a<0)for(let c=0;c=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r=o)&&(r=o)}return r}function Rr(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r>n||r===void 0&&n>=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r>o||r===void 0&&o>=o)&&(r=o)}return r}function Hr(t,e,r=0,n=1/0,o){if(e=Math.floor(e),r=Math.floor(Math.max(0,r)),n=Math.floor(Math.min(t.length-1,n)),!(r<=e&&e<=n))return t;for(o=o===void 0?zn:Di(o);n>r;){if(n-r>600){let u=n-r+1,c=e-r+1,l=Math.log(u),p=.5*Math.exp(2*l/3),f=.5*Math.sqrt(l*p*(u-p)/u)*(c-u/2<0?-1:1),m=Math.max(r,Math.floor(e-c*p/u+f)),d=Math.min(n,Math.floor(e+(u-c)*p/u+f));Hr(t,e,m,d,o)}let i=t[e],a=r,s=n;for(Ke(t,r,e),o(t[n],i)>0&&Ke(t,r,n);a0;)--s}o(t[r],i)===0?Ke(t,r,s):(++s,Ke(t,s,n)),s<=e&&(r=s+1),e<=s&&(n=s-1)}return t}function Ke(t,e,r){let n=t[e];t[e]=t[r],t[r]=n}function Ee(t,e,r){if(t=Float64Array.from(Si(t,r)),!(!(n=t.length)||isNaN(e=+e))){if(e<=0||n<2)return Rr(t);if(e>=1)return ee(t);var n,o=(n-1)*e,i=Math.floor(o),a=ee(Hr(t,i).subarray(0,i+1)),s=Rr(t.subarray(i+1));return a+(s-a)*(o-i)}}function Ae(t,e,r){t=+t,e=+e,r=(o=arguments.length)<2?(e=t,t=0,1):o<3?1:+r;for(var n=-1,o=Math.max(0,Math.ceil((e-t)/r))|0,i=new Array(o);++n+t(e)}function Dc(t,e){return e=Math.max(0,t.bandwidth()-e*2)/2,t.round()&&(e=Math.round(e)),r=>+t(r)+e}function Cc(){return!this.__axis}function Ii(t,e){var r=[],n=null,o=null,i=6,a=6,s=3,u=typeof window<"u"&&window.devicePixelRatio>1?0:.5,c=t===Yn||t===tr?-1:1,l=t===tr||t===Wn?"x":"y",p=t===Yn||t===Xn?Lc:Ec;function f(m){var d=n??(e.ticks?e.ticks.apply(e,r):e.domain()),y=o??(e.tickFormat?e.tickFormat.apply(e,r):Ci),k=Math.max(i,0)+s,_=e.range(),q=+_[0]+u,A=+_[_.length-1]+u,D=(e.bandwidth?Dc:Ac)(e.copy(),u),L=m.selection?m.selection():m,b=L.selectAll(".domain").data([null]),N=L.selectAll(".tick").data(d,e).order(),H=N.exit(),P=N.enter().append("g").attr("class","tick"),I=N.select("line"),h=N.select("text");b=b.merge(b.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),N=N.merge(P),I=I.merge(P.append("line").attr("stroke","currentColor").attr(l+"2",c*i)),h=h.merge(P.append("text").attr("fill","currentColor").attr(l,c*k).attr("dy",t===Yn?"0em":t===Xn?"0.71em":"0.32em")),m!==L&&(b=b.transition(m),N=N.transition(m),I=I.transition(m),h=h.transition(m),H=H.transition(m).attr("opacity",qi).attr("transform",function(T){return isFinite(T=D(T))?p(T+u):this.getAttribute("transform")}),P.attr("opacity",qi).attr("transform",function(T){var E=this.parentNode.__axis;return p((E&&isFinite(E=E(T))?E:D(T))+u)})),H.remove(),b.attr("d",t===tr||t===Wn?a?"M"+c*a+","+q+"H"+u+"V"+A+"H"+c*a:"M"+u+","+q+"V"+A:a?"M"+q+","+c*a+"V"+u+"H"+A+"V"+c*a:"M"+q+","+u+"H"+A),N.attr("opacity",1).attr("transform",function(T){return p(D(T)+u)}),I.attr(l+"2",c*i),h.attr(l,c*k).text(y),L.filter(Cc).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===Wn?"start":t===tr?"end":"middle"),L.each(function(){this.__axis=D})}return f.scale=function(m){return arguments.length?(e=m,f):e},f.ticks=function(){return r=Array.from(arguments),f},f.tickArguments=function(m){return arguments.length?(r=m==null?[]:Array.from(m),f):r.slice()},f.tickValues=function(m){return arguments.length?(n=m==null?null:Array.from(m),f):n&&n.slice()},f.tickFormat=function(m){return arguments.length?(o=m,f):o},f.tickSize=function(m){return arguments.length?(i=a=+m,f):i},f.tickSizeInner=function(m){return arguments.length?(i=+m,f):i},f.tickSizeOuter=function(m){return arguments.length?(a=+m,f):a},f.tickPadding=function(m){return arguments.length?(s=+m,f):s},f.offset=function(m){return arguments.length?(u=+m,f):u},f}function Fr(t){return Ii(Xn,t)}function Or(t){return Ii(tr,t)}var qc={value:()=>{}};function Bi(){for(var t=0,e=arguments.length,r={},n;t=0&&(n=r.slice(o+1),r=r.slice(0,o)),r&&!e.hasOwnProperty(r))throw new Error("unknown type: "+r);return{type:r,name:n}})}Pr.prototype=Bi.prototype={constructor:Pr,on:function(t,e){var r=this._,n=Ic(t+"",r),o,i=-1,a=n.length;if(arguments.length<2){for(;++i0)for(var r=new Array(o),n=0,o,i;n=0&&(e=t.slice(0,r))!=="xmlns"&&(t=t.slice(r+1)),Zn.hasOwnProperty(e)?{space:Zn[e],local:t}:t}function Bc(t){return function(){var e=this.ownerDocument,r=this.namespaceURI;return r===$r&&e.documentElement.namespaceURI===$r?e.createElement(t):e.createElementNS(r,t)}}function Rc(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Ur(t){var e=qt(t);return(e.local?Rc:Bc)(e)}function Hc(){}function re(t){return t==null?Hc:function(){return this.querySelector(t)}}function Ri(t){typeof t!="function"&&(t=re(t));for(var e=this._groups,r=e.length,n=new Array(r),o=0;o=A&&(A=q+1);!(L=k[A])&&++A=0;)(a=n[o])&&(i&&a.compareDocumentPosition(i)^4&&i.parentNode.insertBefore(a,i),i=a);return this}function Xi(t){t||(t=Zc);function e(p,f){return p&&f?t(p.__data__,f.__data__):!p-!f}for(var r=this._groups,n=r.length,o=new Array(n),i=0;ie?1:t>=e?0:NaN}function ji(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function Zi(){return Array.from(this)}function Ji(){for(var t=this._groups,e=0,r=t.length;e1?this.each((e==null?nf:typeof e=="function"?af:of)(t,e,r??"")):Ft(this.node(),t)}function Ft(t,e){return t.style.getPropertyValue(e)||zr(t).getComputedStyle(t,null).getPropertyValue(e)}function sf(t){return function(){delete this[t]}}function uf(t,e){return function(){this[t]=e}}function lf(t,e){return function(){var r=e.apply(this,arguments);r==null?delete this[t]:this[t]=r}}function na(t,e){return arguments.length>1?this.each((e==null?sf:typeof e=="function"?lf:uf)(t,e)):this.node()[t]}function oa(t){return t.trim().split(/^|\s+/)}function Qn(t){return t.classList||new ia(t)}function ia(t){this._node=t,this._names=oa(t.getAttribute("class")||"")}ia.prototype={add:function(t){var e=this._names.indexOf(t);e<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var e=this._names.indexOf(t);e>=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function aa(t,e){for(var r=Qn(t),n=-1,o=e.length;++n=0&&(r=e.slice(n+1),e=e.slice(0,n)),{type:e,name:r}})}function Lf(t){return function(){var e=this.__on;if(e){for(var r=0,n=-1,o=e.length,i;r>8&15|e>>4&240,e>>4&15|e&240,(e&15)<<4|e&15,1):r===8?Yr(e>>24&255,e>>16&255,e>>8&255,(e&255)/255):r===4?Yr(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|e&240,((e&15)<<4|e&15)/255):null):(e=If.exec(t))?new et(e[1],e[2],e[3],1):(e=Nf.exec(t))?new et(e[1]*255/100,e[2]*255/100,e[3]*255/100,1):(e=Bf.exec(t))?Yr(e[1],e[2],e[3],e[4]):(e=Rf.exec(t))?Yr(e[1]*255/100,e[2]*255/100,e[3]*255/100,e[4]):(e=Hf.exec(t))?Aa(e[1],e[2]/100,e[3]/100,1):(e=Ff.exec(t))?Aa(e[1],e[2]/100,e[3]/100,e[4]):_a.hasOwnProperty(t)?Sa(_a[t]):t==="transparent"?new et(NaN,NaN,NaN,0):null}function Sa(t){return new et(t>>16&255,t>>8&255,t&255,1)}function Yr(t,e,r,n){return n<=0&&(t=e=r=NaN),new et(t,e,r,n)}function eo(t){return t instanceof ae||(t=yt(t)),t?(t=t.rgb(),new et(t.r,t.g,t.b,t.opacity)):new et}function qe(t,e,r,n){return arguments.length===1?eo(t):new et(t,e,r,n??1)}function et(t,e,r,n){this.r=+t,this.g=+e,this.b=+r,this.opacity=+n}De(et,qe,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new et(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new et(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new et(oe(this.r),oe(this.g),oe(this.b),Xr(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:La,formatHex:La,formatHex8:$f,formatRgb:Ea,toString:Ea}));function La(){return`#${ne(this.r)}${ne(this.g)}${ne(this.b)}`}function $f(){return`#${ne(this.r)}${ne(this.g)}${ne(this.b)}${ne((isNaN(this.opacity)?1:this.opacity)*255)}`}function Ea(){let t=Xr(this.opacity);return`${t===1?"rgb(":"rgba("}${oe(this.r)}, ${oe(this.g)}, ${oe(this.b)}${t===1?")":`, ${t})`}`}function Xr(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function oe(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function ne(t){return t=oe(t),(t<16?"0":"")+t.toString(16)}function Aa(t,e,r,n){return n<=0?t=e=r=NaN:r<=0||r>=1?t=e=NaN:e<=0&&(t=NaN),new xt(t,e,r,n)}function Ca(t){if(t instanceof xt)return new xt(t.h,t.s,t.l,t.opacity);if(t instanceof ae||(t=yt(t)),!t)return new xt;if(t instanceof xt)return t;t=t.rgb();var e=t.r/255,r=t.g/255,n=t.b/255,o=Math.min(e,r,n),i=Math.max(e,r,n),a=NaN,s=i-o,u=(i+o)/2;return s?(e===i?a=(r-n)/s+(r0&&u<1?0:a,new xt(a,s,u,t.opacity)}function qa(t,e,r,n){return arguments.length===1?Ca(t):new xt(t,e,r,n??1)}function xt(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}De(xt,qa,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new xt(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new xt(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,e=isNaN(t)||isNaN(this.s)?0:this.s,r=this.l,n=r+(r<.5?r:1-r)*e,o=2*r-n;return new et(to(t>=240?t-240:t+120,o,n),to(t,o,n),to(t<120?t+240:t-120,o,n),this.opacity)},clamp(){return new xt(Da(this.h),Wr(this.s),Wr(this.l),Xr(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){let t=Xr(this.opacity);return`${t===1?"hsl(":"hsla("}${Da(this.h)}, ${Wr(this.s)*100}%, ${Wr(this.l)*100}%${t===1?")":`, ${t})`}`}}));function Da(t){return t=(t||0)%360,t<0?t+360:t}function Wr(t){return Math.max(0,Math.min(1,t||0))}function to(t,e,r){return(t<60?e+(r-e)*t/60:t<180?r:t<240?e+(r-e)*(240-t)/60:e)*255}var Ia=Math.PI/180,Na=180/Math.PI;var Fa=-.14861,ro=1.78277,no=-.29227,jr=-.90649,ar=1.97294,Ba=ar*jr,Ra=ar*ro,Ha=ro*no-jr*Fa;function Uf(t){if(t instanceof se)return new se(t.h,t.s,t.l,t.opacity);t instanceof et||(t=eo(t));var e=t.r/255,r=t.g/255,n=t.b/255,o=(Ha*n+Ba*e-Ra*r)/(Ha+Ba-Ra),i=n-o,a=(ar*(r-o)-no*i)/jr,s=Math.sqrt(a*a+i*i)/(ar*o*(1-o)),u=s?Math.atan2(a,i)*Na-120:NaN;return new se(u<0?u+360:u,s,o,t.opacity)}function mt(t,e,r,n){return arguments.length===1?Uf(t):new se(t,e,r,n??1)}function se(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}De(se,mt,or(ae,{brighter(t){return t=t==null?ie:Math.pow(ie,t),new se(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?Ot:Math.pow(Ot,t),new se(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=isNaN(this.h)?0:(this.h+120)*Ia,e=+this.l,r=isNaN(this.s)?0:this.s*e*(1-e),n=Math.cos(t),o=Math.sin(t);return new et(255*(e+r*(Fa*n+ro*o)),255*(e+r*(no*n+jr*o)),255*(e+r*(ar*n)),this.opacity)}}));function oo(t,e,r,n,o){var i=t*t,a=i*t;return((1-3*t+3*i-a)*e+(4-6*i+3*a)*r+(1+3*t+3*i-3*a)*n+a*o)/6}function Oa(t){var e=t.length-1;return function(r){var n=r<=0?r=0:r>=1?(r=1,e-1):Math.floor(r*e),o=t[n],i=t[n+1],a=n>0?t[n-1]:2*o-i,s=n()=>t;function $a(t,e){return function(r){return t+r*e}}function Gf(t,e,r){return t=Math.pow(t,r),e=Math.pow(e,r)-t,r=1/r,function(n){return Math.pow(t+n*e,r)}}function Ua(t,e){var r=e-t;return r?$a(t,r>180||r<-180?r-360*Math.round(r/360):r):Ie(isNaN(t)?e:t)}function Ga(t){return(t=+t)==1?Nt:function(e,r){return r-e?Gf(e,r,t):Ie(isNaN(e)?r:e)}}function Nt(t,e){var r=e-t;return r?$a(t,r):Ie(isNaN(t)?e:t)}var ue=function t(e){var r=Ga(e);function n(o,i){var a=r((o=qe(o)).r,(i=qe(i)).r),s=r(o.g,i.g),u=r(o.b,i.b),c=Nt(o.opacity,i.opacity);return function(l){return o.r=a(l),o.g=s(l),o.b=u(l),o.opacity=c(l),o+""}}return n.gamma=t,n}(1);function Va(t){return function(e){var r=e.length,n=new Array(r),o=new Array(r),i=new Array(r),a,s;for(a=0;ar&&(i=e.slice(r,i),s[a]?s[a]+=i:s[++a]=i),(n=n[0])===(o=o[0])?s[a]?s[a]+=o:s[++a]=o:(s[++a]=null,u.push({i:a,x:Z(n,o)})),r=io.lastIndex;return r180?l+=360:l-c>180&&(c+=360),f.push({i:p.push(o(p)+"rotate(",null,n)-2,x:Z(c,l)})):l&&p.push(o(p)+"rotate("+l+n)}function s(c,l,p,f){c!==l?f.push({i:p.push(o(p)+"skewX(",null,n)-2,x:Z(c,l)}):l&&p.push(o(p)+"skewX("+l+n)}function u(c,l,p,f,m,d){if(c!==p||l!==f){var y=m.push(o(m)+"scale(",null,",",null,")");d.push({i:y-4,x:Z(c,p)},{i:y-2,x:Z(l,f)})}else(p!==1||f!==1)&&m.push(o(m)+"scale("+p+","+f+")")}return function(c,l){var p=[],f=[];return c=t(c),l=t(l),i(c.translateX,c.translateY,l.translateX,l.translateY,p,f),a(c.rotate,l.rotate,p,f),s(c.skewX,l.skewX,p,f),u(c.scaleX,c.scaleY,l.scaleX,l.scaleY,p,f),c=l=null,function(m){for(var d=-1,y=f.length,k;++d=0&&t._call.call(void 0,e),t=t._next;--Ne}function es(){le=(tn=pr.now())+en,Ne=cr=0;try{os()}finally{Ne=0,Jf(),le=0}}function Zf(){var t=pr.now(),e=t-tn;e>rs&&(en-=e,tn=t)}function Jf(){for(var t,e=Kr,r,n=1/0;e;)e._call?(n>e._time&&(n=e._time),t=e,e=e._next):(r=e._next,e._next=null,e=t?t._next=r:Kr=r);fr=t,co(n)}function co(t){if(!Ne){cr&&(cr=clearTimeout(cr));var e=t-le;e>24?(t<1/0&&(cr=setTimeout(es,t-pr.now()-en)),lr&&(lr=clearInterval(lr))):(lr||(tn=pr.now(),lr=setInterval(Zf,rs)),Ne=1,ns(es))}}function nn(t,e,r){var n=new mr;return e=e==null?0:+e,n.restart(o=>{n.stop(),t(o+e)},e,r),n}var Qf=jn("start","end","cancel","interrupt"),Kf=[],ss=0,is=1,an=2,on=3,as=4,sn=5,hr=6;function Pt(t,e,r,n,o,i){var a=t.__transition;if(!a)t.__transition={};else if(r in a)return;tp(t,r,{name:e,index:n,group:o,on:Qf,tween:Kf,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:ss})}function gr(t,e){var r=J(t,e);if(r.state>ss)throw new Error("too late; already scheduled");return r}function rt(t,e){var r=J(t,e);if(r.state>on)throw new Error("too late; already running");return r}function J(t,e){var r=t.__transition;if(!r||!(r=r[e]))throw new Error("transition not found");return r}function tp(t,e,r){var n=t.__transition,o;n[e]=r,r.timer=rn(i,0,r.time);function i(c){r.state=is,r.timer.restart(a,r.delay,r.time),r.delay<=c&&a(c-r.delay)}function a(c){var l,p,f,m;if(r.state!==is)return u();for(l in n)if(m=n[l],m.name===r.name){if(m.state===on)return nn(a);m.state===as?(m.state=hr,m.timer.stop(),m.on.call("interrupt",t,t.__data__,m.index,m.group),delete n[l]):+lan&&n.state=0&&(e=e.slice(0,r)),!e||e==="start"})}function bp(t,e,r){var n,o,i=vp(e)?gr:rt;return function(){var a=i(this,t),s=a.on;s!==n&&(o=(n=s).copy()).on(e,r),a.on=o}}function ys(t,e){var r=this._id;return arguments.length<2?J(this.node(),r).on.on(t):this.each(bp(r,t,e))}function wp(t){return function(){var e=this.parentNode;for(var r in this.__transition)if(+r!==t)return;e&&e.removeChild(this)}}function vs(){return this.on("end.remove",wp(this._id))}function bs(t){var e=this._name,r=this._id;typeof t!="function"&&(t=re(t));for(var n=this._groups,o=n.length,i=new Array(o),a=0;a=0))throw new Error(`invalid digits: ${t}`);if(e>15)return qs;let r=10**e;return function(n){this._+=n[0];for(let o=1,i=n.length;oce)if(!(Math.abs(p*u-c*l)>ce)||!i)this._append`L${this._x1=e},${this._y1=r}`;else{let m=n-a,d=o-s,y=u*u+c*c,k=m*m+d*d,_=Math.sqrt(y),q=Math.sqrt(f),A=i*Math.tan((po-Math.acos((y+f-k)/(2*_*q)))/2),D=A/q,L=A/_;Math.abs(D-1)>ce&&this._append`L${e+D*l},${r+D*p}`,this._append`A${i},${i},0,0,${+(p*m>l*d)},${this._x1=e+L*u},${this._y1=r+L*c}`}}arc(e,r,n,o,i,a){if(e=+e,r=+r,n=+n,a=!!a,n<0)throw new Error(`negative radius: ${n}`);let s=n*Math.cos(o),u=n*Math.sin(o),c=e+s,l=r+u,p=1^a,f=a?o-i:i-o;this._x1===null?this._append`M${c},${l}`:(Math.abs(this._x1-c)>ce||Math.abs(this._y1-l)>ce)&&this._append`L${c},${l}`,n&&(f<0&&(f=f%mo+mo),f>Hp?this._append`A${n},${n},0,1,${p},${e-s},${r-u}A${n},${n},0,1,${p},${this._x1=c},${this._y1=l}`:f>ce&&this._append`A${n},${n},0,${+(f>=po)},${p},${this._x1=e+n*Math.cos(i)},${this._y1=r+n*Math.sin(i)}`)}rect(e,r,n,o){this._append`M${this._x0=this._x1=+e},${this._y0=this._y1=+r}h${n=+n}v${+o}h${-n}Z`}toString(){return this._}};function Is(){return new fe}Is.prototype=fe.prototype;function Ns(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)}function pe(t,e){if((r=(t=e?t.toExponential(e-1):t.toExponential()).indexOf("e"))<0)return null;var r,n=t.slice(0,r);return[n.length>1?n[0]+n.slice(2):n,+t.slice(r+1)]}function Mt(t){return t=pe(Math.abs(t)),t?t[1]:NaN}function Bs(t,e){return function(r,n){for(var o=r.length,i=[],a=0,s=t[0],u=0;o>0&&s>0&&(u+s+1>n&&(s=Math.max(1,n-u)),i.push(r.substring(o-=s,o+s)),!((u+=s+1)>n));)s=t[a=(a+1)%t.length];return i.reverse().join(e)}}function Rs(t){return function(e){return e.replace(/[0-9]/g,function(r){return t[+r]})}}var Op=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function St(t){if(!(e=Op.exec(t)))throw new Error("invalid format: "+t);var e;return new pn({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}St.prototype=pn.prototype;function pn(t){this.fill=t.fill===void 0?" ":t.fill+"",this.align=t.align===void 0?">":t.align+"",this.sign=t.sign===void 0?"-":t.sign+"",this.symbol=t.symbol===void 0?"":t.symbol+"",this.zero=!!t.zero,this.width=t.width===void 0?void 0:+t.width,this.comma=!!t.comma,this.precision=t.precision===void 0?void 0:+t.precision,this.trim=!!t.trim,this.type=t.type===void 0?"":t.type+""}pn.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function Hs(t){t:for(var e=t.length,r=1,n=-1,o;r0&&(n=0);break}return n>0?t.slice(0,n)+t.slice(o+1):t}var ho;function Fs(t,e){var r=pe(t,e);if(!r)return t+"";var n=r[0],o=r[1],i=o-(ho=Math.max(-8,Math.min(8,Math.floor(o/3)))*3)+1,a=n.length;return i===a?n:i>a?n+new Array(i-a+1).join("0"):i>0?n.slice(0,i)+"."+n.slice(i):"0."+new Array(1-i).join("0")+pe(t,Math.max(0,e+i-1))[0]}function go(t,e){var r=pe(t,e);if(!r)return t+"";var n=r[0],o=r[1];return o<0?"0."+new Array(-o).join("0")+n:n.length>o+1?n.slice(0,o+1)+"."+n.slice(o+1):n+new Array(o-n.length+2).join("0")}var xo={"%":(t,e)=>(t*100).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:Ns,e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>go(t*100,e),r:go,s:Fs,X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function yo(t){return t}var Os=Array.prototype.map,Ps=["y","z","a","f","p","n","\xB5","m","","k","M","G","T","P","E","Z","Y"];function $s(t){var e=t.grouping===void 0||t.thousands===void 0?yo:Bs(Os.call(t.grouping,Number),t.thousands+""),r=t.currency===void 0?"":t.currency[0]+"",n=t.currency===void 0?"":t.currency[1]+"",o=t.decimal===void 0?".":t.decimal+"",i=t.numerals===void 0?yo:Rs(Os.call(t.numerals,String)),a=t.percent===void 0?"%":t.percent+"",s=t.minus===void 0?"\u2212":t.minus+"",u=t.nan===void 0?"NaN":t.nan+"";function c(p){p=St(p);var f=p.fill,m=p.align,d=p.sign,y=p.symbol,k=p.zero,_=p.width,q=p.comma,A=p.precision,D=p.trim,L=p.type;L==="n"?(q=!0,L="g"):xo[L]||(A===void 0&&(A=12),D=!0,L="g"),(k||f==="0"&&m==="=")&&(k=!0,f="0",m="=");var b=y==="$"?r:y==="#"&&/[boxX]/.test(L)?"0"+L.toLowerCase():"",N=y==="$"?n:/[%p]/.test(L)?a:"",H=xo[L],P=/[defgprs%]/.test(L);A=A===void 0?6:/[gprs]/.test(L)?Math.max(1,Math.min(21,A)):Math.max(0,Math.min(20,A));function I(h){var T=b,E=N,R,g,x;if(L==="c")E=H(h)+E,h="";else{h=+h;var M=h<0||1/h<0;if(h=isNaN(h)?u:H(Math.abs(h),A),D&&(h=Hs(h)),M&&+h==0&&d!=="+"&&(M=!1),T=(M?d==="("?d:s:d==="-"||d==="("?"":d)+T,E=(L==="s"?Ps[8+ho/3]:"")+E+(M&&d==="("?")":""),P){for(R=-1,g=h.length;++Rx||x>57){E=(x===46?o+h.slice(R+1):h.slice(R))+E,h=h.slice(0,R);break}}}q&&!k&&(h=e(h,1/0));var S=T.length+h.length+E.length,v=S<_?new Array(_-S+1).join(f):"";switch(q&&k&&(h=e(v+h,v.length?_-E.length:1/0),v=""),m){case"<":h=T+h+E+v;break;case"=":h=T+v+h+E;break;case"^":h=v.slice(0,S=v.length>>1)+T+h+E+v.slice(S);break;default:h=v+T+h+E;break}return i(h)}return I.toString=function(){return p+""},I}function l(p,f){var m=c((p=St(p),p.type="f",p)),d=Math.max(-8,Math.min(8,Math.floor(Mt(f)/3)))*3,y=Math.pow(10,-d),k=Ps[8+d/3];return function(_){return m(y*_)+k}}return{format:c,formatPrefix:l}}var mn,bt,dn;vo({thousands:",",grouping:[3],currency:["$",""]});function vo(t){return mn=$s(t),bt=mn.format,dn=mn.formatPrefix,mn}function bo(t){return Math.max(0,-Mt(Math.abs(t)))}function wo(t,e){return Math.max(0,Math.max(-8,Math.min(8,Math.floor(Mt(e)/3)))*3-Mt(Math.abs(t)))}function ko(t,e){return t=Math.abs(t),e=Math.abs(e)-t,Math.max(0,Mt(e)-Mt(t))+1}function Pp(t){var e=0,r=t.children,n=r&&r.length;if(!n)e=1;else for(;--n>=0;)e+=r[n].value;t.value=e}function Us(){return this.eachAfter(Pp)}function Gs(t,e){let r=-1;for(let n of this)t.call(e,n,++r,this);return this}function Vs(t,e){for(var r=this,n=[r],o,i,a=-1;r=n.pop();)if(t.call(e,r,++a,this),o=r.children)for(i=o.length-1;i>=0;--i)n.push(o[i]);return this}function zs(t,e){for(var r=this,n=[r],o=[],i,a,s,u=-1;r=n.pop();)if(o.push(r),i=r.children)for(a=0,s=i.length;a=0;)r+=n[o].value;e.value=r})}function Xs(t){return this.eachBefore(function(e){e.children&&e.children.sort(t)})}function js(t){for(var e=this,r=$p(e,t),n=[e];e!==r;)e=e.parent,n.push(e);for(var o=n.length;t!==r;)n.splice(o,0,t),t=t.parent;return n}function $p(t,e){if(t===e)return t;var r=t.ancestors(),n=e.ancestors(),o=null;for(t=r.pop(),e=n.pop();t===e;)o=t,t=r.pop(),e=n.pop();return o}function Zs(){for(var t=this,e=[t];t=t.parent;)e.push(t);return e}function Js(){return Array.from(this)}function Qs(){var t=[];return this.eachBefore(function(e){e.children||t.push(e)}),t}function Ks(){var t=this,e=[];return t.each(function(r){r!==t&&e.push({source:r.parent,target:r})}),e}function*tu(){var t=this,e,r=[t],n,o,i;do for(e=r.reverse(),r=[];t=e.pop();)if(yield t,n=t.children)for(o=0,i=n.length;o=0;--s)o.push(i=a[s]=new yr(a[s])),i.parent=n,i.depth=n.depth+1;return r.eachBefore(Yp)}function Up(){return Re(this).eachBefore(zp)}function Gp(t){return t.children}function Vp(t){return Array.isArray(t)?t[1]:null}function zp(t){t.data.value!==void 0&&(t.value=t.data.value),t.data=t.data.data}function Yp(t){var e=0;do t.height=e;while((t=t.parent)&&t.height<++e)}function yr(t){this.data=t,this.depth=this.height=0,this.parent=null}yr.prototype=Re.prototype={constructor:yr,count:Us,each:Gs,eachAfter:zs,eachBefore:Vs,find:Ys,sum:Ws,sort:Xs,path:js,ancestors:Zs,descendants:Js,leaves:Qs,links:Ks,copy:Up,[Symbol.iterator]:tu};function eu(t){if(typeof t!="function")throw new Error;return t}function He(){return 0}function Fe(t){return function(){return t}}function ru(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)}function nu(t,e,r,n,o){for(var i=t.children,a,s=-1,u=i.length,c=t.value&&(n-e)/t.value;++sq&&(q=c),b=k*k*L,A=Math.max(q/b,b/_),A>D){k-=c;break}D=A}a.push(u={value:k,dice:m1?n:1)},r}(Wp);function _o(){var t=vr,e=!1,r=1,n=1,o=[0],i=He,a=He,s=He,u=He,c=He;function l(f){return f.x0=f.y0=0,f.x1=r,f.y1=n,f.eachBefore(p),o=[0],e&&f.eachBefore(ru),f}function p(f){var m=o[f.depth],d=f.x0+m,y=f.y0+m,k=f.x1-m,_=f.y1-m;ke&&(r=t,t=e,e=r),function(n){return Math.max(t,Math.min(e,n))}}function Zp(t,e,r){var n=t[0],o=t[1],i=e[0],a=e[1];return o2?Jp:Zp,u=c=null,p}function p(f){return f==null||isNaN(f=+f)?i:(u||(u=s(t.map(n),e,r)))(n(a(f)))}return p.invert=function(f){return a(o((c||(c=s(e,t.map(n),Z)))(f)))},p.domain=function(f){return arguments.length?(t=Array.from(f,So),l()):t.slice()},p.range=function(f){return arguments.length?(e=Array.from(f),l()):e.slice()},p.rangeRound=function(f){return e=Array.from(f),r=ur,l()},p.clamp=function(f){return arguments.length?(a=f?!0:Ut,l()):a!==Ut},p.interpolate=function(f){return arguments.length?(r=f,l()):r},p.unknown=function(f){return arguments.length?(i=f,p):i},function(f,m){return n=f,o=m,l()}}function wr(){return Qp()(Ut,Ut)}function Eo(t,e,r,n){var o=Le(t,e,r),i;switch(n=St(n??",f"),n.type){case"s":{var a=Math.max(Math.abs(t),Math.abs(e));return n.precision==null&&!isNaN(i=wo(o,a))&&(n.precision=i),dn(n,a)}case"":case"e":case"g":case"p":case"r":{n.precision==null&&!isNaN(i=ko(o,Math.max(Math.abs(t),Math.abs(e))))&&(n.precision=i-(n.type==="e"));break}case"f":case"%":{n.precision==null&&!isNaN(i=bo(o))&&(n.precision=i-(n.type==="%")*2);break}}return bt(n)}function Kp(t){var e=t.domain;return t.ticks=function(r){var n=e();return te(n[0],n[n.length-1],r??10)},t.tickFormat=function(r,n){var o=e();return Eo(o[0],o[o.length-1],r??10,n)},t.nice=function(r){r==null&&(r=10);var n=e(),o=0,i=n.length-1,a=n[o],s=n[i],u,c,l=10;for(s0;){if(c=Qe(a,s,r),c===u)return n[o]=a,n[i]=s,e(n);if(c>0)a=Math.floor(a/c)*c,s=Math.ceil(s/c)*c;else if(c<0)a=Math.ceil(a*c)/c,s=Math.floor(s*c)/c;else break;u=c}return t},t}function de(){var t=wr();return t.copy=function(){return hn(t,de())},$t.apply(t,arguments),Kp(t)}function kr(t,e){t=t.slice();var r=0,n=t.length-1,o=t[r],i=t[n],a;return iMath.pow(t,e)}function om(t){return t===Math.E?Math.log:t===10&&Math.log10||t===2&&Math.log2||(t=Math.log(t),e=>Math.log(e)/t)}function lu(t){return(e,r)=>-t(-e,r)}function cu(t){let e=t(su,uu),r=e.domain,n=10,o,i;function a(){return o=om(n),i=nm(n),r()[0]<0?(o=lu(o),i=lu(i),t(tm,em)):t(su,uu),e}return e.base=function(s){return arguments.length?(n=+s,a()):n},e.domain=function(s){return arguments.length?(r(s),a()):r()},e.ticks=s=>{let u=r(),c=u[0],l=u[u.length-1],p=l0){for(;f<=m;++f)for(d=1;dl)break;_.push(y)}}else for(;f<=m;++f)for(d=n-1;d>=1;--d)if(y=f>0?d/i(-f):d*i(f),!(yl)break;_.push(y)}_.length*2{if(s==null&&(s=10),u==null&&(u=n===10?"s":","),typeof u!="function"&&(!(n%1)&&(u=St(u)).precision==null&&(u.trim=!0),u=bt(u)),s===1/0)return u;let c=Math.max(1,n*s/e.ticks().length);return l=>{let p=l/i(Math.round(o(l)));return p*nr(kr(r(),{floor:s=>i(Math.floor(o(s))),ceil:s=>i(Math.ceil(o(s)))})),e}var Ao=new Date,Do=new Date;function z(t,e,r,n){function o(i){return t(i=arguments.length===0?new Date:new Date(+i)),i}return o.floor=i=>(t(i=new Date(+i)),i),o.ceil=i=>(t(i=new Date(i-1)),e(i,1),t(i),i),o.round=i=>{let a=o(i),s=o.ceil(i);return i-a(e(i=new Date(+i),a==null?1:Math.floor(a)),i),o.range=(i,a,s)=>{let u=[];if(i=o.ceil(i),s=s==null?1:Math.floor(s),!(i0))return u;let c;do u.push(c=new Date(+i)),e(i,s),t(i);while(cz(a=>{if(a>=a)for(;t(a),!i(a);)a.setTime(a-1)},(a,s)=>{if(a>=a)if(s<0)for(;++s<=0;)for(;e(a,-1),!i(a););else for(;--s>=0;)for(;e(a,1),!i(a););}),r&&(o.count=(i,a)=>(Ao.setTime(+i),Do.setTime(+a),t(Ao),t(Do),Math.floor(r(Ao,Do))),o.every=i=>(i=Math.floor(i),!isFinite(i)||!(i>0)?null:i>1?o.filter(n?a=>n(a)%i===0:a=>o.count(0,a)%i===0):o)),o}var _r=z(()=>{},(t,e)=>{t.setTime(+t+e)},(t,e)=>e-t);_r.every=t=>(t=Math.floor(t),!isFinite(t)||!(t>0)?null:t>1?z(e=>{e.setTime(Math.floor(e/t)*t)},(e,r)=>{e.setTime(+e+r*t)},(e,r)=>(r-e)/t):_r);var m_=_r.range;var Lt=z(t=>{t.setTime(t-t.getMilliseconds())},(t,e)=>{t.setTime(+t+e*1e3)},(t,e)=>(e-t)/1e3,t=>t.getUTCSeconds()),fu=Lt.range;var Oe=z(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*1e3)},(t,e)=>{t.setTime(+t+e*6e4)},(t,e)=>(e-t)/6e4,t=>t.getMinutes()),im=Oe.range,gn=z(t=>{t.setUTCSeconds(0,0)},(t,e)=>{t.setTime(+t+e*6e4)},(t,e)=>(e-t)/6e4,t=>t.getUTCMinutes()),am=gn.range;var Pe=z(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*1e3-t.getMinutes()*6e4)},(t,e)=>{t.setTime(+t+e*36e5)},(t,e)=>(e-t)/36e5,t=>t.getHours()),sm=Pe.range,xn=z(t=>{t.setUTCMinutes(0,0,0)},(t,e)=>{t.setTime(+t+e*36e5)},(t,e)=>(e-t)/36e5,t=>t.getUTCHours()),um=xn.range;var Rt=z(t=>t.setHours(0,0,0,0),(t,e)=>t.setDate(t.getDate()+e),(t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*6e4)/864e5,t=>t.getDate()-1),lm=Rt.range,Mr=z(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>t.getUTCDate()-1),cm=Mr.range,yn=z(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>Math.floor(t/864e5)),fm=yn.range;function xe(t){return z(e=>{e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)},(e,r)=>{e.setDate(e.getDate()+r*7)},(e,r)=>(r-e-(r.getTimezoneOffset()-e.getTimezoneOffset())*6e4)/6048e5)}var Ht=xe(0),$e=xe(1),mu=xe(2),du=xe(3),Gt=xe(4),hu=xe(5),gu=xe(6),xu=Ht.range,pm=$e.range,mm=mu.range,dm=du.range,hm=Gt.range,gm=hu.range,xm=gu.range;function ye(t){return z(e=>{e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)},(e,r)=>{e.setUTCDate(e.getUTCDate()+r*7)},(e,r)=>(r-e)/6048e5)}var ve=ye(0),Ue=ye(1),yu=ye(2),vu=ye(3),Vt=ye(4),bu=ye(5),wu=ye(6),ku=ve.range,ym=Ue.range,vm=yu.range,bm=vu.range,wm=Vt.range,km=bu.range,_m=wu.range;var Ge=z(t=>{t.setDate(1),t.setHours(0,0,0,0)},(t,e)=>{t.setMonth(t.getMonth()+e)},(t,e)=>e.getMonth()-t.getMonth()+(e.getFullYear()-t.getFullYear())*12,t=>t.getMonth()),Tm=Ge.range,vn=z(t=>{t.setUTCDate(1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCMonth(t.getUTCMonth()+e)},(t,e)=>e.getUTCMonth()-t.getUTCMonth()+(e.getUTCFullYear()-t.getUTCFullYear())*12,t=>t.getUTCMonth()),Mm=vn.range;var pt=z(t=>{t.setMonth(0,1),t.setHours(0,0,0,0)},(t,e)=>{t.setFullYear(t.getFullYear()+e)},(t,e)=>e.getFullYear()-t.getFullYear(),t=>t.getFullYear());pt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:z(e=>{e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)},(e,r)=>{e.setFullYear(e.getFullYear()+r*t)});var Sm=pt.range,wt=z(t=>{t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCFullYear(t.getUTCFullYear()+e)},(t,e)=>e.getUTCFullYear()-t.getUTCFullYear(),t=>t.getUTCFullYear());wt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:z(e=>{e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)},(e,r)=>{e.setUTCFullYear(e.getUTCFullYear()+r*t)});var Lm=wt.range;function Tu(t,e,r,n,o,i){let a=[[Lt,1,1e3],[Lt,5,5*1e3],[Lt,15,15*1e3],[Lt,30,30*1e3],[i,1,6e4],[i,5,5*6e4],[i,15,15*6e4],[i,30,30*6e4],[o,1,36e5],[o,3,3*36e5],[o,6,6*36e5],[o,12,12*36e5],[n,1,864e5],[n,2,2*864e5],[r,1,6048e5],[e,1,2592e6],[e,3,3*2592e6],[t,1,31536e6]];function s(c,l,p){let f=lk).right(a,f);if(m===a.length)return t.every(Le(c/31536e6,l/31536e6,p));if(m===0)return _r.every(Math.max(Le(c,l,p),1));let[d,y]=a[f/a[m-1][2]53)return null;"w"in w||(w.w=1),"Z"in w?(Y=No(Sr(w.y,0,1)),lt=Y.getUTCDay(),Y=lt>4||lt===0?Ue.ceil(Y):Ue(Y),Y=Mr.offset(Y,(w.V-1)*7),w.y=Y.getUTCFullYear(),w.m=Y.getUTCMonth(),w.d=Y.getUTCDate()+(w.w+6)%7):(Y=Io(Sr(w.y,0,1)),lt=Y.getDay(),Y=lt>4||lt===0?$e.ceil(Y):$e(Y),Y=Rt.offset(Y,(w.V-1)*7),w.y=Y.getFullYear(),w.m=Y.getMonth(),w.d=Y.getDate()+(w.w+6)%7)}else("W"in w||"U"in w)&&("w"in w||(w.w="u"in w?w.u%7:"W"in w?1:0),lt="Z"in w?No(Sr(w.y,0,1)).getUTCDay():Io(Sr(w.y,0,1)).getDay(),w.m=0,w.d="W"in w?(w.w+6)%7+w.W*7-(lt+5)%7:w.w+w.U*7-(lt+6)%7);return"Z"in w?(w.H+=w.Z/100|0,w.M+=w.Z%100,No(w)):Io(w)}}function H(C,F,U,w){for(var st=0,Y=F.length,lt=U.length,ct,Qt;st=lt)return-1;if(ct=F.charCodeAt(st++),ct===37){if(ct=F.charAt(st++),Qt=L[ct in Mu?F.charAt(st++):ct],!Qt||(w=Qt(C,U,w))<0)return-1}else if(ct!=U.charCodeAt(w++))return-1}return w}function P(C,F,U){var w=c.exec(F.slice(U));return w?(C.p=l.get(w[0].toLowerCase()),U+w[0].length):-1}function I(C,F,U){var w=m.exec(F.slice(U));return w?(C.w=d.get(w[0].toLowerCase()),U+w[0].length):-1}function h(C,F,U){var w=p.exec(F.slice(U));return w?(C.w=f.get(w[0].toLowerCase()),U+w[0].length):-1}function T(C,F,U){var w=_.exec(F.slice(U));return w?(C.m=q.get(w[0].toLowerCase()),U+w[0].length):-1}function E(C,F,U){var w=y.exec(F.slice(U));return w?(C.m=k.get(w[0].toLowerCase()),U+w[0].length):-1}function R(C,F,U){return H(C,e,F,U)}function g(C,F,U){return H(C,r,F,U)}function x(C,F,U){return H(C,n,F,U)}function M(C){return a[C.getDay()]}function S(C){return i[C.getDay()]}function v(C){return u[C.getMonth()]}function B(C){return s[C.getMonth()]}function G(C){return o[+(C.getHours()>=12)]}function K(C){return 1+~~(C.getMonth()/3)}function ot(C){return a[C.getUTCDay()]}function ht(C){return i[C.getUTCDay()]}function tt(C){return u[C.getUTCMonth()]}function Dt(C){return s[C.getUTCMonth()]}function gt(C){return o[+(C.getUTCHours()>=12)]}function Je(C){return 1+~~(C.getUTCMonth()/3)}return{format:function(C){var F=b(C+="",A);return F.toString=function(){return C},F},parse:function(C){var F=N(C+="",!1);return F.toString=function(){return C},F},utcFormat:function(C){var F=b(C+="",D);return F.toString=function(){return C},F},utcParse:function(C){var F=N(C+="",!0);return F.toString=function(){return C},F}}}var Mu={"-":"",_:" ",0:"0"},Q=/^\s*\d+/,Cm=/^%/,qm=/[\\^$*+?|[\]().{}]/g;function V(t,e,r){var n=t<0?"-":"",o=(n?-t:t)+"",i=o.length;return n+(i[e.toLowerCase(),r]))}function Nm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.w=+n[0],r+n[0].length):-1}function Bm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.u=+n[0],r+n[0].length):-1}function Rm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.U=+n[0],r+n[0].length):-1}function Hm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.V=+n[0],r+n[0].length):-1}function Fm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.W=+n[0],r+n[0].length):-1}function Su(t,e,r){var n=Q.exec(e.slice(r,r+4));return n?(t.y=+n[0],r+n[0].length):-1}function Lu(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.y=+n[0]+(+n[0]>68?1900:2e3),r+n[0].length):-1}function Om(t,e,r){var n=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(r,r+6));return n?(t.Z=n[1]?0:-(n[2]+(n[3]||"00")),r+n[0].length):-1}function Pm(t,e,r){var n=Q.exec(e.slice(r,r+1));return n?(t.q=n[0]*3-3,r+n[0].length):-1}function $m(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.m=n[0]-1,r+n[0].length):-1}function Eu(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.d=+n[0],r+n[0].length):-1}function Um(t,e,r){var n=Q.exec(e.slice(r,r+3));return n?(t.m=0,t.d=+n[0],r+n[0].length):-1}function Au(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.H=+n[0],r+n[0].length):-1}function Gm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.M=+n[0],r+n[0].length):-1}function Vm(t,e,r){var n=Q.exec(e.slice(r,r+2));return n?(t.S=+n[0],r+n[0].length):-1}function zm(t,e,r){var n=Q.exec(e.slice(r,r+3));return n?(t.L=+n[0],r+n[0].length):-1}function Ym(t,e,r){var n=Q.exec(e.slice(r,r+6));return n?(t.L=Math.floor(n[0]/1e3),r+n[0].length):-1}function Wm(t,e,r){var n=Cm.exec(e.slice(r,r+1));return n?r+n[0].length:-1}function Xm(t,e,r){var n=Q.exec(e.slice(r));return n?(t.Q=+n[0],r+n[0].length):-1}function jm(t,e,r){var n=Q.exec(e.slice(r));return n?(t.s=+n[0],r+n[0].length):-1}function Du(t,e){return V(t.getDate(),e,2)}function Zm(t,e){return V(t.getHours(),e,2)}function Jm(t,e){return V(t.getHours()%12||12,e,2)}function Qm(t,e){return V(1+Rt.count(pt(t),t),e,3)}function Bu(t,e){return V(t.getMilliseconds(),e,3)}function Km(t,e){return Bu(t,e)+"000"}function td(t,e){return V(t.getMonth()+1,e,2)}function ed(t,e){return V(t.getMinutes(),e,2)}function rd(t,e){return V(t.getSeconds(),e,2)}function nd(t){var e=t.getDay();return e===0?7:e}function od(t,e){return V(Ht.count(pt(t)-1,t),e,2)}function Ru(t){var e=t.getDay();return e>=4||e===0?Gt(t):Gt.ceil(t)}function id(t,e){return t=Ru(t),V(Gt.count(pt(t),t)+(pt(t).getDay()===4),e,2)}function ad(t){return t.getDay()}function sd(t,e){return V($e.count(pt(t)-1,t),e,2)}function ud(t,e){return V(t.getFullYear()%100,e,2)}function ld(t,e){return t=Ru(t),V(t.getFullYear()%100,e,2)}function cd(t,e){return V(t.getFullYear()%1e4,e,4)}function fd(t,e){var r=t.getDay();return t=r>=4||r===0?Gt(t):Gt.ceil(t),V(t.getFullYear()%1e4,e,4)}function pd(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+V(e/60|0,"0",2)+V(e%60,"0",2)}function Cu(t,e){return V(t.getUTCDate(),e,2)}function md(t,e){return V(t.getUTCHours(),e,2)}function dd(t,e){return V(t.getUTCHours()%12||12,e,2)}function hd(t,e){return V(1+Mr.count(wt(t),t),e,3)}function Hu(t,e){return V(t.getUTCMilliseconds(),e,3)}function gd(t,e){return Hu(t,e)+"000"}function xd(t,e){return V(t.getUTCMonth()+1,e,2)}function yd(t,e){return V(t.getUTCMinutes(),e,2)}function vd(t,e){return V(t.getUTCSeconds(),e,2)}function bd(t){var e=t.getUTCDay();return e===0?7:e}function wd(t,e){return V(ve.count(wt(t)-1,t),e,2)}function Fu(t){var e=t.getUTCDay();return e>=4||e===0?Vt(t):Vt.ceil(t)}function kd(t,e){return t=Fu(t),V(Vt.count(wt(t),t)+(wt(t).getUTCDay()===4),e,2)}function _d(t){return t.getUTCDay()}function Td(t,e){return V(Ue.count(wt(t)-1,t),e,2)}function Md(t,e){return V(t.getUTCFullYear()%100,e,2)}function Sd(t,e){return t=Fu(t),V(t.getUTCFullYear()%100,e,2)}function Ld(t,e){return V(t.getUTCFullYear()%1e4,e,4)}function Ed(t,e){var r=t.getUTCDay();return t=r>=4||r===0?Vt(t):Vt.ceil(t),V(t.getUTCFullYear()%1e4,e,4)}function Ad(){return"+0000"}function qu(){return"%"}function Iu(t){return+t}function Nu(t){return Math.floor(+t/1e3)}var Ve,bn,Ou,Pu,$u;Ro({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function Ro(t){return Ve=Bo(t),bn=Ve.format,Ou=Ve.parse,Pu=Ve.utcFormat,$u=Ve.utcParse,Ve}function Dd(t){return new Date(t)}function Cd(t){return t instanceof Date?+t:+new Date(+t)}function Uu(t,e,r,n,o,i,a,s,u,c){var l=wr(),p=l.invert,f=l.domain,m=c(".%L"),d=c(":%S"),y=c("%I:%M"),k=c("%I %p"),_=c("%a %d"),q=c("%b %d"),A=c("%B"),D=c("%Y");function L(b){return(u(b)1?0:t<-1?ze:Math.acos(t)}function Po(t){return t>=1?Ar:t<=-1?-Ar:Math.asin(t)}function Tn(t){let e=3;return t.digits=function(r){if(!arguments.length)return e;if(r==null)e=null;else{let n=Math.floor(r);if(!(n>=0))throw new RangeError(`invalid digits: ${r}`);e=n}return t},()=>new fe(e)}function Bd(t){return t.innerRadius}function Rd(t){return t.outerRadius}function Hd(t){return t.startAngle}function Fd(t){return t.endAngle}function Od(t){return t&&t.padAngle}function Pd(t,e,r,n,o,i,a,s){var u=r-t,c=n-e,l=a-o,p=s-i,f=p*u-l*c;if(!(f*fR*R+g*g&&(H=I,P=h),{cx:H,cy:P,x01:-l,y01:-p,x11:H*(o/L-1),y11:P*(o/L-1)}}function $o(){var t=Bd,e=Rd,r=W(0),n=null,o=Hd,i=Fd,a=Od,s=null,u=Tn(c);function c(){var l,p,f=+t.apply(this,arguments),m=+e.apply(this,arguments),d=o.apply(this,arguments)-Ar,y=i.apply(this,arguments)-Ar,k=Oo(y-d),_=y>d;if(s||(s=l=u()),mat))s.moveTo(0,0);else if(k>Ye-at)s.moveTo(m*zt(d),m*kt(d)),s.arc(0,0,m,d,y,!_),f>at&&(s.moveTo(f*zt(y),f*kt(y)),s.arc(0,0,f,y,d,_));else{var q=d,A=y,D=d,L=y,b=k,N=k,H=a.apply(this,arguments)/2,P=H>at&&(n?+n.apply(this,arguments):be(f*f+m*m)),I=_n(Oo(m-f)/2,+r.apply(this,arguments)),h=I,T=I,E,R;if(P>at){var g=Po(P/f*kt(H)),x=Po(P/m*kt(H));(b-=g*2)>at?(g*=_?1:-1,D+=g,L-=g):(b=0,D=L=(d+y)/2),(N-=x*2)>at?(x*=_?1:-1,q+=x,A-=x):(N=0,q=A=(d+y)/2)}var M=m*zt(q),S=m*kt(q),v=f*zt(L),B=f*kt(L);if(I>at){var G=m*zt(A),K=m*kt(A),ot=f*zt(D),ht=f*kt(D),tt;if(kat?T>at?(E=Mn(ot,ht,M,S,m,T,_),R=Mn(G,K,v,B,m,T,_),s.moveTo(E.cx+E.x01,E.cy+E.y01),Tat)||!(b>at)?s.lineTo(v,B):h>at?(E=Mn(v,B,G,K,f,-h,_),R=Mn(M,S,ot,ht,f,-h,_),s.lineTo(E.cx+E.x01,E.cy+E.y01),ht?1:e>=t?0:NaN}function Ju(t){return t}function Uo(){var t=Ju,e=Zu,r=null,n=W(0),o=W(Ye),i=W(0);function a(s){var u,c=(s=Sn(s)).length,l,p,f=0,m=new Array(c),d=new Array(c),y=+n.apply(this,arguments),k=Math.min(Ye,Math.max(-Ye,o.apply(this,arguments)-y)),_,q=Math.min(Math.abs(k)/c,i.apply(this,arguments)),A=q*(k<0?-1:1),D;for(u=0;u0&&(f+=D);for(e!=null?m.sort(function(L,b){return e(d[L],d[b])}):r!=null&&m.sort(function(L,b){return r(s[L],s[b])}),u=0,p=f?(k-c*A)/f:0;u0?D*p:0)+A,d[l]={data:s[l],index:u,value:D,startAngle:y,endAngle:_,padAngle:q};return d}return a.value=function(s){return arguments.length?(t=typeof s=="function"?s:W(+s),a):t},a.sortValues=function(s){return arguments.length?(e=s,r=null,a):e},a.sort=function(s){return arguments.length?(r=s,e=null,a):r},a.startAngle=function(s){return arguments.length?(n=typeof s=="function"?s:W(+s),a):n},a.endAngle=function(s){return arguments.length?(o=typeof s=="function"?s:W(+s),a):o},a.padAngle=function(s){return arguments.length?(i=typeof s=="function"?s:W(+s),a):i},a}function Qu(t){return t<0?-1:1}function Ku(t,e,r){var n=t._x1-t._x0,o=e-t._x1,i=(t._y1-t._y0)/(n||o<0&&-0),a=(r-t._y1)/(o||n<0&&-0),s=(i*o+a*n)/(n+o);return(Qu(i)+Qu(a))*Math.min(Math.abs(i),Math.abs(a),.5*Math.abs(s))||0}function tl(t,e){var r=t._x1-t._x0;return r?(3*(t._y1-t._y0)/r-e)/2:e}function Go(t,e,r){var n=t._x0,o=t._y0,i=t._x1,a=t._y1,s=(i-n)/3;t._context.bezierCurveTo(n+s,o+s*e,i-s,a-s*r,i,a)}function Ln(t){this._context=t}Ln.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:Go(this,this._t0,tl(this,this._t0));break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){var r=NaN;if(t=+t,e=+e,!(t===this._x1&&e===this._y1)){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,Go(this,tl(this,r=Ku(this,t,e)),r);break;default:Go(this,this._t0,r=Ku(this,t,e));break}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e,this._t0=r}}};function $d(t){this._context=new el(t)}($d.prototype=Object.create(Ln.prototype)).point=function(t,e){Ln.prototype.point.call(this,e,t)};function el(t){this._context=t}el.prototype={moveTo:function(t,e){this._context.moveTo(e,t)},closePath:function(){this._context.closePath()},lineTo:function(t,e){this._context.lineTo(e,t)},bezierCurveTo:function(t,e,r,n,o,i){this._context.bezierCurveTo(e,t,n,r,i,o)}};function En(t){return new Ln(t)}function Yt(t,e,r){this.k=t,this.x=e,this.y=r}Yt.prototype={constructor:Yt,scale:function(t){return t===1?this:new Yt(this.k*t,this.x,this.y)},translate:function(t,e){return t===0&e===0?this:new Yt(this.k,this.x+this.k*t,this.y+this.k*e)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Vo=new Yt(1,0,0);zo.prototype=Yt.prototype;function zo(t){for(;!t.__zoom;)if(!(t=t.parentNode))return Vo;return t.__zoom}var dt=bt(",.0f"),Wt=bt(",.1f");function Wo(t){function e(c){return c.toString().padStart(2,"0")}let r=Math.floor(t/1e3),n=Math.floor(r/60),o=Math.floor(n/60),i=Math.floor(o/24),a=o%24,s=n%60,u=r%60;return i===0&&a===0&&s===0&&u===0?"0s":i>0?`${i}d ${e(a)}h ${e(s)}m ${e(u)}s`:a>0?`${a}h ${e(s)}m ${e(u)}s`:s>0?`${s}m ${e(u)}s`:`${u}s`}var Ud=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function nl(t){let e=new Date(t*1e3),r=String(e.getDate()).padStart(2,"0"),n=Ud[e.getMonth()],o=e.getFullYear(),i=String(e.getHours()).padStart(2,"0"),a=String(e.getMinutes()).padStart(2,"0"),s=String(e.getSeconds()).padStart(2,"0");return`${r} ${n} ${o} ${i}:${a}:${s}`}var Yo=["bytes","kB","MB","GB","TB","PB"];function ol(t){if(!Number.isFinite(t)||t<0)return"0 bytes";let e=0,r=t;for(;r>=1e3&&eGd(a.charCodeAt(0))).length>=o.length/2?`0x${e}`:o}function Gd(t){return t<32||t>=127&&t<160}function Vd(t){if(t.length===0||t.length%2!==0)return new Uint8Array;let e=new Uint8Array(t.length/2);for(let r=0;r=1e14){let o=t/1e18;n=`${rl(o,4)} ${ll}`}else if(t>=1e5){let o=t/1e9;n=`${rl(o,4)} gwei`}else n=`${t} wei`;return n}function An(t){return!t.startsWith("0x")||t.length<14?t:`${t.slice(0,8)}...${t.slice(-6)}`}function Xt(t,e,r=80,n=44,o=60){let i=e[e.length-1],a=i.t-o*1e3;e=e.filter(A=>A.t>=a);let s={top:2,right:2,bottom:2,left:2},u=r-s.left-s.right,c=n-s.top-s.bottom,l=j(t).select("svg");l.empty()&&(l=j(t).append("svg").attr("width",r).attr("height",n),l.append("g").attr("class","line-group").attr("transform",`translate(${s.left},${s.top})`).append("path").attr("class","sparkline-path").attr("fill","none").attr("stroke","#00bff2").attr("stroke-width",1.5),l.append("g").attr("class","y-axis").attr("transform",`translate(${s.left},${s.top})`)),l.attr("width",r).attr("height",n);let f=l.select("g.line-group").select("path.sparkline-path"),m=i.t,d=wn().domain([new Date(a),new Date(m)]).range([0,u]),[y,k]=Me(e,A=>A.v),_=de().domain([y,k]).range([c,0]).nice(),q=We().x(A=>d(new Date(A.t))).y(A=>_(A.v));if(f.datum(e).attr("d",q).attr("transform",null),e.length>1){let A=u/o;f.attr("transform",`translate(${A},0)`),f.transition().duration(300).attr("transform","translate(0,0)")}}function Cr(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r=o)&&(r=o)}return r}function Xe(t,e){let r;if(e===void 0)for(let n of t)n!=null&&(r>n||r===void 0&&n>=n)&&(r=n);else{let n=-1;for(let o of t)(o=e(o,++n,t))!=null&&(r>o||r===void 0&&o>=o)&&(r=o)}return r}function je(t,e){let r=0;if(e===void 0)for(let n of t)(n=+n)&&(r+=n);else{let n=-1;for(let o of t)(o=+e(o,++n,t))&&(r+=o)}return r}function Xd(t){return t.target.depth}function Xo(t,e){return t.sourceLinks.length?t.depth:e-1}function jo(t){return t.targetLinks.length?t.depth:t.sourceLinks.length?Xe(t.sourceLinks,Xd)-1:0}function Ze(t){return function(){return t}}function fl(t,e){return Dn(t.source,e.source)||t.index-e.index}function pl(t,e){return Dn(t.target,e.target)||t.index-e.index}function Dn(t,e){return t.y0-e.y0}function Zo(t){return t.value}function jd(t){return t.index}function Zd(t){return t.nodes}function Jd(t){return t.links}function ml(t,e){let r=t.get(e);if(!r)throw new Error("missing: "+e);return r}function dl({nodes:t}){for(let e of t){let r=e.y0,n=r;for(let o of e.sourceLinks)o.y0=r+o.width/2,r+=o.width;for(let o of e.targetLinks)o.y1=n+o.width/2,n+=o.width}}function Cn(){let t=0,e=0,r=1,n=1,o=24,i=8,a,s=jd,u=Xo,c,l,p=Zd,f=Jd,m=6;function d(){let g={nodes:p.apply(null,arguments),links:f.apply(null,arguments)};return y(g),k(g),_(g),q(g),L(g),dl(g),g}d.update=function(g){return dl(g),g},d.nodeId=function(g){return arguments.length?(s=typeof g=="function"?g:Ze(g),d):s},d.nodeAlign=function(g){return arguments.length?(u=typeof g=="function"?g:Ze(g),d):u},d.nodeSort=function(g){return arguments.length?(c=g,d):c},d.nodeWidth=function(g){return arguments.length?(o=+g,d):o},d.nodePadding=function(g){return arguments.length?(i=a=+g,d):i},d.nodes=function(g){return arguments.length?(p=typeof g=="function"?g:Ze(g),d):p},d.links=function(g){return arguments.length?(f=typeof g=="function"?g:Ze(g),d):f},d.linkSort=function(g){return arguments.length?(l=g,d):l},d.size=function(g){return arguments.length?(t=e=0,r=+g[0],n=+g[1],d):[r-t,n-e]},d.extent=function(g){return arguments.length?(t=+g[0][0],r=+g[1][0],e=+g[0][1],n=+g[1][1],d):[[t,e],[r,n]]},d.iterations=function(g){return arguments.length?(m=+g,d):m};function y({nodes:g,links:x}){for(let[S,v]of g.entries())v.index=S,v.sourceLinks=[],v.targetLinks=[];let M=new Map(g.map((S,v)=>[s(S,v,g),S]));for(let[S,v]of x.entries()){v.index=S;let{source:B,target:G}=v;typeof B!="object"&&(B=v.source=ml(M,B)),typeof G!="object"&&(G=v.target=ml(M,G)),B.sourceLinks.push(v),G.targetLinks.push(v)}if(l!=null)for(let{sourceLinks:S,targetLinks:v}of g)S.sort(l),v.sort(l)}function k({nodes:g}){for(let x of g)x.value=x.fixedValue===void 0?Math.max(je(x.sourceLinks,Zo),je(x.targetLinks,Zo)):x.fixedValue}function _({nodes:g}){let x=g.length,M=new Set(g),S=new Set,v=0;for(;M.size;){for(let B of M){B.depth=v;for(let{target:G}of B.sourceLinks)S.add(G)}if(++v>x)throw new Error("circular link");M=S,S=new Set}}function q({nodes:g}){let x=g.length,M=new Set(g),S=new Set,v=0;for(;M.size;){for(let B of M){B.height=v;for(let{source:G}of B.targetLinks)S.add(G)}if(++v>x)throw new Error("circular link");M=S,S=new Set}}function A({nodes:g}){let x=Cr(g,v=>v.depth)+1,M=(r-t-o)/(x-1),S=new Array(x);for(let v of g){let B=Math.max(0,Math.min(x-1,Math.floor(u.call(null,v,x))));v.layer=B,v.x0=t+B*M,v.x1=v.x0+o,S[B]?S[B].push(v):S[B]=[v]}if(c)for(let v of S)v.sort(c);return S}function D(g){let x=Xe(g,M=>(n-e-(M.length-1)*a)/je(M,Zo));for(let M of g){let S=e;for(let v of M){v.y0=S,v.y1=S+v.value*x,S=v.y1+a;for(let B of v.sourceLinks)B.width=B.value*x}S=(n-S+a)/(M.length+1);for(let v=0;vM.length)-1)),D(x);for(let M=0;M0))continue;let ht=(K/ot-G.y0)*x;G.y0+=ht,G.y1+=ht,h(G)}c===void 0&&B.sort(Dn),H(B,M)}}function N(g,x,M){for(let S=g.length,v=S-2;v>=0;--v){let B=g[v];for(let G of B){let K=0,ot=0;for(let{target:tt,value:Dt}of G.sourceLinks){let gt=Dt*(tt.layer-G.layer);K+=R(G,tt)*gt,ot+=gt}if(!(ot>0))continue;let ht=(K/ot-G.y0)*x;G.y0+=ht,G.y1+=ht,h(G)}c===void 0&&B.sort(Dn),H(B,M)}}function H(g,x){let M=g.length>>1,S=g[M];I(g,S.y0-a,M-1,x),P(g,S.y1+a,M+1,x),I(g,n,g.length-1,x),P(g,e,0,x)}function P(g,x,M,S){for(;M1e-6&&(v.y0+=B,v.y1+=B),x=v.y1+a}}function I(g,x,M,S){for(;M>=0;--M){let v=g[M],B=(v.y1-x)*S;B>1e-6&&(v.y0-=B,v.y1-=B),x=v.y0-a}}function h({sourceLinks:g,targetLinks:x}){if(l===void 0){for(let{source:{sourceLinks:M}}of x)M.sort(pl);for(let{target:{targetLinks:M}}of g)M.sort(fl)}}function T(g){if(l===void 0)for(let{sourceLinks:x,targetLinks:M}of g)x.sort(pl),M.sort(fl)}function E(g,x){let M=g.y0-(g.sourceLinks.length-1)*a/2;for(let{target:S,width:v}of g.sourceLinks){if(S===x)break;M+=v+a}for(let{source:S,width:v}of x.targetLinks){if(S===g)break;M-=v}return M}function R(g,x){let M=x.y0-(x.targetLinks.length-1)*a/2;for(let{source:S,width:v}of x.targetLinks){if(S===g)break;M+=v+a}for(let{target:S,width:v}of g.sourceLinks){if(S===x)break;M-=v}return M}return d}var Jo=Math.PI,Qo=2*Jo,ke=1e-6,Qd=Qo-ke;function Ko(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function hl(){return new Ko}Ko.prototype=hl.prototype={constructor:Ko,moveTo:function(t,e){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)},closePath:function(){this._x1!==null&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,e){this._+="L"+(this._x1=+t)+","+(this._y1=+e)},quadraticCurveTo:function(t,e,r,n){this._+="Q"+ +t+","+ +e+","+(this._x1=+r)+","+(this._y1=+n)},bezierCurveTo:function(t,e,r,n,o,i){this._+="C"+ +t+","+ +e+","+ +r+","+ +n+","+(this._x1=+o)+","+(this._y1=+i)},arcTo:function(t,e,r,n,o){t=+t,e=+e,r=+r,n=+n,o=+o;var i=this._x1,a=this._y1,s=r-t,u=n-e,c=i-t,l=a-e,p=c*c+l*l;if(o<0)throw new Error("negative radius: "+o);if(this._x1===null)this._+="M"+(this._x1=t)+","+(this._y1=e);else if(p>ke)if(!(Math.abs(l*s-u*c)>ke)||!o)this._+="L"+(this._x1=t)+","+(this._y1=e);else{var f=r-i,m=n-a,d=s*s+u*u,y=f*f+m*m,k=Math.sqrt(d),_=Math.sqrt(p),q=o*Math.tan((Jo-Math.acos((d+p-y)/(2*k*_)))/2),A=q/_,D=q/k;Math.abs(A-1)>ke&&(this._+="L"+(t+A*c)+","+(e+A*l)),this._+="A"+o+","+o+",0,0,"+ +(l*f>c*m)+","+(this._x1=t+D*s)+","+(this._y1=e+D*u)}},arc:function(t,e,r,n,o,i){t=+t,e=+e,r=+r,i=!!i;var a=r*Math.cos(n),s=r*Math.sin(n),u=t+a,c=e+s,l=1^i,p=i?n-o:o-n;if(r<0)throw new Error("negative radius: "+r);this._x1===null?this._+="M"+u+","+c:(Math.abs(this._x1-u)>ke||Math.abs(this._y1-c)>ke)&&(this._+="L"+u+","+c),r&&(p<0&&(p=p%Qo+Qo),p>Qd?this._+="A"+r+","+r+",0,1,"+l+","+(t-a)+","+(e-s)+"A"+r+","+r+",0,1,"+l+","+(this._x1=u)+","+(this._y1=c):p>ke&&(this._+="A"+r+","+r+",0,"+ +(p>=Jo)+","+l+","+(this._x1=t+r*Math.cos(o))+","+(this._y1=e+r*Math.sin(o))))},rect:function(t,e,r,n){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +r+"v"+ +n+"h"+-r+"Z"},toString:function(){return this._}};var ti=hl;function ei(t){return function(){return t}}function gl(t){return t[0]}function xl(t){return t[1]}var yl=Array.prototype.slice;function Kd(t){return t.source}function th(t){return t.target}function eh(t){var e=Kd,r=th,n=gl,o=xl,i=null;function a(){var s,u=yl.call(arguments),c=e.apply(this,u),l=r.apply(this,u);if(i||(i=s=ti()),t(i,+n.apply(this,(u[0]=c,u)),+o.apply(this,u),+n.apply(this,(u[0]=l,u)),+o.apply(this,u)),s)return i=null,s+""||null}return a.source=function(s){return arguments.length?(e=s,a):e},a.target=function(s){return arguments.length?(r=s,a):r},a.x=function(s){return arguments.length?(n=typeof s=="function"?s:ei(+s),a):n},a.y=function(s){return arguments.length?(o=typeof s=="function"?s:ei(+s),a):o},a.context=function(s){return arguments.length?(i=s??null,a):i},a}function rh(t,e,r,n,o){t.moveTo(e,r),t.bezierCurveTo(e=(e+n)/2,r,e,o,n,o)}function ri(){return eh(rh)}function nh(t){return[t.source.x1,t.y0]}function oh(t){return[t.target.x0,t.y1]}function ni(){return ri().source(nh).target(oh)}var qn=class{svg;rectG;linkG;nodeG;sankeyGenerator;width=window.innerWidth;height=250;defs;blueColors=["#E1F5FE","#B3E5FC","#81D4FA","#4FC3F7","#29B6F6","#03A9F4","#039BE5","#0288D1","#0277BD","#01579B"];orangeColors=["#FFF5e1","#FFE0B2","#FFCC80","#FFB74D","#FFA726","#FF9800","#FB8C00","#F57C00","#EF6C00","#E65100"];constructor(e){this.svg=j(e).append("svg").attr("width",window.innerWidth).attr("height",this.height).attr("viewBox",[0,0,window.innerWidth,this.height]).style("max-width","100%").style("height","auto"),this.defs=this.svg.append("defs");let r=this.blueColors.slice(5,-1);r=[...r,...r,...r,...r],this.initGradient("blue-flow",r),this.rectG=this.svg.append("g").attr("stroke","#000"),this.linkG=this.svg.append("g").attr("fill","none").style("mix-blend-mode","normal"),this.nodeG=this.svg.append("g"),this.sankeyGenerator=Cn().nodeId(n=>n.name).nodeAlign(jo).nodeWidth(10).nodePadding(30).nodeSort((n,o)=>n.inclusion&&o.inclusion?n.namen.target.inclusion&&o.target.inclusion?n.source.namei/(r.length-1)).attr("stop-color",o=>o),n.append("animate").attr("attributeName","x1").attr("values","0%;200%").attr("dur","12s").attr("repeatCount","indefinite"),n.append("animate").attr("attributeName","x2").attr("values","100%;300%").attr("dur","12s").attr("repeatCount","indefinite")}isRightAligned(e){return!e.inclusion}update(e,r){this.sankeyGenerator.extent([[100,20],[window.innerWidth-100,this.height-25]]);let n=[],o={};this.width=window.innerWidth-56,this.svg.attr("width",this.width).attr("height",this.height).attr("viewBox",[0,0,this.width,this.height]);for(let l of r.links)l.value>0&&(n.push(l),o[l.source]=!0,o[l.target]=!0);let a={nodes:e.filter(l=>o[l.name]).map(l=>({...l})),links:n.map(l=>({...l}))},{nodes:s,links:u}=this.sankeyGenerator(a);this.rectG.selectAll("rect").data(s,l=>l.name).join("rect").attr("x",l=>l.x0).attr("y",l=>l.y0).attr("height",l=>l.y1-l.y0).attr("width",l=>l.x1-l.x0).attr("fill",l=>(l.name==="P2P Network"&&(l.value=r.hashesReceived),l.inclusion?l.name==="Tx Pool"||l.name==="Added To Block"?"#FFA726":"#00BFF2":"#555")),this.linkG.selectAll("path").data(u,l=>l.index).join("path").attr("d",ni()).attr("stroke",l=>l.target.inclusion?"url(#blue-flow)":"#333").attr("stroke-width",l=>Math.max(1,l.width??1));let c=this.nodeG.selectAll("text").data(s,l=>l.name).join(l=>l.append("text").attr("data-last","0"),l=>l,l=>l.remove());c.attr("data-last",function(l){return j(this).attr("data-current")||"0"}).attr("data-current",l=>(l.targetLinks||[]).reduce((f,m)=>f+(m.value||0),0)||l.value||0).attr("x",l=>this.isRightAligned(l)?l.x1+6:l.x0-6).attr("y",l=>(l.y0+l.y1)/2).attr("dy","-0.5em").attr("text-anchor",l=>this.isRightAligned(l)?"start":"end").text(l=>l.name).each(function(){j(this).selectAll("tspan.number").data([0]).join("tspan").attr("class","number").attr("x",()=>{let l=j(this).datum();return l&&l.inclusion?l.x1+6:l.x0-6}).attr("dy","1em")}),c.selectAll("tspan.number").transition().duration(500).tween("text",function(){let l=j(this),p=j(this.parentNode),f=p.empty()?0:parseFloat(p.attr("data-last")||"0"),m=p.empty()?0:parseFloat(p.attr("data-current")||"0"),d=Z(f,m);return function(y){l.text(bt(",.0f")(d(y)))}})}};function vl(t,e,r,n,o,i,a,s){let u=window.innerWidth-56,l={name:"root",children:[...n.map(h=>({name:o(h),item:h,size:a(h)}))]},p=Re(l).sum(h=>h.children?0:a(h.data?h.data.item:h.item)).sort(h=>h.children?0:i(h.data?h.data.item:h.item)),f=p.value??0,m=f>0?f/r:0,d=Math.min(u,u*m);_o().size([d,e-1]).round(!0).tile(vr.ratio(1)).paddingOuter(.5).paddingInner(2)(p);let[y,k]=Me(n,s),_=y&&y>0?y:1e-6,q=k||1,A=kn(Fo).domain([_,q]);function D(h){let T=s(h),E=T>0?T:1e-6;return A(E)}let L=j(t).select("svg");if(L.empty()){L=j(t).append("svg").attr("width",u).attr("height",e).attr("viewBox",[0,0,u,e]);let h=L.append("defs"),T=h.append("pattern").attr("id","unusedStripes").attr("patternUnits","userSpaceOnUse").attr("width",8).attr("height",8);T.append("rect").attr("class","pattern-bg").attr("width",8).attr("height",8).attr("fill","#444"),T.append("path").attr("d","M0,0 l8,8").attr("stroke","#000").attr("stroke-width",1),L.append("rect").attr("class","unused").attr("fill","url(#unusedStripes)").attr("opacity",1).attr("width",u).attr("height",e).attr("stroke","#fff").attr("stroke-width",1),h.append("marker").attr("id","arrowStart").attr("markerWidth",10).attr("markerHeight",10).attr("refX",5).attr("refY",5).attr("orient","auto").attr("markerUnits","strokeWidth").append("path").attr("d","M10,0 L0,5 L10,10").attr("fill","#ccc"),h.append("marker").attr("id","arrowEnd").attr("markerWidth",10).attr("markerHeight",10).attr("refX",5).attr("refY",5).attr("orient","auto").attr("markerUnits","strokeWidth").append("path").attr("d","M0,0 L10,5 L0,10").attr("fill","#ccc")}L.attr("width",u).attr("height",e).attr("viewBox",[0,0,u,e]),L.selectAll("rect.unused").attr("width",u);let b=p.leaves();L.selectAll("g.node").data(b,h=>h.data.name).join(h=>{let T=h.append("g").attr("class","node").attr("data-hash",E=>E.data.name).attr("transform",E=>`translate(${E.x0},${E.y0})`).attr("opacity",0);return T.append("rect").attr("stroke","#000").attr("stroke-width",.5).attr("width",0).attr("height",0).attr("fill",E=>D(E.data.item)),T.transition().duration(600).attr("opacity",1),T.select("rect").transition().duration(600).attr("width",E=>E.x1-E.x0).attr("height",E=>E.y1-E.y0),T},h=>(h.transition().duration(600).attr("transform",T=>`translate(${T.x0},${T.y0})`).attr("opacity",1),h.select("rect").transition().duration(600).attr("width",T=>T.x1-T.x0).attr("height",T=>T.y1-T.y0).attr("fill",T=>D(T.data.item)),h),h=>{h.transition().duration(600).attr("opacity",0).remove()});let H=(r-f)/r,I=H>=.1?[{key:"unused-label",x:d,w:u-d,ratio:H}]:[];L.selectAll("line.unused-arrow").data(I,h=>h.key).join(h=>h.append("line").attr("class","unused-arrow").attr("x1",T=>T.x+10).attr("x2",T=>T.x+T.w-10).attr("y1",145).attr("y2",145).attr("stroke","#ccc").attr("stroke-width",2).attr("marker-start","url(#arrowStart)").attr("marker-end","url(#arrowEnd)").attr("opacity",0).call(T=>T.transition().duration(600).attr("opacity",1)),h=>h.transition().duration(600).attr("x1",T=>T.x+10).attr("x2",T=>T.x+T.w-10),h=>h.transition().duration(600).attr("opacity",0).remove()),L.selectAll("text.unused-label").data(I,h=>h.key).join(h=>h.append("text").attr("class","unused-label").attr("x",T=>T.x+T.w/2).attr("y",135).attr("fill","#ccc").attr("font-size",14).attr("text-anchor","middle").attr("opacity",0).text(T=>`${(T.ratio*100).toFixed(1)}% available`).call(T=>T.transition().duration(600).attr("opacity",1)),h=>h.transition().duration(600).attr("x",T=>T.x+T.w/2).text(T=>`${(T.ratio*100).toFixed(1)}% available`),h=>h.transition().duration(600).attr("opacity",0).remove())}function bl(t,e,r=36){let n={top:4,right:4,bottom:20,left:20},o=t.getBoundingClientRect().width,i=100,a=j(t).append("svg").style("display","block").style("background","black").attr("width",o).attr("height",i),s=a.append("g").attr("transform",`translate(${n.left},${n.top})`);function u(){return o-n.left-n.right}let c=i-n.top-n.bottom,l=[],p,f=br().domain(Ae(r)).range([0,u()]).paddingInner(.3).paddingOuter(.1),m=de().range([c,0]);function d(){return xr().duration(750)}function y(A){if(!A.length)return{min:0,q1:0,median:0,q3:0,max:0,whiskerLow:0,whiskerHigh:0};let D=A.slice().sort(ft),L=D[0],b=D[D.length-1],N=Ee(D,.25),H=Ee(D,.5),P=Ee(D,.75),I=P-N,h=Math.max(L,N-1.5*I),T=Math.min(b,P+1.5*I);return{min:L,q1:N,median:H,q3:P,max:b,whiskerLow:h,whiskerHigh:T}}function k(A,D){let L=A.map(e).filter(x=>Number.isFinite(x)&&x>=0),b=y(L);if(l.length{x.xIndex-=1});l.length&&l[0].xIndex<0;){let x=l.shift();x&&(p=x.stats.median)}l.push({xIndex:r-1,blockNumber:D,stats:b,values:L})}let N=ee(l,x=>x.stats.whiskerHigh)||1;m.domain([0,N]);let H=s.selectAll(".box-group").data(l,x=>x.xIndex);H.exit().transition(d()).attr("transform",x=>`translate(${f(x.xIndex)||0},${c}) scale(0.001,0.001)`).remove();let P=H.enter().append("g").attr("class","box-group").attr("stroke-width",1).attr("transform",x=>`translate(${f(x.xIndex)||0}, ${c}) scale(0.001,0.001)`);P.append("line").attr("class","whisker-line").attr("stroke","#aaa"),P.append("rect").attr("class","box-rect").attr("stroke","white").attr("fill","gray"),P.append("line").attr("class","median-line").attr("stroke","#ccc").attr("stroke-width",1),P.append("line").attr("class","whisker-cap lower").attr("stroke","#aaa"),P.append("line").attr("class","whisker-cap upper").attr("stroke","#aaa"),P.append("g").attr("class","points-group"),H=P.merge(H),H.transition(d()).attr("transform",x=>`translate(${f(x.xIndex)||0},0) scale(1,1)`),H.each(function(x){let M=j(this),S=x.stats,v=f.bandwidth(),B,G=l.find(ot=>ot.xIndex===x.xIndex-1);G?B=G.stats.median:x.xIndex===0&&p!==void 0&&(B=p);let K="gray";B!==void 0&&(S.median>B?K="rgb(127, 63, 63)":S.median{x.selectAll("text").attr("fill","white"),x.selectAll("line,path").attr("stroke","white")});let h=Fr(f).tickFormat(x=>{let M=l.find(S=>S.xIndex===x);return M?String(M.blockNumber):""}),T=s.append("g").attr("class","x-axis").attr("transform",`translate(0,${c})`).call(h),E=f.bandwidth();E<25&&T.selectAll(".tick").each(function(x,M){M/2%2!==0&&j(this).remove()}),T.call(x=>{x.selectAll("text").attr("fill","white"),x.selectAll("line,path").attr("stroke","white")}),s.selectAll(".median-trend").remove();let R=l.filter(x=>x.xIndex>=0).sort((x,M)=>x.xIndex-M.xIndex),g=We().x(x=>(f(x.xIndex)??0)+E/2).y(x=>m(x.stats.median)).curve(En);s.append("path").attr("class","median-trend").datum(R).attr("fill","none").attr("stroke","#FFA726").attr("stroke-width",2).transition(d()).attr("d",g)}function _(){o=t.getBoundingClientRect().width,a.attr("width",o),f.range([0,u()]),q()}function q(){s.selectAll(".box-group").transition().duration(0).attr("transform",I=>`translate(${f(I.xIndex)||0},0)`),s.selectAll(".y-axis").remove(),s.selectAll(".x-axis").remove();let A=Or(m).ticks(3);s.append("g").attr("class","y-axis").call(A).call(I=>{I.selectAll("text").attr("fill","white"),I.selectAll("line,path").attr("stroke","white")});let D=Fr(f).tickFormat(I=>{let h=l.find(T=>T.xIndex===I);return h?String(h.blockNumber):""}),L=s.append("g").attr("class","x-axis").attr("transform",`translate(0,${c})`).call(D);f.bandwidth()<25&&L.selectAll(".tick").each(function(I,h){h%2!==0&&j(this).remove()}),L.call(I=>{I.selectAll("text").attr("fill","white"),I.selectAll("line,path").attr("stroke","white")}),s.selectAll(".median-trend").remove();let N=l.filter(I=>I.xIndex>=0).sort((I,h)=>I.xIndex-h.xIndex),H=f.bandwidth(),P=We().x(I=>(f(I.xIndex)??0)+H/2).y(I=>m(I.stats.median)).curve(En);s.append("path").attr("class","median-trend").datum(N).attr("fill","none").attr("stroke","#FFA726").attr("stroke-width",2).attr("d",P)}return{update:k,resize:_}}var qr=100,ih=120,ah=qr+ih,sh=qr,wl=qr/2,uh=j("#pie-chart").append("svg").attr("width",ah).attr("height",sh).attr("overflow","visible"),kl=uh.append("g").attr("transform",`translate(${qr/2}, ${qr/2})`),lh=me().range(Ho),ch=Uo().sort(null).value(t=>t.count),oi=$o().innerRadius(0).outerRadius(wl),fh=kl.append("g").attr("class","slice-layer"),ph=kl.append("g").attr("class","label-layer");function _l(t){let e=ch(t),r=e.map(m=>{let[d,y]=oi.centroid(m);return{...m,centroidY:y}}),n=r.slice().sort((m,d)=>m.centroidY-d.centroidY),o=18,i=-((n.length-1)*o)/2,a=wl+20,s={};n.forEach((m,d)=>{s[m.data.type]={x:a,y:i+d*o}});let u=fh.selectAll("path").data(e,m=>m.data.type);u.exit().remove(),u.enter().append("path").attr("stroke","#222").style("stroke-width","1px").attr("fill",m=>lh(m.data.type)).each(function(m){this._current=m}).merge(u).transition().duration(750).attrTween("d",function(m){let d=vt(this._current,m);return this._current=d(0),y=>oi(d(y))});let l=ph.selectAll("g.label").data(r,m=>m.data.type);l.exit().remove();let p=l.enter().append("g").attr("class","label").style("pointer-events","none");p.append("polyline").attr("fill","none").attr("stroke","#fff"),p.append("text").style("alignment-baseline","middle").style("text-anchor","start").style("fill","#fff");let f=p.merge(l);f.select("polyline").transition().duration(750).attr("points",m=>{let[d,y]=oi.centroid(m),{x:k,y:_}=s[m.data.type],q=k*.6;return`${d},${y} ${q},${_} ${k},${_}`}),f.select("text").transition().duration(750).attr("transform",m=>{let d=s[m.data.type];return`translate(${d.x},${d.y})`}).tween("label",function(m){return()=>{this.textContent=`${m.data.type} (${m.data.count})`}})}function Tl(t){switch(t){case 0:return"Legacy";case 1:return"AccessList";case 2:return"Eip1559";case 3:return"Blob";case 4:return"SetCode";case 5:return"TxCreate";default:return"Unknown"}}function ii(t){switch(t){case"0x095ea7b3":return"approve";case"0xa9059cbb":return"transfer";case"0x23b872dd":return"transferFrom";case"0xd0e30db0":return"deposit";case"0xe8e33700":case"0xf305d719":return"addLiquidity";case"0xbaa2abde":case"0x02751cec":case"0xaf2979eb":case"0xded9382a":case"0x5b0d5984":case"0x2195995c":return"removeLiquidity";case"0xfb3bdb41":case"0x7ff36ab5":case"0xb6f9de95":case"0x18cbafe5":case"0x791ac947":case"0x38ed1739":case"0x5c11d795":case"0x4a25d94a":case"0x5f575529":case"0x6b68764c":case"0x845a101f":case"0x8803dbee":return"swap";case"0x24856bc3":case"0x3593564c":return"dex";case"0x":return"ETH transfer";default:return t}}function Ml(t){switch(t){case"0xdac17f958d2ee523a2206206994597c13d831ec7":return"usdt";case"0x4ecaba5870353805a9f068101a40e0f32ed605c6":return"usdt";case"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48":return"usdc";case"0xddafbb505ad214d7b80b1f830fccc89b60fb7a83":return"usdc";case"0x6b175474e89094c44da98b954eedeac495271d0f":return"dai";case"0x44fa8e6f47987339850636f88629646662444217":return"dai";case"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2":return"weth";case"0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1":return"weth";case"0x7a250d5630b4cf539739df2c5dacb4c659f2488d":return"uniswap v2";case"0x66a9893cc07d91d95644aedd05d03f95e1dba8af":return"uniswap v4";case"0x2f848984984d6c3c036174ce627703edaf780479":return"xen minter";case"0x0a252663dbcc0b073063d6420a40319e438cfa59":return"xen";case"0x881d40237659c251811cec9c364ef91dc08d300c":return"metamask";default:return t}}var Wh=tc(),Pn=class{nodeLog;ansiConvert=new Wh;logs=[];constructor(e){this.nodeLog=document.getElementById(e)}receivedLog(e){let r=JSON.parse(e.data);for(let n of r){let o=this.ansiConvert.toHtml(n);this.logs.length>=100&&this.logs.shift(),this.logs.push(o)}}appendLogs(){if(this.logs.length>0){let e=!1;(this.nodeLog.scrollHeight<500||this.nodeLog.scrollTop250;)this.nodeLog.firstChild.remove(),n--;e&&window.setTimeout(()=>this.scrollLogs(),17)}}resize(){let e=document.body.getBoundingClientRect();var n=this.nodeLog.getBoundingClientRect().top-e.top,o=window.innerHeight-n-16;o>0&&(this.nodeLog.style.height=`${o}px`)}scrollLogs(){this.nodeLog.scrollTop=this.nodeLog.scrollHeight}};function $(t,e){t.innerText!==e&&(t.innerText=e)}var $n=class{lastGasLimit=36e6;minGas;medianGas;aveGas;maxGas;gasLimit;gasLimitDelta;constructor(e,r,n,o,i,a){this.minGas=document.getElementById(e),this.medianGas=document.getElementById(r),this.aveGas=document.getElementById(n),this.maxGas=document.getElementById(o),this.gasLimit=document.getElementById(i),this.gasLimitDelta=document.getElementById(a)}parseEvent(e){if(document.hidden)return;let r=JSON.parse(e.data);$(this.minGas,r.minGas.toFixed(2)),$(this.medianGas,r.medianGas.toFixed(2)),$(this.aveGas,r.aveGas.toFixed(2)),$(this.maxGas,r.maxGas.toFixed(2)),$(this.gasLimit,dt(r.gasLimit)),$(this.gasLimitDelta,r.gasLimit>this.lastGasLimit?"\u{1F446}":r.gasLimitparseInt(t.effectiveGasPrice,16)/1e9,36);function dc(t,e){do if(!(t.matches===void 0||!t.matches(e)))return t;while(t=t.parentElement);return null}function kg(t,e,r,n,o){t.addEventListener(e,function(i){try{let a=dc(i.target,r);a!==null&&n.apply(a,arguments)}catch{}},o)}var ec=[],rc=[],nc=[],oc=[],ic=[],ac=[],sc=[],pi=0,mi=0,di=0,hi=0,gi=0,Un=0;function Te(t,e){t.push(e),t.length>60&&t.shift()}var _g=new qn("#txPoolFlow"),bi=null,uc=!1;function Tg(t){if(!uc){if(t.pooledTx==0){document.getElementById("txPoolFlow").classList.add("not-active");return}setTimeout(Ti,10),document.getElementById("txPoolFlow").classList.remove("not-active"),uc=!0}let e=performance.now(),r=e/1e3,n=r-Un,o=0,i=0,a=0,s=0;for(let c of t.links)c.target==="Received Txs"&&(o+=c.value),c.target==="Tx Pool"&&(i+=c.value),c.target==="Added To Block"&&(a+=c.value),c.target==="Duplicate"&&(s+=c.value);let u=t.hashesReceived;if(Un!==0&&(Te(ec,{t:e,v:u-gi}),Te(rc,{t:e,v:o-pi}),Te(ic,{t:e,v:s-hi}),Te(nc,{t:e,v:i-mi}),Te(oc,{t:e,v:a-di})),!document.hidden){if(!bi)return;_g.update(bi,t),$(Xh,dt(t.pooledTx)),$(jh,dt(t.pooledBlobTx)),$(Zh,dt(t.pooledTx+t.pooledBlobTx)),Un!==0&&(Xt(document.getElementById("sparkHashesTps"),ec),Xt(document.getElementById("sparkReceivedTps"),rc),Xt(document.getElementById("sparkDuplicateTps"),ic),Xt(document.getElementById("sparkTxPoolTps"),nc),Xt(document.getElementById("sparkBlockTps"),oc),$(Jh,Wt((a-di)/n)),$(Qh,Wt((o-pi)/n)),$(Kh,Wt((i-mi)/n)),$(tg,Wt((s-hi)/n)),$(eg,Wt((u-gi)/n)))}Un=r,pi=o,mi=i,di=a,hi=s,gi=u}var _i=new Pn("nodeLog"),Mg=new $n("minGas","medianGas","aveGas","maxGas","gasLimit","gasLimitDelta"),Jt=new EventSource("data/events");Jt.addEventListener("log",t=>_i.receivedLog(t));Jt.addEventListener("processed",t=>Mg.parseEvent(t));Jt.addEventListener("nodeData",t=>{let e=JSON.parse(t.data),r=al(e.network),n=`Nethermind [${r}]${e.instance?" - "+e.instance:""}`;document.title!=n&&(document.title=n),$(rg,e.version),$(ng,r),document.getElementById("network-logo").src=`logos/${sl(e.network)}`,$(pc,Wo(e.uptime)),cl(e.gasToken)});Jt.addEventListener("txNodes",t=>{bi=JSON.parse(t.data)});Jt.addEventListener("txLinks",t=>{if(document.hidden)return;let e=JSON.parse(t.data);Tg(e)});var wi=0,hc=0,lc=!1;Jt.addEventListener("forkChoice",t=>{let e=performance.now();if(hc=e-wi,wi=e,document.hidden)return;let r=JSON.parse(t.data),n=parseInt(r.head.number,16);!lc&&n!==0&&(lc=!0,document.getElementById("latestBlock").classList.remove("not-active"),setTimeout(Ti,10));let o=parseInt(r.safe,16),i=parseInt(r.finalized,16);$(og,n.toFixed(0)),$(ig,o.toFixed(0)),$(ag,i.toFixed(0)),$(sg,`(${(o-n).toFixed(0)})`),$(ug,`(${(i-n).toFixed(0)})`);let a=r.head;if(a.tx.length===0)return;let s=a.tx.map((u,c)=>{let l=a.receipts[c];return{block:a.number,order:c,...u,...l}});$(hg,il(a.extraData)),$(gg,dt(parseInt(a.gasUsed,16))),$(xg,dt(parseInt(a.gasLimit,16))),$(yg,ol(parseInt(a.size,16))),$(vg,nl(parseInt(a.timestamp,16))),$(bg,dt(a.tx.length)),$(wg,dt(a.tx.reduce((u,c)=>u+c.blobs,0))),vl(document.getElementById("block"),160,parseInt(r.head.gasLimit,16),s,u=>u.hash,u=>u.order,u=>parseInt(u.gasUsed,16),u=>parseInt(u.effectiveGasPrice,16)*parseInt(u.gasUsed,16)),mc.update(s,n),_t.push(...s),ki=_t.length,_t.length>25e4&&_t.slice(_t.length-25e3),gc=Lg(s)});var gc,Sg="";kg(document.getElementById("block"),"pointermove","g.node",t=>{let r=dc(t.target,"g.node").dataset.hash,n=gc[r];if(!n)return;let o=document.getElementById("txDetails");return Sg!==r&&(o.innerHTML=`

Transaction ${An(n.hash)}

diff --git a/src/Nethermind/Nethermind.UI/scripts/app.ts b/src/Nethermind/Nethermind.UI/scripts/app.ts index 0de9516d3c4..e1f9605b621 100644 --- a/src/Nethermind/Nethermind.UI/scripts/app.ts +++ b/src/Nethermind/Nethermind.UI/scripts/app.ts @@ -202,7 +202,7 @@ function updateTxPool(txPool: TxPool) { const logWindow = new LogWindow("nodeLog"); const gasInfo = new GasInfo("minGas", "medianGas", "aveGas", "maxGas", "gasLimit", "gasLimitDelta"); -const sse = new EventSource("/data/events"); +const sse = new EventSource("data/events"); sse.addEventListener("log", (e) => logWindow.receivedLog(e)); sse.addEventListener("processed", (e) => gasInfo.parseEvent(e)); From a84d40a2dac12e981b6771411a82cd6b8470491c Mon Sep 17 00:00:00 2001 From: Desant pivo Date: Tue, 23 Dec 2025 16:03:30 +0100 Subject: [PATCH 123/255] fix: use IHttpClient from DI in MergePlugin instead of creating HttpClient directly (#9995) * Update MergePlugin.cs * Update DefaultHttpClient.cs * Update src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update MergePlugin.cs * Update DefaultHttpClient.cs --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Nethermind.Facade/Proxy/DefaultHttpClient.cs | 9 +++++++-- src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs | 6 ++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Nethermind/Nethermind.Facade/Proxy/DefaultHttpClient.cs b/src/Nethermind/Nethermind.Facade/Proxy/DefaultHttpClient.cs index 53765e36759..0f9e168c9f8 100644 --- a/src/Nethermind/Nethermind.Facade/Proxy/DefaultHttpClient.cs +++ b/src/Nethermind/Nethermind.Facade/Proxy/DefaultHttpClient.cs @@ -12,7 +12,7 @@ namespace Nethermind.Facade.Proxy { - public class DefaultHttpClient : IHttpClient + public class DefaultHttpClient : IHttpClient, IDisposable { private readonly HttpClient _client; private readonly IJsonSerializer _jsonSerializer; @@ -25,7 +25,7 @@ public DefaultHttpClient( IJsonSerializer jsonSerializer, ILogManager logManager, int retries = 3, - int retryDelayMilliseconds = 1000) + int retryDelayMilliseconds = 100) { _client = client ?? throw new ArgumentNullException(nameof(client)); _jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer)); @@ -110,5 +110,10 @@ private enum Method Get, Post } + + public void Dispose() + { + _client?.Dispose(); + } } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs index 73a85cae16e..a6a37aa8e2a 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs @@ -342,6 +342,7 @@ protected override void Load(ContainerBuilder builder) : NoGCStrategy.Instance, ctx.Resolve()); }) + .AddSingleton() ; } @@ -357,11 +358,8 @@ IBlockImprovementContextFactory CreateBlockImprovementContextFactory(IComponentC return new BlockImprovementContextFactory(blockProducer!, TimeSpan.FromSeconds(maxSingleImprovementTimePerSlot)); } - ILogManager logManager = ctx.Resolve(); IStateReader stateReader = ctx.Resolve(); - IJsonSerializer jsonSerializer = ctx.Resolve(); - - DefaultHttpClient httpClient = new(new HttpClient(), jsonSerializer, logManager, retryDelayMilliseconds: 100); + IHttpClient httpClient = ctx.Resolve(); IBoostRelay boostRelay = new BoostRelay(httpClient, mergeConfig.BuilderRelayUrl); return new BoostBlockImprovementContextFactory(blockProducer!, TimeSpan.FromSeconds(maxSingleImprovementTimePerSlot), boostRelay, stateReader); } From 40329f84008968639741dc5a0c358e421ae1dc4c Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Tue, 23 Dec 2025 21:06:27 +0300 Subject: [PATCH 124/255] Validate blobs lengths (#9999) --- .../TransactionSelectorTests.cs | 12 +++---- .../Validators/TxValidatorTests.cs | 14 +++++++++ .../Producers/TxPoolTxSource.cs | 31 +++++++++++++------ .../Validators/TxValidator.cs | 6 ++-- 4 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs index 357f86fe67c..2866322ce40 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs @@ -25,7 +25,6 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Test; using Nethermind.Crypto; -using Nethermind.State; namespace Nethermind.Blockchain.Test { @@ -164,6 +163,7 @@ public static IEnumerable EnoughShardBlobTransactionsSelectedTestCases }); maxTransactionsSelected.Transactions[1].BlobVersionedHashes = new byte[maxTransactionsSelected.ReleaseSpec.MaxBlobCount - 1][]; + maxTransactionsSelected.Transactions[1].NetworkWrapper = new ShardBlobNetworkWrapper(new byte[5][], new byte[5][], new byte[5][], ProofVersion.V0); maxTransactionsSelected.ExpectedSelectedTransactions.AddRange( maxTransactionsSelected.Transactions.OrderBy(static t => t.Nonce).Take(2)); yield return new TestCaseData(maxTransactionsSelected).SetName("Enough transactions selected"); @@ -173,19 +173,17 @@ public static IEnumerable EnoughShardBlobTransactionsSelectedTestCases enoughTransactionsSelected.ReleaseSpec = Cancun.Instance; enoughTransactionsSelected.BaseFee = 1; + ulong maxBlobCount = enoughTransactionsSelected.ReleaseSpec.MaxBlobCount; Transaction[] expectedSelectedTransactions = enoughTransactionsSelected.Transactions.OrderBy(static t => t.Nonce).ToArray(); expectedSelectedTransactions[0].Type = TxType.Blob; - expectedSelectedTransactions[0].BlobVersionedHashes = - new byte[enoughTransactionsSelected.ReleaseSpec.MaxBlobCount][]; + expectedSelectedTransactions[0].BlobVersionedHashes = new byte[maxBlobCount][]; + expectedSelectedTransactions[0].NetworkWrapper = new ShardBlobNetworkWrapper(new byte[maxBlobCount][], new byte[maxBlobCount][], new byte[maxBlobCount][], ProofVersion.V0); expectedSelectedTransactions[0].MaxFeePerBlobGas = 1; - expectedSelectedTransactions[0].NetworkWrapper = - new ShardBlobNetworkWrapper(new byte[1][], new byte[1][], new byte[1][], ProofVersion.V0); expectedSelectedTransactions[1].Type = TxType.Blob; expectedSelectedTransactions[1].BlobVersionedHashes = new byte[1][]; + expectedSelectedTransactions[1].NetworkWrapper = new ShardBlobNetworkWrapper(new byte[1][], new byte[1][], new byte[1][], ProofVersion.V0); expectedSelectedTransactions[1].MaxFeePerBlobGas = 1; - expectedSelectedTransactions[1].NetworkWrapper = - new ShardBlobNetworkWrapper(new byte[1][], new byte[1][], new byte[1][], ProofVersion.V0); enoughTransactionsSelected.ExpectedSelectedTransactions.AddRange( expectedSelectedTransactions.Where(static (_, index) => index != 1)); yield return new TestCaseData(enoughTransactionsSelected).SetName( diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs index 9cb84ee9ce4..8dcb6a44720 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs @@ -851,6 +851,20 @@ static TransactionBuilder MakeTestObject(int blobCount = 1) => Buil TestName = "Proofs count does not match hashes count", ExpectedResult = false }; + yield return new TestCaseData(Cancun.Instance, MakeTestObject() + .With(static tx => tx.NetworkWrapper = ((ShardBlobNetworkWrapper)tx.NetworkWrapper!) with { Blobs = [], Commitments = [], Proofs = [] }) + .SignedAndResolved().TestObject) + { + TestName = "Blobs count does not match network wrapper items counts, empty blobs", + ExpectedResult = false + }; + yield return new TestCaseData(Cancun.Instance, MakeTestObject(2) + .With(static tx => tx.BlobVersionedHashes = [.. tx.BlobVersionedHashes!.Take(1)]) + .SignedAndResolved().TestObject) + { + TestName = "Blobs count does not match network wrapper items counts, less hashes", + ExpectedResult = false + }; yield return new TestCaseData(Cancun.Instance, MakeTestObject() .With(static tx => ((ShardBlobNetworkWrapper)tx.NetworkWrapper!).Commitments[0][1] ^= 0xFF) .SignedAndResolved().TestObject) diff --git a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs index f664421c82d..3faeb58aef4 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs @@ -105,20 +105,31 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi bool ResolveBlob(Transaction blobTx, out Transaction fullBlobTx) { - if (TryGetFullBlobTx(blobTx, out fullBlobTx)) + if (!TryGetFullBlobTx(blobTx, out fullBlobTx)) { - ProofVersion? proofVersion = (fullBlobTx.NetworkWrapper as ShardBlobNetworkWrapper)?.Version; - if (spec.BlobProofVersion != proofVersion) - { - if (_logger.IsTrace) _logger.Trace($"Declining {blobTx.ToShortString()}, {spec.BlobProofVersion} is wanted, but tx's proof version is {proofVersion}."); - return false; - } + if (_logger.IsTrace) _logger.Trace($"Declining {blobTx.ToShortString()}, failed to get full version of this blob tx from TxPool."); + return false; + } - return true; + if (fullBlobTx.NetworkWrapper is not ShardBlobNetworkWrapper wrapper) + { + if (_logger.IsTrace) _logger.Trace($"Declining {blobTx.ToShortString()}, missing blob data."); + return false; } - if (_logger.IsTrace) _logger.Trace($"Declining {blobTx.ToShortString()}, failed to get full version of this blob tx from TxPool."); - return false; + if (spec.BlobProofVersion != wrapper.Version) + { + if (_logger.IsTrace) _logger.Trace($"Declining {blobTx.ToShortString()}, {spec.BlobProofVersion} is wanted, but tx's proof version is {wrapper.Version}."); + return false; + } + + if (wrapper.Blobs.Length != blobTx.BlobVersionedHashes.Length) + { + if (_logger.IsTrace) _logger.Trace($"Declining {blobTx.ToShortString()}, incorrect blob count."); + return false; + } + + return true; } } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs index bec7ae4e8d2..14467894203 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs @@ -281,15 +281,15 @@ public ValidationResult IsWellFormed(Transaction transaction, IReleaseSpec relea return transaction switch { { NetworkWrapper: null } => ValidationResult.Success, - { Type: TxType.Blob, NetworkWrapper: ShardBlobNetworkWrapper wrapper } => ValidateBlobs(transaction, wrapper, releaseSpec), + { Type: TxType.Blob, NetworkWrapper: ShardBlobNetworkWrapper wrapper } => ValidateBlobs(transaction, wrapper), { Type: TxType.Blob } or { NetworkWrapper: not null } => TxErrorMessages.InvalidTransactionForm, }; - static ValidationResult ValidateBlobs(Transaction transaction, ShardBlobNetworkWrapper wrapper, IReleaseSpec _) + static ValidationResult ValidateBlobs(Transaction transaction, ShardBlobNetworkWrapper wrapper) { IBlobProofsVerifier proofsManager = IBlobProofsManager.For(wrapper.Version); - return !proofsManager.ValidateLengths(wrapper) ? TxErrorMessages.InvalidBlobDataSize : + return (transaction.BlobVersionedHashes?.Length ?? 0) != wrapper.Blobs.Length || !proofsManager.ValidateLengths(wrapper) ? TxErrorMessages.InvalidBlobDataSize : transaction.BlobVersionedHashes is null || !proofsManager.ValidateHashes(wrapper, transaction.BlobVersionedHashes) ? TxErrorMessages.InvalidBlobHashes : !proofsManager.ValidateProofs(wrapper) ? TxErrorMessages.InvalidBlobProofs : ValidationResult.Success; From e2d0072e21b71954ff1dba3dac15861ced56fee0 Mon Sep 17 00:00:00 2001 From: kurahin Date: Tue, 23 Dec 2025 20:08:28 +0200 Subject: [PATCH 125/255] refactor(AuRa): remove redundant Create override (#10014) --- .../AuRaPostMergeBlockProducerFactory.cs | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/src/Nethermind/Nethermind.Merge.AuRa/AuRaPostMergeBlockProducerFactory.cs b/src/Nethermind/Nethermind.Merge.AuRa/AuRaPostMergeBlockProducerFactory.cs index 7e7d16409bc..32dbe8ed998 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/AuRaPostMergeBlockProducerFactory.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/AuRaPostMergeBlockProducerFactory.cs @@ -29,25 +29,5 @@ public AuRaPostMergeBlockProducerFactory( gasLimitCalculator) { } - - public override PostMergeBlockProducer Create( - IBlockProducerEnv producerEnv, - ITxSource? txSource = null) - { - TargetAdjustedGasLimitCalculator targetAdjustedGasLimitCalculator = - new(_specProvider, _blocksConfig); - - return new PostMergeBlockProducer( - txSource ?? producerEnv.TxSource, - producerEnv.ChainProcessor, - producerEnv.BlockTree, - producerEnv.ReadOnlyStateProvider, - _gasLimitCalculator ?? targetAdjustedGasLimitCalculator, - _sealEngine, - _timestamper, - _specProvider, - _logManager, - _blocksConfig); - } } } From e62a72f45c88ed9dad529e307bf008565dfa86b8 Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Wed, 24 Dec 2025 07:29:08 +0800 Subject: [PATCH 126/255] Feature/Worldstate backend (#9089) * WorldState backend Fix check failure Add small test Whitespace Different setter Slight cleanup Whitespace Rename to scope provider Add code to `IWorldStateScopeProvider`. (#9291) * Add codedb * Add test * Whitespace * use span on set Fix TestworldStateFactory build Rename to update state root Refactor/Nicer IWorldStateScopeProvider interface (#9375) * Reduce interfacae surface area * Fix build * Fix random * Fix randomly failing pyspec test * Whitespace Refactor/Slight cleanup to world state write batch API. (#9400) Remove on account updated callback Fix build Feature/add back `OnAccountUpdated` (#9436) * Add back on account updated * Hint get * Update src/Nethermind/Nethermind.Evm/State/IWorldStateScopeProvider.cs Co-authored-by: Lukasz Rozmej * Fix build --------- Co-authored-by: Lukasz Rozmej Feature/worldstate scope provider manager (#9306) * World state manager to return scope provider * Fix build * Fix build Fix selfdestruct Fix selfdestruct not called in some case Fix build Whitespace Fix build Slight per on small contract * Fix build * Whitespace * Update src/Nethermind/Nethermind.State/TrieStoreScopeProvider.cs Co-authored-by: Marc * Address comment * Make test more consistent * Extra comment * Fix precompile cache config * Remove missed comment * Address comment --------- Co-authored-by: Marc --- .../Store/WorldStateBenchmarks.cs | 3 +- ...lockProducerBaseTests.IsProducingBlocks.cs | 11 +- .../TransactionsExecutorTests.cs | 2 +- .../CliqueBlockProducerTests.cs | 6 +- .../StartBlockProducerAuRa.cs | 5 +- .../AutoReadOnlyTxProcessingEnvFactory.cs | 17 +- .../Processing/BlockCachePreWarmer.cs | 34 +- .../IReadOnlyTxProcessingEnvFactory.cs | 2 - .../Processing/PrewarmerEnvFactory.cs | 31 ++ .../Producers/BlockProducerEnvFactory.cs | 2 +- .../Stateless/StatelessBlockProcessingEnv.cs | 4 +- .../Blockchain/TestBlockchain.cs | 1 + .../Container/ContainerBuilderExtensions.cs | 10 + .../TestWorldStateFactory.cs | 15 +- .../AccountStateProviderExtensions.cs | 14 - .../Nethermind.Core/IAccountStateProvider.cs | 2 + .../StandardDbInitializerTests.cs | 1 + .../Nethermind.Era1.Test/Era1ModuleTests.cs | 19 +- .../Nethermind.Evm.Test/Eip1283Tests.cs | 1 + .../Nethermind.Evm.Test/Eip2200Tests.cs | 1 + .../Nethermind.Evm.Test/Eip2935Tests.cs | 1 + .../Eip3529RefundsTests.cs | 1 + .../Nethermind.Evm.Test/Eip6780Tests.cs | 1 + .../Tracing/ProofTxTracerTests.cs | 1 + .../State/IReadOnlyStateProviderExtensions.cs | 7 +- .../Nethermind.Evm/State/IWorldState.cs | 4 +- .../State/IWorldStateExtensions.cs | 6 + .../State/IWorldStateScopeProvider.cs | 132 ++++++++ .../FlashbotsModuleTests.cs | 2 +- .../Rbuilder/RbuilderRpcModuleTests.cs | 3 +- .../Modules/BlockProcessingModule.cs | 3 + .../Modules/MainProcessingContext.cs | 20 +- .../Modules/NethermindModule.cs | 1 + .../Modules/PrewarmerModule.cs | 68 ++++ .../PruningTrieStateFactory.cs | 38 +-- .../Steps/InitializeBlockchain.cs | 3 +- .../EthModuleBenchmarks.cs | 2 +- .../Modules/Proof/ProofRpcModuleTests.cs | 4 +- .../EngineModuleTests.HelperFunctions.cs | 12 +- .../StatsCollectorTests.cs | 2 +- .../StorageProviderTests.cs | 282 ++++++++++++++- .../TrieStoreScopeProviderTests.cs | 99 ++++++ .../WorldStateManagerTests.cs | 9 +- .../Healing/HealingStorageTreeFactory.cs | 16 - .../Healing/HealingWorldState.cs | 21 -- .../Healing/HealingWorldStateScopeProvider.cs | 27 ++ .../Nethermind.State/IWorldStateManager.cs | 16 +- .../OverridableEnv/OverridableEnvFactory.cs | 13 +- .../OverridableWorldStateManager.cs | 15 +- .../PartialStorageProviderBase.cs | 20 +- .../PersistentStorageProvider.cs | 274 +++++---------- .../Nethermind.State/PreBlockCaches.cs | 1 - .../PrewarmerScopeProvider.cs | 154 +++++++++ .../Nethermind.State/StateProvider.cs | 158 ++------- src/Nethermind/Nethermind.State/StateTree.cs | 42 +++ .../Nethermind.State/StorageTree.cs | 31 +- .../TrieStoreScopeProvider.cs | 320 ++++++++++++++++++ src/Nethermind/Nethermind.State/WorldState.cs | 128 ++++--- .../Nethermind.State/WorldStateManager.cs | 27 +- .../WorldStateMetricsDecorator.cs | 7 + .../Pruning/TreeStoreTests.cs | 8 +- .../PruningScenariosTests.cs | 11 +- .../Nethermind.Trie.Test/TrieTests.cs | 2 +- .../Nethermind.Trie/NodeStorageCache.cs | 35 ++ .../Nethermind.Trie/PreCachedTrieStore.cs | 10 +- 65 files changed, 1543 insertions(+), 675 deletions(-) create mode 100644 src/Nethermind/Nethermind.Consensus/Processing/PrewarmerEnvFactory.cs delete mode 100644 src/Nethermind/Nethermind.Core/AccountStateProviderExtensions.cs create mode 100644 src/Nethermind/Nethermind.Evm/State/IWorldStateScopeProvider.cs create mode 100644 src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs create mode 100644 src/Nethermind/Nethermind.State.Test/TrieStoreScopeProviderTests.cs delete mode 100644 src/Nethermind/Nethermind.State/Healing/HealingStorageTreeFactory.cs delete mode 100644 src/Nethermind/Nethermind.State/Healing/HealingWorldState.cs create mode 100644 src/Nethermind/Nethermind.State/Healing/HealingWorldStateScopeProvider.cs create mode 100644 src/Nethermind/Nethermind.State/PrewarmerScopeProvider.cs create mode 100644 src/Nethermind/Nethermind.State/TrieStoreScopeProvider.cs create mode 100644 src/Nethermind/Nethermind.Trie/NodeStorageCache.cs diff --git a/src/Nethermind/Nethermind.Benchmark/Store/WorldStateBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Store/WorldStateBenchmarks.cs index 8a37c31c0c3..e9378a6c9a8 100644 --- a/src/Nethermind/Nethermind.Benchmark/Store/WorldStateBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Store/WorldStateBenchmarks.cs @@ -6,6 +6,7 @@ using Autofac; using BenchmarkDotNet.Attributes; using DotNetty.Common.Utilities; +using Nethermind.Consensus.Processing; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; @@ -44,7 +45,7 @@ public void Setup() .AddModule(new TestNethermindModule()) .Build(); - IWorldState worldState = _globalWorldState = _container.Resolve().GlobalWorldState; + IWorldState worldState = _globalWorldState = _container.Resolve().WorldState; using var _ = worldState.BeginScope(IWorldState.PreGenesis); Random rand = new Random(0); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.IsProducingBlocks.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.IsProducingBlocks.cs index 1470ec99471..4a5bce87837 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.IsProducingBlocks.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.IsProducingBlocks.cs @@ -25,6 +25,7 @@ using Nethermind.Specs; using Nethermind.Specs.Forks; using Nethermind.Evm.State; +using Nethermind.State; using NSubstitute; using NUnit.Framework; @@ -40,7 +41,7 @@ public async Task DevBlockProducer_IsProducingBlocks_returns_expected_results() DevBlockProducer blockProducer = new( Substitute.For(), testRpc.BlockchainProcessor, - testRpc.WorldStateManager.GlobalWorldState, + testRpc.MainWorldState, testRpc.BlockTree, testRpc.Timestamper, testRpc.SpecProvider, @@ -59,7 +60,7 @@ public async Task TestBlockProducer_IsProducingBlocks_returns_expected_results() TestBlockProducer blockProducer = new( Substitute.For(), testRpc.BlockchainProcessor, - testRpc.WorldStateManager.GlobalWorldState, + testRpc.MainWorldState, Substitute.For(), testRpc.BlockTree, testRpc.Timestamper, @@ -81,7 +82,7 @@ public async Task MinedBlockProducer_IsProducingBlocks_returns_expected_results( testRpc.BlockchainProcessor, Substitute.For(), testRpc.BlockTree, - testRpc.WorldStateManager.GlobalWorldState, + testRpc.MainWorldState, Substitute.For(), testRpc.Timestamper, testRpc.SpecProvider, @@ -123,7 +124,7 @@ public async Task CliqueBlockProducer_IsProducingBlocks_returns_expected_results CliqueBlockProducer blockProducer = new( Substitute.For(), testRpc.BlockchainProcessor, - testRpc.WorldStateManager.GlobalWorldState, + testRpc.MainWorldState, testRpc.Timestamper, Substitute.For(), Substitute.For(), @@ -152,7 +153,7 @@ public async Task DevBlockProducer_OnGlobalWorldState_IsProducingAndSuggestingBl DevBlockProducer blockProducer = new( Substitute.For(), testRpc.BlockchainProcessor, - testRpc.WorldStateManager.GlobalWorldState, + new WorldState(testRpc.WorldStateManager.GlobalWorldState, testRpc.LogManager), testRpc.BlockTree, testRpc.Timestamper, testRpc.SpecProvider, diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs index f61ef983831..edfe3d13558 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs @@ -364,7 +364,7 @@ public void BlockProductionTransactionsExecutor_calculates_block_size_using_prop } } - public class WorldStateStab() : WorldState(Substitute.For(), Substitute.For(), LimboLogs.Instance), IWorldState + public class WorldStateStab() : WorldState(Substitute.For(), LimboLogs.Instance), IWorldState { // we cannot mock ref methods ref readonly UInt256 IWorldState.GetBalance(Address address) => ref UInt256.MaxValue; diff --git a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs index b242c70e9c9..e21da4ac482 100644 --- a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs @@ -105,7 +105,7 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f SepoliaSpecProvider testnetSpecProvider = SepoliaSpecProvider.Instance; IReleaseSpec finalSpec = testnetSpecProvider.GetFinalSpec(); - IWorldState stateProvider = container.Resolve().GlobalWorldState; + IWorldState stateProvider = container.Resolve().WorldState; using (stateProvider.BeginScope(IWorldState.PreGenesis)) { stateProvider.CreateAccount(TestItem.PrivateKeyD.Address, 100.Ether()); @@ -280,7 +280,7 @@ public On ProcessBadGenesis() public On ProcessGenesis(PrivateKey nodeKey) { - using var _ = _containers[nodeKey].Resolve().GlobalWorldState.BeginScope(IWorldState.PreGenesis); + using var _ = _containers[nodeKey].Resolve().WorldState.BeginScope(IWorldState.PreGenesis); if (_logger.IsInfo) _logger.Info($"SUGGESTING GENESIS ON {nodeKey.Address}"); _blockTrees[nodeKey].SuggestBlock(_genesis).Should().Be(AddBlockResult.Added); _blockEvents[nodeKey].WaitOne(_timeout); @@ -289,7 +289,7 @@ public On ProcessGenesis(PrivateKey nodeKey) public On ProcessGenesis3Validators(PrivateKey nodeKey) { - using var _ = _containers[nodeKey].Resolve().GlobalWorldState.BeginScope(IWorldState.PreGenesis); + using var _ = _containers[nodeKey].Resolve().WorldState.BeginScope(IWorldState.PreGenesis); _blockTrees[nodeKey].SuggestBlock(_genesis3Validators); _blockEvents[nodeKey].WaitOne(_timeout); return this; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs index 0254a504f2c..caa2c2fd893 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs @@ -259,15 +259,16 @@ BlockProducerEnv Create() { ReadOnlyBlockTree readOnlyBlockTree = blockTree.AsReadOnly(); - IWorldState worldState = worldStateManager.CreateResettableWorldState(); + IWorldStateScopeProvider worldStateScopeProvider = worldStateManager.CreateResettableWorldState(); ILifetimeScope innerLifetime = lifetimeScope.BeginLifetimeScope((builder) => builder - .AddSingleton(worldState) + .AddSingleton(worldStateScopeProvider) .AddSingleton(BlockchainProcessor.Options.NoReceipts) .AddSingleton(CreateBlockProcessor) .AddDecorator()); lifetimeScope.Disposer.AddInstanceForAsyncDisposal(innerLifetime); IBlockchainProcessor chainProcessor = innerLifetime.Resolve(); + IWorldState worldState = innerLifetime.Resolve(); return new BlockProducerEnv(readOnlyBlockTree, chainProcessor, worldState, CreateTxSourceForProducer()); } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs index f8496e46569..50582c606ca 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs @@ -15,24 +15,11 @@ public class AutoReadOnlyTxProcessingEnvFactory(ILifetimeScope parentLifetime, I { public IReadOnlyTxProcessorSource Create() { - IWorldState worldState = worldStateManager.CreateResettableWorldState(); + IWorldStateScopeProvider worldState = worldStateManager.CreateResettableWorldState(); ILifetimeScope childScope = parentLifetime.BeginLifetimeScope((builder) => { builder - .AddSingleton(worldState) - .AddSingleton(); - }); - - return childScope.Resolve(); - } - - public IReadOnlyTxProcessorSource CreateForWarmingUp(IWorldState worldStateToWarmUp) - { - IWorldState worldState = worldStateManager.CreateWorldStateForWarmingUp(worldStateToWarmUp); - ILifetimeScope childScope = parentLifetime.BeginLifetimeScope((builder) => - { - builder - .AddSingleton(worldState) + .AddSingleton(worldState) .AddSingleton(); }); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockCachePreWarmer.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockCachePreWarmer.cs index 5305d5ccdbe..5fc465c2ea6 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockCachePreWarmer.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockCachePreWarmer.cs @@ -25,30 +25,30 @@ namespace Nethermind.Consensus.Processing; public sealed class BlockCachePreWarmer( - IReadOnlyTxProcessingEnvFactory envFactory, - IWorldState worldStateToWarmup, + PrewarmerEnvFactory envFactory, int concurrency, - ILogManager logManager, - PreBlockCaches? preBlockCaches = null + NodeStorageCache nodeStorageCache, + PreBlockCaches preBlockCaches, + ILogManager logManager ) : IBlockCachePreWarmer { private int _concurrencyLevel = (concurrency == 0 ? Math.Min(Environment.ProcessorCount - 1, 16) : concurrency); - private readonly ObjectPool _envPool = new DefaultObjectPool(new ReadOnlyTxProcessingEnvPooledObjectPolicy(envFactory, worldStateToWarmup), Environment.ProcessorCount * 2); + private readonly ObjectPool _envPool = new DefaultObjectPool(new ReadOnlyTxProcessingEnvPooledObjectPolicy(envFactory, preBlockCaches), Environment.ProcessorCount * 2); private readonly ILogger _logger = logManager.GetClassLogger(); private BlockStateSource? _currentBlockState = null; public BlockCachePreWarmer( - IReadOnlyTxProcessingEnvFactory envFactory, - IWorldState worldStateToWarmup, + PrewarmerEnvFactory envFactory, IBlocksConfig blocksConfig, - ILogManager logManager, - PreBlockCaches? preBlockCaches = null + NodeStorageCache nodeStorageCache, + PreBlockCaches preBlockCaches, + ILogManager logManager ) : this( envFactory, - worldStateToWarmup, blocksConfig.PreWarmStateConcurrency, - logManager, - preBlockCaches) + nodeStorageCache, + preBlockCaches, + logManager) { } @@ -58,6 +58,8 @@ public Task PreWarmCaches(Block suggestedBlock, BlockHeader? parent, IReleaseSpe { _currentBlockState = new(this, suggestedBlock, parent, spec); CacheType result = preBlockCaches.ClearCaches(); + result |= nodeStorageCache.ClearCaches() ? CacheType.Rlp : CacheType.None; + nodeStorageCache.Enabled = true; if (result != default) { if (_logger.IsWarn) _logger.Warn($"Caches {result} are not empty. Clearing them."); @@ -82,8 +84,10 @@ public CacheType ClearCaches() { if (_logger.IsDebug) _logger.Debug("Clearing caches"); CacheType cachesCleared = preBlockCaches?.ClearCaches() ?? default; - if (_logger.IsDebug) _logger.Debug($"Cleared caches: {cachesCleared}"); + nodeStorageCache.Enabled = false; + cachesCleared |= nodeStorageCache.ClearCaches() ? CacheType.Rlp : CacheType.None; + if (_logger.IsDebug) _logger.Debug($"Cleared caches: {cachesCleared}"); return cachesCleared; } @@ -373,9 +377,9 @@ public void Dispose() private static void DisposeThreadState(AddressWarmingState state) => state.Dispose(); } - private class ReadOnlyTxProcessingEnvPooledObjectPolicy(IReadOnlyTxProcessingEnvFactory envFactory, IWorldState worldStateToWarmUp) : IPooledObjectPolicy + private class ReadOnlyTxProcessingEnvPooledObjectPolicy(PrewarmerEnvFactory envFactory, PreBlockCaches preBlockCaches) : IPooledObjectPolicy { - public IReadOnlyTxProcessorSource Create() => envFactory.CreateForWarmingUp(worldStateToWarmUp); + public IReadOnlyTxProcessorSource Create() => envFactory.Create(preBlockCaches); public bool Return(IReadOnlyTxProcessorSource obj) => true; } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/IReadOnlyTxProcessingEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Processing/IReadOnlyTxProcessingEnvFactory.cs index baeb04fb694..2d46d4d7004 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/IReadOnlyTxProcessingEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/IReadOnlyTxProcessingEnvFactory.cs @@ -2,12 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Blockchain; -using Nethermind.Evm.State; namespace Nethermind.Consensus.Processing; public interface IReadOnlyTxProcessingEnvFactory { public IReadOnlyTxProcessorSource Create(); - public IReadOnlyTxProcessorSource CreateForWarmingUp(IWorldState worldState); } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/PrewarmerEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Processing/PrewarmerEnvFactory.cs new file mode 100644 index 00000000000..17b3d97d0a8 --- /dev/null +++ b/src/Nethermind/Nethermind.Consensus/Processing/PrewarmerEnvFactory.cs @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Autofac; +using Nethermind.Blockchain; +using Nethermind.Core; +using Nethermind.Evm.State; +using Nethermind.State; + +namespace Nethermind.Consensus.Processing; + +public class PrewarmerEnvFactory(IWorldStateManager worldStateManager, ILifetimeScope parentLifetime) +{ + public IReadOnlyTxProcessorSource Create(PreBlockCaches preBlockCaches) + { + var worldState = new PrewarmerScopeProvider( + worldStateManager.CreateResettableWorldState(), + preBlockCaches, + populatePreBlockCache: true + ); + + ILifetimeScope childScope = parentLifetime.BeginLifetimeScope((builder) => + { + builder + .AddSingleton(worldState) + .AddSingleton(); + }); + + return childScope.Resolve(); + } +} diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs index 83b40ae45eb..3002b39d235 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs @@ -31,7 +31,7 @@ protected virtual ContainerBuilder ConfigureBuilder(ContainerBuilder builder) => public IBlockProducerEnv Create() { - IWorldState worldState = worldStateManager.CreateResettableWorldState(); + IWorldStateScopeProvider worldState = worldStateManager.CreateResettableWorldState(); ILifetimeScope lifetimeScope = rootLifetime.BeginLifetimeScope(builder => ConfigureBuilder(builder) .AddScoped(worldState)); diff --git a/src/Nethermind/Nethermind.Consensus/Stateless/StatelessBlockProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Stateless/StatelessBlockProcessingEnv.cs index b145d04b4d7..055a46dec12 100644 --- a/src/Nethermind/Nethermind.Consensus/Stateless/StatelessBlockProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Stateless/StatelessBlockProcessingEnv.cs @@ -36,8 +36,8 @@ public IBlockProcessor BlockProcessor public IWorldState WorldState { get => _worldState ??= new WorldState( - new RawTrieStore(witness.NodeStorage), - witness.CodeDb, logManager); + new TrieStoreScopeProvider(new RawTrieStore(witness.NodeStorage), + witness.CodeDb, logManager), logManager); } private IBlockProcessor GetProcessor() diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 8c427246dd4..4cec9335358 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -61,6 +61,7 @@ public class TestBlockchain : IDisposable public ITxPool TxPool => _fromContainer.TxPool; public IForkInfo ForkInfo => _fromContainer.ForkInfo; public IWorldStateManager WorldStateManager => _fromContainer.WorldStateManager; + public IWorldState MainWorldState => MainProcessingContext.WorldState; public IReadOnlyTxProcessingEnvFactory ReadOnlyTxProcessingEnvFactory => _fromContainer.ReadOnlyTxProcessingEnvFactory; public IShareableTxProcessorSource ShareableTxProcessorSource => _fromContainer.ShareableTxProcessorSource; public IBranchProcessor BranchProcessor => _fromContainer.MainProcessingContext.BranchProcessor; diff --git a/src/Nethermind/Nethermind.Core.Test/Container/ContainerBuilderExtensions.cs b/src/Nethermind/Nethermind.Core.Test/Container/ContainerBuilderExtensions.cs index e49a3b60427..7c47d05007b 100644 --- a/src/Nethermind/Nethermind.Core.Test/Container/ContainerBuilderExtensions.cs +++ b/src/Nethermind/Nethermind.Core.Test/Container/ContainerBuilderExtensions.cs @@ -5,6 +5,7 @@ using Autofac; using Autofac.Core; using Nethermind.Blockchain; +using Nethermind.Core.Specs; using Nethermind.Evm.State; using Nethermind.Specs.ChainSpecStyle; @@ -92,4 +93,13 @@ public static ContainerBuilder WithGenesisPostProcessor(this ContainerBuilder bu }); }); } + + public static ContainerBuilder WithGenesisPostProcessor(this ContainerBuilder builder, + Action postProcessor) + { + return builder.AddScoped((worldState, specProvider) => new FunctionalGenesisPostProcessor((block) => + { + postProcessor(block, worldState, specProvider); + })); + } } diff --git a/src/Nethermind/Nethermind.Core.Test/TestWorldStateFactory.cs b/src/Nethermind/Nethermind.Core.Test/TestWorldStateFactory.cs index b6295ac8bec..e3d2ffc6d15 100644 --- a/src/Nethermind/Nethermind.Core.Test/TestWorldStateFactory.cs +++ b/src/Nethermind/Nethermind.Core.Test/TestWorldStateFactory.cs @@ -14,15 +14,12 @@ namespace Nethermind.Core.Test; public static class TestWorldStateFactory { - public static IWorldState CreateForTest() - { - return CreateForTest(TestMemDbProvider.Init(), LimboLogs.Instance); - } - - public static IWorldState CreateForTest(IDbProvider dbProvider, ILogManager logManager) + public static IWorldState CreateForTest(IDbProvider? dbProvider = null, ILogManager? logManager = null) { PruningConfig pruningConfig = new PruningConfig(); TestFinalizedStateProvider finalizedStateProvider = new TestFinalizedStateProvider(pruningConfig.PruningBoundary); + dbProvider ??= TestMemDbProvider.Init(); + logManager ??= LimboLogs.Instance; TrieStore trieStore = new TrieStore( new NodeStorage(dbProvider.StateDb), No.Pruning, @@ -31,7 +28,7 @@ public static IWorldState CreateForTest(IDbProvider dbProvider, ILogManager logM pruningConfig, LimboLogs.Instance); finalizedStateProvider.TrieStore = trieStore; - return new WorldState(trieStore, dbProvider.CodeDb, logManager); + return new WorldState(new TrieStoreScopeProvider(trieStore, dbProvider.CodeDb, logManager), logManager); } public static (IWorldState, IStateReader) CreateForTestWithStateReader(IDbProvider? dbProvider = null, ILogManager? logManager = null) @@ -49,7 +46,7 @@ public static (IWorldState, IStateReader) CreateForTestWithStateReader(IDbProvid pruningConfig, LimboLogs.Instance); finalizedStateProvider.TrieStore = trieStore; - return (new WorldState(trieStore, dbProvider.CodeDb, logManager), new StateReader(trieStore, dbProvider.CodeDb, logManager)); + return (new WorldState(new TrieStoreScopeProvider(trieStore, dbProvider.CodeDb, logManager), logManager), new StateReader(trieStore, dbProvider.CodeDb, logManager)); } public static WorldStateManager CreateWorldStateManagerForTest(IDbProvider dbProvider, ILogManager logManager) @@ -64,7 +61,7 @@ public static WorldStateManager CreateWorldStateManagerForTest(IDbProvider dbPro pruningConfig, LimboLogs.Instance); finalizedStateProvider.TrieStore = trieStore; - var worldState = new WorldState(trieStore, dbProvider.CodeDb, logManager); + var worldState = new TrieStoreScopeProvider(trieStore, dbProvider.CodeDb, logManager); return new WorldStateManager(worldState, trieStore, dbProvider, logManager); } diff --git a/src/Nethermind/Nethermind.Core/AccountStateProviderExtensions.cs b/src/Nethermind/Nethermind.Core/AccountStateProviderExtensions.cs deleted file mode 100644 index 23ba0f6de61..00000000000 --- a/src/Nethermind/Nethermind.Core/AccountStateProviderExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Runtime.CompilerServices; - -namespace Nethermind.Core -{ - [SkipLocalsInit] - public static class AccountStateProviderExtensions - { - public static bool HasCode(this IAccountStateProvider stateProvider, Address address) => - stateProvider.TryGetAccount(address, out AccountStruct account) && account.HasCode; - } -} diff --git a/src/Nethermind/Nethermind.Core/IAccountStateProvider.cs b/src/Nethermind/Nethermind.Core/IAccountStateProvider.cs index ec52457f1a5..5b949c67dea 100644 --- a/src/Nethermind/Nethermind.Core/IAccountStateProvider.cs +++ b/src/Nethermind/Nethermind.Core/IAccountStateProvider.cs @@ -38,5 +38,7 @@ ValueHash256 GetCodeHash(Address address) TryGetAccount(address, out AccountStruct account); return account.CodeHash; } + + bool HasCode(Address address) => TryGetAccount(address, out AccountStruct account) && account.HasCode; } } diff --git a/src/Nethermind/Nethermind.Db.Test/StandardDbInitializerTests.cs b/src/Nethermind/Nethermind.Db.Test/StandardDbInitializerTests.cs index e61cf1a1078..b8323d308f4 100644 --- a/src/Nethermind/Nethermind.Db.Test/StandardDbInitializerTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/StandardDbInitializerTests.cs @@ -10,6 +10,7 @@ using Nethermind.Api; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; +using Nethermind.Config; using Nethermind.Core; using Nethermind.Core.Test; using Nethermind.Core.Test.Db; diff --git a/src/Nethermind/Nethermind.Era1.Test/Era1ModuleTests.cs b/src/Nethermind/Nethermind.Era1.Test/Era1ModuleTests.cs index 2cbcdb0a7fc..0dfb24a1d47 100644 --- a/src/Nethermind/Nethermind.Era1.Test/Era1ModuleTests.cs +++ b/src/Nethermind/Nethermind.Era1.Test/Era1ModuleTests.cs @@ -118,8 +118,12 @@ public async Task ImportAndExportGethFiles(string network) [Test] public async Task CreateEraAndVerifyAccumulators() { - TestBlockchain testBlockchain = await BasicTestBlockchain.Create(); - IWorldState worldState = testBlockchain.WorldStateManager.GlobalWorldState; + TestBlockchain testBlockchain = await BasicTestBlockchain.Create( + configurer: (builder) => builder.WithGenesisPostProcessor((block, state, specProvider) => + { + state.AddToBalance(TestItem.AddressA, 10.Ether(), specProvider.GenesisSpec); + }) + ); using TempPath tmpFile = TempPath.GetTempFile(); Block genesis = testBlockchain.BlockFinder.FindBlock(0)!; @@ -129,16 +133,7 @@ public async Task CreateEraAndVerifyAccumulators() UInt256 nonce = 0; List blocks = []; - using (worldState.BeginScope(genesis.Header)) - { - worldState.AddToBalance(TestItem.AddressA, 10.Ether(), testBlockchain.SpecProvider.GenesisSpec); - worldState.RecalculateStateRoot(); - - genesis.Header.StateRoot = worldState.StateRoot; - worldState.CommitTree(0); - - blocks.Add(genesis); - } + blocks.Add(genesis); BlockHeader uncle = Build.A.BlockHeader.TestObject; diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip1283Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip1283Tests.cs index 995cdf9d043..0f75f89071d 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip1283Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip1283Tests.cs @@ -5,6 +5,7 @@ using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Evm.State; using Nethermind.Specs; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip2200Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip2200Tests.cs index f7e749380a7..df8b99a330d 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip2200Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip2200Tests.cs @@ -5,6 +5,7 @@ using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Evm.State; using Nethermind.Specs; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip2935Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip2935Tests.cs index 02869cbc12e..b1f12b1bd27 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip2935Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip2935Tests.cs @@ -6,6 +6,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Evm.State; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Specs; diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs index de51c08b541..09d1ce61a4a 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs @@ -8,6 +8,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Blockchain.Tracing.ParityStyle; +using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; using Nethermind.Specs; diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip6780Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip6780Tests.cs index 2722a62827f..12d4704a5d2 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip6780Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip6780Tests.cs @@ -26,6 +26,7 @@ using Nethermind.Core.Crypto; using System; using Nethermind.Core.Specs; +using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Evm.Test diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/ProofTxTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/ProofTxTracerTests.cs index 93f0e39762f..60ba34a5f03 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/ProofTxTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/ProofTxTracerTests.cs @@ -5,6 +5,7 @@ using Nethermind.Core; using Nethermind.Core.Test.Builders; using Nethermind.Blockchain.Tracing.Proofs; +using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Evm/State/IReadOnlyStateProviderExtensions.cs b/src/Nethermind/Nethermind.Evm/State/IReadOnlyStateProviderExtensions.cs index 3e12df463d5..119d43ef09b 100644 --- a/src/Nethermind/Nethermind.Evm/State/IReadOnlyStateProviderExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/State/IReadOnlyStateProviderExtensions.cs @@ -9,11 +9,6 @@ namespace Nethermind.Evm.State { public static class IReadOnlyStateProviderExtensions { - public static byte[] GetCode(this IReadOnlyStateProvider stateProvider, Address address) - { - stateProvider.TryGetAccount(address, out AccountStruct account); - return !account.HasCode ? [] : stateProvider.GetCode(in account.CodeHash) ?? []; - } /// /// Checks if has code that is not a delegation, according to the rules of eip-3607 and eip-7702. /// Where possible a cache for code lookup should be used, since the fallback will read from . @@ -31,7 +26,7 @@ public static bool IsInvalidContractSender( spec.IsEip3607Enabled && stateProvider.HasCode(sender) && (!spec.IsEip7702Enabled - || (!isDelegatedCode?.Invoke(sender) ?? !Eip7702Constants.IsDelegatedCode(GetCode(stateProvider, sender)))); + || (!isDelegatedCode?.Invoke(sender) ?? !Eip7702Constants.IsDelegatedCode(stateProvider.GetCode(sender)))); /// /// Checks if has code that is not a delegation, according to the rules of eip-3607 and eip-7702. diff --git a/src/Nethermind/Nethermind.Evm/State/IWorldState.cs b/src/Nethermind/Nethermind.Evm/State/IWorldState.cs index 0a50362bedd..803a18596ea 100644 --- a/src/Nethermind/Nethermind.Evm/State/IWorldState.cs +++ b/src/Nethermind/Nethermind.Evm/State/IWorldState.cs @@ -24,6 +24,7 @@ public interface IWorldState : IJournal, IReadOnlyStateProvider IDisposable BeginScope(BlockHeader? baseBlock); bool IsInScope { get; } + IWorldStateScopeProvider ScopeProvider { get; } new ref readonly UInt256 GetBalance(Address address); new ref readonly ValueHash256 GetCodeHash(Address address); bool HasStateForBlock(BlockHeader? baseBlock); @@ -129,9 +130,6 @@ public interface IWorldState : IJournal, IReadOnlyStateProvider void SetNonce(Address address, in UInt256 nonce); /* snapshots */ - - void Commit(IReleaseSpec releaseSpec, bool isGenesis = false, bool commitRoots = true); - void Commit(IReleaseSpec releaseSpec, IWorldStateTracer tracer, bool isGenesis = false, bool commitRoots = true); /// diff --git a/src/Nethermind/Nethermind.Evm/State/IWorldStateExtensions.cs b/src/Nethermind/Nethermind.Evm/State/IWorldStateExtensions.cs index a0749cce8ab..c0e73a6a311 100644 --- a/src/Nethermind/Nethermind.Evm/State/IWorldStateExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/State/IWorldStateExtensions.cs @@ -5,6 +5,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Evm.Tracing.State; namespace Nethermind.Evm.State; @@ -16,4 +17,9 @@ public static void InsertCode(this IWorldState worldState, Address address, Read ValueHash256 codeHash = code.Length == 0 ? ValueKeccak.OfAnEmptyString : ValueKeccak.Compute(code.Span); worldState.InsertCode(address, codeHash, code, spec, isGenesis); } + + public static void Commit(this IWorldState worldState, IReleaseSpec releaseSpec, bool isGenesis = false, bool commitRoots = true) + { + worldState.Commit(releaseSpec, NullStateTracer.Instance, isGenesis, commitRoots); + } } diff --git a/src/Nethermind/Nethermind.Evm/State/IWorldStateScopeProvider.cs b/src/Nethermind/Nethermind.Evm/State/IWorldStateScopeProvider.cs new file mode 100644 index 00000000000..96f1e1d7de8 --- /dev/null +++ b/src/Nethermind/Nethermind.Evm/State/IWorldStateScopeProvider.cs @@ -0,0 +1,132 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Int256; + +namespace Nethermind.Evm.State; + +/// +/// An interface for storage backend for . This interface does not have +/// logic for snapshot/rollback and code. Operations must be done using . +/// +public interface IWorldStateScopeProvider +{ + bool HasRoot(BlockHeader? baseBlock); + IScope BeginScope(BlockHeader? baseBlock); + + public interface IScope : IDisposable + { + Hash256 RootHash { get; } + + void UpdateRootHash(); + + /// + /// Get the account information for the following address. + /// Note: Do not rely on as it may be modified after write. Instead use . + /// + /// + /// + Account? Get(Address address); + + /// + /// Call when top level application read an account without going through this scope to reduce time during commit later. + /// + /// + /// + void HintGet(Address address, Account? account); + + /// + /// The code db + /// + ICodeDb CodeDb { get; } + + /// + /// Create a per address storage tree. Multiple call to the same + /// address yield the same . The returned object + /// must not be used after , and should be re-created. + /// + /// + /// + IStorageTree CreateStorageTree(Address address); + + /// + /// Begin a write batch to update the world state. + /// + /// For optimization, estimated account number. + /// + IWorldStateWriteBatch StartWriteBatch(int estimatedAccountNum); + + /// + /// A commit will traverse the dirty nodes in the tree, calculate the hash and save + /// the tree to underlying store. + /// That said, will always call + /// first. + /// + void Commit(long blockNumber); + } + + public interface ICodeDb + { + byte[]? GetCode(in ValueHash256 codeHash); + + ICodeSetter BeginCodeWrite(); + } + + public interface IStorageTree + { + Hash256 RootHash { get; } + + byte[] Get(in UInt256 index); + + void HintGet(in UInt256 index, byte[]? value); + + /// + /// Used by JS tracer. May not work on some database layout. + /// + /// + /// + byte[] Get(in ValueHash256 hash); + } + + public interface IWorldStateWriteBatch : IDisposable + { + public event EventHandler OnAccountUpdated; + + // Note: Null account imply removal and clearing of storage. + void Set(Address key, Account? account); + + IStorageWriteBatch CreateStorageWriteBatch(Address key, int estimatedEntries); + } + + public class AccountUpdated(Address Address, Account? Account) : EventArgs + { + public Address Address { get; init; } = Address; + public Account? Account { get; init; } = Account; + + public void Deconstruct(out Address Address, out Account? Account) + { + Address = this.Address; + Account = this.Account; + } + } + + public interface IStorageWriteBatch : IDisposable + { + void Set(in UInt256 index, byte[] value); + + /// + /// Self-destruct. Maybe costly. Must be called first. + /// Note: Is called on new account or dead account at start of tx also. + /// Note: May not get called if the account is removed at the end of the time of commit. + /// + void Clear(); + } + + public interface ICodeSetter : IDisposable + { + void Set(in ValueHash256 codeHash, ReadOnlySpan code); + } +} diff --git a/src/Nethermind/Nethermind.Flashbots.Test/FlashbotsModuleTests.cs b/src/Nethermind/Nethermind.Flashbots.Test/FlashbotsModuleTests.cs index b024ebe1e23..e5b74f0a7a7 100644 --- a/src/Nethermind/Nethermind.Flashbots.Test/FlashbotsModuleTests.cs +++ b/src/Nethermind/Nethermind.Flashbots.Test/FlashbotsModuleTests.cs @@ -67,7 +67,7 @@ public virtual async Task TestValidateBuilderSubmissionV3() private Block CreateBlock(EngineModuleTests.MergeTestBlockchain chain) { BlockHeader currentHeader = chain.BlockTree.Head.Header; - IWorldState State = chain.WorldStateManager.GlobalWorldState; + IWorldState State = chain.MainWorldState; using var _ = State.BeginScope(IWorldState.PreGenesis); State.CreateAccount(TestKeysAndAddress.TestAddr, TestKeysAndAddress.TestBalance); UInt256 nonce = State.GetNonce(TestKeysAndAddress.TestAddr); diff --git a/src/Nethermind/Nethermind.Flashbots.Test/Rbuilder/RbuilderRpcModuleTests.cs b/src/Nethermind/Nethermind.Flashbots.Test/Rbuilder/RbuilderRpcModuleTests.cs index b7688fa13d8..013e78afd1d 100644 --- a/src/Nethermind/Nethermind.Flashbots.Test/Rbuilder/RbuilderRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.Flashbots.Test/Rbuilder/RbuilderRpcModuleTests.cs @@ -18,6 +18,7 @@ using Nethermind.Specs.Forks; using Nethermind.Evm.State; using Nethermind.JsonRpc; +using Nethermind.Logging; using Nethermind.State; using NUnit.Framework; using Bytes = Nethermind.Core.Extensions.Bytes; @@ -61,7 +62,7 @@ public async Task Test_getCodeByHash() byte[] theCodeBytes = Bytes.FromHexString(theCode); Hash256 theHash = Keccak.Compute(theCodeBytes); - IWorldState worldState = _worldStateManager.GlobalWorldState; + IWorldState worldState = new WorldState(_worldStateManager.GlobalWorldState, LimboLogs.Instance); using (worldState.BeginScope(IWorldState.PreGenesis)) { worldState.CreateAccount(TestItem.AddressA, 100000); diff --git a/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs b/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs index 232d3d24c96..9ad13948399 100644 --- a/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs @@ -23,11 +23,13 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Evm; +using Nethermind.Evm.State; using Nethermind.State.OverridableEnv; using Nethermind.Evm.TransactionProcessing; using Nethermind.Init.Steps; using Nethermind.JsonRpc.Modules.Eth.GasPrice; using Nethermind.Logging; +using Nethermind.State; using Nethermind.TxPool; namespace Nethermind.Init.Modules; @@ -49,6 +51,7 @@ protected override void Load(ContainerBuilder builder) .AddScoped() .AddScoped() .AddSingleton() + .AddScoped() .AddScoped() .AddScoped() .AddSingleton() diff --git a/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs b/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs index 9b4969d3962..0798e16fe2c 100644 --- a/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs +++ b/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs @@ -24,23 +24,19 @@ public class MainProcessingContext : IMainProcessingContext, BlockProcessor.Bloc public MainProcessingContext( ILifetimeScope rootLifetimeScope, IReceiptConfig receiptConfig, - IBlocksConfig blocksConfig, IInitConfig initConfig, IBlockValidationModule[] blockValidationModules, IMainProcessingModule[] mainProcessingModules, IWorldStateManager worldStateManager, CompositeBlockPreprocessorStep compositeBlockPreprocessorStep, IBlockTree blockTree, - IPrecompileProvider precompileProvider, ILogManager logManager) { - - IWorldState mainWorldState = worldStateManager.GlobalWorldState; ILifetimeScope innerScope = rootLifetimeScope.BeginLifetimeScope((builder) => { builder // These are main block processing specific - .AddSingleton(mainWorldState) + .AddSingleton(worldStateManager.GlobalWorldState) .AddModule(blockValidationModules) .AddScoped() .AddSingleton(this) @@ -65,20 +61,6 @@ public MainProcessingContext( // And finally, to wrap things up. .AddScoped() ; - - if (blocksConfig.PreWarmStateOnBlockProcessing) - { - builder - .AddScoped((mainWorldState as IPreBlockCaches)!.Caches) - .AddScoped() - .AddDecorator((ctx, originalCodeInfoRepository) => - { - PreBlockCaches preBlockCaches = ctx.Resolve(); - // Note: The use of FrozenDictionary means that this cannot be used for other processing env also due to risk of memory leak. - return new CachedCodeInfoRepository(precompileProvider, originalCodeInfoRepository, blocksConfig.CachePrecompilesOnBlockProcessing ? preBlockCaches?.PrecompileCache : null); - }) - ; - } }); _components = innerScope.Resolve(); diff --git a/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs b/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs index 19dbd2105bb..9ff2ea05f82 100644 --- a/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs @@ -49,6 +49,7 @@ protected override void Load(ContainerBuilder builder) configProvider.GetConfig() )) .AddModule(new WorldStateModule(configProvider.GetConfig())) + .AddModule(new PrewarmerModule(configProvider.GetConfig())) .AddModule(new BuiltInStepsModule()) .AddModule(new RpcModules(configProvider.GetConfig())) .AddModule(new EraModule()) diff --git a/src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs b/src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs new file mode 100644 index 00000000000..ebdc79106b0 --- /dev/null +++ b/src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs @@ -0,0 +1,68 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Autofac; +using Nethermind.Blockchain; +using Nethermind.Config; +using Nethermind.Consensus.Processing; +using Nethermind.Core; +using Nethermind.Core.Container; +using Nethermind.Evm; +using Nethermind.Evm.State; +using Nethermind.State; +using Nethermind.Trie; +using Nethermind.Trie.Pruning; + +namespace Nethermind.Init.Modules; + +public class PrewarmerModule(IBlocksConfig blocksConfig) : Module +{ + protected override void Load(ContainerBuilder builder) + { + if (blocksConfig.PreWarmStateOnBlockProcessing) + { + builder + + // Note: There is a special logic for this in `PruningTrieStateFactory`. + .AddSingleton() + + // Note: Need a small modification to have this work on all branch processor due to the shared + // NodeStorageCache and the FrozenDictionary and the fact that some processing does not have + // branch processor, and use block processor instead. + .AddSingleton(); + } + } + + public class PrewarmerMainProcessingModule : Module, IMainProcessingModule + { + protected override void Load(ContainerBuilder builder) + { + builder + // Singleton so that all child env share the same caches. Note: this module is applied per-processing + // module, so singleton here is like scoped but exclude inner prewarmer lifetime. + .AddSingleton() + .AddScoped() + .Add() + + // These are the actual decorated component that provide cached result + .AddDecorator((ctx, worldStateScopeProvider) => + { + if (worldStateScopeProvider is PrewarmerScopeProvider) return worldStateScopeProvider; // Inner world state + return new PrewarmerScopeProvider( + worldStateScopeProvider, + ctx.Resolve(), + populatePreBlockCache: false + ); + }) + .AddDecorator((ctx, originalCodeInfoRepository) => + { + IBlocksConfig blocksConfig = ctx.Resolve(); + PreBlockCaches preBlockCaches = ctx.Resolve(); + IPrecompileProvider precompileProvider = ctx.Resolve(); + // Note: The use of FrozenDictionary means that this cannot be used for other processing env also due to risk of memory leak. + return new CachedCodeInfoRepository(precompileProvider, originalCodeInfoRepository, + blocksConfig.CachePrecompilesOnBlockProcessing ? preBlockCaches?.PrecompileCache : null); + }); + } + } +} diff --git a/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs b/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs index 13ee2178775..3857c679cff 100644 --- a/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs +++ b/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs @@ -33,7 +33,6 @@ public class PruningTrieStateFactory( ISyncConfig syncConfig, IInitConfig initConfig, IPruningConfig pruningConfig, - IBlocksConfig blockConfig, IDbProvider dbProvider, IBlockTree blockTree, IFileSystem fileSystem, @@ -45,7 +44,8 @@ public class PruningTrieStateFactory( ChainSpec chainSpec, IDisposableStack disposeStack, Lazy pathRecovery, - ILogManager logManager + ILogManager logManager, + NodeStorageCache? nodeStorageCache = null ) { private readonly ILogger _logger = logManager.GetClassLogger(); @@ -55,35 +55,29 @@ ILogManager logManager CompositePruningTrigger compositePruningTrigger = new CompositePruningTrigger(); IPruningTrieStore trieStore = mainPruningTrieStoreFactory.PruningTrieStore; + ITrieStore mainWorldTrieStore = trieStore; - PreBlockCaches? preBlockCaches = null; - if (blockConfig.PreWarmStateOnBlockProcessing) + + if (nodeStorageCache is not null) { - preBlockCaches = new PreBlockCaches(); - mainWorldTrieStore = new PreCachedTrieStore(trieStore, preBlockCaches.RlpCache); + mainWorldTrieStore = new PreCachedTrieStore(mainWorldTrieStore, nodeStorageCache); } IKeyValueStoreWithBatching codeDb = dbProvider.CodeDb; - IWorldState worldState = syncConfig.TrieHealing - ? new HealingWorldState( + IWorldStateScopeProvider scopeProvider = syncConfig.TrieHealing + ? new HealingWorldStateScopeProvider( mainWorldTrieStore, - mainNodeStorage, codeDb, + mainNodeStorage, pathRecovery, - logManager, - preBlockCaches, - // Main thread should only read from prewarm caches, not spend extra time updating them. - populatePreBlockCache: false) - : new WorldState( + logManager) + : new TrieStoreScopeProvider( mainWorldTrieStore, codeDb, - logManager, - preBlockCaches, - // Main thread should only read from prewarm caches, not spend extra time updating them. - populatePreBlockCache: false); + logManager); IWorldStateManager stateManager = new WorldStateManager( - worldState, + scopeProvider, trieStore, dbProvider, logManager, @@ -102,8 +96,7 @@ ILogManager logManager mainNodeStorage, nodeStorageFactory, trieStore, - compositePruningTrigger, - preBlockCaches + compositePruningTrigger ); VerifyTrieStarter verifyTrieStarter = new(stateManager, processExit!, logManager); @@ -125,8 +118,7 @@ private void InitializeFullPruning(IDb stateDb, INodeStorage mainNodeStorage, INodeStorageFactory nodeStorageFactory, IPruningTrieStore trieStore, - CompositePruningTrigger compositePruningTrigger, - PreBlockCaches? preBlockCaches) + CompositePruningTrigger compositePruningTrigger) { IPruningTrigger? CreateAutomaticTrigger(string dbPath) { diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index c0c8fd44f14..d2219630519 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -8,7 +8,6 @@ using Nethermind.Api; using Nethermind.Api.Steps; using Nethermind.Blockchain; -using Nethermind.Blockchain.Spec; using Nethermind.Config; using Nethermind.Consensus; using Nethermind.Consensus.Comparers; @@ -18,6 +17,7 @@ using Nethermind.Consensus.Scheduler; using Nethermind.Core; using Nethermind.Core.Attributes; +using Nethermind.Logging; using Nethermind.State; using Nethermind.TxPool; using Nethermind.Wallet; @@ -33,6 +33,7 @@ namespace Nethermind.Init.Steps public class InitializeBlockchain(INethermindApi api, IChainHeadInfoProvider chainHeadInfoProvider) : IStep { private readonly INethermindApi _api = api; + private ILogManager _logManager = api.LogManager; public async Task Execute(CancellationToken _) { diff --git a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs index 31e5bf34e9a..9cbb7b4e5f7 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs @@ -43,7 +43,7 @@ public void GlobalSetup() .AddSingleton(MainnetSpecProvider.Instance) .Build(); - IWorldState stateProvider = _container.Resolve().GlobalWorldState; + IWorldState stateProvider = _container.Resolve().WorldState; stateProvider.CreateAccount(Address.Zero, 1000.Ether()); IReleaseSpec spec = MainnetSpecProvider.Instance.GenesisSpec; stateProvider.Commit(spec); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs index d32babccfc7..24c3e30e824 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs @@ -61,7 +61,7 @@ public async Task Setup() _worldStateManager = TestWorldStateFactory.CreateWorldStateManagerForTest(_dbProvider, LimboLogs.Instance); Hash256 stateRoot; - IWorldState worldState = _worldStateManager.GlobalWorldState; + IWorldState worldState = new WorldState(_worldStateManager.GlobalWorldState, LimboLogs.Instance); using (var _ = worldState.BeginScope(IWorldState.PreGenesis)) { worldState.CreateAccount(TestItem.AddressA, 100000); @@ -884,7 +884,7 @@ private async Task TestCallWithStorageAndCode(byte[] code, UInt256 gasPrice, Add private (IWorldState, Hash256) CreateInitialState(byte[]? code) { - IWorldState stateProvider = _worldStateManager.GlobalWorldState; + IWorldState stateProvider = new WorldState(_worldStateManager.GlobalWorldState, LimboLogs.Instance); using var _ = stateProvider.BeginScope(IWorldState.PreGenesis); AddAccount(stateProvider, TestItem.AddressA, 1.Ether()); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs index d8d3db23462..acedf80e7f0 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs @@ -103,7 +103,7 @@ private static ExecutionPayload CreateBlockRequest(MergeTestBlockchain chain, Ex ExecutionPayload blockRequest = CreateBlockRequestInternal(parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot); Block? block = blockRequest.TryGetBlock().Block; - IWorldState globalWorldState = chain.WorldStateManager.GlobalWorldState; + IWorldState globalWorldState = chain.MainWorldState; using (globalWorldState.BeginScope(parent.TryGetBlock().Block!.Header)) { chain.WithdrawalProcessor?.ProcessWithdrawals(block!, chain.SpecProvider.GenesisSpec); @@ -131,7 +131,7 @@ private static ExecutionPayloadV3 CreateBlockRequestV3( ExecutionPayloadV3 blockRequestV3 = CreateBlockRequestInternal(parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot); Block? block = blockRequestV3.TryGetBlock().Block; - IWorldState globalWorldState = chain.WorldStateManager.GlobalWorldState; + IWorldState globalWorldState = chain.MainWorldState; using (globalWorldState.BeginScope(parent.TryGetBlock().Block!.Header)) { var blockHashStore = new BlockhashStore(globalWorldState); @@ -154,12 +154,12 @@ private static ExecutionPayloadV3 CreateBlockRequestV4(MergeTestBlockchain chain ExecutionPayloadV3 blockRequestV4 = CreateBlockRequestInternal(parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot); Block? block = blockRequestV4.TryGetBlock().Block; - var beaconBlockRootHandler = new BeaconBlockRootHandler(chain.TxProcessor, chain.WorldStateManager.GlobalWorldState); + var beaconBlockRootHandler = new BeaconBlockRootHandler(chain.TxProcessor, chain.MainWorldState); IReleaseSpec spec = chain.SpecProvider.GetSpec(block!.Header); - chain.TxProcessor.SetBlockExecutionContext(new BlockExecutionContext(block.Header, spec)); - beaconBlockRootHandler.StoreBeaconRoot(block, spec, NullTxTracer.Instance); - IWorldState globalWorldState = chain.WorldStateManager.GlobalWorldState; + chain.TxProcessor.SetBlockExecutionContext(new BlockExecutionContext(block!.Header, spec)); + beaconBlockRootHandler.StoreBeaconRoot(block!, spec, NullTxTracer.Instance); + IWorldState globalWorldState = chain.MainWorldState; Snapshot before = globalWorldState.TakeSnapshot(); var blockHashStore = new BlockhashStore(globalWorldState); blockHashStore.ApplyBlockhashStateChanges(block.Header, chain.SpecProvider.GetSpec(block.Header)); diff --git a/src/Nethermind/Nethermind.State.Test/StatsCollectorTests.cs b/src/Nethermind/Nethermind.State.Test/StatsCollectorTests.cs index 713304b13a8..6690ce95da3 100644 --- a/src/Nethermind/Nethermind.State.Test/StatsCollectorTests.cs +++ b/src/Nethermind/Nethermind.State.Test/StatsCollectorTests.cs @@ -28,7 +28,7 @@ public void Can_collect_stats([Values(false, true)] bool parallel) MemDb stateDb = new MemDb(); NodeStorage nodeStorage = new NodeStorage(stateDb); TestRawTrieStore trieStore = new(nodeStorage); - WorldState stateProvider = new(trieStore, codeDb, LimboLogs.Instance); + WorldState stateProvider = new(new TrieStoreScopeProvider(trieStore, codeDb, LimboLogs.Instance), LimboLogs.Instance); StateReader stateReader = new StateReader(trieStore, codeDb, LimboLogs.Instance); Hash256 stateRoot; diff --git a/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs b/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs index 57b3e78e394..cc25eea210a 100644 --- a/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs +++ b/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Concurrent; using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -441,6 +442,135 @@ public void Selfdestruct_clears_cache() provider.Get(nonAccessedStorageCell).ToArray().Should().BeEquivalentTo(StorageTree.ZeroBytes); } + [Test] + public void Selfdestruct_works_across_blocks() + { + Context ctx = new(setInitialState: false, trackWrittenData: true); + WorldState provider = BuildStorageProvider(ctx); + + BlockHeader baseBlock = null; + using (provider.BeginScope(baseBlock)) + { + provider.CreateAccountIfNotExists(TestItem.AddressA, 100); + provider.Set(new StorageCell(TestItem.AddressA, 100), [1]); + provider.Set(new StorageCell(TestItem.AddressA, 200), [2]); + + provider.Commit(Frontier.Instance); + provider.CommitTree(0); + + baseBlock = Build.A.BlockHeader.WithStateRoot(provider.StateRoot).TestObject; + } + + Hash256 originalStateRoot = baseBlock.StateRoot; + + ctx.WrittenData.Clear(); + + using (provider.BeginScope(baseBlock)) + { + provider.CreateAccountIfNotExists(TestItem.AddressA, 100); + provider.ClearStorage(TestItem.AddressA); + provider.Set(new StorageCell(TestItem.AddressA, 101), [10]); + provider.Set(new StorageCell(TestItem.AddressA, 200), [2]); + + provider.Commit(Frontier.Instance); + provider.CommitTree(0); + + baseBlock = Build.A.BlockHeader.WithParent(baseBlock).WithStateRoot(provider.StateRoot).TestObject; + } + + baseBlock.StateRoot.Should().NotBe(originalStateRoot); + + ctx.WrittenData.SelfDestructed[TestItem.AddressA].Should().BeTrue(); + ctx.WrittenData.Clear(); + + using (provider.BeginScope(baseBlock)) + { + provider.CreateAccountIfNotExists(TestItem.AddressA, 100); + provider.ClearStorage(TestItem.AddressA); + provider.Set(new StorageCell(TestItem.AddressA, 100), [1]); + provider.Set(new StorageCell(TestItem.AddressA, 200), [2]); + + provider.Commit(Frontier.Instance); + provider.CommitTree(0); + + baseBlock = Build.A.BlockHeader.WithParent(baseBlock).WithStateRoot(provider.StateRoot).TestObject; + } + + baseBlock.StateRoot.Should().Be(originalStateRoot); + + ctx.WrittenData.SelfDestructed[TestItem.AddressA].Should().BeTrue(); + } + + [Test] + public void Selfdestruct_works_even_when_its_the_only_call() + { + Context ctx = new(setInitialState: false, trackWrittenData: true); + WorldState provider = BuildStorageProvider(ctx); + + BlockHeader baseBlock = null; + using (provider.BeginScope(baseBlock)) + { + provider.CreateAccountIfNotExists(TestItem.AddressA, 100); + provider.Set(new StorageCell(TestItem.AddressA, 100), [1]); + provider.Set(new StorageCell(TestItem.AddressA, 200), [2]); + + provider.Commit(Frontier.Instance); + provider.CommitTree(0); + + baseBlock = Build.A.BlockHeader.WithStateRoot(provider.StateRoot).TestObject; + } + + ctx.WrittenData.Clear(); + + using (provider.BeginScope(baseBlock)) + { + provider.CreateAccountIfNotExists(TestItem.AddressA, 100); + provider.ClearStorage(TestItem.AddressA); + provider.DeleteAccount(TestItem.AddressA); + + provider.Commit(Frontier.Instance); + provider.CommitTree(0); + + baseBlock = Build.A.BlockHeader.WithParent(baseBlock).WithStateRoot(provider.StateRoot).TestObject; + } + + ctx.WrittenData.SelfDestructed[TestItem.AddressA].Should().BeTrue(); + ctx.WrittenData.Clear(); + + using (provider.BeginScope(baseBlock)) + { + provider.CreateAccountIfNotExists(TestItem.AddressA, 100); + provider.Get(new StorageCell(TestItem.AddressA, 100)).ToArray().Should().BeEquivalentTo(StorageTree.ZeroBytes); + + provider.Commit(Frontier.Instance); + provider.CommitTree(0); + } + } + + [Test] + public void Selfdestruct_in_the_same_transaction() + { + Context ctx = new(setInitialState: false); + WorldState provider = BuildStorageProvider(ctx); + + BlockHeader baseBlock = null; + using (provider.BeginScope(baseBlock)) + { + provider.CreateAccountIfNotExists(TestItem.AddressA, 100); + provider.Set(new StorageCell(TestItem.AddressA, 100), [1]); + provider.Set(new StorageCell(TestItem.AddressA, 200), [2]); + provider.ClearStorage(TestItem.AddressA); + provider.DeleteAccount(TestItem.AddressA); + + provider.Commit(Frontier.Instance); + provider.CommitTree(0); + + baseBlock = Build.A.BlockHeader.WithStateRoot(provider.StateRoot).TestObject; + } + + baseBlock.StateRoot.Should().Be(Keccak.EmptyTreeHash); + } + [Test] public void Selfdestruct_persist_between_commit() { @@ -460,7 +590,8 @@ public void Selfdestruct_persist_between_commit() [TestCase(1000)] public void Set_empty_value_for_storage_cell_without_read_clears_data(int numItems) { - IWorldState worldState = new WorldState(TestTrieStoreFactory.Build(new MemDb(), LimboLogs.Instance), Substitute.For(), LogManager); + IWorldState worldState = new WorldState( + new TrieStoreScopeProvider(TestTrieStoreFactory.Build(new MemDb(), LimboLogs.Instance), new MemDb(), LimboLogs.Instance), LogManager); using var disposable = worldState.BeginScope(IWorldState.PreGenesis); worldState.CreateAccount(TestItem.AddressA, 1); @@ -494,7 +625,8 @@ public void Set_empty_value_for_storage_cell_without_read_clears_data(int numIte [Test] public void Set_empty_value_for_storage_cell_with_read_clears_data() { - IWorldState worldState = new WorldState(TestTrieStoreFactory.Build(new MemDb(), LimboLogs.Instance), Substitute.For(), LogManager); + IWorldState worldState = new WorldState( + new TrieStoreScopeProvider(TestTrieStoreFactory.Build(new MemDb(), LimboLogs.Instance), new MemDb(), LimboLogs.Instance), LogManager); using var disposable = worldState.BeginScope(IWorldState.PreGenesis); worldState.CreateAccount(TestItem.AddressA, 1); @@ -525,13 +657,33 @@ public void Set_empty_value_for_storage_cell_with_read_clears_data() private class Context { public WorldState StateProvider { get; } + internal WrittenData WrittenData = null; public readonly Address Address1 = new(Keccak.Compute("1")); public readonly Address Address2 = new(Keccak.Compute("2")); - public Context(PreBlockCaches preBlockCaches = null, bool setInitialState = true) + public Context(PreBlockCaches preBlockCaches = null, bool setInitialState = true, bool trackWrittenData = false) { - StateProvider = new WorldState(TestTrieStoreFactory.Build(new MemDb(), LimboLogs.Instance), Substitute.For(), LogManager, preBlockCaches); + IWorldStateScopeProvider scopeProvider = new TrieStoreScopeProvider( + TestTrieStoreFactory.Build(new MemDb(), LimboLogs.Instance), + new MemDb(), LimboLogs.Instance); + + if (preBlockCaches is not null) + { + scopeProvider = new PrewarmerScopeProvider(scopeProvider, preBlockCaches, populatePreBlockCache: true); + } + + if (trackWrittenData) + { + WrittenData = new WrittenData( + new ConcurrentDictionary(), + new ConcurrentDictionary(), + new ConcurrentDictionary() + ); + scopeProvider = new WritesInterceptor(scopeProvider, WrittenData); + } + + StateProvider = new WorldState(scopeProvider, LogManager); if (setInitialState) { StateProvider.BeginScope(IWorldState.PreGenesis); @@ -541,4 +693,126 @@ public Context(PreBlockCaches preBlockCaches = null, bool setInitialState = true } } } + + internal record WrittenData( + ConcurrentDictionary Accounts, + ConcurrentDictionary Slots, + ConcurrentDictionary SelfDestructed) + { + public void Clear() + { + Accounts.Clear(); + Slots.Clear(); + SelfDestructed.Clear(); + } + } + + private class WritesInterceptor(IWorldStateScopeProvider scopeProvider, WrittenData writtenData) : IWorldStateScopeProvider + { + + public bool HasRoot(BlockHeader baseBlock) + { + return scopeProvider.HasRoot(baseBlock); + } + + public IWorldStateScopeProvider.IScope BeginScope(BlockHeader baseBlock) + { + return new ScopeDecorator(scopeProvider.BeginScope(baseBlock), writtenData); + } + + private class ScopeDecorator(IWorldStateScopeProvider.IScope baseScope, WrittenData writtenData) : IWorldStateScopeProvider.IScope + { + public void Dispose() + { + baseScope.Dispose(); + } + + public Hash256 RootHash => baseScope.RootHash; + + public void UpdateRootHash() + { + baseScope.UpdateRootHash(); + } + + public Account Get(Address address) + { + return baseScope.Get(address); + } + + public void HintGet(Address address, Account account) + { + baseScope.HintGet(address, account); + } + + public IWorldStateScopeProvider.ICodeDb CodeDb => baseScope.CodeDb; + + public IWorldStateScopeProvider.IStorageTree CreateStorageTree(Address address) + { + return baseScope.CreateStorageTree(address); + } + + public IWorldStateScopeProvider.IWorldStateWriteBatch StartWriteBatch(int estimatedAccountNum) + { + return new WriteBatchDecorator(baseScope.StartWriteBatch(estimatedAccountNum), writtenData); + } + + public void Commit(long blockNumber) + { + baseScope.Commit(blockNumber); + } + } + + private class WriteBatchDecorator( + IWorldStateScopeProvider.IWorldStateWriteBatch writeBatch, + WrittenData writtenData + ) + : IWorldStateScopeProvider.IWorldStateWriteBatch + { + public void Dispose() + { + writeBatch.Dispose(); + } + + public event EventHandler OnAccountUpdated + { + add => writeBatch.OnAccountUpdated += value; + remove => writeBatch.OnAccountUpdated -= value; + } + + public void Set(Address key, Account account) + { + writeBatch.Set(key, account); + } + + public IWorldStateScopeProvider.IStorageWriteBatch CreateStorageWriteBatch(Address key, int estimatedEntries) + { + return new StorageWriteBatchDecorator(writeBatch.CreateStorageWriteBatch(key, estimatedEntries), key, writtenData); + + } + } + + private class StorageWriteBatchDecorator( + IWorldStateScopeProvider.IStorageWriteBatch baseStorageBatch, + Address address, + WrittenData writtenData + ) : IWorldStateScopeProvider.IStorageWriteBatch + { + public void Dispose() + { + baseStorageBatch?.Dispose(); + } + + public void Set(in UInt256 index, byte[] value) + { + baseStorageBatch.Set(in index, value); + writtenData.Slots[new StorageCell(address, index)] = value; + } + + public void Clear() + { + baseStorageBatch.Clear(); + writtenData.SelfDestructed[address] = true; + } + } + } } diff --git a/src/Nethermind/Nethermind.State.Test/TrieStoreScopeProviderTests.cs b/src/Nethermind/Nethermind.State.Test/TrieStoreScopeProviderTests.cs new file mode 100644 index 00000000000..d3742eec32b --- /dev/null +++ b/src/Nethermind/Nethermind.State.Test/TrieStoreScopeProviderTests.cs @@ -0,0 +1,99 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using FluentAssertions; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test; +using Nethermind.Core.Test.Builders; +using Nethermind.Db; +using Nethermind.Evm.State; +using Nethermind.Logging; +using Nethermind.State; +using NUnit.Framework; + +namespace Nethermind.Store.Test; + +public class TrieStoreScopeProviderTests +{ + [Test] + public void Test_CanSaveToState() + { + TestMemDb kv = new TestMemDb(); + IWorldStateScopeProvider scopeProvider = new TrieStoreScopeProvider(new TestRawTrieStore(kv), new MemDb(), LimboLogs.Instance); + + Hash256 stateRoot; + using (var scope = scopeProvider.BeginScope(null)) + { + scope.Get(TestItem.AddressA).Should().Be(null); + using (var writeBatch = scope.StartWriteBatch(1)) + { + writeBatch.Set(TestItem.AddressA, new Account(100, 100)); + } + + scope.Commit(1); + stateRoot = scope.RootHash; + } + + stateRoot.Should().NotBe(Keccak.EmptyTreeHash); + kv.WritesCount.Should().Be(1); + + using (var scope = scopeProvider.BeginScope(Build.A.BlockHeader.WithStateRoot(stateRoot).WithNumber(1).TestObject)) + { + scope.Get(TestItem.AddressA).Balance.Should().Be(100); + } + } + + [Test] + public void Test_CanSaveToStorage() + { + TestMemDb kv = new TestMemDb(); + IWorldStateScopeProvider scopeProvider = new TrieStoreScopeProvider(new TestRawTrieStore(kv), new MemDb(), LimboLogs.Instance); + + Hash256 stateRoot; + using (var scope = scopeProvider.BeginScope(null)) + { + scope.Get(TestItem.AddressA).Should().Be(null); + + using (var writeBatch = scope.StartWriteBatch(1)) + { + writeBatch.Set(TestItem.AddressA, new Account(100, 100)); + + using (var storageSet = writeBatch.CreateStorageWriteBatch(TestItem.AddressA, 1)) + { + storageSet.Set(1, [1, 2, 3]); + } + } + + scope.Commit(1); + stateRoot = scope.RootHash; + } + + stateRoot.Should().NotBe(Keccak.EmptyTreeHash); + kv.WritesCount.Should().Be(2); + + using (var scope = scopeProvider.BeginScope(Build.A.BlockHeader.WithStateRoot(stateRoot).WithNumber(1).TestObject)) + { + var storage = scope.CreateStorageTree(TestItem.AddressA); + storage.Get(1).Should().BeEquivalentTo([1, 2, 3]); + } + } + + [Test] + public void Test_CanSaveToCode() + { + TestMemDb kv = new TestMemDb(); + TestMemDb codeKv = new TestMemDb(); + IWorldStateScopeProvider scopeProvider = new TrieStoreScopeProvider(new TestRawTrieStore(kv), codeKv, LimboLogs.Instance); + + using (var scope = scopeProvider.BeginScope(null)) + { + using (var writer = scope.CodeDb.BeginCodeWrite()) + { + writer.Set(TestItem.KeccakA, [1, 2, 3]); + } + } + + codeKv.WritesCount.Should().Be(1); + } +} diff --git a/src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs b/src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs index 4295bba26d4..c85913a1dba 100644 --- a/src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs +++ b/src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs @@ -7,6 +7,7 @@ using Nethermind.Blockchain; using Nethermind.Blockchain.Synchronization; using Nethermind.Config; +using Nethermind.Consensus.Processing; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; @@ -28,7 +29,7 @@ public class WorldStateManagerTests [Test] public void ShouldProxyGlobalWorldState() { - IWorldState worldState = Substitute.For(); + IWorldStateScopeProvider worldState = Substitute.For(); IPruningTrieStore trieStore = Substitute.For(); IDbProvider dbProvider = TestMemDbProvider.Init(); WorldStateManager worldStateManager = new WorldStateManager(worldState, trieStore, dbProvider, LimboLogs.Instance); @@ -39,7 +40,7 @@ public void ShouldProxyGlobalWorldState() [Test] public void ShouldProxyReorgBoundaryEvent() { - IWorldState worldState = Substitute.For(); + IWorldStateScopeProvider worldState = Substitute.For(); IPruningTrieStore trieStore = Substitute.For(); IDbProvider dbProvider = TestMemDbProvider.Init(); WorldStateManager worldStateManager = new WorldStateManager(worldState, trieStore, dbProvider, LimboLogs.Instance); @@ -55,7 +56,7 @@ public void ShouldProxyReorgBoundaryEvent() [TestCase(INodeStorage.KeyScheme.HalfPath, false)] public void ShouldNotSupportHashLookupOnHalfpath(INodeStorage.KeyScheme keyScheme, bool hashSupported) { - IWorldState worldState = Substitute.For(); + IWorldStateScopeProvider worldState = Substitute.For(); IPruningTrieStore trieStore = Substitute.For(); IReadOnlyTrieStore readOnlyTrieStore = Substitute.For(); trieStore.AsReadOnly().Returns(readOnlyTrieStore); @@ -93,7 +94,7 @@ public void ShouldAnnounceReorgOnDispose() .AddSingleton(blockTree) .Build(); - IWorldState worldState = ctx.Resolve().GlobalWorldState; + IWorldState worldState = ctx.Resolve().WorldState; Hash256 stateRoot; diff --git a/src/Nethermind/Nethermind.State/Healing/HealingStorageTreeFactory.cs b/src/Nethermind/Nethermind.State/Healing/HealingStorageTreeFactory.cs deleted file mode 100644 index c1f1f59d0cd..00000000000 --- a/src/Nethermind/Nethermind.State/Healing/HealingStorageTreeFactory.cs +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Logging; -using Nethermind.Trie.Pruning; - -namespace Nethermind.State.Healing; - -public class HealingStorageTreeFactory(INodeStorage nodeStorage, Lazy recovery) : IStorageTreeFactory -{ - public StorageTree Create(Address address, IScopedTrieStore trieStore, Hash256 storageRoot, Hash256 stateRoot, ILogManager? logManager) => - new HealingStorageTree(trieStore, nodeStorage, storageRoot, logManager, address, stateRoot, recovery); -} diff --git a/src/Nethermind/Nethermind.State/Healing/HealingWorldState.cs b/src/Nethermind/Nethermind.State/Healing/HealingWorldState.cs deleted file mode 100644 index 78c6097e413..00000000000 --- a/src/Nethermind/Nethermind.State/Healing/HealingWorldState.cs +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using Nethermind.Core; -using Nethermind.Logging; -using Nethermind.Trie.Pruning; - -namespace Nethermind.State.Healing; - -public class HealingWorldState( - ITrieStore trieStore, - INodeStorage nodeStorage, - IKeyValueStoreWithBatching? codeDb, - Lazy pathRecovery, - ILogManager? logManager, - PreBlockCaches? preBlockCaches = null, - bool populatePreBlockCache = true) - : WorldState(trieStore, codeDb, logManager, new HealingStateTree(trieStore, nodeStorage, pathRecovery, logManager), new HealingStorageTreeFactory(nodeStorage, pathRecovery), preBlockCaches, populatePreBlockCache) -{ -} diff --git a/src/Nethermind/Nethermind.State/Healing/HealingWorldStateScopeProvider.cs b/src/Nethermind/Nethermind.State/Healing/HealingWorldStateScopeProvider.cs new file mode 100644 index 00000000000..920d1066d96 --- /dev/null +++ b/src/Nethermind/Nethermind.State/Healing/HealingWorldStateScopeProvider.cs @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Evm.State; +using Nethermind.Logging; +using Nethermind.Trie.Pruning; + +namespace Nethermind.State.Healing; + +public class HealingWorldStateScopeProvider(ITrieStore trieStore, IKeyValueStoreWithBatching codeDb, INodeStorage nodeStorage, Lazy recovery, ILogManager logManager) : TrieStoreScopeProvider(trieStore, codeDb, logManager) +{ + private readonly ILogManager? _logManager = logManager; + private readonly ITrieStore _trieStore = trieStore; + + protected override StateTree CreateStateTree() + { + return new HealingStateTree(_trieStore, nodeStorage, recovery, _logManager); + } + + protected override StorageTree CreateStorageTree(Address address, Hash256 storageRoot) + { + return new HealingStorageTree(_trieStore.GetTrieStore(address), nodeStorage, storageRoot, _logManager, address, _backingStateTree.RootHash, recovery); + } +} diff --git a/src/Nethermind/Nethermind.State/IWorldStateManager.cs b/src/Nethermind/Nethermind.State/IWorldStateManager.cs index a4ad6c9dacf..6c56f8ca6dd 100644 --- a/src/Nethermind/Nethermind.State/IWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/IWorldStateManager.cs @@ -5,7 +5,6 @@ using System.Threading; using Nethermind.Core; using Nethermind.Evm.State; -using Nethermind.State.Healing; using Nethermind.State.SnapServer; using Nethermind.Trie.Pruning; @@ -13,7 +12,7 @@ namespace Nethermind.State; public interface IWorldStateManager { - IWorldState GlobalWorldState { get; } + IWorldStateScopeProvider GlobalWorldState { get; } IStateReader GlobalStateReader { get; } ISnapServer? SnapServer { get; } IReadOnlyKeyValueStore? HashServer { get; } @@ -22,14 +21,7 @@ public interface IWorldStateManager /// Used by read only tasks that need to execute blocks. /// /// - IWorldState CreateResettableWorldState(); - - /// - /// Create a read only world state to warm up another world state - /// - /// Specify a world state to warm up by the returned world state. - /// - IWorldState CreateWorldStateForWarmingUp(IWorldState forWarmup); + IWorldStateScopeProvider CreateResettableWorldState(); event EventHandler? ReorgBoundaryReached; @@ -52,7 +44,7 @@ public interface IWorldStateManager public interface IOverridableWorldScope { - IDisposable BeginScope(BlockHeader? header); - IWorldState WorldState { get; } + IWorldStateScopeProvider WorldState { get; } IStateReader GlobalStateReader { get; } + void ResetOverrides(); } diff --git a/src/Nethermind/Nethermind.State/OverridableEnv/OverridableEnvFactory.cs b/src/Nethermind/Nethermind.State/OverridableEnv/OverridableEnvFactory.cs index 9cd841602bf..18209cddf5b 100644 --- a/src/Nethermind/Nethermind.State/OverridableEnv/OverridableEnvFactory.cs +++ b/src/Nethermind/Nethermind.State/OverridableEnv/OverridableEnvFactory.cs @@ -9,6 +9,7 @@ using Nethermind.Core.Specs; using Nethermind.Evm; using Nethermind.Evm.State; +using Nethermind.Logging; namespace Nethermind.State.OverridableEnv; @@ -18,7 +19,7 @@ public IOverridableEnv Create() { IOverridableWorldScope overridableScope = worldStateManager.CreateOverridableWorldScope(); ILifetimeScope childLifetimeScope = parentLifetimeScope.BeginLifetimeScope((builder) => builder - .AddSingleton(overridableScope.WorldState) + .AddSingleton(overridableScope.WorldState) .AddDecorator() .AddScoped((codeInfoRepo) => (codeInfoRepo as OverridableCodeInfoRepository)!)); @@ -33,19 +34,20 @@ ISpecProvider specProvider { private IDisposable? _worldScopeCloser; private readonly IOverridableCodeInfoRepository _codeInfoRepository = childLifetimeScope.Resolve(); + private readonly IWorldState _worldState = childLifetimeScope.Resolve(); public IDisposable BuildAndOverride(BlockHeader header, Dictionary? stateOverride) { if (_worldScopeCloser is not null) throw new InvalidOperationException("Previous overridable world scope was not closed"); Reset(); - _worldScopeCloser = overridableScope.BeginScope(header); + _worldScopeCloser = _worldState.BeginScope(header); IDisposable scope = new Scope(this); if (stateOverride is not null) { - overridableScope.WorldState.ApplyStateOverrides(_codeInfoRepository, stateOverride, specProvider.GetSpec(header), header.Number); - header.StateRoot = overridableScope.WorldState.StateRoot; + _worldState.ApplyStateOverrides(_codeInfoRepository, stateOverride, specProvider.GetSpec(header), header.Number); + header.StateRoot = _worldState.StateRoot; } return scope; @@ -65,11 +67,12 @@ private void Reset() _worldScopeCloser?.Dispose(); _worldScopeCloser = null; + overridableScope.ResetOverrides(); } protected override void Load(ContainerBuilder builder) => builder - .AddScoped(overridableScope.WorldState) + .AddScoped(_worldState) .AddScoped(overridableScope.GlobalStateReader) .AddScoped(this) .AddScoped(_codeInfoRepository) diff --git a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs index b64ff4a156a..46412024a93 100644 --- a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs @@ -1,8 +1,6 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; -using Nethermind.Core; using Nethermind.Db; using Nethermind.Evm.State; using Nethermind.Logging; @@ -21,19 +19,10 @@ public OverridableWorldStateManager(IDbProvider dbProvider, IReadOnlyTrieStore t _dbProvider = readOnlyDbProvider; OverlayTrieStore overlayTrieStore = new(readOnlyDbProvider.StateDb, trieStore); _reader = new(overlayTrieStore, readOnlyDbProvider.CodeDb, logManager); - WorldState = new WorldState(overlayTrieStore, readOnlyDbProvider.CodeDb, logManager, null, true); + WorldState = new TrieStoreScopeProvider(overlayTrieStore, readOnlyDbProvider.CodeDb, logManager); } - public IWorldState WorldState { get; } - public IDisposable BeginScope(BlockHeader? header) - { - IDisposable closer = WorldState.BeginScope(header); - return new Reactive.AnonymousDisposable(() => - { - closer.Dispose(); - ResetOverrides(); - }); - } + public IWorldStateScopeProvider WorldState { get; } public IStateReader GlobalStateReader => _reader; public void ResetOverrides() diff --git a/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs b/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs index d1b125d01e9..a37cc2c3aed 100644 --- a/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs +++ b/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs @@ -141,19 +141,11 @@ public void Restore(int snapshot) } - /// - /// Commit persistent storage - /// - public void Commit(bool commitRoots = true) - { - Commit(NullStateTracer.Instance, commitRoots); - } - /// /// Commit persistent storage /// /// State tracer - public void Commit(IStorageTracer tracer, bool commitRoots = true) + public void Commit(IStorageTracer tracer) { if (_changes.Count == 0) { @@ -163,16 +155,6 @@ public void Commit(IStorageTracer tracer, bool commitRoots = true) { CommitCore(tracer); } - - if (commitRoots) - { - CommitStorageRoots(); - } - } - - protected virtual void CommitStorageRoots() - { - // Commit storage roots } /// diff --git a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs index a62d6d194c5..930f2ecf35d 100644 --- a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs +++ b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -16,10 +17,9 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Resettables; using Nethermind.Core.Threading; +using Nethermind.Evm.State; using Nethermind.Evm.Tracing.State; using Nethermind.Logging; -using Nethermind.Serialization.Rlp; -using Nethermind.Trie.Pruning; using Nethermind.Int256; using Nethermind.Trie; @@ -33,10 +33,8 @@ namespace Nethermind.State; /// internal sealed class PersistentStorageProvider : PartialStorageProviderBase { - private readonly ITrieStore _trieStore; + private IWorldStateScopeProvider.IScope _currentScope; private readonly StateProvider _stateProvider; - private readonly ILogManager? _logManager; - private readonly IStorageTreeFactory _storageTreeFactory; private readonly Dictionary _storages = new(4_096); private readonly Dictionary _toUpdateRoots = new(); @@ -46,30 +44,18 @@ internal sealed class PersistentStorageProvider : PartialStorageProviderBase private readonly Dictionary _originalValues = new(); private readonly HashSet _committedThisRound = new(); - private readonly ConcurrentDictionary? _preBlockCache; /// /// Manages persistent storage allowing for snapshotting and restoring /// Persists data to ITrieStore /// - public PersistentStorageProvider(ITrieStore trieStore, + public PersistentStorageProvider( StateProvider stateProvider, - ILogManager logManager, - IStorageTreeFactory? storageTreeFactory, - ConcurrentDictionary? preBlockCache, - bool populatePreBlockCache) : base(logManager) + ILogManager logManager) : base(logManager) { - _trieStore = trieStore ?? throw new ArgumentNullException(nameof(trieStore)); - _stateProvider = stateProvider ?? throw new ArgumentNullException(nameof(stateProvider)); - _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); - _storageTreeFactory = storageTreeFactory ?? new StorageTreeFactory(); - _preBlockCache = preBlockCache; - _populatePreBlockCache = populatePreBlockCache; + _stateProvider = stateProvider; } - public Hash256 StateRoot { get; set; } = null!; - internal readonly bool _populatePreBlockCache; - /// /// Reset the storage state /// @@ -85,6 +71,11 @@ public override void Reset(bool resetBlockChanges = true) } } + public void SetBackendScope(IWorldStateScopeProvider.IScope scope) + { + _currentScope = scope; + } + /// /// Get the current value at the specified location /// @@ -119,6 +110,11 @@ public byte[] GetOriginal(in StorageCell storageCell) return value; } + public Hash256 GetStorageRoot(Address address) + { + return GetOrCreateStorage(address).StorageRoot; + } + private HashSet? _tempToUpdateRoots; /// /// Called by Commit @@ -243,7 +239,7 @@ protected override void CommitCore(IStorageTracer tracer) } } - protected override void CommitStorageRoots() + internal void FlushToTree(IWorldStateScopeProvider.IWorldStateWriteBatch writeBatch) { if (_toUpdateRoots.Count == 0) { @@ -273,19 +269,22 @@ void UpdateRootHashesSingleThread() } PerContractState contractState = kvp.Value; - (int writes, int skipped) = contractState.ProcessStorageChanges(); + (int writes, int skipped) = contractState.ProcessStorageChanges(writeBatch.CreateStorageWriteBatch(kvp.Key, kvp.Value.EstimatedChanges)); ReportMetrics(writes, skipped); - if (writes > 0) - { - _stateProvider.UpdateStorageRoot(address: kvp.Key, contractState.RootHash); - } } } void UpdateRootHashesMultiThread() { // We can recalculate the roots in parallel as they are all independent tries - using var storages = _storages.ToPooledList(); + using ArrayPoolList<(AddressAsKey Key, PerContractState ContractState, IWorldStateScopeProvider.IStorageWriteBatch WriteBatch)> storages = _storages + .Select((kv) => ( + kv.Key, + kv.Value, + writeBatch.CreateStorageWriteBatch(kv.Key, kv.Value.EstimatedChanges) + )) + .ToPooledList(_storages.Count); + ParallelUnbalancedWork.For( 0, storages.Count, @@ -300,7 +299,7 @@ void UpdateRootHashesMultiThread() return state; } - (int writes, int skipped) = kvp.Value.ProcessStorageChanges(); + (int writes, int skipped) = kvp.ContractState.ProcessStorageChanges(kvp.WriteBatch); if (writes == 0) { // Mark as no changes; we set as false rather than removing so @@ -317,19 +316,6 @@ void UpdateRootHashesMultiThread() return state; }, (state) => ReportMetrics(state.writes, state.skips)); - - // Update the storage roots in the main thread not in parallel, - // as can't update the StateTrie in parallel. - foreach (ref var kvp in storages.AsSpan()) - { - if (!_toUpdateRoots.TryGetValue(kvp.Key, out bool hasChanges) || !hasChanges) - { - continue; - } - - // Update the storage root for the Account - _stateProvider.UpdateStorageRoot(address: kvp.Key, kvp.Value.RootHash); - } } static void ReportMetrics(int writes, int skipped) @@ -345,38 +331,8 @@ static void ReportMetrics(int writes, int skipped) } } - /// - /// Commit persistent storage trees - /// - /// Current block number - public void CommitTrees(IBlockCommitter blockCommitter) + public void ClearStorageMap() { - // Note: These all run in about 0.4ms. So the little overhead like attempting to sort the tasks - // may make it worse. Always check on mainnet. - - using ArrayPoolListRef commitTask = new(_storages.Count); - foreach (PerContractState storage in _storages.Values) - { - storage.EnsureStorageTree(); // Cannot be called concurrently - if (blockCommitter.TryRequestConcurrencyQuota()) - { - commitTask.Add(Task.Factory.StartNew((ctx) => - { - PerContractState st = (PerContractState)ctx; - st.Commit(); - st.Return(); - blockCommitter.ReturnConcurrencyQuota(); - }, storage)); - } - else - { - storage.Commit(); - storage.Return(); - } - } - - Task.WaitAll(commitTask.AsSpan()); - _storages.Clear(); } @@ -391,10 +347,6 @@ public void WarmUp(in StorageCell storageCell, bool isEmpty) { if (isEmpty) { - if (_preBlockCache is not null) - { - _preBlockCache[storageCell] = []; - } } else { @@ -437,27 +389,18 @@ public override void ClearStorage(Address address) { base.ClearStorage(address); - // here it is important to make sure that we will not reuse the same tree when the contract is revived - // by means of CREATE 2 - notice that the cached trie may carry information about items that were not - // touched in this block, hence were not zeroed above - // TODO: how does it work with pruning? - _toUpdateRoots.Remove(address); + _toUpdateRoots.TryAdd(address, true); PerContractState state = GetOrCreateStorage(address); state.Clear(); } - private class StorageTreeFactory : IStorageTreeFactory - { - public StorageTree Create(Address address, IScopedTrieStore trieStore, Hash256 storageRoot, Hash256 stateRoot, ILogManager? logManager) - => new(trieStore, storageRoot, logManager); - } - private sealed class DefaultableDictionary() { private bool _missingAreDefault; private readonly Dictionary _dictionary = new(Comparer.Instance); - public int EstimatedSize => _dictionary.Count; + public int EstimatedSize => _dictionary.Count + (_missingAreDefault ? 1 : 0); + public bool HasClear => _missingAreDefault; public int Capacity => _dictionary.Capacity; public void Reset() @@ -507,17 +450,22 @@ public bool Equals(UInt256 x, UInt256 y) public int GetHashCode([DisallowNull] UInt256 obj) => MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(in obj, 1)).FastHash(); } + + public void UnmarkClear() + { + _missingAreDefault = false; + } } private sealed class PerContractState : IReturnable { private static readonly Func _loadFromTreeStorageFunc = LoadFromTreeStorage; + private IWorldStateScopeProvider.IStorageTree? _backend; private readonly DefaultableDictionary BlockChange = new(); + private bool _wasWritten = false; private PersistentStorageProvider _provider; private Address _address; - private StorageTree? StorageTree; - private bool _wasWritten = false; private PerContractState(Address address, PersistentStorageProvider provider) => Initialize(address, provider); @@ -527,27 +475,30 @@ private void Initialize(Address address, PersistentStorageProvider provider) _provider = provider; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void EnsureStorageTree() + public int EstimatedChanges => BlockChange.EstimatedSize; + + public Hash256 StorageRoot { - if (StorageTree is not null) return; + get + { + EnsureStorageTree(); + return _backend.RootHash; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void EnsureStorageTree() + { + if (_backend is not null) return; CreateStorageTree(); } [MethodImpl(MethodImplOptions.NoInlining)] private void CreateStorageTree() { - // Note: GetStorageRoot is not concurrent safe! And so do this whole method! - Account? acc = _provider._stateProvider.GetAccount(_address); - Hash256 storageRoot = acc?.StorageRoot ?? Keccak.EmptyTreeHash; - bool isEmpty = storageRoot == Keccak.EmptyTreeHash; // We know all lookups will be empty against this tree - StorageTree = _provider._storageTreeFactory.Create(_address, - _provider._trieStore.GetTrieStore(_address), - storageRoot, - _provider.StateRoot, - _provider._logManager); + _backend = _provider._currentScope.CreateStorageTree(_address); + bool isEmpty = _backend.RootHash == Keccak.EmptyTreeHash; if (isEmpty && !_wasWritten) { // Slight optimization that skips the tree @@ -555,24 +506,9 @@ private void CreateStorageTree() } } - public Hash256 RootHash - { - get - { - EnsureStorageTree(); - return StorageTree.RootHash; - } - } - - public void Commit() - { - EnsureStorageTree(); - StorageTree.Commit(); - } - public void Clear() { - StorageTree = new StorageTree(_provider._trieStore.GetTrieStore(_address), Keccak.EmptyTreeHash, _provider._logManager); + EnsureStorageTree(); BlockChange.ClearAndSetMissingAsDefault(); } @@ -580,7 +516,7 @@ public void Return() { _address = null; _provider = null; - StorageTree = null; + _backend = null; _wasWritten = false; Pool.Return(this); } @@ -604,9 +540,7 @@ public ReadOnlySpan LoadFromTree(in StorageCell storageCell) ref StorageChangeTrace valueChange = ref BlockChange.GetValueRefOrAddDefault(storageCell.Index, out bool exists); if (!exists) { - byte[] value = !_provider._populatePreBlockCache ? - LoadFromTreeReadPreWarmCache(in storageCell) : - LoadFromTreePopulatePrewarmCache(in storageCell); + byte[] value = LoadFromTreeStorage(storageCell); valueChange = new(value, value); } @@ -619,100 +553,48 @@ public ReadOnlySpan LoadFromTree(in StorageCell storageCell) return valueChange.After; } - private byte[] LoadFromTreeReadPreWarmCache(in StorageCell storageCell) - { - if (_provider._preBlockCache?.TryGetValue(storageCell, out byte[] value) ?? false) - { - Db.Metrics.IncrementStorageTreeCache(); - } - else - { - value = LoadFromTreeStorage(storageCell); - } - return value; - } - - private byte[] LoadFromTreePopulatePrewarmCache(in StorageCell storageCell) - { - long priorReads = Db.Metrics.ThreadLocalStorageTreeReads; - - byte[] value = _provider._preBlockCache is not null - ? _provider._preBlockCache.GetOrAdd(storageCell, _loadFromTreeStorageFunc, this) - : LoadFromTreeStorage(storageCell); - - if (Db.Metrics.ThreadLocalStorageTreeReads == priorReads) - { - // Read from Concurrent Cache - Db.Metrics.IncrementStorageTreeCache(); - } - return value; - } - - private byte[] LoadFromTreeStorage(in StorageCell storageCell) + private byte[] LoadFromTreeStorage(StorageCell storageCell) { Db.Metrics.IncrementStorageTreeReads(); EnsureStorageTree(); return !storageCell.IsHash - ? StorageTree.Get(storageCell.Index) - : StorageTree.GetArray(storageCell.Hash.Bytes); + ? _backend.Get(storageCell.Index) + : _backend.Get(storageCell.Hash); } private static byte[] LoadFromTreeStorage(StorageCell storageCell, PerContractState @this) => @this.LoadFromTreeStorage(storageCell); - public (int writes, int skipped) ProcessStorageChanges() + public (int writes, int skipped) ProcessStorageChanges(IWorldStateScopeProvider.IStorageWriteBatch storageWriteBatch) { EnsureStorageTree(); + using IWorldStateScopeProvider.IStorageWriteBatch _ = storageWriteBatch; + int writes = 0; int skipped = 0; - if (BlockChange.EstimatedSize < PatriciaTree.MinEntriesToParallelizeThreshold) + + if (BlockChange.HasClear) { - foreach (var kvp in BlockChange) - { - byte[] after = kvp.Value.After; - if (!Bytes.AreEqual(kvp.Value.Before, after) || kvp.Value.IsInitialValue) - { - BlockChange[kvp.Key] = new(after, after); - StorageTree.Set(kvp.Key, after); - writes++; - } - else - { - skipped++; - } - } + storageWriteBatch.Clear(); + BlockChange.UnmarkClear(); // Note: Until the storage write batch is disposed, this BlockCache will pass read through the uncleared storage tree } - else - { - using ArrayPoolListRef bulkWrite = new(BlockChange.EstimatedSize); - Span keyBuf = stackalloc byte[32]; - foreach (KeyValuePair kvp in BlockChange) + foreach (var kvp in BlockChange) + { + byte[] after = kvp.Value.After; + if (!Bytes.AreEqual(kvp.Value.Before, after) || kvp.Value.IsInitialValue) { - byte[] after = kvp.Value.After; - if (!Bytes.AreEqual(kvp.Value.Before, after) || kvp.Value.IsInitialValue) - { - BlockChange[kvp.Key] = new(after, after); + BlockChange[kvp.Key] = new(after, after); + storageWriteBatch.Set(kvp.Key, after); - StorageTree.ComputeKeyWithLookup(kvp.Key, keyBuf); - bulkWrite.Add(StorageTree.CreateBulkSetEntry(new ValueHash256(keyBuf), after)); - - writes++; - } - else - { - skipped++; - } + writes++; + } + else + { + skipped++; } - - StorageTree.BulkSet(bulkWrite); - } - - if (writes > 0) - { - StorageTree.UpdateRootHash(canBeParallel: writes > 64); } return (writes, skipped); @@ -720,7 +602,7 @@ private static byte[] LoadFromTreeStorage(StorageCell storageCell, PerContractSt public void RemoveStorageTree() { - StorageTree = null; + _backend = null; } internal static PerContractState Rent(Address address, PersistentStorageProvider persistentStorageProvider) diff --git a/src/Nethermind/Nethermind.State/PreBlockCaches.cs b/src/Nethermind/Nethermind.State/PreBlockCaches.cs index 5b5e1635560..08586d2c8a8 100644 --- a/src/Nethermind/Nethermind.State/PreBlockCaches.cs +++ b/src/Nethermind/Nethermind.State/PreBlockCaches.cs @@ -31,7 +31,6 @@ public PreBlockCaches() [ () => _storageCache.NoResizeClear() ? CacheType.Storage : CacheType.None, () => _stateCache.NoResizeClear() ? CacheType.State : CacheType.None, - () => _rlpCache.NoResizeClear() ? CacheType.Rlp : CacheType.None, () => _precompileCache.NoResizeClear() ? CacheType.Precompile : CacheType.None ]; } diff --git a/src/Nethermind/Nethermind.State/PrewarmerScopeProvider.cs b/src/Nethermind/Nethermind.State/PrewarmerScopeProvider.cs new file mode 100644 index 00000000000..d88567071d1 --- /dev/null +++ b/src/Nethermind/Nethermind.State/PrewarmerScopeProvider.cs @@ -0,0 +1,154 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Concurrent; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Db; +using Nethermind.Evm.State; +using Nethermind.Int256; + +namespace Nethermind.State; + +public class PrewarmerScopeProvider( + IWorldStateScopeProvider baseProvider, + PreBlockCaches preBlockCaches, + bool populatePreBlockCache = true +) : IWorldStateScopeProvider, IPreBlockCaches +{ + public bool HasRoot(BlockHeader? baseBlock) => baseProvider.HasRoot(baseBlock); + + public IWorldStateScopeProvider.IScope BeginScope(BlockHeader? baseBlock) => new ScopeWrapper(baseProvider.BeginScope(baseBlock), preBlockCaches, populatePreBlockCache); + + public PreBlockCaches? Caches => preBlockCaches; + public bool IsWarmWorldState => !populatePreBlockCache; + + private sealed class ScopeWrapper( + IWorldStateScopeProvider.IScope baseScope, + PreBlockCaches preBlockCaches, + bool populatePreBlockCache) + : IWorldStateScopeProvider.IScope + { + ConcurrentDictionary preBlockCache = preBlockCaches.StateCache; + + public void Dispose() => baseScope.Dispose(); + + public IWorldStateScopeProvider.ICodeDb CodeDb => baseScope.CodeDb; + + public IWorldStateScopeProvider.IStorageTree CreateStorageTree(Address address) + { + return new StorageTreeWrapper( + baseScope.CreateStorageTree(address), + preBlockCaches.StorageCache, + address, + populatePreBlockCache); + } + + public IWorldStateScopeProvider.IWorldStateWriteBatch StartWriteBatch(int estimatedAccountNum) + { + return baseScope.StartWriteBatch(estimatedAccountNum); + } + + public void Commit(long blockNumber) => baseScope.Commit(blockNumber); + + public Hash256 RootHash => baseScope.RootHash; + + public void UpdateRootHash() + { + baseScope.UpdateRootHash(); + } + + public Account? Get(Address address) + { + AddressAsKey addressAsKey = address; + if (populatePreBlockCache) + { + long priorReads = Metrics.ThreadLocalStateTreeReads; + Account? account = preBlockCache.GetOrAdd(address, GetFromBaseTree); + + if (Metrics.ThreadLocalStateTreeReads == priorReads) + { + Metrics.IncrementStateTreeCacheHits(); + } + return account; + } + else + { + if (preBlockCache?.TryGetValue(addressAsKey, out Account? account) ?? false) + { + baseScope.HintGet(address, account); + Metrics.IncrementStateTreeCacheHits(); + } + else + { + account = GetFromBaseTree(addressAsKey); + } + return account; + } + } + + public void HintGet(Address address, Account? account) => baseScope.HintGet(address, account); + + private Account? GetFromBaseTree(AddressAsKey address) + { + return baseScope.Get(address); + } + } + + private sealed class StorageTreeWrapper( + IWorldStateScopeProvider.IStorageTree baseStorageTree, + ConcurrentDictionary preBlockCache, + Address address, + bool populatePreBlockCache + ) : IWorldStateScopeProvider.IStorageTree + { + public Hash256 RootHash => baseStorageTree.RootHash; + + public byte[] Get(in UInt256 index) + { + StorageCell storageCell = new StorageCell(address, in index); // TODO: Make the dictionary use UInt256 directly + if (populatePreBlockCache) + { + long priorReads = Db.Metrics.ThreadLocalStorageTreeReads; + + byte[] value = preBlockCache.GetOrAdd(storageCell, LoadFromTreeStorage); + + if (Db.Metrics.ThreadLocalStorageTreeReads == priorReads) + { + // Read from Concurrent Cache + Db.Metrics.IncrementStorageTreeCache(); + } + return value; + } + else + { + if (preBlockCache?.TryGetValue(storageCell, out byte[] value) ?? false) + { + baseStorageTree.HintGet(index, value); + Db.Metrics.IncrementStorageTreeCache(); + } + else + { + value = LoadFromTreeStorage(storageCell); + } + return value; + } + } + + public void HintGet(in UInt256 index, byte[]? value) => baseStorageTree.HintGet(in index, value); + + private byte[] LoadFromTreeStorage(StorageCell storageCell) + { + Db.Metrics.IncrementStorageTreeReads(); + + return !storageCell.IsHash + ? baseStorageTree.Get(storageCell.Index) + : baseStorageTree.Get(storageCell.Hash); + } + + public byte[] Get(in ValueHash256 hash) => + // Not a critical path. so we just forward for simplicity + baseStorageTree.Get(in hash); + } +} diff --git a/src/Nethermind/Nethermind.State/StateProvider.cs b/src/Nethermind/Nethermind.State/StateProvider.cs index 7587ebd28e7..7819e506ae7 100644 --- a/src/Nethermind/Nethermind.State/StateProvider.cs +++ b/src/Nethermind/Nethermind.State/StateProvider.cs @@ -18,12 +18,10 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Resettables; using Nethermind.Core.Specs; +using Nethermind.Evm.State; using Nethermind.Evm.Tracing.State; using Nethermind.Int256; using Nethermind.Logging; -using Nethermind.Serialization.Rlp; -using Nethermind.Trie; -using Nethermind.Trie.Pruning; using Metrics = Nethermind.Db.Metrics; using static Nethermind.State.StateProvider; @@ -43,46 +41,22 @@ internal class StateProvider private readonly ClockKeyCacheNonConcurrent _persistedCodeInsertFilter = new(1_024); private readonly ClockKeyCacheNonConcurrent _blockCodeInsertFilter = new(256); private readonly Dictionary _blockChanges = new(4_096); - private readonly ConcurrentDictionary? _preBlockCache; private readonly List _keptInCache = new(); private readonly ILogger _logger; - private readonly IKeyValueStoreWithBatching _codeDb; private Dictionary _codeBatch; private Dictionary.AlternateLookup _codeBatchAlternate; private readonly List _changes = new(Resettable.StartCapacity); - internal readonly StateTree _tree; - private readonly Func _getStateFromTrie; + internal IWorldStateScopeProvider.IScope? _tree; - private readonly bool _populatePreBlockCache; private bool _needsStateRootUpdate; + private IWorldStateScopeProvider.ICodeDb? _codeDb; - public StateProvider(IScopedTrieStore? trieStore, - IKeyValueStoreWithBatching codeDb, - ILogManager logManager, - StateTree? stateTree = null, - ConcurrentDictionary? preBlockCache = null, - bool populatePreBlockCache = true) + public StateProvider( + ILogManager logManager) { - _preBlockCache = preBlockCache; - _populatePreBlockCache = populatePreBlockCache; _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - _codeDb = codeDb ?? throw new ArgumentNullException(nameof(codeDb)); - _tree = stateTree ?? new StateTree(trieStore, logManager); - _getStateFromTrie = address => - { - Metrics.IncrementStateTreeReads(); - return _tree.Get(address); - }; - } - - public void Accept(ITreeVisitor visitor, Hash256? stateRoot, VisitingOptions? visitingOptions = null) where TCtx : struct, INodeContext - { - ArgumentNullException.ThrowIfNull(visitor); - ArgumentNullException.ThrowIfNull(stateRoot); - - _tree.Accept(visitor, stateRoot, visitingOptions); } public void RecalculateStateRoot() @@ -101,7 +75,14 @@ public Hash256 StateRoot [DoesNotReturn, StackTraceHidden] static void ThrowStateRootNeedsToBeUpdated() => throw new InvalidOperationException("State root needs to be updated"); } - set => _tree.RootHash = value; + } + + public int ChangedAccountCount => _blockChanges.Count; + + public void SetScope(IWorldStateScopeProvider.IScope? scope) + { + _tree = scope; + _codeDb = scope?.CodeDb; } public bool IsContract(Address address) @@ -129,16 +110,6 @@ public UInt256 GetNonce(Address address) return account?.Nonce ?? UInt256.Zero; } - public Hash256 GetStorageRoot(Address address) - { - Account? account = GetThroughCache(address); - return account is not null ? account.StorageRoot : ThrowIfNull(address); - - [DoesNotReturn, StackTraceHidden] - static Hash256 ThrowIfNull(Address address) - => throw new InvalidOperationException($"Account {address} is null when accessing storage root"); - } - public ref readonly UInt256 GetBalance(Address address) { Account? account = GetThroughCache(address); @@ -160,8 +131,8 @@ public bool InsertCode(Address address, in ValueHash256 codeHash, ReadOnlyMemory _codeBatchAlternate = _codeBatch.GetAlternateLookup(); } if (MemoryMarshal.TryGetArray(code, out ArraySegment codeArray) - && codeArray.Offset == 0 - && codeArray.Count == code.Length) + && codeArray.Offset == 0 + && codeArray.Count == code.Length) { _codeBatchAlternate[codeHash] = codeArray.Array; } @@ -283,32 +254,6 @@ public void AddToBalance(Address address, in UInt256 balanceChange, IReleaseSpec SetNewBalance(address, balanceChange, releaseSpec, false); } - /// - /// This is a coupling point between storage provider and state provider. - /// This is pointing at the architectural change likely required where Storage and State Provider are represented by a single world state class. - /// - /// - /// - public void UpdateStorageRoot(Address address, Hash256 storageRoot) - { - _needsStateRootUpdate = true; - Account account = GetThroughCache(address) ?? ThrowNullAccount(address); - if (account.StorageRoot != storageRoot) - { - if (_logger.IsTrace) Trace(address, storageRoot, account); - Account changedAccount = account.WithChangedStorageRoot(storageRoot); - PushUpdate(address, changedAccount); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - void Trace(Address address, Hash256 storageRoot, Account account) - => _logger.Trace($"Update {address} S {account.StorageRoot} -> {storageRoot}"); - - [DoesNotReturn, StackTraceHidden] - static Account ThrowNullAccount(Address address) - => throw new InvalidOperationException($"Account {address} is null when updating storage hash"); - } - public void IncrementNonce(Address address, UInt256 delta) { _needsStateRootUpdate = true; @@ -360,7 +305,7 @@ private byte[] GetCodeCore(in ValueHash256 codeHash) if (_codeBatch is null || !_codeBatchAlternate.TryGetValue(codeHash, out byte[]? code)) { - code = _codeDb[codeHash.Bytes]; + code = _codeDb.GetCode(codeHash); } return code ?? ThrowMissingCode(in codeHash); @@ -533,24 +478,17 @@ public bool AddToBalanceAndCreateIfNotExists(Address address, in UInt256 balance } } - public void Commit(IReleaseSpec releaseSpec, bool commitRoots, bool isGenesis) - => Commit(releaseSpec, NullStateTracer.Instance, commitRoots, isGenesis); - public void Commit(IReleaseSpec releaseSpec, IWorldStateTracer stateTracer, bool commitRoots, bool isGenesis) { Task codeFlushTask = !commitRoots || _codeBatch is null || _codeBatch.Count == 0 ? Task.CompletedTask - : CommitCodeAsync(); + : CommitCodeAsync(_codeDb); bool isTracing = _logger.IsTrace; int stepsBack = _changes.Count - 1; if (stepsBack < 0) { if (isTracing) TraceNoChanges(); - if (commitRoots) - { - FlushToTree(); - } codeFlushTask.GetAwaiter().GetResult(); return; @@ -675,14 +613,9 @@ public void Commit(IReleaseSpec releaseSpec, IWorldStateTracer stateTracer, bool _nullAccountReads.Clear(); _intraTxCache.ResetAndClear(); - if (commitRoots) - { - FlushToTree(); - } - codeFlushTask.GetAwaiter().GetResult(); - Task CommitCodeAsync() + Task CommitCodeAsync(IWorldStateScopeProvider.ICodeDb codeDb) { Dictionary dict = Interlocked.Exchange(ref _codeBatch, null); if (dict is null) return Task.CompletedTask; @@ -690,12 +623,12 @@ Task CommitCodeAsync() return Task.Run(() => { - using (var batch = _codeDb.StartWriteBatch()) + using (var batch = codeDb.BeginCodeWrite()) { // Insert ordered for improved performance foreach (var kvp in dict.OrderBy(static kvp => kvp.Key)) { - batch.PutSpan(kvp.Key.Value.Bytes, kvp.Value); + batch.Set(kvp.Key.Value, kvp.Value); } } @@ -747,25 +680,18 @@ static void ThrowUnexpectedPosition(int currentPosition, int i, int forAssertion => throw new InvalidOperationException($"Expected checked value {forAssertion} to be equal to {currentPosition} - {i}"); } - private void FlushToTree() + internal void FlushToTree(IWorldStateScopeProvider.IWorldStateWriteBatch writeBatch) { int writes = 0; int skipped = 0; - using ArrayPoolListRef bulkWrite = new(_blockChanges.Count); foreach (AddressAsKey key in _blockChanges.Keys) { ref ChangeTrace change = ref CollectionsMarshal.GetValueRefOrNullRef(_blockChanges, key); if (change.Before != change.After) { change.Before = change.After; - - KeccakCache.ComputeTo(key.Value.Bytes, out ValueHash256 keccak); - - Account account = change.After; - Rlp accountRlp = account is null ? null : account.IsTotallyEmpty ? StateTree.EmptyAccountRlp : Rlp.Encode(account); - - bulkWrite.Add(new PatriciaTree.BulkSetEntry(keccak, accountRlp?.Bytes)); + writeBatch.Set(key, change.After); writes++; } else @@ -774,8 +700,6 @@ private void FlushToTree() } } - _tree.BulkSet(bulkWrite); - if (writes > 0) Metrics.IncrementStateTreeWrites(writes); if (skipped > 0) @@ -791,9 +715,8 @@ public bool WarmUp(Address address) ref ChangeTrace accountChanges = ref CollectionsMarshal.GetValueRefOrAddDefault(_blockChanges, addressAsKey, out bool exists); if (!exists) { - Account? account = !_populatePreBlockCache ? - GetStateReadPreWarmCache(addressAsKey) : - GetStatePopulatePrewarmCache(addressAsKey); + Metrics.IncrementStateTreeReads(); + Account? account = _tree.Get(address); accountChanges = new(account, account); } @@ -804,34 +727,7 @@ public bool WarmUp(Address address) return accountChanges.After; } - private Account? GetStatePopulatePrewarmCache(AddressAsKey addressAsKey) - { - long priorReads = Metrics.ThreadLocalStateTreeReads; - Account? account = _preBlockCache is not null - ? _preBlockCache.GetOrAdd(addressAsKey, _getStateFromTrie) - : _getStateFromTrie(addressAsKey); - - if (Metrics.ThreadLocalStateTreeReads == priorReads) - { - Metrics.IncrementStateTreeCacheHits(); - } - return account; - } - - private Account? GetStateReadPreWarmCache(AddressAsKey addressAsKey) - { - if (_preBlockCache?.TryGetValue(addressAsKey, out Account? account) ?? false) - { - Metrics.IncrementStateTreeCacheHits(); - } - else - { - account = _getStateFromTrie(addressAsKey); - } - return account; - } - - private void SetState(Address address, Account? account) + internal void SetState(Address address, Account? account) { ref ChangeTrace accountChanges = ref CollectionsMarshal.GetValueRefOrAddDefault(_blockChanges, address, out _); accountChanges.After = account; @@ -956,14 +852,12 @@ public void Reset(bool resetBlockChanges = true) void Trace() => _logger.Trace("Clearing state provider caches"); } - public void CommitTree() + public void UpdateStateRootIfNeeded() { if (_needsStateRootUpdate) { RecalculateStateRoot(); } - - _tree.Commit(); } // used in EthereumTests diff --git a/src/Nethermind/Nethermind.State/StateTree.cs b/src/Nethermind/Nethermind.State/StateTree.cs index ff0f9e0a360..cc3a384659b 100644 --- a/src/Nethermind/Nethermind.State/StateTree.cs +++ b/src/Nethermind/Nethermind.State/StateTree.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using Nethermind.Core; using Nethermind.Core.Buffers; +using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Db; using Nethermind.Logging; @@ -73,6 +74,32 @@ public void Set(Address address, Account? account) Set(keccak.BytesAsSpan, account is null ? null : account.IsTotallyEmpty ? EmptyAccountRlp : Rlp.Encode(account)); } + public StateTreeBulkSetter BeginSet(int estimatedEntries) + { + return new StateTreeBulkSetter(estimatedEntries, this); + } + + public class StateTreeBulkSetter(int estimatedEntries, StateTree tree) : IDisposable + { + ArrayPoolList _bulkWrite = new(estimatedEntries); + + public void Set(Address key, Account account) + { + KeccakCache.ComputeTo(key.Bytes, out ValueHash256 keccak); + + Rlp accountRlp = account is null ? null : account.IsTotallyEmpty ? StateTree.EmptyAccountRlp : Rlp.Encode(account); + + _bulkWrite.Add(new BulkSetEntry(keccak, accountRlp?.Bytes)); + } + + public void Dispose() + { + using ArrayPoolListRef asRef = new ArrayPoolListRef(_bulkWrite.AsSpan()); + tree.BulkSet(asRef); + _bulkWrite.Dispose(); + } + } + [DebuggerStepThrough] public Rlp? Set(Hash256 keccak, Account? account) { @@ -89,5 +116,20 @@ public void Set(Address address, Account? account) Set(keccak.Bytes, rlp); return rlp; } + + public Account? Get(Address address) + { + return Get(address, null); + } + + public void UpdateRootHash() + { + UpdateRootHash(true); + } + + public void Commit() + { + Commit(false, WriteFlags.None); + } } } diff --git a/src/Nethermind/Nethermind.State/StorageTree.cs b/src/Nethermind/Nethermind.State/StorageTree.cs index f1f71924f1d..088fa41fa35 100644 --- a/src/Nethermind/Nethermind.State/StorageTree.cs +++ b/src/Nethermind/Nethermind.State/StorageTree.cs @@ -6,8 +6,11 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using Nethermind.Core; +using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Evm.State; using Nethermind.Logging; using Nethermind.Int256; using Nethermind.Serialization.Rlp; @@ -16,7 +19,7 @@ namespace Nethermind.State { - public class StorageTree : PatriciaTree + public class StorageTree : PatriciaTree, IWorldStateScopeProvider.IStorageTree { private const int LookupSize = 1024; private static readonly FrozenDictionary Lookup = CreateLookup(); @@ -124,6 +127,32 @@ public byte[] GetArray(ReadOnlySpan rawKey, Hash256? rootHash = null) return rlp.DecodeByteArray(); } + public void Commit() + { + Commit(false, WriteFlags.None); + } + + public void Clear() + { + RootHash = EmptyTreeHash; + } + + public bool WasEmptyTree => RootHash == EmptyTreeHash; + + public byte[] Get(in UInt256 index) + { + return Get(index, null); + } + + public void HintGet(in UInt256 index, byte[]? value) + { + } + + public byte[] Get(in ValueHash256 hash) + { + return GetArray(hash.Bytes, null); + } + [SkipLocalsInit] public void Set(in UInt256 index, byte[] value) { diff --git a/src/Nethermind/Nethermind.State/TrieStoreScopeProvider.cs b/src/Nethermind/Nethermind.State/TrieStoreScopeProvider.cs new file mode 100644 index 00000000000..6f0a26a2b21 --- /dev/null +++ b/src/Nethermind/Nethermind.State/TrieStoreScopeProvider.cs @@ -0,0 +1,320 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Nethermind.Core; +using Nethermind.Core.Collections; +using Nethermind.Core.Crypto; +using Nethermind.Evm.State; +using Nethermind.Int256; +using Nethermind.Logging; +using Nethermind.Trie; +using Nethermind.Trie.Pruning; +using NonBlocking; + +namespace Nethermind.State; + +public class TrieStoreScopeProvider : IWorldStateScopeProvider +{ + private readonly ITrieStore _trieStore; + private readonly ILogManager _logManager; + protected StateTree _backingStateTree; + private readonly KeyValueWithBatchingBackedCodeDb _codeDb; + + public TrieStoreScopeProvider(ITrieStore trieStore, IKeyValueStoreWithBatching codeDb, ILogManager logManager) + { + _trieStore = trieStore; + _logManager = logManager; + _codeDb = new KeyValueWithBatchingBackedCodeDb(codeDb); + + _backingStateTree = CreateStateTree(); + } + + protected virtual StateTree CreateStateTree() + { + return new StateTree(_trieStore.GetTrieStore(null), _logManager); + } + + public bool HasRoot(BlockHeader? baseBlock) + { + return _trieStore.HasRoot(baseBlock?.StateRoot ?? Keccak.EmptyTreeHash); + } + + public IWorldStateScopeProvider.IScope BeginScope(BlockHeader? baseBlock) + { + var trieStoreCloser = _trieStore.BeginScope(baseBlock); + _backingStateTree.RootHash = baseBlock?.StateRoot ?? Keccak.EmptyTreeHash; + + return new TrieStoreWorldStateBackendScope(_backingStateTree, this, _codeDb, trieStoreCloser, _logManager); + } + + protected virtual StorageTree CreateStorageTree(Address address, Hash256 storageRoot) + { + return new StorageTree(_trieStore.GetTrieStore(address), storageRoot, _logManager); + } + + private class TrieStoreWorldStateBackendScope : IWorldStateScopeProvider.IScope + { + public void Dispose() + { + _trieStoreCloser.Dispose(); + _backingStateTree.RootHash = Keccak.EmptyTreeHash; + _storages.Clear(); + } + + public Hash256 RootHash => _backingStateTree.RootHash; + public void UpdateRootHash() => _backingStateTree.UpdateRootHash(); + + public Account? Get(Address address) + { + ref Account? account = ref CollectionsMarshal.GetValueRefOrAddDefault(_loadedAccounts, address, out bool exists); + if (!exists) + { + account = _backingStateTree.Get(address); + } + + return account; + } + + public void HintGet(Address address, Account? account) + { + _loadedAccounts.TryAdd(address, account); + } + + public IWorldStateScopeProvider.ICodeDb CodeDb => _codeDb1; + + internal StateTree _backingStateTree; + private readonly Dictionary _storages = new(); + private readonly Dictionary _loadedAccounts = new(); + private readonly TrieStoreScopeProvider _scopeProvider; + private readonly IWorldStateScopeProvider.ICodeDb _codeDb1; + private readonly IDisposable _trieStoreCloser; + private readonly ILogManager _logManager; + + public TrieStoreWorldStateBackendScope(StateTree backingStateTree, TrieStoreScopeProvider scopeProvider, IWorldStateScopeProvider.ICodeDb codeDb, IDisposable trieStoreCloser, ILogManager logManager) + { + _backingStateTree = backingStateTree; + _logManager = logManager; + _scopeProvider = scopeProvider; + _codeDb1 = codeDb; + _trieStoreCloser = trieStoreCloser; + } + + public IWorldStateScopeProvider.IWorldStateWriteBatch StartWriteBatch(int estimatedAccountNumber) + { + return new WorldStateWriteBatch(this, estimatedAccountNumber, _logManager.GetClassLogger()); + } + + public void Commit(long blockNumber) + { + using var blockCommitter = _scopeProvider._trieStore.BeginBlockCommit(blockNumber); + + // Note: These all runs in about 0.4ms. So the little overhead like attempting to sort the tasks + // may make it worst. Always check on mainnet. + using ArrayPoolList commitTask = new ArrayPoolList(_storages.Count); + foreach (KeyValuePair storage in _storages) + { + if (blockCommitter.TryRequestConcurrencyQuota()) + { + commitTask.Add(Task.Factory.StartNew((ctx) => + { + StorageTree st = (StorageTree)ctx; + st.Commit(); + blockCommitter.ReturnConcurrencyQuota(); + }, storage.Value)); + } + else + { + storage.Value.Commit(); + } + } + + Task.WaitAll(commitTask.AsSpan()); + _backingStateTree.Commit(); + _storages.Clear(); + } + + internal StorageTree LookupStorageTree(Address address) + { + if (_storages.TryGetValue(address, out var storageTree)) + { + return storageTree; + } + + storageTree = _scopeProvider.CreateStorageTree(address, Get(address)?.StorageRoot ?? Keccak.EmptyTreeHash); + _storages[address] = storageTree; + return storageTree; + } + + public void ClearLoadedAccounts() + { + _loadedAccounts.Clear(); + } + + public IWorldStateScopeProvider.IStorageTree CreateStorageTree(Address address) + { + return LookupStorageTree(address); + } + } + + private class WorldStateWriteBatch( + TrieStoreWorldStateBackendScope scope, + int estimatedAccountCount, + ILogger logger) : IWorldStateScopeProvider.IWorldStateWriteBatch + { + private readonly Dictionary _dirtyAccounts = new(estimatedAccountCount); + private readonly ConcurrentQueue<(AddressAsKey, Hash256)> _dirtyStorageTree = new(); + + public event EventHandler? OnAccountUpdated; + + public void Set(Address key, Account? account) + { + _dirtyAccounts[key] = account; + } + + public IWorldStateScopeProvider.IStorageWriteBatch CreateStorageWriteBatch(Address address, int estimatedEntries) + { + return new StorageTreeBulkWriteBatch(estimatedEntries, scope.LookupStorageTree(address), this, address); + } + + public void MarkDirty(AddressAsKey address, Hash256 storageTreeRootHash) + { + _dirtyStorageTree.Enqueue((address, storageTreeRootHash)); + } + + public void Dispose() + { + while (_dirtyStorageTree.TryDequeue(out (AddressAsKey, Hash256) entry)) + { + (AddressAsKey key, Hash256 storageRoot) = entry; + if (!_dirtyAccounts.TryGetValue(key, out var account)) account = scope.Get(key); + if (account == null && storageRoot == Keccak.EmptyTreeHash) continue; + account ??= ThrowNullAccount(key); + account = account!.WithChangedStorageRoot(storageRoot); + _dirtyAccounts[key] = account; + OnAccountUpdated?.Invoke(key, new IWorldStateScopeProvider.AccountUpdated(key, account)); + if (logger.IsTrace) Trace(key, storageRoot, account); + } + + using (var stateSetter = scope._backingStateTree.BeginSet(_dirtyAccounts.Count)) + { + foreach (var kv in _dirtyAccounts) + { + stateSetter.Set(kv.Key, kv.Value); + } + } + + scope.ClearLoadedAccounts(); + + + [MethodImpl(MethodImplOptions.NoInlining)] + void Trace(Address address, Hash256 storageRoot, Account? account) + => logger.Trace($"Update {address} S {account?.StorageRoot} -> {storageRoot}"); + + [DoesNotReturn, StackTraceHidden] + static Account ThrowNullAccount(Address address) + => throw new InvalidOperationException($"Account {address} is null when updating storage hash"); + } + } + + private class StorageTreeBulkWriteBatch(int estimatedEntries, StorageTree storageTree, WorldStateWriteBatch worldStateWriteBatch, AddressAsKey address) : IWorldStateScopeProvider.IStorageWriteBatch + { + // Slight optimization on small contract as the index hash can be precalculated in some case. + private const int MIN_ENTRIES_TO_BATCH = 16; + + private bool _hasSelfDestruct; + private bool _wasSetCalled = false; + + private ArrayPoolList? _bulkWrite = + estimatedEntries > MIN_ENTRIES_TO_BATCH + ? new(estimatedEntries) + : null; + + private ValueHash256 _keyBuff = new ValueHash256(); + + public void Set(in UInt256 index, byte[] value) + { + _wasSetCalled = true; + if (_bulkWrite is null) + { + storageTree.Set(index, value); + } + else + { + StorageTree.ComputeKeyWithLookup(index, _keyBuff.BytesAsSpan); + _bulkWrite.Add(StorageTree.CreateBulkSetEntry(_keyBuff, value)); + } + } + + public void Clear() + { + if (_bulkWrite is null) + { + storageTree.RootHash = Keccak.EmptyTreeHash; + } + else + { + if (_wasSetCalled) throw new InvalidOperationException("Must call clear first in a storage write batch"); + _hasSelfDestruct = true; + } + } + + public void Dispose() + { + bool hasSet = _wasSetCalled || _hasSelfDestruct; + if (_bulkWrite is not null) + { + if (_hasSelfDestruct) + { + storageTree.RootHash = Keccak.EmptyTreeHash; + } + + using ArrayPoolListRef asRef = + new ArrayPoolListRef(_bulkWrite.AsSpan()); + storageTree.BulkSet(asRef); + + _bulkWrite?.Dispose(); + } + + if (hasSet) + { + storageTree.UpdateRootHash(_bulkWrite?.Count > 64); + worldStateWriteBatch.MarkDirty(address, storageTree.RootHash); + } + } + } + + private class KeyValueWithBatchingBackedCodeDb(IKeyValueStoreWithBatching codeDb) : IWorldStateScopeProvider.ICodeDb + { + public byte[]? GetCode(in ValueHash256 codeHash) + { + return codeDb[codeHash.Bytes]?.ToArray(); + } + + public IWorldStateScopeProvider.ICodeSetter BeginCodeWrite() + { + return new CodeSetter(codeDb.StartWriteBatch()); + } + + private class CodeSetter(IWriteBatch writeBatch) : IWorldStateScopeProvider.ICodeSetter + { + public void Set(in ValueHash256 codeHash, ReadOnlySpan code) + { + writeBatch.PutSpan(codeHash.Bytes, code); + } + + public void Dispose() + { + writeBatch.Dispose(); + } + } + } +} diff --git a/src/Nethermind/Nethermind.State/WorldState.cs b/src/Nethermind/Nethermind.State/WorldState.cs index 91d32300615..3ea6da61759 100644 --- a/src/Nethermind/Nethermind.State/WorldState.cs +++ b/src/Nethermind/Nethermind.State/WorldState.cs @@ -15,7 +15,6 @@ using Nethermind.Evm.Tracing.State; using Nethermind.Int256; using Nethermind.Logging; -using Nethermind.Trie.Pruning; [assembly: InternalsVisibleTo("Ethereum.Test.Base")] [assembly: InternalsVisibleTo("Ethereum.Blockchain.Test")] @@ -27,16 +26,14 @@ namespace Nethermind.State { - public class WorldState : IWorldState, IPreBlockCaches + public class WorldState : IWorldState { internal readonly StateProvider _stateProvider; internal readonly PersistentStorageProvider _persistentStorageProvider; private readonly TransientStorageProvider _transientStorageProvider; - private readonly ITrieStore _trieStore; - private bool _isInScope = false; + private IWorldStateScopeProvider.IScope? _currentScope; + private bool _isInScope; private readonly ILogger _logger; - private PreBlockCaches? PreBlockCaches { get; } - public bool IsWarmWorldState { get; } public Hash256 StateRoot { @@ -45,52 +42,32 @@ public Hash256 StateRoot GuardInScope(); return _stateProvider.StateRoot; } - private set - { - _stateProvider.StateRoot = value; - _persistentStorageProvider.StateRoot = value; - } - } - - public WorldState(ITrieStore trieStore, IKeyValueStoreWithBatching? codeDb, ILogManager? logManager) - : this(trieStore, codeDb, logManager, null, null) - { } - internal WorldState( - ITrieStore trieStore, - IKeyValueStoreWithBatching? codeDb, - ILogManager? logManager, - StateTree? stateTree = null, - IStorageTreeFactory? storageTreeFactory = null, - PreBlockCaches? preBlockCaches = null, - bool populatePreBlockCache = true) + public WorldState( + IWorldStateScopeProvider scopeProvider, + ILogManager? logManager) { - PreBlockCaches = preBlockCaches; - IsWarmWorldState = !populatePreBlockCache; - _trieStore = trieStore; - _stateProvider = new StateProvider(trieStore.GetTrieStore(null), codeDb, logManager, stateTree, PreBlockCaches?.StateCache, populatePreBlockCache); - _persistentStorageProvider = new PersistentStorageProvider(trieStore, _stateProvider, logManager, storageTreeFactory, PreBlockCaches?.StorageCache, populatePreBlockCache); + ScopeProvider = scopeProvider; + _stateProvider = new StateProvider(logManager); + _persistentStorageProvider = new PersistentStorageProvider(_stateProvider, logManager); _transientStorageProvider = new TransientStorageProvider(logManager); _logger = logManager.GetClassLogger(); } - public WorldState(ITrieStore trieStore, IKeyValueStoreWithBatching? codeDb, ILogManager? logManager, PreBlockCaches? preBlockCaches, bool populatePreBlockCache = true) - : this(trieStore, codeDb, logManager, null, preBlockCaches: preBlockCaches, populatePreBlockCache: populatePreBlockCache) - { - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] private void GuardInScope() { - if (!_isInScope) ThrowOutOfScope(); + if (_currentScope is null) ThrowOutOfScope(); } [Conditional("DEBUG")] [MethodImpl(MethodImplOptions.AggressiveInlining)] private void DebugGuardInScope() { - if (!_isInScope) ThrowOutOfScope(); +#if DEBUG + if (_currentScope is null) ThrowOutOfScope(); +#endif } [StackTraceHidden, DoesNotReturn] @@ -107,10 +84,34 @@ public Account GetAccount(Address address) bool IAccountStateProvider.TryGetAccount(Address address, out AccountStruct account) { - account = _stateProvider.GetAccount(address).ToStruct(); + // Note: This call is for compatibility with `IAccountStateProvider` and should not be called directly by VM. Because its slower. + account = _stateProvider.GetAccount(address) + .WithChangedStorageRoot(_persistentStorageProvider.GetStorageRoot(address)) + .ToStruct(); + return !account.IsTotallyEmpty; } + UInt256 IAccountStateProvider.GetNonce(Address address) + { + return _stateProvider.GetAccount(address).Nonce; + } + + UInt256 IAccountStateProvider.GetBalance(Address address) + { + return _stateProvider.GetAccount(address).Balance; + } + + bool IAccountStateProvider.IsStorageEmpty(Address address) + { + return _persistentStorageProvider.GetStorageRoot(address) == Keccak.EmptyTreeHash; + } + + bool IAccountStateProvider.HasCode(Address address) + { + return _stateProvider.GetAccount(address).HasCode; + } + public bool IsContract(Address address) { DebugGuardInScope(); @@ -212,11 +213,6 @@ public void SubtractFromBalance(Address address, in UInt256 balanceChange, IRele DebugGuardInScope(); _stateProvider.SubtractFromBalance(address, balanceChange, spec); } - public void UpdateStorageRoot(Address address, Hash256 storageRoot) - { - DebugGuardInScope(); - _stateProvider.UpdateStorageRoot(address, storageRoot); - } public void IncrementNonce(Address address, UInt256 delta) { DebugGuardInScope(); @@ -231,12 +227,9 @@ public void DecrementNonce(Address address, UInt256 delta) public void CommitTree(long blockNumber) { DebugGuardInScope(); - using (IBlockCommitter committer = _trieStore.BeginBlockCommit(blockNumber)) - { - _persistentStorageProvider.CommitTrees(committer); - _stateProvider.CommitTree(); - } - _persistentStorageProvider.StateRoot = _stateProvider.StateRoot; + _stateProvider.UpdateStateRootIfNeeded(); + _currentScope.Commit(blockNumber); + _persistentStorageProvider.ClearStorageMap(); } public UInt256 GetNonce(Address address) @@ -254,20 +247,23 @@ public IDisposable BeginScope(BlockHeader? baseBlock) if (_logger.IsTrace) _logger.Trace($"Beginning WorldState scope with baseblock {baseBlock?.ToString(BlockHeader.Format.Short) ?? "null"} with stateroot {baseBlock?.StateRoot?.ToString() ?? "null"}."); - StateRoot = baseBlock?.StateRoot ?? Keccak.EmptyTreeHash; - IDisposable trieStoreCloser = _trieStore.BeginScope(baseBlock); + _currentScope = ScopeProvider.BeginScope(baseBlock); + _stateProvider.SetScope(_currentScope); + _persistentStorageProvider.SetBackendScope(_currentScope); return new Reactive.AnonymousDisposable(() => { Reset(); - StateRoot = Keccak.EmptyTreeHash; - trieStoreCloser.Dispose(); + _stateProvider.SetScope(null); + _currentScope.Dispose(); + _currentScope = null; _isInScope = false; if (_logger.IsTrace) _logger.Trace($"WorldState scope for baseblock {baseBlock?.ToString(BlockHeader.Format.Short) ?? "null"} closed"); }); } - public bool IsInScope => _isInScope; + public bool IsInScope => _currentScope is not null; + public IWorldStateScopeProvider ScopeProvider { get; } public ref readonly UInt256 GetBalance(Address address) { @@ -279,7 +275,7 @@ public ValueHash256 GetStorageRoot(Address address) { DebugGuardInScope(); if (address == null) throw new ArgumentNullException(nameof(address)); - return _stateProvider.GetStorageRoot(address); + return _persistentStorageProvider.GetStorageRoot(address); } public byte[] GetCode(Address address) @@ -319,23 +315,23 @@ public bool IsDeadAccount(Address address) public bool HasStateForBlock(BlockHeader? header) { - return _trieStore.HasRoot(header?.StateRoot ?? Keccak.EmptyTreeHash); - } - - public void Commit(IReleaseSpec releaseSpec, bool isGenesis = false, bool commitRoots = true) - { - DebugGuardInScope(); - _persistentStorageProvider.Commit(commitRoots); - _transientStorageProvider.Commit(commitRoots); - _stateProvider.Commit(releaseSpec, commitRoots, isGenesis); + return ScopeProvider.HasRoot(header); } public void Commit(IReleaseSpec releaseSpec, IWorldStateTracer tracer, bool isGenesis = false, bool commitRoots = true) { DebugGuardInScope(); - _persistentStorageProvider.Commit(tracer, commitRoots); - _transientStorageProvider.Commit(tracer, commitRoots); + _transientStorageProvider.Commit(tracer); + _persistentStorageProvider.Commit(tracer); _stateProvider.Commit(releaseSpec, tracer, commitRoots, isGenesis); + + if (commitRoots) + { + using IWorldStateScopeProvider.IWorldStateWriteBatch writeBatch = _currentScope.StartWriteBatch(_stateProvider.ChangedAccountCount); + writeBatch.OnAccountUpdated += (_, updatedAccount) => _stateProvider.SetState(updatedAccount.Address, updatedAccount.Account); + _persistentStorageProvider.FlushToTree(writeBatch); + _stateProvider.FlushToTree(writeBatch); + } } public Snapshot TakeSnapshot(bool newTransactionStart = false) @@ -385,7 +381,5 @@ public void ResetTransient() DebugGuardInScope(); _transientStorageProvider.Reset(); } - - PreBlockCaches? IPreBlockCaches.Caches => PreBlockCaches; } } diff --git a/src/Nethermind/Nethermind.State/WorldStateManager.cs b/src/Nethermind/Nethermind.State/WorldStateManager.cs index 6d384c06e0d..b6f5838627f 100644 --- a/src/Nethermind/Nethermind.State/WorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/WorldStateManager.cs @@ -7,16 +7,14 @@ using Nethermind.Db; using Nethermind.Evm.State; using Nethermind.Logging; -using Nethermind.State.Healing; using Nethermind.State.SnapServer; -using Nethermind.Trie; using Nethermind.Trie.Pruning; namespace Nethermind.State; public class WorldStateManager : IWorldStateManager { - private readonly IWorldState _worldState; + private readonly IWorldStateScopeProvider _worldState; private readonly IPruningTrieStore _trieStore; private readonly IReadOnlyTrieStore _readOnlyTrieStore; private readonly ILogManager _logManager; @@ -26,7 +24,7 @@ public class WorldStateManager : IWorldStateManager private readonly ILastNStateRootTracker _lastNStateRootTracker; public WorldStateManager( - IWorldState worldState, + IWorldStateScopeProvider worldState, IPruningTrieStore trieStore, IDbProvider dbProvider, ILogManager logManager, @@ -46,7 +44,7 @@ public WorldStateManager( _lastNStateRootTracker = lastNStateRootTracker; } - public IWorldState GlobalWorldState => _worldState; + public IWorldStateScopeProvider GlobalWorldState => _worldState; public IReadOnlyKeyValueStore? HashServer => _trieStore.Scheme != INodeStorage.KeyScheme.Hash ? null : _trieStore.TrieNodeRlpStore; @@ -60,24 +58,9 @@ public event EventHandler? ReorgBoundaryReached public ISnapServer? SnapServer => _trieStore.Scheme == INodeStorage.KeyScheme.Hash ? null : new SnapServer.SnapServer(_readOnlyTrieStore, _readaOnlyCodeCb, GlobalStateReader, _logManager, _lastNStateRootTracker); - public IWorldState CreateResettableWorldState() + public IWorldStateScopeProvider CreateResettableWorldState() { - return new WorldState( - _readOnlyTrieStore, - _readaOnlyCodeCb, - _logManager); - } - - public IWorldState CreateWorldStateForWarmingUp(IWorldState forWarmup) - { - PreBlockCaches? preBlockCaches = (forWarmup as IPreBlockCaches)?.Caches; - return preBlockCaches is not null - ? new WorldState( - new PreCachedTrieStore(_readOnlyTrieStore, preBlockCaches.RlpCache), - _readaOnlyCodeCb, - _logManager, - preBlockCaches) - : CreateResettableWorldState(); + return new TrieStoreScopeProvider(_readOnlyTrieStore, _readaOnlyCodeCb, _logManager); } public IOverridableWorldScope CreateOverridableWorldScope() diff --git a/src/Nethermind/Nethermind.State/WorldStateMetricsDecorator.cs b/src/Nethermind/Nethermind.State/WorldStateMetricsDecorator.cs index 799ef5d0709..5d1ff549165 100644 --- a/src/Nethermind/Nethermind.State/WorldStateMetricsDecorator.cs +++ b/src/Nethermind/Nethermind.State/WorldStateMetricsDecorator.cs @@ -125,6 +125,7 @@ public void CommitTree(long blockNumber) public IDisposable BeginScope(BlockHeader? baseBlock) => innerState.BeginScope(baseBlock); public bool IsInScope => innerState.IsInScope; + public IWorldStateScopeProvider ScopeProvider => innerState.ScopeProvider; public ref readonly UInt256 GetBalance(Address account) => ref innerState.GetBalance(account); @@ -133,4 +134,10 @@ public void CommitTree(long blockNumber) public ref readonly ValueHash256 GetCodeHash(Address address) => ref innerState.GetCodeHash(address); ValueHash256 IAccountStateProvider.GetCodeHash(Address address) => innerState.GetCodeHash(address); + + UInt256 IAccountStateProvider.GetNonce(Address address) => innerState.GetNonce(address); + + bool IAccountStateProvider.IsStorageEmpty(Address address) => innerState.IsStorageEmpty(address); + + bool IAccountStateProvider.HasCode(Address address) => innerState.HasCode(address); } diff --git a/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs b/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs index 30d8de15fbb..b1e3316a132 100644 --- a/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs @@ -20,6 +20,7 @@ using Nethermind.Specs; using Nethermind.Evm.State; using Nethermind.State; +using Nethermind.State.Healing; using Nethermind.Trie.Pruning; using NSubstitute; using NUnit.Framework; @@ -972,6 +973,7 @@ public async Task Will_Trigger_ReorgBoundaryEvent_On_Prune() if (i > 4) { + fullTrieStore.WaitForPruning(); Assert.That(() => reorgBoundary, Is.EqualTo(i - 3).After(10000, 100)); } else @@ -1035,8 +1037,7 @@ public void When_SomeKindOfNonResolvedNotInMainWorldState_OnPrune_DoNotDeleteNod }); WorldState worldState = new WorldState( - fullTrieStore, - memDbProvider.CodeDb, + new TrieStoreScopeProvider(fullTrieStore, memDbProvider.CodeDb, _logManager), LimboLogs.Instance); // Simulate some kind of cache access which causes unresolved node to remain. @@ -1057,7 +1058,8 @@ public void When_SomeKindOfNonResolvedNotInMainWorldState_OnPrune_DoNotDeleteNod (Hash256, ValueHash256) SetupStartingState() { - WorldState worldState = new WorldState(new TestRawTrieStore(nodeStorage), memDbProvider.CodeDb, LimboLogs.Instance); + WorldState worldState = new WorldState( + new TrieStoreScopeProvider(new TestRawTrieStore(nodeStorage), memDbProvider.CodeDb, LimboLogs.Instance), LimboLogs.Instance); using var _ = worldState.BeginScope(IWorldState.PreGenesis); worldState.CreateAccountIfNotExists(address, UInt256.One); worldState.Set(new StorageCell(address, slot), TestItem.KeccakB.BytesToArray()); diff --git a/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs b/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs index 77818a4f0c9..1e7bc90dd31 100644 --- a/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs @@ -228,10 +228,10 @@ private PruningContext(TestPruningStrategy pruningStrategy, IPersistenceStrategy _pruningConfig = pruningConfig ?? new PruningConfig() { TrackPastKeys = false }; _finalizedStateProvider = new TestFinalizedStateProvider(_pruningConfig.PruningBoundary); - _trieStore = new TrieStore( - new NodeStorage(_stateDb), _pruningStrategy, _persistenceStrategy, _finalizedStateProvider, _pruningConfig, _logManager); + _trieStore = new TrieStore(new NodeStorage(_stateDb), _pruningStrategy, _persistenceStrategy, _finalizedStateProvider, _pruningConfig, _logManager); _finalizedStateProvider.TrieStore = _trieStore; - _stateProvider = new WorldState(_trieStore, _codeDb, _logManager); + _stateProvider = new WorldState( + new TrieStoreScopeProvider(_trieStore, _codeDb, _logManager), _logManager); _stateReader = new StateReader(_trieStore, _codeDb, _logManager); _worldStateCloser = _stateProvider.BeginScope(IWorldState.PreGenesis); } @@ -439,11 +439,10 @@ public PruningContext DisposeAndRecreate() { _worldStateCloser!.Dispose(); _trieStore.Dispose(); - TestFinalizedStateProvider finalizedStateProvider = new TestFinalizedStateProvider(_pruningConfig.PruningBoundary); _trieStore = new TrieStore(new NodeStorage(_stateDb), _pruningStrategy, _persistenceStrategy, finalizedStateProvider, _pruningConfig, _logManager); - finalizedStateProvider.TrieStore = _trieStore; - _stateProvider = new WorldState(_trieStore, _codeDb, _logManager); + _stateProvider = new WorldState( + new TrieStoreScopeProvider(_trieStore, _codeDb, _logManager), _logManager); _stateReader = new StateReader(_trieStore, _codeDb, _logManager); return this; } diff --git a/src/Nethermind/Nethermind.Trie.Test/TrieTests.cs b/src/Nethermind/Nethermind.Trie.Test/TrieTests.cs index 5a4ebb0887d..cc8bbf89371 100644 --- a/src/Nethermind/Nethermind.Trie.Test/TrieTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/TrieTests.cs @@ -1119,7 +1119,7 @@ public void Fuzz_accounts_with_storage( } else { - accounts[i] = TestItem.GenerateRandomAccount(); + accounts[i] = TestItem.GenerateRandomAccount(_random); } addresses[i] = TestItem.GetRandomAddress(_random); diff --git a/src/Nethermind/Nethermind.Trie/NodeStorageCache.cs b/src/Nethermind/Nethermind.Trie/NodeStorageCache.cs new file mode 100644 index 00000000000..75236286b82 --- /dev/null +++ b/src/Nethermind/Nethermind.Trie/NodeStorageCache.cs @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Concurrent; +using Nethermind.Core.Collections; + +namespace Nethermind.Trie; + +public sealed class NodeStorageCache +{ + private ConcurrentDictionary _cache = new(); + + private volatile bool _enabled = false; + + public bool Enabled + { + get => _enabled; + set => _enabled = value; + } + + public byte[]? GetOrAdd(NodeKey nodeKey, Func tryLoadRlp) + { + if (!_enabled) + { + return tryLoadRlp(nodeKey); + } + return _cache.GetOrAdd(nodeKey, tryLoadRlp); + } + + public bool ClearCaches() + { + return _cache.NoResizeClear(); + } +} diff --git a/src/Nethermind/Nethermind.Trie/PreCachedTrieStore.cs b/src/Nethermind/Nethermind.Trie/PreCachedTrieStore.cs index 0fd1def8239..dc6d9b6d1fa 100644 --- a/src/Nethermind/Nethermind.Trie/PreCachedTrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/PreCachedTrieStore.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Concurrent; using System.Numerics; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -10,18 +9,17 @@ namespace Nethermind.Trie; -public class PreCachedTrieStore : ITrieStore +public sealed class PreCachedTrieStore : ITrieStore { private readonly ITrieStore _inner; - private readonly ConcurrentDictionary _preBlockCache; + private readonly NodeStorageCache _preBlockCache; private readonly Func _loadRlp; private readonly Func _tryLoadRlp; - public PreCachedTrieStore(ITrieStore inner, - ConcurrentDictionary preBlockCache) + public PreCachedTrieStore(ITrieStore inner, NodeStorageCache cache) { _inner = inner; - _preBlockCache = preBlockCache; + _preBlockCache = cache; // Capture the delegate once for default path to avoid the allocation of the lambda per call _loadRlp = (NodeKey key) => _inner.LoadRlp(key.Address, in key.Path, key.Hash, flags: ReadFlags.None); From 81f7afb473ebe98492277d19fb68efc24df3080d Mon Sep 17 00:00:00 2001 From: Desant pivo Date: Wed, 24 Dec 2025 01:59:55 +0100 Subject: [PATCH 127/255] fix: use ArgumentNullException for null logManager in EthStatsClient (#10018) Update EthStatsClient.cs --- src/Nethermind/Nethermind.EthStats/Clients/EthStatsClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.EthStats/Clients/EthStatsClient.cs b/src/Nethermind/Nethermind.EthStats/Clients/EthStatsClient.cs index e6d47686a70..cf34ee2e6b9 100644 --- a/src/Nethermind/Nethermind.EthStats/Clients/EthStatsClient.cs +++ b/src/Nethermind/Nethermind.EthStats/Clients/EthStatsClient.cs @@ -32,7 +32,7 @@ public EthStatsClient( _urlFromConfig = urlFromConfig ?? throw new ArgumentNullException(nameof(urlFromConfig)); _reconnectionInterval = reconnectionInterval; _messageSender = messageSender ?? throw new ArgumentNullException(nameof(messageSender)); - _logger = logManager?.GetClassLogger() ?? throw new ArgumentException(nameof(logManager)); + _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); } internal string BuildUrl() From 787cfba88faa5c530f37e2942e60846c647e9c9f Mon Sep 17 00:00:00 2001 From: emmmm <155267286+eeemmmmmm@users.noreply.github.com> Date: Tue, 23 Dec 2025 20:00:10 -0500 Subject: [PATCH 128/255] fix: correct BlobTxMissingBlobs error message (#10015) * fix: correct BlobTxMissingBlobs error message * fix --- src/Nethermind/Nethermind.Core/Messages/TxErrorMessages.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Messages/TxErrorMessages.cs b/src/Nethermind/Nethermind.Core/Messages/TxErrorMessages.cs index c4ede3a46c5..f3da0ea2ef0 100644 --- a/src/Nethermind/Nethermind.Core/Messages/TxErrorMessages.cs +++ b/src/Nethermind/Nethermind.Core/Messages/TxErrorMessages.cs @@ -44,8 +44,8 @@ public static string InvalidTxChainId(ulong expected, ulong? actual) => public static string BlobTxGasLimitExceeded(ulong totalDataGas, ulong maxBlobGas) => $"BlobTxGasLimitExceeded: Transaction's totalDataGas={totalDataGas} exceeded MaxBlobGas per transaction={maxBlobGas}."; - public const string BlobTxMissingBlobs = - "blob transaction missing blob hashes"; + public static readonly string BlobTxMissingBlobs = + $"blob transaction must have at least {Eip4844Constants.MinBlobsPerTransaction} blob"; public const string MissingBlobVersionedHash = "MissingBlobVersionedHash: Must be set."; From 553ac70017e5ce565f485c89465ec658393c26a6 Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Thu, 25 Dec 2025 10:49:17 +0100 Subject: [PATCH 129/255] Change KzgPolynomialCommitments.BlsModulus to new instead of parse (#10032) --- src/Nethermind/Nethermind.Crypto/KzgPolynomialCommitments.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Crypto/KzgPolynomialCommitments.cs b/src/Nethermind/Nethermind.Crypto/KzgPolynomialCommitments.cs index 3e67ebcc309..3d0dd4151e0 100644 --- a/src/Nethermind/Nethermind.Crypto/KzgPolynomialCommitments.cs +++ b/src/Nethermind/Nethermind.Crypto/KzgPolynomialCommitments.cs @@ -15,9 +15,8 @@ namespace Nethermind.Crypto; public static class KzgPolynomialCommitments { // https://eips.ethereum.org/EIPS/eip-4844#parameters - public static readonly UInt256 BlsModulus = - UInt256.Parse("52435875175126190479447740508185965837690552500527637822603658699938581184513", - System.Globalization.NumberStyles.Integer); + // 52435875175126190479447740508185965837690552500527637822603658699938581184513 + public static readonly UInt256 BlsModulus = new(18446744069414584321ul, 6034159408538082302ul, 3691218898639771653ul, 8353516859464449352ul); public const byte KzgBlobHashVersionV1 = 1; From 5ab1dd4d8dac8998814527dabf38380204d45a5d Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Sat, 27 Dec 2025 10:35:11 +0800 Subject: [PATCH 130/255] Fix/isStorageEmpty check does not get reflected until after commit. (#10039) * ADd logger * Slightly more log * Actually fix it * Uses a different dedicated is empty check * Fix code formatting in WorldStateScopeOperationLogger (#10040) * Initial plan * Fix formatting: Add space before colon in class declaration Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> * Update src/Nethermind/Nethermind.Core/Account.cs Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.State/PersistentStorageProvider.cs Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.State/WorldStateScopeOperationLogger.cs Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.State/WorldStateScopeOperationLogger.cs Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.State/WorldStateScopeOperationLogger.cs Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.State/WorldStateScopeOperationLogger.cs Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.State/WorldStateScopeOperationLogger.cs Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.State/WorldStateScopeOperationLogger.cs Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.State/WorldStateScopeOperationLogger.cs Co-authored-by: Lukasz Rozmej --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> Co-authored-by: Lukasz Rozmej --- src/Nethermind/Nethermind.Core/Account.cs | 3 + .../Modules/MainProcessingContext.cs | 9 +- src/Nethermind/Nethermind.Runner/NLog.config | 3 + .../StorageProviderTests.cs | 26 +++ .../PersistentStorageProvider.cs | 16 ++ src/Nethermind/Nethermind.State/WorldState.cs | 2 +- .../WorldStateScopeOperationLogger.cs | 153 ++++++++++++++++++ 7 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 src/Nethermind/Nethermind.State/WorldStateScopeOperationLogger.cs diff --git a/src/Nethermind/Nethermind.Core/Account.cs b/src/Nethermind/Nethermind.Core/Account.cs index ab7b335ff02..d0166e228f2 100644 --- a/src/Nethermind/Nethermind.Core/Account.cs +++ b/src/Nethermind/Nethermind.Core/Account.cs @@ -127,6 +127,9 @@ public Account WithChangedCodeHash(Hash256 newCodeHash) } public AccountStruct ToStruct() => new(Nonce, Balance, StorageRoot, CodeHash); + + public override string ToString() => + $"[Account|N:{Nonce}|B:{Balance}|S:{StorageRoot}|C:{CodeHash}]"; } public readonly struct AccountStruct : IEquatable diff --git a/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs b/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs index 0798e16fe2c..210416b8651 100644 --- a/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs +++ b/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs @@ -32,11 +32,18 @@ public MainProcessingContext( IBlockTree blockTree, ILogManager logManager) { + + IWorldStateScopeProvider worldState = worldStateManager.GlobalWorldState; + if (logManager.GetClassLogger().IsTrace) + { + worldState = new WorldStateScopeOperationLogger(worldStateManager.GlobalWorldState, logManager); + } + ILifetimeScope innerScope = rootLifetimeScope.BeginLifetimeScope((builder) => { builder // These are main block processing specific - .AddSingleton(worldStateManager.GlobalWorldState) + .AddSingleton(worldState) .AddModule(blockValidationModules) .AddScoped() .AddSingleton(this) diff --git a/src/Nethermind/Nethermind.Runner/NLog.config b/src/Nethermind/Nethermind.Runner/NLog.config index b78b9a6083f..59c90820b85 100644 --- a/src/Nethermind/Nethermind.Runner/NLog.config +++ b/src/Nethermind/Nethermind.Runner/NLog.config @@ -176,6 +176,9 @@ + + + diff --git a/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs b/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs index cc25eea210a..338fd4b038c 100644 --- a/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs +++ b/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs @@ -571,6 +571,32 @@ public void Selfdestruct_in_the_same_transaction() baseBlock.StateRoot.Should().Be(Keccak.EmptyTreeHash); } + [Test] + public void Selfdestruct_before_commit_will_mark_contract_as_empty() + { + Context ctx = new(setInitialState: false); + IWorldState provider = BuildStorageProvider(ctx); + + BlockHeader baseBlock = null; + using (provider.BeginScope(baseBlock)) + { + provider.CreateAccountIfNotExists(TestItem.AddressA, 100); + provider.Set(new StorageCell(TestItem.AddressA, 100), [1]); + provider.Set(new StorageCell(TestItem.AddressA, 200), [2]); + provider.Commit(Frontier.Instance); + provider.CommitTree(0); + + baseBlock = Build.A.BlockHeader.WithStateRoot(provider.StateRoot).TestObject; + } + + using (provider.BeginScope(baseBlock)) + { + provider.ClearStorage(TestItem.AddressA); + provider.DeleteAccount(TestItem.AddressA); + Assert.That(provider.IsStorageEmpty(TestItem.AddressA), Is.True); + } + } + [Test] public void Selfdestruct_persist_between_commit() { diff --git a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs index 930f2ecf35d..2437a37db43 100644 --- a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs +++ b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs @@ -115,6 +115,9 @@ public Hash256 GetStorageRoot(Address address) return GetOrCreateStorage(address).StorageRoot; } + public bool IsStorageEmpty(Address address) => + GetOrCreateStorage(address).IsEmpty; + private HashSet? _tempToUpdateRoots; /// /// Called by Commit @@ -486,6 +489,19 @@ public Hash256 StorageRoot } } + public bool IsEmpty + { + get + { + // _backend.RootHash is not reflected until after commit, but this need to be reflected before commit + // for SelfDestruct, since the deletion is not part of changelog, it need to be handled here. + if (BlockChange.HasClear) return true; + + EnsureStorageTree(); + return _backend.RootHash == Keccak.EmptyTreeHash; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void EnsureStorageTree() { diff --git a/src/Nethermind/Nethermind.State/WorldState.cs b/src/Nethermind/Nethermind.State/WorldState.cs index 3ea6da61759..893db5c11d3 100644 --- a/src/Nethermind/Nethermind.State/WorldState.cs +++ b/src/Nethermind/Nethermind.State/WorldState.cs @@ -104,7 +104,7 @@ UInt256 IAccountStateProvider.GetBalance(Address address) bool IAccountStateProvider.IsStorageEmpty(Address address) { - return _persistentStorageProvider.GetStorageRoot(address) == Keccak.EmptyTreeHash; + return _persistentStorageProvider.IsStorageEmpty(address); } bool IAccountStateProvider.HasCode(Address address) diff --git a/src/Nethermind/Nethermind.State/WorldStateScopeOperationLogger.cs b/src/Nethermind/Nethermind.State/WorldStateScopeOperationLogger.cs new file mode 100644 index 00000000000..eda6421c878 --- /dev/null +++ b/src/Nethermind/Nethermind.State/WorldStateScopeOperationLogger.cs @@ -0,0 +1,153 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Threading; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; +using Nethermind.Evm.State; +using Nethermind.Int256; +using Nethermind.Logging; + +namespace Nethermind.State; + +public class WorldStateScopeOperationLogger(IWorldStateScopeProvider baseScopeProvider, ILogManager logManager) : IWorldStateScopeProvider +{ + private ILogger _logger = logManager.GetClassLogger(); + private long _currentScopeId = 0; + + public bool HasRoot(BlockHeader? baseBlock) => + baseScopeProvider.HasRoot(baseBlock); + + public IWorldStateScopeProvider.IScope BeginScope(BlockHeader? baseBlock) + { + long scopeId = Interlocked.Increment(ref _currentScopeId); + return new ScopeWrapper(baseScopeProvider.BeginScope(baseBlock), scopeId, _logger); + } + + private class ScopeWrapper(IWorldStateScopeProvider.IScope innerScope, long scopeId, ILogger logger) : IWorldStateScopeProvider.IScope + { + public void Dispose() + { + innerScope.Dispose(); + logger.Trace($"{scopeId}: Scope disposed"); + } + + public Hash256 RootHash => innerScope.RootHash; + + public void UpdateRootHash() + { + innerScope.UpdateRootHash(); + logger.Trace($"{scopeId}: Update root hash"); + } + + public Account? Get(Address address) + { + Account? res = innerScope.Get(address); + logger.Trace($"{scopeId}: Get account {address}, got {res}"); + return res; + } + + public void HintGet(Address address, Account? account) + { + innerScope.HintGet(address, account); + } + + public IWorldStateScopeProvider.ICodeDb CodeDb => innerScope.CodeDb; + + public IWorldStateScopeProvider.IStorageTree CreateStorageTree(Address address) => + new StorageTreeWrapper(innerScope.CreateStorageTree(address), address, scopeId, logger); + + public IWorldStateScopeProvider.IWorldStateWriteBatch StartWriteBatch(int estimatedAccountNum) => + new WriteBatchWrapper(innerScope.StartWriteBatch(estimatedAccountNum), scopeId, logger); + + public void Commit(long blockNumber) => innerScope.Commit(blockNumber); + } + + private class StorageTreeWrapper(IWorldStateScopeProvider.IStorageTree storageTree, Address address, long scopeId, ILogger logger) : IWorldStateScopeProvider.IStorageTree + { + public Hash256 RootHash => storageTree.RootHash; + + public byte[] Get(in UInt256 index) + { + byte[]? bytes = storageTree.Get(in index); + logger.Trace($"{scopeId}: S:{address} Get slot {index}, got {bytes?.ToHexString()}"); + return bytes; + } + + public void HintGet(in UInt256 index, byte[]? value) => storageTree.HintGet(in index, value); + + public byte[] Get(in ValueHash256 hash) + { + byte[]? bytes = storageTree.Get(in hash); + logger.Trace($"{scopeId}: S:{address} Get slot via hash {hash}, got {bytes?.ToHexString()}"); + return bytes; + } + } + + private class WriteBatchWrapper : IWorldStateScopeProvider.IWorldStateWriteBatch + { + private readonly IWorldStateScopeProvider.IWorldStateWriteBatch _writeBatch; + private readonly long _scopeId; + private readonly ILogger _logger1; + + public WriteBatchWrapper(IWorldStateScopeProvider.IWorldStateWriteBatch writeBatch, long scopeId, ILogger logger) + { + _writeBatch = writeBatch; + _scopeId = scopeId; + _logger1 = logger; + + _writeBatch.OnAccountUpdated += (sender, updated) => + { + logger.Trace($"{scopeId}: OnAccountUpdated callback. {updated.Address} -> {updated.Account}"); + }; + } + + public void Dispose() + { + _writeBatch.Dispose(); + _logger1.Trace($"{_scopeId}: Write batch disposed"); + } + + public event EventHandler? OnAccountUpdated + { + add => _writeBatch.OnAccountUpdated += value; + remove => _writeBatch.OnAccountUpdated -= value; + } + + public void Set(Address key, Account? account) + { + _writeBatch.Set(key, account); + _logger1.Trace($"{_scopeId}: Set account {key} to {account}"); + } + + public IWorldStateScopeProvider.IStorageWriteBatch CreateStorageWriteBatch(Address key, int estimatedEntries) => + new StorageWriteBatchWrapper(_writeBatch.CreateStorageWriteBatch(key, estimatedEntries), key, _scopeId, _logger1); + } + + private class StorageWriteBatchWrapper( + IWorldStateScopeProvider.IStorageWriteBatch writeBatch, + Address address, + long scopeId, + ILogger logger) : IWorldStateScopeProvider.IStorageWriteBatch + { + public void Dispose() + { + writeBatch.Dispose(); + logger.Trace($"{scopeId}: {address}, Storage write batch disposed"); + } + + public void Set(in UInt256 index, byte[] value) + { + writeBatch.Set(in index, value); + logger.Trace($"{scopeId}: {address}, Set {index} to {value?.ToHexString()}"); + } + + public void Clear() + { + writeBatch.Clear(); + logger.Trace($"{scopeId}: {address}, Clear"); + } + } +} From e7a0a34351a03530ec1bc2b34fc2cbf7c29220a4 Mon Sep 17 00:00:00 2001 From: sashass1315 Date: Sun, 28 Dec 2025 01:23:36 +0200 Subject: [PATCH 131/255] fix: use GaugeMetric for PeerCandidateCount (#10004) --- src/Nethermind/Nethermind.Network/Metrics.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Network/Metrics.cs b/src/Nethermind/Nethermind.Network/Metrics.cs index abbfa0c15fd..6cd555d2709 100644 --- a/src/Nethermind/Nethermind.Network/Metrics.cs +++ b/src/Nethermind/Nethermind.Network/Metrics.cs @@ -103,7 +103,7 @@ public static class Metrics [KeyIsLabel("protocol", "message")] public static NonBlocking.ConcurrentDictionary IncomingP2PMessageBytes { get; } = new(); - [CounterMetric] + [GaugeMetric] [Description("Number of candidate peers in peer manager")] [DetailedMetric] public static int PeerCandidateCount { get; set; } From f1476711702f5e1578a2dd4506a6ce04943ff34d Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Sun, 28 Dec 2025 11:16:15 +0100 Subject: [PATCH 132/255] Fix IsTracing calculation by making it lazy (#10053) --- .../Nethermind.Evm/Tracing/TxTracer.cs | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/Tracing/TxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/TxTracer.cs index d8500f9220b..9bc615cafd6 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/TxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/TxTracer.cs @@ -13,23 +13,25 @@ namespace Nethermind.Evm.Tracing; public abstract class TxTracer : ITxTracer { - [SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")] - protected TxTracer() + private bool? _isTracing; + + public bool IsTracing { - IsTracing = IsTracingReceipt - || IsTracingActions - || IsTracingOpLevelStorage - || IsTracingMemory - || IsTracingInstructions - || IsTracingRefunds - || IsTracingCode - || IsTracingStack - || IsTracingBlockHash - || IsTracingAccess - || IsTracingFees - || IsTracingLogs; + get => _isTracing ??= IsTracingReceipt + || IsTracingActions + || IsTracingOpLevelStorage + || IsTracingMemory + || IsTracingInstructions + || IsTracingRefunds + || IsTracingCode + || IsTracingStack + || IsTracingBlockHash + || IsTracingAccess + || IsTracingFees + || IsTracingLogs; + protected set => _isTracing = value; } - public bool IsTracing { get; protected set; } + public virtual bool IsTracingState { get; protected set; } public virtual bool IsTracingReceipt { get; protected set; } public virtual bool IsTracingActions { get; protected set; } From f872648596c4e887e0f04ba4e6cecae782286686 Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Sun, 28 Dec 2025 11:17:38 +0100 Subject: [PATCH 133/255] Auto-update fast sync settings (#10055) Co-authored-by: rubo --- src/Nethermind/Nethermind.Runner/configs/base-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/base-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/chiado.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/gnosis.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/joc-testnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sepolia.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-mainnet.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-sepolia.json | 4 ++-- 14 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index ce54754e2b7..a68dafe7363 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 39730000, - "PivotHash": "0x31ba2c3f57ac39d1a0db01a7235cbadab5c27f9a53428ed1019f1a9833617895" + "PivotNumber": 40030000, + "PivotHash": "0x5c90880ea1e205ab07cc587b73760271ebbceedaf0c00a163e2bb60dac66cad9" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index fb0359cea53..c3c9c0dfd8b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 35240000, - "PivotHash": "0xa5b10f28961e206d30c6e4d49f69b601d1f59949847d25e61706a92dbbe94813" + "PivotNumber": 35540000, + "PivotHash": "0xc2502a90d5a1d21254bd4c613be06816e9a9d87719f74d3ea41714b30cc3098d" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.json b/src/Nethermind/Nethermind.Runner/configs/chiado.json index 2743d08630b..46f5eef1e28 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.json +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.json @@ -18,8 +18,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 19330000, - "PivotHash": "0x9d5e94c722999f8d24f5540d24314fb50298788ce3b9584130b4f90d0b741409", + "PivotNumber": 19430000, + "PivotHash": "0xb7f24304de674835b2c056f26c872949152a66aab1844df60efdda986d4b7b36", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": 10000000000, "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.json b/src/Nethermind/Nethermind.Runner/configs/gnosis.json index c5742788e0f..d75db0f5215 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.json +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.json @@ -14,8 +14,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 43740000, - "PivotHash": "0xd2e0891cd60dec73ced28f67d16a0d8dd7f0e5e0278e44ff32d450e358c9f930", + "PivotNumber": 43850000, + "PivotHash": "0xf27984f12faa543ecaada2564b8fb66a3488abc4d4aebcd8d03c59accdb91c33", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000, diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json index 51cbc2f03d2..b2a83375973 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 21320000, - "PivotHash": "0x481e4c8d23f9aecf95ec6513b3887aac0d1fde06f127fe39e5c60fb5aedb2861", - "PivotTotalDifficulty": "38477426" + "PivotNumber": 21440000, + "PivotHash": "0x986a542bc4eda557266d001ea82b4d734446bc53b0b5b05dbb21cbef4dd5e8c1", + "PivotTotalDifficulty": "38655935" }, "Metrics": { "NodeName": "JOC-Mainnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json index 384c1ba679d..552584682f4 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 14930000, - "PivotHash": "0x445d340047d192588c9869d7564fb31884631181fcaacea2f9acb6cea98ccfec", - "PivotTotalDifficulty": "24871865" + "PivotNumber": 15050000, + "PivotHash": "0xa76e62e7236f647246e47696bfbc8d3fcf2d8df1664d62197fc2f2fef3a2e472", + "PivotTotalDifficulty": "25060219" }, "Metrics": { "NodeName": "JOC-Testnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json index 19b0cc9e644..3a30f79acc4 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 26900000, - "PivotHash": "0x440a8e2cc7670a094acbd1f0ee8a59bfdcc6a7e66712ca4dd5c17e1e7a9296bc", + "PivotNumber": 27130000, + "PivotHash": "0x01922d659e4fb8918d40febde2b9d26a71b2dec2f39b2b9ab90425628e33b442", "PivotTotalDifficulty": "0", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json index 062590c2c5d..8f427a8f31a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 22280000, - "PivotHash": "0x84d6fa98aac973d62c1a3bfc7ea9ff6e5b3d7118fe906592e624548750761051", + "PivotNumber": 22580000, + "PivotHash": "0x16c23c7588f52856a3422ea7e6b4052b9f0287017f01e05cda78f19a3c8f5a87", "PivotTotalDifficulty": "37331807", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index 7656ce8e73d..ce3fe1857d8 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -10,8 +10,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 24056000, - "PivotHash": "0x55ef3495449858196d13149bee4a61c95a139fea674cecc262a1313f37f45f25", + "PivotNumber": 24106000, + "PivotHash": "0x2d2ac74ae7ca57ee08feef9e0cb6241f5c761e9408fa15fc0c9b944873a60895", "PivotTotalDifficulty": "58750003716598352816469", "FastSyncCatchUpHeightDelta": "10000000000", "AncientReceiptsBarrier": 15537394, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index 6e934a1e057..6dd0bd5106a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -15,8 +15,8 @@ "FastSyncCatchUpHeightDelta": "10000000000", "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, - "PivotNumber": 145330000, - "PivotHash": "0x65bcb7297272faf0198968b40890ba8aa59764982ff7099e3ae00ebffe0b317e" + "PivotNumber": 145630000, + "PivotHash": "0x8b3d9430308aa1586140f05826b351dc07b68205341bb4de9b0c0dd35765148b" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index 42a3b15f36f..7120b6ccf62 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 37220000, - "PivotHash": "0x8f5f71dc3c7bd02b93b08c6967e72920edf25a4e44202f1a30063b6e607dec98" + "PivotNumber": 37530000, + "PivotHash": "0x8db44f466e83096f4db5b65928ebddcc798200f510d26a41d4d10636582b0737" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index 1e55080c2fc..64769451266 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -17,8 +17,8 @@ "FastSync": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 9881000, - "PivotHash": "0x4ee04d56b4218d5034a10541b1221477009ff50ec4c2a875143f50afeec821d3", + "PivotNumber": 9927000, + "PivotHash": "0x83b4469d7485dc6fde0be253ccc21b165d1eb5c76a4f7f0227c6d468730c5f27", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 1450409, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index d78f7685831..af7bdc25991 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 23460000, - "PivotHash": "0xad968bde1f46ad7f27e0442f141bd3bbee3efb36c8da93c7cf17d59002e8cdbe" + "PivotNumber": 23760000, + "PivotHash": "0x048798c8c100aa79c35588bf18358d90f340f8d9431b722de8e8d5c715e66dc3" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index 973e6a71866..7a4df5860e1 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 22850000, - "PivotHash": "0x0a7087f1c90fc7a7c7c72c64d3aba17f35ea78075933eede4e376daec43fd632" + "PivotNumber": 23150000, + "PivotHash": "0x9f91d2e4e3b632b3a5ef1ff64cbd691242f61cfaf30af7c4907ae54bc1a4cca8" }, "Discovery": { "DiscoveryVersion": "V5" From 2230f35e9cfaaaded68effb77485e8d5415b57cb Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Sun, 28 Dec 2025 11:25:04 +0100 Subject: [PATCH 134/255] Merge package release workflows (#10049) --- .github/workflows/publish-nuget.yml | 48 -------------------------- .github/workflows/publish-packages.yml | 46 +++++++++++++++++++++++- 2 files changed, 45 insertions(+), 49 deletions(-) delete mode 100644 .github/workflows/publish-nuget.yml diff --git a/.github/workflows/publish-nuget.yml b/.github/workflows/publish-nuget.yml deleted file mode 100644 index c9495bd65f8..00000000000 --- a/.github/workflows/publish-nuget.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Publish NuGet packages - -on: - release: - types: [published] - -jobs: - publish: - name: Publish Nethermind.ReferenceAssemblies - runs-on: ubuntu-latest - if: ${{ !github.event.release.prerelease }} - steps: - - name: Check out Nethermind repository - uses: actions/checkout@v6 - with: - ref: ${{ github.event.release.tag_name }} - - - name: Set up .NET - uses: actions/setup-dotnet@v5 - - - name: Download Nethermind reference assemblies - id: download - run: | - json=$(curl -s ${{ github.event.release.assets_url }}) - asset=$(echo "$json" | jq -r '.[] | select(.name | contains("ref-assemblies"))') - name=$(echo "$asset" | jq -r '.name') - url=$(echo "$asset" | jq -r '.browser_download_url') - curl -sL $url -o refasm.zip - unzip refasm.zip -d src/Nethermind/Nethermind.ReferenceAssemblies/ref - echo "asset-name=$name" >> $GITHUB_OUTPUT - - - name: Submit package - working-directory: src/Nethermind/Nethermind.ReferenceAssemblies - run: | - dotnet pack -c release - dotnet nuget push ../artifacts/**/*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json - - - name: Create GitHub app token - id: gh-app - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ vars.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - - - name: Delete asset from release - env: - GITHUB_TOKEN: ${{ steps.gh-app.outputs.token }} - run: gh release delete-asset ${{ github.event.release.tag_name }} ${{ steps.download.outputs.asset-name }} -y diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml index 8c57f6e7a28..30637b0e1d3 100644 --- a/.github/workflows/publish-packages.yml +++ b/.github/workflows/publish-packages.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest if: ${{ !github.event.release.prerelease }} steps: - - name: Check out Nethermind repository + - name: Check out repository uses: actions/checkout@v6 with: ref: ${{ github.event.release.tag_name }} @@ -143,3 +143,47 @@ jobs: git commit -am "$message" git push origin $head_branch gh pr create -B main -H $head_branch -t "$message" -b "Auto-updated Homebrew formula for Nethermind v${{ github.event.release.tag_name }}" + + publish-nuget: + name: Publish Nethermind.ReferenceAssemblies + runs-on: ubuntu-latest + if: ${{ !github.event.release.prerelease }} + steps: + - name: Check out repository + uses: actions/checkout@v6 + with: + ref: ${{ github.event.release.tag_name }} + + - name: Set up .NET + uses: actions/setup-dotnet@v5 + + - name: Download Nethermind reference assemblies + id: download + run: | + json=$(curl -s ${{ github.event.release.assets_url }}) + asset=$(echo "$json" | jq -r '.[] | select(.name | contains("ref-assemblies"))') + name=$(echo "$asset" | jq -r '.name') + url=$(echo "$asset" | jq -r '.browser_download_url') + curl -sL $url -o refasm.zip + unzip refasm.zip -d src/Nethermind/Nethermind.ReferenceAssemblies/ref + echo "asset-name=$name" >> $GITHUB_OUTPUT + + - name: Submit package + working-directory: src/Nethermind/Nethermind.ReferenceAssemblies + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + run: | + dotnet pack -c release + dotnet nuget push ../artifacts/**/*.nupkg -k "$NUGET_API_KEY" -s https://api.nuget.org/v3/index.json + + - name: Create GitHub app token + id: gh-app + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ vars.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + + - name: Delete asset from release + env: + GITHUB_TOKEN: ${{ steps.gh-app.outputs.token }} + run: gh release delete-asset ${{ github.event.release.tag_name }} ${{ steps.download.outputs.asset-name }} -y From 0416efdb080789f9ffb4ec7b226f9b3dea35fcab Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Sun, 28 Dec 2025 11:34:04 +0100 Subject: [PATCH 135/255] Fix/get logs optimization (#9923) * try fix * Fix tests * Try fix * Fix * Fix from & to * Fix block in the future * Fix build * Fix range in the future * Fix block range * to * Fix tests * Fix json rpc tests * Fix formatting * Fix blockchain tests * Fix suggestions * Fix tags * Remove address from AddressFilter * Fix tests * Fix address filter * Optimize Filter changes * fix * refactor * Apply suggestions from code review Co-authored-by: Nikita Mescheryakov --------- Co-authored-by: Nikita Meshcheriakov --- .../Builders/FilterBuilder.cs | 2 +- .../Filters/AddressFilterTests.cs | 30 +++++----------- .../Filters/FilterStoreTests.cs | 6 ++-- .../Nethermind.Facade/BlockchainBridge.cs | 6 ++-- .../Filters/AddressFilter.cs | 34 +++++++++---------- .../Nethermind.Facade/Filters/FilterStore.cs | 5 ++- .../Filters/Topics/AnyTopicsFilter.cs | 26 +++++--------- .../Filters/Topics/SequenceTopicsFilter.cs | 10 ++---- .../Nethermind.Facade/IBlockchainBridge.cs | 6 ++-- .../Nethermind.JsonRpc/Modules/Eth/Filter.cs | 25 +++++++------- 10 files changed, 61 insertions(+), 89 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs b/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs index ee7cc539f26..86c7706fe3f 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs @@ -125,7 +125,7 @@ public FilterBuilder WithAddress(Address address) public FilterBuilder WithAddresses(params Address[] addresses) { - _address = new AddressFilter(addresses.Select(static a => new AddressAsKey(a))); + _address = new AddressFilter(addresses.Select(static a => new AddressAsKey(a)).ToHashSet()); return this; } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs index 69d73ec8c18..4fe896388c7 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs @@ -73,7 +73,7 @@ public void Accepts_any_address_by_ref() [Test] public void Accepts_any_address_when_set_is_empty() { - AddressAsKey[] addresses = []; + HashSet addresses = new(); AddressFilter filter = new AddressFilter(addresses); filter.Accepts(TestItem.AddressA).Should().BeTrue(); @@ -84,7 +84,7 @@ public void Accepts_any_address_when_set_is_empty() [Test] public void Accepts_any_address_when_set_is_empty_by_ref() { - AddressAsKey[] addresses = []; + HashSet addresses = new(); AddressFilter filter = new AddressFilter(addresses); AddressStructRef addressARef = TestItem.AddressA.ToStructRef(); @@ -98,10 +98,7 @@ public void Accepts_any_address_when_set_is_empty_by_ref() [Test] public void Accepts_only_addresses_in_a_set() { - AddressAsKey[] addresses = - [ - TestItem.AddressA, TestItem.AddressC - ]; + HashSet addresses = [TestItem.AddressA, TestItem.AddressC]; AddressFilter filter = new AddressFilter(addresses); filter.Accepts(TestItem.AddressA).Should().BeTrue(); @@ -112,10 +109,7 @@ public void Accepts_only_addresses_in_a_set() [Test] public void Accepts_only_addresses_in_a_set_by_ref() { - AddressAsKey[] addresses = - [ - TestItem.AddressA, TestItem.AddressC - ]; + HashSet addresses = [TestItem.AddressA, TestItem.AddressC]; AddressFilter filter = new AddressFilter(addresses); AddressStructRef addressARef = TestItem.AddressA.ToStructRef(); @@ -187,7 +181,7 @@ public void Matches_bloom_using_any_address_by_ref() [Test] public void Matches_any_bloom_when_set_is_empty() { - AddressAsKey[] addresses = []; + HashSet addresses = new(); AddressFilter filter = new AddressFilter(addresses); filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); @@ -198,7 +192,7 @@ public void Matches_any_bloom_when_set_is_empty() [Test] public void Matches_any_bloom_when_set_is_empty_by_ref() { - AddressAsKey[] addresses = []; + HashSet addresses = new(); AddressFilter filter = new AddressFilter(addresses); BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); @@ -235,10 +229,7 @@ public void Matches_any_bloom_when_set_is_forced_null_by_ref() [Test] public void Matches_any_bloom_using_addresses_set() { - AddressAsKey[] addresses = - [ - TestItem.AddressA, TestItem.AddressC - ]; + HashSet addresses = [TestItem.AddressA, TestItem.AddressC]; AddressFilter filter = new AddressFilter(addresses); filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); @@ -249,10 +240,7 @@ public void Matches_any_bloom_using_addresses_set() [Test] public void Matches_any_bloom_using_addresses_set_by_ref() { - AddressAsKey[] addresses = - [ - TestItem.AddressA, TestItem.AddressC - ]; + HashSet addresses = [TestItem.AddressA, TestItem.AddressC]; AddressFilter filter = new AddressFilter(addresses); BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); @@ -266,7 +254,7 @@ public void Matches_any_bloom_using_addresses_set_by_ref() private static Core.Bloom BloomFromAddress(Address address) { LogEntry entry = new LogEntry(address, [], []); - Core.Bloom bloom = new Core.Bloom(new[] { entry }); + Core.Bloom bloom = new Core.Bloom([entry]); return bloom; } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs index 51e67845edd..78cfc3f70b6 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterStoreTests.cs @@ -103,14 +103,14 @@ public static IEnumerable CorrectlyCreatesAddressFilterTestCases get { yield return new TestCaseData(null, AddressFilter.AnyAddress); - yield return new TestCaseData(new[] { new AddressAsKey(TestItem.AddressA) }, new AddressFilter(TestItem.AddressA)); - yield return new TestCaseData(new[] { new AddressAsKey(TestItem.AddressA), new AddressAsKey(TestItem.AddressB) }, + yield return new TestCaseData(new HashSet { new(TestItem.AddressA) }, new AddressFilter(TestItem.AddressA)); + yield return new TestCaseData(new HashSet { new(TestItem.AddressA), new(TestItem.AddressB) }, new AddressFilter([TestItem.AddressA, TestItem.AddressB])); } } [TestCaseSource(nameof(CorrectlyCreatesAddressFilterTestCases))] - public void Correctly_creates_address_filter(AddressAsKey[] address, AddressFilter expected) + public void Correctly_creates_address_filter(HashSet address, AddressFilter expected) { BlockParameter from = new(100); BlockParameter to = new(BlockParameterType.Latest); diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 2568c84941f..2b03bd8dbfa 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -289,7 +289,7 @@ public ulong GetChainId() public IEnumerable GetLogs( BlockParameter fromBlock, BlockParameter toBlock, - AddressAsKey[]? addresses = null, + HashSet? addresses = null, IEnumerable? topics = null, CancellationToken cancellationToken = default) { @@ -300,7 +300,7 @@ public IEnumerable GetLogs( public LogFilter GetFilter( BlockParameter fromBlock, BlockParameter toBlock, - AddressAsKey[]? addresses = null, + HashSet? addresses = null, IEnumerable? topics = null) { return filterStore.CreateLogFilter(fromBlock, toBlock, addresses, topics, false); @@ -326,7 +326,7 @@ public bool TryGetLogs(int filterId, out IEnumerable filterLogs, Canc } public int NewFilter(BlockParameter fromBlock, BlockParameter toBlock, - AddressAsKey[]? address = null, IEnumerable? topics = null) + HashSet? address = null, IEnumerable? topics = null) { LogFilter filter = filterStore.CreateLogFilter(fromBlock, toBlock, address, topics); filterStore.SaveFilter(filter); diff --git a/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs b/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs index ccdcd9e4672..dbbd31ae246 100644 --- a/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs +++ b/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs @@ -7,7 +7,7 @@ namespace Nethermind.Blockchain.Filters { - public class AddressFilter + public class AddressFilter(HashSet addresses) { public static readonly AddressFilter AnyAddress = new([]); @@ -17,29 +17,25 @@ public AddressFilter(Address address) : this([address]) { } - public AddressFilter(IEnumerable addresses) - { - Addresses = addresses.ToHashSet(); - } - - public HashSet Addresses { get; } + public HashSet Addresses { get; } = addresses; private Bloom.BloomExtract[] AddressesBloomExtracts => _addressesBloomIndexes ??= CalculateBloomExtracts(); public bool Accepts(Address address) => Addresses.Count == 0 || Addresses.Contains(address); public bool Accepts(ref AddressStructRef address) { - if (Addresses.Count > 0) + if (Addresses.Count == 0) { - foreach (var a in Addresses) - { - if (a == address) return true; - } + return true; + } - return false; + foreach (AddressAsKey a in Addresses) + { + if (a == address) return true; } - return true; + return false; + } public bool Matches(Bloom bloom) @@ -48,9 +44,10 @@ public bool Matches(Bloom bloom) { return true; } - foreach (Bloom.BloomExtract index in AddressesBloomExtracts) + + for (var i = 0; i < AddressesBloomExtracts.Length; i++) { - if (bloom.Matches(index)) + if (bloom.Matches(AddressesBloomExtracts[i])) { return true; } @@ -65,9 +62,10 @@ public bool Matches(ref BloomStructRef bloom) { return true; } - foreach (Bloom.BloomExtract index in AddressesBloomExtracts) + + for (var i = 0; i < AddressesBloomExtracts.Length; i++) { - if (bloom.Matches(index)) + if (bloom.Matches(AddressesBloomExtracts[i])) { return true; } diff --git a/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs b/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs index 6976dad25e9..1a0fe2d5cde 100644 --- a/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs +++ b/src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs @@ -123,8 +123,7 @@ public BlockFilter CreateBlockFilter(bool setId = true) => public PendingTransactionFilter CreatePendingTransactionFilter(bool setId = true) => new(GetFilterId(setId)); - public LogFilter CreateLogFilter(BlockParameter fromBlock, BlockParameter toBlock, - AddressAsKey[]? addresses = null, IEnumerable? topics = null, bool setId = true) => + public LogFilter CreateLogFilter(BlockParameter fromBlock, BlockParameter toBlock, HashSet? addresses = null, IEnumerable? topics = null, bool setId = true) => new(GetFilterId(setId), fromBlock, toBlock, @@ -202,7 +201,7 @@ private static TopicExpression GetTopicExpression(FilterTopic? filterTopic) return AnyTopic.Instance; } - private static AddressFilter GetAddress(AddressAsKey[]? addresses) => addresses is null ? AddressFilter.AnyAddress : new AddressFilter(addresses); + private static AddressFilter GetAddress(HashSet? addresses) => addresses is null ? AddressFilter.AnyAddress : new AddressFilter(addresses); private static FilterTopic?[]? GetFilterTopics(IEnumerable? topics) => topics?.Select(GetTopic).ToArray(); diff --git a/src/Nethermind/Nethermind.Facade/Filters/Topics/AnyTopicsFilter.cs b/src/Nethermind/Nethermind.Facade/Filters/Topics/AnyTopicsFilter.cs index 60ce1106828..7bf063bfb60 100644 --- a/src/Nethermind/Nethermind.Facade/Filters/Topics/AnyTopicsFilter.cs +++ b/src/Nethermind/Nethermind.Facade/Filters/Topics/AnyTopicsFilter.cs @@ -8,25 +8,17 @@ namespace Nethermind.Blockchain.Filters.Topics { - public class AnyTopicsFilter : TopicsFilter + public class AnyTopicsFilter(params TopicExpression[] expressions) : TopicsFilter { - - private readonly TopicExpression[] _expressions; - - public AnyTopicsFilter(params TopicExpression[] expressions) - { - _expressions = expressions; - } - public override bool Accepts(LogEntry entry) => Accepts(entry.Topics); private bool Accepts(Hash256[] topics) { - for (int i = 0; i < _expressions.Length; i++) + for (int i = 0; i < expressions.Length; i++) { for (int j = 0; j < topics.Length; j++) { - if (_expressions[i].Accepts(topics[j])) + if (expressions[i].Accepts(topics[j])) { return true; } @@ -45,11 +37,11 @@ public override bool Accepts(ref LogEntryStructRef entry) Span buffer = stackalloc byte[32]; var iterator = new KeccaksIterator(entry.TopicsRlp, buffer); - for (int i = 0; i < _expressions.Length; i++) + for (int i = 0; i < expressions.Length; i++) { if (iterator.TryGetNext(out var keccak)) { - if (_expressions[i].Accepts(ref keccak)) + if (expressions[i].Accepts(ref keccak)) { return true; } @@ -67,9 +59,9 @@ public override bool Matches(Bloom bloom) { bool result = true; - for (int i = 0; i < _expressions.Length; i++) + for (int i = 0; i < expressions.Length; i++) { - result = _expressions[i].Matches(bloom); + result = expressions[i].Matches(bloom); if (result) { break; @@ -83,9 +75,9 @@ public override bool Matches(ref BloomStructRef bloom) { bool result = true; - for (int i = 0; i < _expressions.Length; i++) + for (int i = 0; i < expressions.Length; i++) { - result = _expressions[i].Matches(ref bloom); + result = expressions[i].Matches(ref bloom); if (result) { break; diff --git a/src/Nethermind/Nethermind.Facade/Filters/Topics/SequenceTopicsFilter.cs b/src/Nethermind/Nethermind.Facade/Filters/Topics/SequenceTopicsFilter.cs index 7386afe49ad..a3d28197ba3 100644 --- a/src/Nethermind/Nethermind.Facade/Filters/Topics/SequenceTopicsFilter.cs +++ b/src/Nethermind/Nethermind.Facade/Filters/Topics/SequenceTopicsFilter.cs @@ -9,16 +9,12 @@ namespace Nethermind.Blockchain.Filters.Topics { - public class SequenceTopicsFilter : TopicsFilter, IEquatable + public class SequenceTopicsFilter(params TopicExpression[] expressions) + : TopicsFilter, IEquatable { public static readonly SequenceTopicsFilter AnyTopic = new(); - private readonly TopicExpression[] _expressions; - - public SequenceTopicsFilter(params TopicExpression[] expressions) - { - _expressions = expressions; - } + private readonly TopicExpression[] _expressions = expressions; public override bool Accepts(LogEntry entry) => Accepts(entry.Topics); diff --git a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs index 21e95dcc502..d4bed512d8d 100644 --- a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs @@ -36,16 +36,16 @@ public interface IBlockchainBridge : ILogFinder int NewBlockFilter(); int NewPendingTransactionFilter(); - int NewFilter(BlockParameter fromBlock, BlockParameter toBlock, AddressAsKey[]? address = null, IEnumerable? topics = null); + int NewFilter(BlockParameter fromBlock, BlockParameter toBlock, HashSet? address = null, IEnumerable? topics = null); void UninstallFilter(int filterId); bool FilterExists(int filterId); Hash256[] GetBlockFilterChanges(int filterId); Hash256[] GetPendingTransactionFilterChanges(int filterId); FilterLog[] GetLogFilterChanges(int filterId); FilterType GetFilterType(int filterId); - LogFilter GetFilter(BlockParameter fromBlock, BlockParameter toBlock, AddressAsKey[]? addresses = null, IEnumerable? topics = null); + LogFilter GetFilter(BlockParameter fromBlock, BlockParameter toBlock, HashSet? addresses = null, IEnumerable? topics = null); IEnumerable GetLogs(LogFilter filter, BlockHeader fromBlock, BlockHeader toBlock, CancellationToken cancellationToken = default); - IEnumerable GetLogs(BlockParameter fromBlock, BlockParameter toBlock, AddressAsKey[]? addresses = null, IEnumerable? topics = null, CancellationToken cancellationToken = default); + IEnumerable GetLogs(BlockParameter fromBlock, BlockParameter toBlock, HashSet? addresses = null, IEnumerable? topics = null, CancellationToken cancellationToken = default); bool TryGetLogs(int filterId, out IEnumerable filterLogs, CancellationToken cancellationToken = default); void RunTreeVisitor(ITreeVisitor treeVisitor, Hash256 stateRoot) where TCtx : struct, INodeContext; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/Filter.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/Filter.cs index 0343cbf9445..57f26cee883 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/Filter.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/Filter.cs @@ -13,7 +13,7 @@ namespace Nethermind.JsonRpc.Modules.Eth; public class Filter : IJsonRpcParam { - public AddressAsKey[]? Address { get; set; } + public HashSet? Address { get; set; } public BlockParameter FromBlock { get; set; } @@ -72,7 +72,7 @@ public void ReadJson(JsonElement filter, JsonSerializerOptions options) } } - private static AddressAsKey[]? GetAddress(JsonElement token, JsonSerializerOptions options) + private static HashSet? GetAddress(JsonElement token, JsonSerializerOptions options) { switch (token.ValueKind) { @@ -81,14 +81,13 @@ public void ReadJson(JsonElement filter, JsonSerializerOptions options) case JsonValueKind.String: return [new AddressAsKey(new Address(token.ToString()))]; case JsonValueKind.Array: - var enumerator = token.EnumerateArray(); - List result = new(); - while (enumerator.MoveNext()) + HashSet result = new(token.GetArrayLength()); + foreach (JsonElement element in token.EnumerateArray()) { - result.Add(new(new Address(enumerator.Current.ToString()))); + result.Add(new(new Address(element.ToString()))); } - return result.ToArray(); + return result; default: throw new ArgumentException("invalid address field"); } @@ -101,7 +100,7 @@ public void ReadJson(JsonElement filter, JsonSerializerOptions options) yield break; } - foreach (var token in array.GetValueOrDefault().EnumerateArray()) + foreach (JsonElement token in array.Value.EnumerateArray()) { switch (token.ValueKind) { @@ -112,14 +111,14 @@ public void ReadJson(JsonElement filter, JsonSerializerOptions options) yield return [new Hash256(token.GetString()!)]; break; case JsonValueKind.Array: - JsonElement.ArrayEnumerator enumerator = token.EnumerateArray(); - List result = new(); - while (enumerator.MoveNext()) + Hash256[] result = new Hash256[token.GetArrayLength()]; + int i = 0; + foreach (JsonElement element in token.EnumerateArray()) { - result.Add(new(enumerator.Current.ToString())); + result[i++] = new Hash256(element.ToString()); } - yield return result.ToArray(); + yield return result; break; default: throw new ArgumentException("invalid topics field"); From bf97c42f140f4a8839588f41e20e45a86735d91a Mon Sep 17 00:00:00 2001 From: ANtutov Date: Sun, 28 Dec 2025 14:52:50 +0200 Subject: [PATCH 136/255] fix: resource cleanup in BeaconHeadersSyncFeed (#10037) * fix: resource cleanup in BeaconHeadersSyncFeed * remove override --- .../Synchronization/BeaconHeadersSyncFeed.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncFeed.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncFeed.cs index eaf122d7f2a..4a5ed73063b 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncFeed.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncFeed.cs @@ -112,16 +112,6 @@ protected override void FinishAndCleanUp() FallAsleep(); PostFinishCleanUp(); } - - protected override void PostFinishCleanUp() - { - HeadersSyncProgressLoggerReport.Update(TotalBlocks); - HeadersSyncProgressLoggerReport.MarkEnd(); - ClearDependencies(); // there may be some dependencies from wrong branches - _pending.Clear(); // there may be pending wrong branches - _sent.Clear(); // we my still be waiting for some bad branches - } - public override Task PrepareRequest(CancellationToken cancellationToken = default) { if (_pivotNumber != ExpectedPivotNumber) From 1cb6b080af3ef48c20ff5f4bafae1df70e7bdf61 Mon Sep 17 00:00:00 2001 From: Bashmunta Date: Sun, 28 Dec 2025 21:28:54 +0200 Subject: [PATCH 137/255] perf: avoid rlp encode-decode in simulate receipt recovery (#10021) * perf: avoid rlp encode-decode in simulate receipt recovery * fix --- .../Simulate/SimulateDictionaryBlockStore.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryBlockStore.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryBlockStore.cs index 600332daf7d..7c16e0f7331 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryBlockStore.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryBlockStore.cs @@ -53,16 +53,10 @@ public void Delete(long blockNumber, Hash256 blockHash) return readonlyBaseBlockStore.GetRlp(blockNumber, blockHash); } - public ReceiptRecoveryBlock? GetReceiptRecoveryBlock(long blockNumber, Hash256 blockHash) - { - if (_blockNumDict.TryGetValue(blockNumber, out Block block)) - { - using NettyRlpStream newRlp = _blockDecoder.EncodeToNewNettyStream(block); - using var memoryManager = new CappedArrayMemoryManager(newRlp.Data); - return _blockDecoder.DecodeToReceiptRecoveryBlock(memoryManager, memoryManager.Memory, RlpBehaviors.None); - } - return readonlyBaseBlockStore.GetReceiptRecoveryBlock(blockNumber, blockHash); - } + public ReceiptRecoveryBlock? GetReceiptRecoveryBlock(long blockNumber, Hash256 blockHash) => + _blockNumDict.TryGetValue(blockNumber, out Block block) + ? new ReceiptRecoveryBlock(block) + : readonlyBaseBlockStore.GetReceiptRecoveryBlock(blockNumber, blockHash); public void Cache(Block block) => Insert(block); From 89ec6a27152b2f34f69632eee45aaee9392cc05d Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Sun, 28 Dec 2025 22:20:45 +0100 Subject: [PATCH 138/255] Fix CodeQL workflow (#10056) --- .github/workflows/codeql.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 43b3d18e32f..82079d5bff2 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -20,20 +20,30 @@ jobs: matrix: language: ['csharp', 'actions'] steps: + - name: Free up disk space + uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 + with: + large-packages: false + tool-cache: false + - name: Check out repository uses: actions/checkout@v6 + - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} queries: security-and-quality packs: githubsecuritylab/codeql-csharp-queries + - name: Set up .NET uses: actions/setup-dotnet@v5 + - name: Build Nethermind working-directory: src/Nethermind run: dotnet build Nethermind.slnx -c release + - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 with: category: '/language:${{ matrix.language }}' From e9098312db58eadd43b7a8fc5e3158454f4d2aee Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Mon, 29 Dec 2025 02:50:37 -0500 Subject: [PATCH 139/255] Check for 0 in MOD opcode (#10061) Check for 0 in Mod --- .../Instructions/EvmInstructions.Math2Param.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs index 78ab517518a..18b127e5c9b 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs @@ -165,7 +165,17 @@ public struct OpMod : IOpMath2Param { public static long GasCost => GasCostOf.Low; public static void Operation(in UInt256 a, in UInt256 b, out UInt256 result) - => UInt256.Mod(in a, in b, out result); + { + if (b.IsZeroOrOne) + { + // Modulo with 0 or 1 yields zero. + result = default; + } + else + { + UInt256.Mod(in a, in b, out result); + } + } } /// From fbdc38ef5ab07d761c922a558c8fc818176fd64f Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Mon, 29 Dec 2025 03:25:45 -0500 Subject: [PATCH 140/255] Keep EXP opcode in UInt256 domain (#10060) * Keep EXP opcode in UInt256 domain * Is bytes --- .../Instructions/EvmInstructions.Math2Param.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs index 18b127e5c9b..97d43989373 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math2Param.cs @@ -279,15 +279,15 @@ public static EvmExceptionType InstructionExp(VirtualM // Charge the fixed gas cost for exponentiation. TGasPolicy.Consume(ref gas, GasCostOf.Exp); - // Pop the base value from the stack. - if (!stack.PopUInt256(out UInt256 a)) + // Pop the base value and exponent from the stack. + if (!stack.PopUInt256(out UInt256 a) || + !stack.PopUInt256(out UInt256 exponent)) + { goto StackUnderflow; - - // Pop the exponent as a 256-bit word. - ReadOnlySpan bytes = stack.PopWord256(); + } // Determine the effective byte-length of the exponent. - int leadingZeros = bytes.LeadingZerosCount(); + int leadingZeros = exponent.CountLeadingZeros() >> 3; if (leadingZeros == 32) { // Exponent is zero, so the result is 1. @@ -310,7 +310,7 @@ public static EvmExceptionType InstructionExp(VirtualM else { // Perform exponentiation and push the 256-bit result onto the stack. - UInt256.Exp(a, new UInt256(bytes, true), out UInt256 result); + UInt256.Exp(in a, in exponent, out UInt256 result); stack.PushUInt256(in result); } } From c14fcd8ec91434c50c53f4a20e35dc3c02ea38c1 Mon Sep 17 00:00:00 2001 From: yyhrnk Date: Mon, 29 Dec 2025 15:03:17 +0200 Subject: [PATCH 141/255] fix: DataFeed constructor null checks (#10062) --- src/Nethermind/Nethermind.Runner/Monitoring/DataFeed.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Runner/Monitoring/DataFeed.cs b/src/Nethermind/Nethermind.Runner/Monitoring/DataFeed.cs index 6553a6433fc..8d3e0f0fd2a 100644 --- a/src/Nethermind/Nethermind.Runner/Monitoring/DataFeed.cs +++ b/src/Nethermind/Nethermind.Runner/Monitoring/DataFeed.cs @@ -57,7 +57,7 @@ public DataFeed( CancellationToken lifetime) { ArgumentNullException.ThrowIfNull(txPool); - ArgumentNullException.ThrowIfNull(syncPeerPool); + ArgumentNullException.ThrowIfNull(specProvider); ArgumentNullException.ThrowIfNull(receiptFinder); ArgumentNullException.ThrowIfNull(blockTree); ArgumentNullException.ThrowIfNull(syncPeerPool); From 271d8ef015910d5a34eb0c983824cc3cf43b03dc Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 29 Dec 2025 17:19:01 +0300 Subject: [PATCH 142/255] Update schema (#10035) --- .../BlockTreeTests.cs | 34 +++++++++--------- .../BlockTree.Initializer.cs | 7 ++-- .../Synchronization/ISyncConfig.cs | 14 +++----- .../Synchronization/SyncConfig.cs | 9 ++--- .../Eth/EthSyncingInfoTests.cs | 6 ++-- .../HistoryPrunerTests.cs | 2 +- .../Modules/Eth/EthRpcModuleTests.cs | 2 +- .../EngineModuleTests.Synchronization.cs | 6 ++-- .../Synchronization/BeaconHeadersSyncTests.cs | 8 ++--- .../Synchronization/BeaconPivotTests.cs | 2 +- .../configs/arena-z-mainnet.json | 4 +-- .../configs/arena-z-sepolia.json | 4 +-- .../configs/automata-mainnet.json | 4 +-- .../configs/base-mainnet.json | 2 +- .../configs/base-sepolia.json | 4 +-- .../configs/bob-mainnet.json | 2 +- .../configs/boba-mainnet.json | 4 +-- .../configs/boba-sepolia.json | 4 +-- .../configs/camp-sepolia.json | 4 +-- .../configs/celo-sep-sepolia.json | 2 +- .../configs/cyber-mainnet.json | 2 +- .../configs/cyber-sepolia.json | 2 +- .../configs/ethernity-mainnet.json | 2 +- .../configs/ethernity-sepolia.json | 2 +- .../configs/fraxtal-mainnet.json | 2 +- .../configs/funki-mainnet.json | 2 +- .../configs/funki-sepolia.json | 2 +- .../configs/hashkeychain-mainnet.json | 2 +- .../Nethermind.Runner/configs/hoodi.json | 2 +- .../configs/ink-mainnet.json | 2 +- .../configs/ink-sepolia.json | 2 +- .../configs/lisk-mainnet.json | 2 +- .../configs/lisk-sepolia.json | 2 +- .../configs/lyra-mainnet.json | 4 +-- .../Nethermind.Runner/configs/mainnet.json | 2 +- .../configs/metal-mainnet.json | 2 +- .../configs/metal-sepolia.json | 2 +- .../configs/mint-mainnet.json | 2 +- .../configs/mode-mainnet.json | 2 +- .../configs/mode-sepolia.json | 2 +- .../Nethermind.Runner/configs/op-mainnet.json | 2 +- .../Nethermind.Runner/configs/op-sepolia.json | 2 +- .../configs/orderly-mainnet.json | 2 +- .../configs/ozean-sepolia.json | 2 +- .../configs/pivotal-sepolia.json | 2 +- .../configs/polynomial-mainnet.json | 2 +- .../configs/race-mainnet.json | 2 +- .../configs/race-sepolia.json | 2 +- .../configs/redstone-mainnet.json | 2 +- .../configs/settlus-mainnet-mainnet.json | 2 +- .../configs/settlus-sepolia-sepolia.json | 4 +-- .../configs/shape-mainnet.json | 4 +-- .../configs/shape-sepolia.json | 4 +-- .../configs/soneium-mainnet.json | 2 +- .../configs/soneium-minato-sepolia.json | 4 +-- .../configs/sseed-mainnet.json | 4 +-- .../configs/surge-hoodi.json | 2 +- .../configs/swan-mainnet.json | 2 +- .../configs/swell-mainnet.json | 2 +- .../configs/tbn-mainnet.json | 2 +- .../configs/tbn-sepolia.json | 2 +- .../configs/unichain-mainnet.json | 2 +- .../configs/unichain-sepolia.json | 2 +- .../configs/worldchain-mainnet.json | 2 +- .../configs/worldchain-sepolia.json | 2 +- .../configs/xterio-eth-mainnet.json | 2 +- .../configs/zora-mainnet.json | 2 +- .../configs/zora-sepolia.json | 2 +- .../BlockDownloaderTests.cs | 2 +- .../E2ESyncTests.cs | 2 +- .../FastBlocks/BodiesSyncFeedTests.cs | 4 +-- .../FastBlocks/FastHeadersSyncTests.cs | 36 +++++++++---------- .../FastBlocks/ReceiptsSyncFeedTests.cs | 8 ++--- .../ForwardHeaderProviderTests.cs | 2 +- .../MultiSyncModeSelectorTests.Scenario.cs | 2 +- .../ReceiptSyncFeedTests.cs | 2 +- .../SnapSync/StateSyncPivotTest.cs | 2 +- .../SyncProgressResolverTests.cs | 16 ++++----- .../SyncReportTest.cs | 4 +-- .../FastBlocks/FastHeadersSyncFeed.cs | 2 +- tools/SchemaGenerator/SchemaGenerator.csproj | 1 - tools/SchemaGenerator/SchemaGenerator.slnx | 1 - 82 files changed, 154 insertions(+), 162 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs index 8042d314406..e873b4e5123 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System; @@ -1146,7 +1146,7 @@ public void When_lowestInsertedHeaderWasNotPersisted_useBinarySearchToLoadLowest SyncConfig syncConfig = new() { FastSync = true, - PivotNumber = beginIndex.ToString(), + PivotNumber = beginIndex, }; BlockTreeBuilder builder = Build.A @@ -1177,7 +1177,7 @@ public void When_lowestInsertedHeaderWasPersisted_doNot_useBinarySearchToLoadLow SyncConfig syncConfig = new() { FastSync = true, - PivotNumber = "105", + PivotNumber = 105, }; BlockTreeBuilder builder = Build.A @@ -1218,7 +1218,7 @@ public void Does_not_load_bestKnownNumber_before_syncPivot(long syncPivot, long SyncConfig syncConfig = new() { FastSync = true, - PivotNumber = $"{syncPivot}" + PivotNumber = syncPivot }; MemDb blockInfosDb = new MemDb(); @@ -1275,7 +1275,7 @@ public void Loads_best_known_correctly_on_inserts(long beginIndex, long inserted SyncConfig syncConfig = new() { - PivotNumber = beginIndex.ToString(), + PivotNumber = beginIndex, FastSync = true, }; @@ -1312,7 +1312,7 @@ public void Loads_best_head_up_to_best_persisted_state() SyncConfig syncConfig = new() { - PivotNumber = "0", + PivotNumber = 0, FastSync = true, }; @@ -1366,7 +1366,7 @@ public void Loads_best_known_correctly_on_inserts_followed_by_suggests(long pivo { SyncConfig syncConfig = new() { - PivotNumber = pivotNumber.ToString(), + PivotNumber = pivotNumber, }; BlockTreeBuilder builder = Build.A.BlockTree() .WithoutSettingHead @@ -1402,7 +1402,7 @@ public void Loads_best_known_correctly_when_head_before_pivot() int head = 10; SyncConfig syncConfig = new() { - PivotNumber = pivotNumber.ToString() + PivotNumber = pivotNumber }; BlockTreeBuilder treeBuilder = Build.A.BlockTree().OfChainLength(head + 1); @@ -1423,7 +1423,7 @@ public void Cannot_insert_genesis() SyncConfig syncConfig = new() { - PivotNumber = pivotNumber.ToString(), + PivotNumber = pivotNumber, }; BlockTree tree = Build.A.BlockTree() @@ -1444,7 +1444,7 @@ public void Should_set_zero_total_difficulty() SyncConfig syncConfig = new() { - PivotNumber = pivotNumber.ToString(), + PivotNumber = pivotNumber, }; CustomSpecProvider specProvider = new(((ForkActivation)0, London.Instance)); @@ -1472,7 +1472,7 @@ public void Inserts_blooms() SyncConfig syncConfig = new() { - PivotNumber = pivotNumber.ToString(), + PivotNumber = pivotNumber, }; IBloomStorage bloomStorage = Substitute.For(); @@ -1503,7 +1503,7 @@ public void Block_loading_is_lazy() { SyncConfig syncConfig = new() { - PivotNumber = 0L.ToString(), + PivotNumber = 0L, }; BlockTreeBuilder builder = Build.A.BlockTree() @@ -2037,7 +2037,7 @@ public void Load_SyncPivot_FromConfig() SyncConfig syncConfig = new SyncConfig() { FastSync = true, - PivotNumber = "999", + PivotNumber = 999, PivotHash = Hash256.Zero.ToString(), }; BlockTree blockTree = Build.A.BlockTree().WithSyncConfig(syncConfig).TestObject; @@ -2050,7 +2050,7 @@ public void Load_SyncPivot_FromDb() SyncConfig syncConfig = new SyncConfig() { FastSync = true, - PivotNumber = "999", + PivotNumber = 999, PivotHash = Hash256.Zero.ToString(), }; IDb metadataDb = new MemDb(); @@ -2069,7 +2069,7 @@ public void On_UpdateMainBranch_UpdateSyncPivot_ToLowestPersistedHeader() SyncConfig syncConfig = new() { FastSync = true, - PivotNumber = pivotNumber.ToString(), + PivotNumber = pivotNumber, PivotHash = TestItem.KeccakA.ToString(), }; @@ -2112,7 +2112,7 @@ public void On_ForkChoiceUpdated_UpdateSyncPivot_ToFinalizedHeader_BeforePersist SyncConfig syncConfig = new() { FastSync = true, - PivotNumber = pivotNumber.ToString(), + PivotNumber = pivotNumber, PivotHash = TestItem.KeccakA.ToString(), }; @@ -2160,7 +2160,7 @@ public void On_UpdateMainBranch_UpdateSyncPivot_ToHeaderUnderReorgDepth() SyncConfig syncConfig = new() { FastSync = true, - PivotNumber = pivotNumber.ToString(), + PivotNumber = pivotNumber, PivotHash = TestItem.KeccakA.ToString(), }; diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs index 3b2e7231c45..a3fdae24ed3 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System; @@ -7,7 +7,6 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Db; -using Nethermind.Serialization.Json; using Nethermind.Serialization.Rlp; namespace Nethermind.Blockchain; @@ -373,7 +372,7 @@ private void LoadSyncPivot() byte[]? pivotFromDb = _metadataDb.Get(MetadataDbKeys.UpdatedPivotData); if (pivotFromDb is null) { - _syncPivot = (LongConverter.FromString(_syncConfig.PivotNumber), _syncConfig.PivotHash is null ? null : new Hash256(Bytes.FromHexString(_syncConfig.PivotHash))); + _syncPivot = (_syncConfig.PivotNumber, _syncConfig.PivotHash is null ? null : new Hash256(Bytes.FromHexString(_syncConfig.PivotHash))); return; } @@ -383,7 +382,7 @@ private void LoadSyncPivot() if (updatedPivotBlockHash.IsZero) { - _syncPivot = (LongConverter.FromString(_syncConfig.PivotNumber), _syncConfig.PivotHash is null ? null : new Hash256(Bytes.FromHexString(_syncConfig.PivotHash))); + _syncPivot = (_syncConfig.PivotNumber, _syncConfig.PivotHash is null ? null : new Hash256(Bytes.FromHexString(_syncConfig.PivotHash))); return; } diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs index 45871f73fa1..acd70b687a4 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs @@ -1,13 +1,10 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System; using Nethermind.Config; -using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; using Nethermind.Db; using Nethermind.Int256; -using Nethermind.Serialization.Json; namespace Nethermind.Blockchain.Synchronization; @@ -48,14 +45,11 @@ public interface ISyncConfig : IConfig string PivotTotalDifficulty { get; } [ConfigItem(Description = "The number of the pivot block for the Fast sync mode.", DefaultValue = "0")] - string PivotNumber { get; set; } + long PivotNumber { get; set; } [ConfigItem(Description = "The hash of the pivot block for the Fast sync mode.", DefaultValue = "null")] string? PivotHash { get; set; } - [ConfigItem(DisabledForCli = true, HiddenFromDocs = true, DefaultValue = "0")] - private long PivotNumberParsed => LongConverter.FromString(PivotNumber); - [ConfigItem(DisabledForCli = true, HiddenFromDocs = true, DefaultValue = "0")] UInt256 PivotTotalDifficultyParsed => UInt256.Parse(PivotTotalDifficulty ?? "0"); @@ -74,7 +68,7 @@ public interface ISyncConfig : IConfig public long AncientBodiesBarrier { get; set; } [ConfigItem(DisabledForCli = true, HiddenFromDocs = true, DefaultValue = "1")] - public long AncientBodiesBarrierCalc => Math.Max(1, Math.Min(PivotNumberParsed, AncientBodiesBarrier)); + public long AncientBodiesBarrierCalc => Math.Max(1, Math.Min(PivotNumber, AncientBodiesBarrier)); [ConfigItem(Description = $$""" The earliest receipt downloaded with fast sync when `{{nameof(DownloadReceiptsInFastSync)}}` is set to `true`. The actual value is determined as follows: @@ -88,7 +82,7 @@ public interface ISyncConfig : IConfig public long AncientReceiptsBarrier { get; set; } [ConfigItem(DisabledForCli = true, HiddenFromDocs = true, DefaultValue = "1")] - public long AncientReceiptsBarrierCalc => Math.Max(1, Math.Min(PivotNumberParsed, Math.Max(AncientBodiesBarrier, AncientReceiptsBarrier))); + public long AncientReceiptsBarrierCalc => Math.Max(1, Math.Min(PivotNumber, Math.Max(AncientBodiesBarrier, AncientReceiptsBarrier))); [ConfigItem(Description = "Whether to use the Snap sync mode.", DefaultValue = "false")] public bool SnapSync { get; set; } diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs index 22c59297319..3060c83855a 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs @@ -1,5 +1,6 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only + using Nethermind.Config; using Nethermind.Core.Extensions; using Nethermind.Db; @@ -35,10 +36,10 @@ public bool SynchronizationEnabled public long AncientBodiesBarrier { get; set; } public long AncientReceiptsBarrier { get; set; } public string PivotTotalDifficulty { get; set; } - private string _pivotNumber = "0"; - public string PivotNumber + private long _pivotNumber = 0; + public long PivotNumber { - get => FastSync || SnapSync ? _pivotNumber : "0"; + get => FastSync || SnapSync ? _pivotNumber : 0; set => _pivotNumber = value; } diff --git a/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs b/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs index f5cd1c2d830..9ca570581b6 100644 --- a/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; @@ -95,7 +95,7 @@ public void IsSyncing_AncientBarriers(bool resolverDownloadingBodies, // AncientReceiptsBarrierCalc = Max(1, Min(Pivot, Max(BodiesBarrier, ReceiptsBarrier))) = ReceiptsBarrier = 900 DownloadBodiesInFastSync = true, DownloadReceiptsInFastSync = true, - PivotNumber = "1000" + PivotNumber = 1000 }; IBlockTree blockTree = Substitute.For(); blockTree.SyncPivot.Returns((1000, Keccak.Zero)); @@ -171,7 +171,7 @@ public void IsSyncing_ReturnsFalseOnFastSyncWithoutPivot(long bestHeader, long c { FastSync = true, SnapSync = true, - PivotNumber = "0", // Equivalent to not having a pivot + PivotNumber = 0, // Equivalent to not having a pivot }; EthSyncingInfo ethSyncingInfo = new(blockTree, syncPointers, syncConfig, new StaticSelector(SyncMode.All), syncProgressResolver, LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.History.Test/HistoryPrunerTests.cs b/src/Nethermind/Nethermind.History.Test/HistoryPrunerTests.cs index 1a9e756427c..801c6283290 100644 --- a/src/Nethermind/Nethermind.History.Test/HistoryPrunerTests.cs +++ b/src/Nethermind/Nethermind.History.Test/HistoryPrunerTests.cs @@ -39,7 +39,7 @@ public class HistoryPrunerTests { AncientBodiesBarrier = BeaconGenesisBlockNumber, AncientReceiptsBarrier = BeaconGenesisBlockNumber, - PivotNumber = "100", + PivotNumber = 100, SnapSync = true }; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index 9f8c5fb387e..fa1030ce93a 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -1674,7 +1674,7 @@ public static async Task CreateWithAncientBarriers(long blockNumber) var cutBlock = blockNumber; config.AncientBodiesBarrier = cutBlock; config.AncientReceiptsBarrier = cutBlock; - config.PivotNumber = cutBlock.ToString(); + config.PivotNumber = cutBlock; config.SnapSync = true; return config; }); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs index e3fff19a3d5..9fd3627c86c 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs @@ -845,7 +845,7 @@ public async Task Blocks_before_pivots_should_not_be_added_if_node_has_never_bee syncConfig = new SyncConfig { FastSync = true, - PivotNumber = syncedBlockTree.Head?.Number.ToString() ?? "", + PivotNumber = syncedBlockTree.Head?.Number ?? 0, PivotHash = syncedBlockTree.HeadHash?.ToString() ?? "", PivotTotalDifficulty = syncedBlockTree.Head?.TotalDifficulty?.ToString() ?? "" }; @@ -873,7 +873,7 @@ public async Task Blocks_before_pivots_should_not_be_added_if_node_has_been_sync syncConfig = new SyncConfig { FastSync = true, - PivotNumber = syncedBlockTree.Head?.Number.ToString() ?? "", + PivotNumber = syncedBlockTree.Head?.Number ?? 0, PivotHash = syncedBlockTree.HeadHash?.ToString() ?? "", PivotTotalDifficulty = syncedBlockTree.Head?.TotalDifficulty?.ToString() ?? "" }; @@ -903,7 +903,7 @@ public async Task Maintain_correct_pointers_for_beacon_sync_in_fast_sync() syncConfig = new SyncConfig { FastSync = true, - PivotNumber = syncedBlockTree.Head?.Number.ToString() ?? "", + PivotNumber = syncedBlockTree.Head?.Number ?? 0, PivotHash = syncedBlockTree.HeadHash?.ToString() ?? "", PivotTotalDifficulty = syncedBlockTree.Head?.TotalDifficulty?.ToString() ?? "" }; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs index 78ccb2a059e..13702ebf637 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs @@ -150,7 +150,7 @@ public async Task Can_keep_returning_nulls_after_all_batches_were_prepared() SyncConfig = new SyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, @@ -180,7 +180,7 @@ public async Task Finishes_when_all_downloaded() ISyncConfig syncConfig = new SyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }; @@ -214,7 +214,7 @@ public void Feed_able_to_sync_when_new_pivot_is_set() ISyncConfig syncConfig = new SyncConfig { FastSync = true, - PivotNumber = "500", + PivotNumber = 500, PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000000" // default difficulty in block tree builder }; @@ -302,7 +302,7 @@ public async Task When_pivot_changed_during_header_sync_after_chain_merged__do_n ISyncConfig syncConfig = new SyncConfig { FastSync = true, - PivotNumber = "0", + PivotNumber = 0, PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "0" }; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs index 08b3311202e..99c271e5c2d 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs @@ -29,7 +29,7 @@ public void Setup() _syncConfig = new SyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }; diff --git a/src/Nethermind/Nethermind.Runner/configs/arena-z-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/arena-z-mainnet.json index bab58793cb5..a8c3e9a1a32 100644 --- a/src/Nethermind/Nethermind.Runner/configs/arena-z-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/arena-z-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://rpc.arena-z.gg" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/arena-z-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/arena-z-sepolia.json index e5f4106176c..44960241092 100644 --- a/src/Nethermind/Nethermind.Runner/configs/arena-z-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/arena-z-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://testnet-rpc.arena-z.gg" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/automata-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/automata-mainnet.json index c30c764476e..58e2b9de89b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/automata-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/automata-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://automata-mainnet.alt.technology/" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index a68dafe7363..15b33ed0086 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000", + "FastSyncCatchUpHeightDelta": 10000000000, "PivotNumber": 40030000, "PivotHash": "0x5c90880ea1e205ab07cc587b73760271ebbceedaf0c00a163e2bb60dac66cad9" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index c3c9c0dfd8b..3cab4cce994 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000", + "FastSyncCatchUpHeightDelta": 10000000000, "PivotNumber": 35540000, "PivotHash": "0xc2502a90d5a1d21254bd4c613be06816e9a9d87719f74d3ea41714b30cc3098d" }, @@ -36,4 +36,4 @@ "Optimism": { "SequencerUrl": "https://sepolia-sequencer.base.org" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/bob-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/bob-mainnet.json index d79f8353c61..de9ab8e3207 100644 --- a/src/Nethermind/Nethermind.Runner/configs/bob-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/bob-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/boba-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/boba-mainnet.json index 3343389f324..04edc8fadbe 100644 --- a/src/Nethermind/Nethermind.Runner/configs/boba-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/boba-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://mainnet.boba.network" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/boba-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/boba-sepolia.json index c488fa4552f..7c959010a94 100644 --- a/src/Nethermind/Nethermind.Runner/configs/boba-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/boba-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://sepolia.boba.network" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/camp-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/camp-sepolia.json index 2bcfaa686a5..3a77232fae2 100644 --- a/src/Nethermind/Nethermind.Runner/configs/camp-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/camp-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://rpc.camp-network-testnet.gelato.digital" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json index 6452392575c..412aa76db8d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/cyber-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/cyber-mainnet.json index bd2a0fb4c36..0cbf9321894 100644 --- a/src/Nethermind/Nethermind.Runner/configs/cyber-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/cyber-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/cyber-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/cyber-sepolia.json index 2873df985ed..1d2025dbfc6 100644 --- a/src/Nethermind/Nethermind.Runner/configs/cyber-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/cyber-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/ethernity-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/ethernity-mainnet.json index a0da27de9c7..6098c3a4592 100644 --- a/src/Nethermind/Nethermind.Runner/configs/ethernity-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/ethernity-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/ethernity-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/ethernity-sepolia.json index 0fcb8d3694c..d59c3c57b0f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/ethernity-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/ethernity-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/fraxtal-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/fraxtal-mainnet.json index 3d0f5f85f91..91c9b400916 100644 --- a/src/Nethermind/Nethermind.Runner/configs/fraxtal-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/fraxtal-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/funki-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/funki-mainnet.json index 03f3a9f72cf..a065f1ef7f1 100644 --- a/src/Nethermind/Nethermind.Runner/configs/funki-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/funki-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/funki-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/funki-sepolia.json index 43684359e3c..9c5f4864d3a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/funki-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/funki-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/hashkeychain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/hashkeychain-mainnet.json index 2e2ec620d81..0c33c128bfa 100644 --- a/src/Nethermind/Nethermind.Runner/configs/hashkeychain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/hashkeychain-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/hoodi.json b/src/Nethermind/Nethermind.Runner/configs/hoodi.json index f0529fbb6c8..4c38c876d55 100644 --- a/src/Nethermind/Nethermind.Runner/configs/hoodi.json +++ b/src/Nethermind/Nethermind.Runner/configs/hoodi.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Metrics": { "NodeName": "Hoodi" diff --git a/src/Nethermind/Nethermind.Runner/configs/ink-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/ink-mainnet.json index b60ad9afb77..d6651db31ec 100644 --- a/src/Nethermind/Nethermind.Runner/configs/ink-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/ink-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/ink-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/ink-sepolia.json index 03e7b161e4c..736d7db6b9e 100644 --- a/src/Nethermind/Nethermind.Runner/configs/ink-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/ink-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/lisk-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/lisk-mainnet.json index 328cff8f05a..062eb61cf07 100644 --- a/src/Nethermind/Nethermind.Runner/configs/lisk-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/lisk-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/lisk-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/lisk-sepolia.json index d21a5722f34..c074053666b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/lisk-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/lisk-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/lyra-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/lyra-mainnet.json index f78b7f1ad24..1a8af9d222d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/lyra-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/lyra-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://rpc.lyra.finance" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index ce3fe1857d8..3d72b85c4ca 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -13,7 +13,7 @@ "PivotNumber": 24106000, "PivotHash": "0x2d2ac74ae7ca57ee08feef9e0cb6241f5c761e9408fa15fc0c9b944873a60895", "PivotTotalDifficulty": "58750003716598352816469", - "FastSyncCatchUpHeightDelta": "10000000000", + "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 15537394, "AncientBodiesBarrier": 15537394 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/metal-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/metal-mainnet.json index 7c217972a0f..6a2ee18ce7c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/metal-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/metal-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/metal-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/metal-sepolia.json index f1c84bb655f..9eb0d621ab1 100644 --- a/src/Nethermind/Nethermind.Runner/configs/metal-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/metal-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/mint-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mint-mainnet.json index 21d524f4daf..3ea8b656f21 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mint-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mint-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/mode-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mode-mainnet.json index 838b1b051c4..c08a2fe4380 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mode-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mode-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/mode-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/mode-sepolia.json index 08474c9cc0f..d6a2340b72c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mode-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/mode-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index 6dd0bd5106a..ae2bf0b44fd 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000", + "FastSyncCatchUpHeightDelta": 10000000000, "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, "PivotNumber": 145630000, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index 7120b6ccf62..dc37bc59914 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000", + "FastSyncCatchUpHeightDelta": 10000000000, "PivotNumber": 37530000, "PivotHash": "0x8db44f466e83096f4db5b65928ebddcc798200f510d26a41d4d10636582b0737" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/orderly-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/orderly-mainnet.json index 52c3b27c3ca..3aac45e5d24 100644 --- a/src/Nethermind/Nethermind.Runner/configs/orderly-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/orderly-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/ozean-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/ozean-sepolia.json index a38c80ae97e..a0dad90d46a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/ozean-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/ozean-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/pivotal-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/pivotal-sepolia.json index 8dda3a43954..a06fdc39b8c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/pivotal-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/pivotal-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/polynomial-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/polynomial-mainnet.json index 3d90623e18f..5e80eecda0d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/polynomial-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/polynomial-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/race-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/race-mainnet.json index 7daa781170f..68ed6cd4cf0 100644 --- a/src/Nethermind/Nethermind.Runner/configs/race-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/race-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/race-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/race-sepolia.json index 26f827d313c..8fd9fb4acee 100644 --- a/src/Nethermind/Nethermind.Runner/configs/race-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/race-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/redstone-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/redstone-mainnet.json index c567b0e6127..98d54970e0e 100644 --- a/src/Nethermind/Nethermind.Runner/configs/redstone-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/redstone-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/settlus-mainnet-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/settlus-mainnet-mainnet.json index 1e8a3d93b86..1b870437826 100644 --- a/src/Nethermind/Nethermind.Runner/configs/settlus-mainnet-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/settlus-mainnet-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/settlus-sepolia-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/settlus-sepolia-sepolia.json index e56a98d2720..15c0149a964 100644 --- a/src/Nethermind/Nethermind.Runner/configs/settlus-sepolia-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/settlus-sepolia-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://settlus-sep-testnet-sequencer.g.alchemy.com/" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/shape-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/shape-mainnet.json index a6b15850740..da9ccc1845c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/shape-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/shape-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://shape-mainnet-sequencer.g.alchemy.com" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/shape-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/shape-sepolia.json index 8cded2c56e9..faa5eb85959 100644 --- a/src/Nethermind/Nethermind.Runner/configs/shape-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/shape-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://shape-sepolia-sequencer.g.alchemy.com" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/soneium-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/soneium-mainnet.json index ae9a769fb31..3d246d647bc 100644 --- a/src/Nethermind/Nethermind.Runner/configs/soneium-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/soneium-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/soneium-minato-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/soneium-minato-sepolia.json index 5768e1879a6..92e05621ad1 100644 --- a/src/Nethermind/Nethermind.Runner/configs/soneium-minato-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/soneium-minato-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://rpc.minato.soneium.org" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/sseed-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/sseed-mainnet.json index 128a3cdb0c3..1000203289d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sseed-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/sseed-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://mainnet.superseed.xyz" } -} \ No newline at end of file +} diff --git a/src/Nethermind/Nethermind.Runner/configs/surge-hoodi.json b/src/Nethermind/Nethermind.Runner/configs/surge-hoodi.json index 6ea551e391c..c05e1cafcdf 100644 --- a/src/Nethermind/Nethermind.Runner/configs/surge-hoodi.json +++ b/src/Nethermind/Nethermind.Runner/configs/surge-hoodi.json @@ -13,7 +13,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Pruning": { "PruningBoundary": 1000 diff --git a/src/Nethermind/Nethermind.Runner/configs/swan-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/swan-mainnet.json index 43553239008..f5c31feaf49 100644 --- a/src/Nethermind/Nethermind.Runner/configs/swan-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/swan-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/swell-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/swell-mainnet.json index 86b70258293..0e11106aae7 100644 --- a/src/Nethermind/Nethermind.Runner/configs/swell-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/swell-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/tbn-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/tbn-mainnet.json index c7c28891363..25f3a8f8930 100644 --- a/src/Nethermind/Nethermind.Runner/configs/tbn-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/tbn-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/tbn-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/tbn-sepolia.json index 22462abfc6f..1d294e96314 100644 --- a/src/Nethermind/Nethermind.Runner/configs/tbn-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/tbn-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/unichain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/unichain-mainnet.json index 9239c6afe4f..db237391970 100644 --- a/src/Nethermind/Nethermind.Runner/configs/unichain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/unichain-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/unichain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/unichain-sepolia.json index 8f751367852..83a206258c8 100644 --- a/src/Nethermind/Nethermind.Runner/configs/unichain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/unichain-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index af7bdc25991..087836562d0 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000", + "FastSyncCatchUpHeightDelta": 10000000000, "PivotNumber": 23760000, "PivotHash": "0x048798c8c100aa79c35588bf18358d90f340f8d9431b722de8e8d5c715e66dc3" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index 7a4df5860e1..b119d014b14 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000", + "FastSyncCatchUpHeightDelta": 10000000000, "PivotNumber": 23150000, "PivotHash": "0x9f91d2e4e3b632b3a5ef1ff64cbd691242f61cfaf30af7c4907ae54bc1a4cca8" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/xterio-eth-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/xterio-eth-mainnet.json index 7e2e6907cfb..593b4b1f909 100644 --- a/src/Nethermind/Nethermind.Runner/configs/xterio-eth-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/xterio-eth-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/zora-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/zora-mainnet.json index 0fc8a6d876c..bb02d09fcf5 100644 --- a/src/Nethermind/Nethermind.Runner/configs/zora-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/zora-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/zora-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/zora-sepolia.json index 31eb7c42128..00c020b35de 100644 --- a/src/Nethermind/Nethermind.Runner/configs/zora-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/zora-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": "10000000000" + "FastSyncCatchUpHeightDelta": 10000000000 }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs index 1f6e5a39800..0cbbaae30d4 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs @@ -589,7 +589,7 @@ public async Task Can_DownloadBlockOutOfOrder(bool isMerge) { FastSync = true, StateMinDistanceFromHead = fastSyncLag, - PivotNumber = syncPivot.Number.ToString(), + PivotNumber = syncPivot.Number, PivotHash = syncPivot.Hash!.ToString(), }; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/E2ESyncTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/E2ESyncTests.cs index 398d142a009..29d322ab0c3 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/E2ESyncTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/E2ESyncTests.cs @@ -286,7 +286,7 @@ private async Task SetPivot(SyncConfig syncConfig, CancellationToken cancellatio long serverHeadNumber = serverBlockTree.Head!.Number; BlockHeader pivot = serverBlockTree.FindHeader(serverHeadNumber - HeadPivotDistance)!; syncConfig.PivotHash = pivot.Hash!.ToString(); - syncConfig.PivotNumber = pivot.Number.ToString(); + syncConfig.PivotNumber = pivot.Number; syncConfig.PivotTotalDifficulty = pivot.TotalDifficulty!.Value.ToString(); } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs index a3a70527e1d..e019dbc6130 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs @@ -66,7 +66,7 @@ public void Setup() { FastSync = true, PivotHash = _pivotBlock.Hash!.ToString(), - PivotNumber = _pivotBlock.Number.ToString(), + PivotNumber = _pivotBlock.Number, AncientBodiesBarrier = 0, DownloadBodiesInFastSync = true, }; @@ -191,7 +191,7 @@ public void When_finished_sync_with_old_default_barrier_then_finishes_immediatel { _syncConfig.AncientBodiesBarrier = AncientBarrierInConfig; _syncConfig.AncientReceiptsBarrier = AncientBarrierInConfig; - _syncConfig.PivotNumber = (AncientBarrierInConfig + 1_000_000).ToString(); + _syncConfig.PivotNumber = AncientBarrierInConfig + 1_000_000; _syncPointers.LowestInsertedBodyNumber = JustStarted ? null : _pivotBlock.Number; if (previousBarrierInDb is not null) _metadataDb.Set(MetadataDbKeys.BodiesBarrierWhenStarted, previousBarrierInDb.Value.ToBigEndianByteArrayWithoutLeadingZeros()); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs index f8adb18a78f..e72a272a30f 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs @@ -67,7 +67,7 @@ public async Task Can_prepare_3_requests_in_a_row() syncConfig: new TestSyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, @@ -101,7 +101,7 @@ public async Task Can_handle_forks_with_persisted_headers() syncConfig: new TestSyncConfig { FastSync = true, - PivotNumber = pivotBlock.Number.ToString(), + PivotNumber = pivotBlock.Number, PivotHash = pivotBlock.Hash!.ToString(), PivotTotalDifficulty = pivotBlock.TotalDifficulty.ToString()!, }, @@ -141,7 +141,7 @@ public async Task When_next_header_hash_update_is_delayed_do_not_drop_peer() syncConfig: new TestSyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = pivot.Hash!.Bytes.ToHexString(), PivotTotalDifficulty = pivot.TotalDifficulty.ToString()! }, @@ -200,7 +200,7 @@ public async Task Can_prepare_several_request_and_ignore_request_from_previous_s syncConfig: new TestSyncConfig { FastSync = true, - PivotNumber = "500", + PivotNumber = 500, PivotHash = pivot.Hash!.Bytes.ToHexString(), PivotTotalDifficulty = pivot.TotalDifficulty!.ToString()! }, @@ -246,7 +246,7 @@ public async Task Will_dispatch_when_only_partially_processed_dependency() syncConfig: new TestSyncConfig { FastSync = true, - PivotNumber = pivot.Number.ToString(), + PivotNumber = pivot.Number, PivotHash = pivot.Hash!.ToString(), PivotTotalDifficulty = pivot.TotalDifficulty.ToString()!, }, @@ -317,7 +317,7 @@ public async Task Can_reset_and_not_hang_when_a_batch_is_processing() syncConfig: new TestSyncConfig { FastSync = true, - PivotNumber = "500", + PivotNumber = 500, PivotHash = pivot.Hash!.Bytes.ToHexString(), PivotTotalDifficulty = pivot.TotalDifficulty!.ToString()! }, @@ -372,7 +372,7 @@ public async Task Can_keep_returning_nulls_after_all_batches_were_prepared() syncConfig: new TestSyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, @@ -403,7 +403,7 @@ public async Task Finishes_when_all_downloaded() new TestSyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, @@ -437,7 +437,7 @@ public async Task Can_resume_downloading_from_parent_of_lowest_inserted_header() new TestSyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, @@ -479,7 +479,7 @@ public async Task Can_insert_all_good_headers_from_dependent_batch_with_missing_ { var peerChain = CachedBlockTreeBuilder.OfLength(1000); var pivotHeader = peerChain.FindHeader(998)!; - var syncConfig = new TestSyncConfig { FastSync = true, PivotNumber = pivotHeader.Number.ToString(), PivotHash = pivotHeader.Hash!.ToString(), PivotTotalDifficulty = pivotHeader.TotalDifficulty.ToString()! }; + var syncConfig = new TestSyncConfig { FastSync = true, PivotNumber = pivotHeader.Number, PivotHash = pivotHeader.Hash!.ToString(), PivotTotalDifficulty = pivotHeader.TotalDifficulty.ToString()! }; IBlockTree localBlockTree = Build.A.BlockTree(peerChain.FindBlock(0, BlockTreeLookupOptions.None)!, null).WithSyncConfig(syncConfig).TestObject; localBlockTree.SyncPivot = (pivotHeader.Number, pivotHeader.Hash); @@ -535,7 +535,7 @@ public async Task Does_not_download_persisted_header() { var peerChain = CachedBlockTreeBuilder.OfLength(1000); var pivotHeader = peerChain.FindHeader(999)!; - var syncConfig = new TestSyncConfig { FastSync = true, PivotNumber = pivotHeader.Number.ToString(), PivotHash = pivotHeader.Hash!.ToString(), PivotTotalDifficulty = pivotHeader.TotalDifficulty.ToString()! }; + var syncConfig = new TestSyncConfig { FastSync = true, PivotNumber = pivotHeader.Number, PivotHash = pivotHeader.Hash!.ToString(), PivotTotalDifficulty = pivotHeader.TotalDifficulty.ToString()! }; IBlockTree localBlockTree = Build.A.BlockTree(peerChain.FindBlock(0, BlockTreeLookupOptions.None)!, null).WithSyncConfig(syncConfig).TestObject; localBlockTree.SyncPivot = (pivotHeader.Number, pivotHeader.Hash); @@ -591,7 +591,7 @@ public async Task Limits_persisted_headers_dependency() var syncConfig = new TestSyncConfig { FastSync = true, - PivotNumber = pivotHeader.Number.ToString(), + PivotNumber = pivotHeader.Number, PivotHash = pivotHeader.Hash!.ToString(), PivotTotalDifficulty = pivotHeader.TotalDifficulty.ToString()!, FastHeadersMemoryBudget = (ulong)100.KB(), @@ -623,7 +623,7 @@ public async Task Can_use_persisted_header_without_total_difficulty() var syncConfig = new TestSyncConfig { FastSync = true, - PivotNumber = pivotHeader.Number.ToString(), + PivotNumber = pivotHeader.Number, PivotHash = pivotHeader.Hash!.ToString(), PivotTotalDifficulty = pivotHeader.TotalDifficulty.ToString()! }; @@ -666,7 +666,7 @@ public async Task Will_never_lose_batch_on_invalid_batch() new TestSyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, @@ -737,7 +737,7 @@ public void IsFinished_returns_false_when_headers_not_downloaded() FastSync = true, DownloadBodiesInFastSync = true, DownloadReceiptsInFastSync = true, - PivotNumber = "1", + PivotNumber = 1, }; blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(2).WithStateRoot(TestItem.KeccakA).TestObject); @@ -764,7 +764,7 @@ public void When_lowestInsertedHeaderHasNoTD_then_fetchFromBlockTreeAgain() syncConfig: new TestSyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = TestItem.KeccakA.ToString(), PivotTotalDifficulty = "1000", }, @@ -797,7 +797,7 @@ public void When_cant_determine_pivot_total_difficulty_then_throw() syncConfig: new TestSyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = TestItem.KeccakA.ToString(), PivotTotalDifficulty = "1000", }, @@ -822,7 +822,7 @@ public async Task Should_Limit_BatchSize_ToEstimate() syncConfig: new TestSyncConfig { FastSync = true, - PivotNumber = "1000", + PivotNumber = 1000, PivotHash = TestItem.KeccakA.ToString(), PivotTotalDifficulty = "1000", }, diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs index 6899a675222..9ae8b4d0746 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs @@ -108,7 +108,7 @@ public void Setup() _syncConfig = new TestSyncConfig { FastSync = true, - PivotNumber = _pivotNumber.ToString(), + PivotNumber = _pivotNumber, PivotHash = Keccak.Zero.ToString() }; _blockTree.SyncPivot.Returns((_pivotNumber, Keccak.Zero)); @@ -282,7 +282,7 @@ private void LoadScenario(Scenario scenario) private void LoadScenario(Scenario scenario, ISyncConfig syncConfig) { _syncConfig = syncConfig; - _syncConfig.PivotNumber = _pivotNumber.ToString(); + _syncConfig.PivotNumber = _pivotNumber; _syncConfig.PivotHash = scenario.Blocks.Last()?.Hash?.ToString(); _blockTree.SyncPivot.Returns((_pivotNumber, scenario.Blocks.Last()?.Hash!)); _syncPointers = Substitute.For(); @@ -412,7 +412,7 @@ public void Is_fast_block_receipts_finished_returns_false_when_receipts_not_down FastSync = true, DownloadBodiesInFastSync = true, DownloadReceiptsInFastSync = true, - PivotNumber = "1", + PivotNumber = 1, }; _blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); @@ -433,7 +433,7 @@ public void Is_fast_block_bodies_finished_returns_true_when_bodies_not_downloade FastSync = true, DownloadBodiesInFastSync = false, DownloadReceiptsInFastSync = true, - PivotNumber = "1", + PivotNumber = 1, }; _blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ForwardHeaderProviderTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ForwardHeaderProviderTests.cs index 78df4b4c558..dbda18297e0 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ForwardHeaderProviderTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ForwardHeaderProviderTests.cs @@ -118,7 +118,7 @@ public async Task Ancestor_lookup_with_sync_pivot() { }, new ConfigProvider(new SyncConfig() { - PivotNumber = syncPivot.Number.ToString(), + PivotNumber = syncPivot.Number, PivotHash = syncPivot.Hash!.ToString(), })); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs index f5852c48faf..8313c70c314 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs @@ -171,7 +171,7 @@ private void SetDefaults() SyncProgressResolver.SyncPivot.Returns((Pivot.Number, Keccak.Zero)); SyncConfig.FastSync = false; - SyncConfig.PivotNumber = Pivot.Number.ToString(); + SyncConfig.PivotNumber = Pivot.Number; SyncConfig.PivotHash = Keccak.Zero.ToString(); SyncConfig.SynchronizationEnabled = true; SyncConfig.NetworkingEnabled = true; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ReceiptSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ReceiptSyncFeedTests.cs index 60c714970dd..ff7c6bc9f6b 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ReceiptSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ReceiptSyncFeedTests.cs @@ -65,7 +65,7 @@ public void Setup() { FastSync = true, PivotHash = _pivotBlock.Hash!.ToString(), - PivotNumber = _pivotBlock.Number.ToString(), + PivotNumber = _pivotBlock.Number, AncientBodiesBarrier = 0, DownloadBodiesInFastSync = true, }; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/StateSyncPivotTest.cs b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/StateSyncPivotTest.cs index bd6404cf9c0..815606d13b7 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/StateSyncPivotTest.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/StateSyncPivotTest.cs @@ -34,7 +34,7 @@ int syncPivot Synchronization.FastSync.StateSyncPivot stateSyncPivot = new Synchronization.FastSync.StateSyncPivot(blockTree, new TestSyncConfig() { - PivotNumber = syncPivot.ToString(), + PivotNumber = syncPivot, FastSync = true, StateMinDistanceFromHead = minDistance, StateMaxDistanceFromHead = maxDistance, diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs index 4a8bcfde2c0..af08c2f41a6 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs @@ -28,7 +28,7 @@ public void Header_block_is_0_when_no_header_was_suggested() IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { - PivotNumber = "1", + PivotNumber = 1, }; SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); @@ -43,7 +43,7 @@ public void Best_block_is_0_when_no_block_was_suggested() IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { - PivotNumber = "1", + PivotNumber = 1, }; SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); @@ -58,7 +58,7 @@ public void Best_state_is_head_when_there_are_no_suggested_blocks() IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { - PivotNumber = "1", + PivotNumber = 1, }; SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); @@ -76,7 +76,7 @@ public void Best_state_is_suggested_if_there_is_suggested_block_with_state() IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { - PivotNumber = "1", + PivotNumber = 1, }; SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); @@ -98,7 +98,7 @@ public void Best_state_is_head_if_there_is_suggested_block_without_state() IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { - PivotNumber = "1", + PivotNumber = 1, }; SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); @@ -120,7 +120,7 @@ public void Is_fast_block_finished_returns_true_when_no_fast_sync_is_used() SyncConfig syncConfig = new() { FastSync = false, - PivotNumber = "1", + PivotNumber = 1, }; SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); @@ -139,7 +139,7 @@ public void Is_fast_block_bodies_finished_returns_false_when_blocks_not_download FastSync = true, DownloadBodiesInFastSync = true, DownloadReceiptsInFastSync = true, - PivotNumber = "1", + PivotNumber = 1, }; blockTree.SyncPivot.Returns((1, Hash256.Zero)); @@ -159,7 +159,7 @@ public void Is_fast_block_receipts_finished_returns_true_when_receipts_not_downl FastSync = true, DownloadBodiesInFastSync = true, DownloadReceiptsInFastSync = false, - PivotNumber = "1", + PivotNumber = 1, }; blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs index d542b0498f0..f8a0a0eeafa 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs @@ -84,7 +84,7 @@ public void Ancient_bodies_and_receipts_are_reported_correctly() SyncConfig syncConfig = new() { FastSync = true, - PivotNumber = "100", + PivotNumber = 100, }; SyncReport syncReport = new(pool, Substitute.For(), syncConfig, Substitute.For(), logManager, timerFactory); @@ -127,7 +127,7 @@ public void Ancient_bodies_and_receipts_are_not_reported_until_feed_finishes_Ini SyncConfig syncConfig = new() { FastSync = true, - PivotNumber = "100", + PivotNumber = 100, }; if (setBarriers) { diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs index ec74a91c718..ad3fc5c5c1d 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs @@ -225,7 +225,7 @@ protected virtual void ResetPivot() private UInt256 TryGetPivotTotalDifficulty(Hash256 headerHash) { - if (_pivotNumber == LongConverter.FromString(_syncConfig.PivotNumber)) + if (_pivotNumber == _syncConfig.PivotNumber) return _syncConfig.PivotTotalDifficultyParsed; // Pivot is the same as in config // Got from header diff --git a/tools/SchemaGenerator/SchemaGenerator.csproj b/tools/SchemaGenerator/SchemaGenerator.csproj index d86b000abd9..5ba04fe94ec 100644 --- a/tools/SchemaGenerator/SchemaGenerator.csproj +++ b/tools/SchemaGenerator/SchemaGenerator.csproj @@ -13,7 +13,6 @@ - diff --git a/tools/SchemaGenerator/SchemaGenerator.slnx b/tools/SchemaGenerator/SchemaGenerator.slnx index f8247a54fa9..db27dc75b1a 100644 --- a/tools/SchemaGenerator/SchemaGenerator.slnx +++ b/tools/SchemaGenerator/SchemaGenerator.slnx @@ -2,7 +2,6 @@ - From 00d56ae19badf1e5a3f9a94132d2182c61b190e2 Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Mon, 29 Dec 2025 17:01:04 +0100 Subject: [PATCH 143/255] Remove MetricsController._metricTypes (#10057) --- .../Metrics/MetricsController.cs | 39 +++++-------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs b/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs index 2a3c91c3a89..e8b139e4f4f 100644 --- a/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs +++ b/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs @@ -30,10 +30,9 @@ public partial class MetricsController : IMetricsController { private readonly int _intervalMilliseconds; private Timer _timer = null!; - private static bool _staticLabelsInitialized = false; + private static bool _staticLabelsInitialized; private readonly Dictionary _metricUpdaters = new(); - private readonly HashSet _metricTypes = new(); // Largely for testing reason internal readonly Dictionary _individualUpdater = new(); @@ -157,14 +156,6 @@ public void Observe(double value, IMetricLabels? labels = null) } } - public void RegisterMetrics(Type type) - { - if (_metricTypes.Add(type)) - { - EnsurePropertiesCached(type); - } - } - internal record CommonMetricInfo(string Name, string Description, Dictionary Tags); private static CommonMetricInfo DetermineMetricInfo(MemberInfo member) @@ -182,7 +173,7 @@ Dictionary CreateTags() => private static Gauge CreateMemberInfoMetricsGauge(MemberInfo member, params string[] labels) { - var metricInfo = DetermineMetricInfo(member); + CommonMetricInfo metricInfo = DetermineMetricInfo(member); return CreateGauge(metricInfo.Name, metricInfo.Description, metricInfo.Tags, labels); } @@ -218,7 +209,7 @@ private static string GetStaticMemberInfo(Type givenInformer, string givenName) return value.ToString()!; } - private void EnsurePropertiesCached(Type type) + public void RegisterMetrics(Type type) { if (!_metricUpdaters.ContainsKey(type)) { @@ -230,7 +221,7 @@ private void EnsurePropertiesCached(Type type) IList metricUpdaters = new List(); IEnumerable members = type.GetProperties().Concat(type.GetFields()); - foreach (var member in members) + foreach (MemberInfo member in members) { if (member.GetCustomAttribute() is not null && !_enableDetailedMetric) continue; if (TryCreateMetricUpdater(type, meter, member, out IMetricUpdater updater)) @@ -364,26 +355,16 @@ private void UpdateAllMetricsInner() callback(); } - foreach (Type metricType in _metricTypes) + foreach (IMetricUpdater[] updaters in _metricUpdaters.Values) { - UpdateMetrics(metricType); + foreach (IMetricUpdater metricUpdater in updaters) + { + metricUpdater.Update(); + } } } - public void AddMetricsUpdateAction(Action callback) - { - _callbacks.Add(callback); - } - - private void UpdateMetrics(Type type) - { - EnsurePropertiesCached(type); - - foreach (IMetricUpdater metricUpdater in _metricUpdaters[type]) - { - metricUpdater.Update(); - } - } + public void AddMetricsUpdateAction(Action callback) => _callbacks.Add(callback); private static string GetGaugeNameKey(params string[] par) => string.Join('.', par); From fee0f239e070415f598cd4c9a382d656479640ea Mon Sep 17 00:00:00 2001 From: igladun Date: Mon, 29 Dec 2025 18:02:06 +0200 Subject: [PATCH 144/255] Fixes #9577: resolve race condition in StateSyncFeedTests.Big_test (#9972) * fix(sync): resolve race condition in StateSyncFeedTests.Big_test (#9577) * fix(sync): Isolate block tree cache in StateSyncFeedTestsBase to fix parallel test failures * changes --------- Co-authored-by: Lukasz Rozmej --- .../FastSync/StateSyncFeedTestsBase.cs | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs index 23037d91fc9..9a735cfe8bb 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs @@ -43,8 +43,8 @@ public abstract class StateSyncFeedTestsBase(int defaultPeerCount = 1, int defau { public const int TimeoutLength = 20000; - private static IBlockTree? _blockTree; - protected static IBlockTree BlockTree => LazyInitializer.EnsureInitialized(ref _blockTree, static () => Build.A.BlockTree().OfChainLength(100).TestObject); + // Chain length used for test block trees, use a constant to avoid shared state + private const int TestChainLength = 100; protected ILogger _logger; protected ILogManager _logManager = null!; @@ -93,9 +93,12 @@ protected IContainer PrepareDownloader(DbContext dbContext, Action builder.RegisterBuildCallback((ctx) => { + IBlockTree blockTree = ctx.Resolve(); ISyncPeerPool peerPool = ctx.Resolve(); - foreach (ISyncPeer syncPeer in syncPeers) + foreach (SyncPeerMock syncPeer in syncPeers) { + // Set per-test block tree to avoid race conditions during parallel execution + syncPeer.SetBlockTree(blockTree); peerPool.AddPeer(syncPeer); } }); @@ -121,9 +124,10 @@ protected ContainerBuilder BuildTestContainerBuilder(DbContext dbContext, int sy .AddSingleton(dbContext.LocalNodeStorage) // Use factory function to make it lazy in case test need to replace IBlockTree + // Cache key includes type name so different inherited test classes don't share the same blocktree .AddSingleton((ctx) => CachedBlockTreeBuilder.BuildCached( - $"{nameof(StateSyncFeedTestsBase)}{dbContext.RemoteStateTree.RootHash}{BlockTree.BestSuggestedHeader!.Number}", - () => Build.A.BlockTree().WithStateRoot(dbContext.RemoteStateTree.RootHash).OfChainLength((int)BlockTree.BestSuggestedHeader!.Number))) + $"{GetType().Name}{dbContext.RemoteStateTree.RootHash}{TestChainLength}", + () => Build.A.BlockTree().WithStateRoot(dbContext.RemoteStateTree.RootHash).OfChainLength(TestChainLength))) .Add(); @@ -280,6 +284,9 @@ protected class SyncPeerMock : BaseSyncPeerMock private readonly Func, Task>>? _executorResultFunction; private readonly long _maxRandomizedLatencyMs; + // Per-test block tree to avoid race conditions during parallel test execution + private IBlockTree? _blockTree; + public SyncPeerMock( IDb stateDb, IDb codeDb, @@ -345,6 +352,11 @@ public void SetFilter(Hash256[]? availableHashes) _filter = availableHashes; } + public void SetBlockTree(IBlockTree blockTree) + { + _blockTree = blockTree; + } + public override bool TryGetSatelliteProtocol(string protocol, out T protocolHandler) where T : class { if (protocol == Protocol.Snap) @@ -358,7 +370,7 @@ public override bool TryGetSatelliteProtocol(string protocol, out T protocolH public override Task GetHeadBlockHeader(Hash256? hash, CancellationToken token) { - return Task.FromResult(BlockTree.Head?.Header); + return Task.FromResult(_blockTree?.Head?.Header); } public override Task> GetByteCodes(IReadOnlyList codeHashes, CancellationToken token) From 6c788e201db504860aee416f6ea62b431c5a04d4 Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Tue, 30 Dec 2025 18:28:25 +0800 Subject: [PATCH 145/255] Perf/TryGetDirtyNode (#10067) * Try get dirty child * Appendmut set last * Should be inside instead * Fix tracelog * Fix trace again --- .../Nethermind.Trie.Test/TrieNodeTests.cs | 10 ++--- .../Nethermind.Trie/PatriciaTree.cs | 43 ++++++++++--------- src/Nethermind/Nethermind.Trie/TrieNode.cs | 8 +++- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs b/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs index c63615da3a0..3338f249dda 100644 --- a/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs @@ -481,7 +481,7 @@ public void Can_encode_branch_with_nulls() public void Is_child_dirty_on_extension_when_child_is_null_returns_false() { TrieNode node = new(NodeType.Extension); - Assert.That(node.IsChildDirty(0), Is.False); + Assert.That(node.TryGetDirtyChild(0, out TrieNode? childNode), Is.False); } [Test] @@ -489,7 +489,7 @@ public void Is_child_dirty_on_extension_when_child_is_null_node_returns_false() { TrieNode node = new(NodeType.Extension); node.SetChild(0, null); - Assert.That(node.IsChildDirty(0), Is.False); + Assert.That(node.TryGetDirtyChild(0, out TrieNode? dirtyChild), Is.False); } [Test] @@ -498,7 +498,7 @@ public void Is_child_dirty_on_extension_when_child_is_not_dirty_returns_false() TrieNode node = new(NodeType.Extension); TrieNode cleanChild = new(NodeType.Leaf, Keccak.Zero); node.SetChild(0, cleanChild); - Assert.That(node.IsChildDirty(0), Is.False); + Assert.That(node.TryGetDirtyChild(0, out TrieNode? dirtyChild), Is.False); } [Test] @@ -507,7 +507,7 @@ public void Is_child_dirty_on_extension_when_child_is_dirty_returns_true() TrieNode node = new(NodeType.Extension); TrieNode dirtyChild = new(NodeType.Leaf); node.SetChild(0, dirtyChild); - Assert.That(node.IsChildDirty(0), Is.True); + Assert.That(node.TryGetDirtyChild(0, out TrieNode? _), Is.True); } [Test] @@ -797,7 +797,7 @@ public void Extension_child_as_keccak_not_dirty() trieNode.SetChild(0, child); trieNode.PrunePersistedRecursively(1); - trieNode.IsChildDirty(0).Should().Be(false); + trieNode.TryGetDirtyChild(0, out TrieNode? dirtyChild).Should().Be(false); } [TestCase(true)] diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs index 4f04300e3d3..e8638015ad4 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs @@ -163,27 +163,28 @@ private TrieNode Commit(ICommitter committer, ref TreePath path, TrieNode node, { if (path.Length > maxLevelForConcurrentCommit) { + path.AppendMut(0); for (int i = 0; i < 16; i++) { - if (node.IsChildDirty(i)) + if (node.TryGetDirtyChild(i, out TrieNode? childNode)) { - path.AppendMut(i); - TrieNode childNode = node.GetChildWithChildPath(TrieStore, ref path, i); + path.SetLast(i); TrieNode newChildNode = Commit(committer, ref path, childNode, maxLevelForConcurrentCommit); if (!ReferenceEquals(childNode, newChildNode)) { node[i] = newChildNode; } - path.TruncateOne(); } else { if (_logger.IsTrace) { + path.SetLast(i); Trace(node, ref path, i); } } } + path.TruncateOne(); } else { @@ -199,37 +200,37 @@ Task CreateTaskForPath(TreePath childPath, TrieNode childNode, int idx) => Task. ArrayPoolList? childTasks = null; + path.AppendMut(0); for (int i = 0; i < 16; i++) { - if (node.IsChildDirty(i)) + if (node.TryGetDirtyChild(i, out TrieNode childNode)) { + path.SetLast(i); if (i < 15 && committer.TryRequestConcurrentQuota()) { childTasks ??= new ArrayPoolList(15); - TreePath childPath = path.Append(i); - TrieNode childNode = node.GetChildWithChildPath(TrieStore, ref childPath, i); - childTasks.Add(CreateTaskForPath(childPath, childNode, i)); + // path is copied here + childTasks.Add(CreateTaskForPath(path, childNode, i)); } else { - path.AppendMut(i); - TrieNode childNode = node.GetChildWithChildPath(TrieStore, ref path, i); TrieNode newChildNode = Commit(committer, ref path, childNode!, maxLevelForConcurrentCommit); if (!ReferenceEquals(childNode, newChildNode)) { node[i] = newChildNode; } - path.TruncateOne(); } } else { if (_logger.IsTrace) { + path.SetLast(i); Trace(node, ref path, i); } } } + path.TruncateOne(); if (childTasks is not null) { @@ -241,13 +242,7 @@ Task CreateTaskForPath(TreePath childPath, TrieNode childNode, int idx) => Task. else if (node.NodeType == NodeType.Extension) { int previousPathLength = node.AppendChildPath(ref path, 0); - TrieNode extensionChild = node.GetChildWithChildPath(TrieStore, ref path, 0); - if (extensionChild is null) - { - ThrowInvalidExtension(); - } - - if (extensionChild.IsDirty) + if (node.TryGetDirtyChild(0, out TrieNode? extensionChild)) { TrieNode newExtensionChild = Commit(committer, ref path, extensionChild, maxLevelForConcurrentCommit); if (!ReferenceEquals(newExtensionChild, extensionChild)) @@ -255,9 +250,15 @@ Task CreateTaskForPath(TreePath childPath, TrieNode childNode, int idx) => Task. node[0] = newExtensionChild; } } - else + else if (_logger.IsTrace) { - if (_logger.IsTrace) TraceExtensionSkip(extensionChild); + extensionChild = node.GetChildWithChildPath(TrieStore, ref path, 0); + if (extensionChild is null) + { + ThrowInvalidExtension(); + } + + TraceExtensionSkip(extensionChild); } path.TruncateMut(previousPathLength); } @@ -285,7 +286,7 @@ Task CreateTaskForPath(TreePath childPath, TrieNode childNode, int idx) => Task. [MethodImpl(MethodImplOptions.NoInlining)] void Trace(TrieNode node, ref TreePath path, int i) { - TrieNode child = node.GetChild(TrieStore, ref path, i); + TrieNode child = node.GetChildWithChildPath(TrieStore, ref path, i); if (child is not null) { _logger.Trace($"Skipping commit of {child}"); diff --git a/src/Nethermind/Nethermind.Trie/TrieNode.cs b/src/Nethermind/Nethermind.Trie/TrieNode.cs index 09d62723325..d9b2907a12c 100644 --- a/src/Nethermind/Nethermind.Trie/TrieNode.cs +++ b/src/Nethermind/Nethermind.Trie/TrieNode.cs @@ -641,7 +641,7 @@ static void ThrowNotABranch() } } - public bool IsChildDirty(int i) + public bool TryGetDirtyChild(int i, [NotNullWhen(true)] out TrieNode? dirtyChild) { if (IsExtension) { @@ -651,20 +651,24 @@ public bool IsChildDirty(int i) ref var data = ref _nodeData[i]; if (data is null) { + dirtyChild = null; return false; } if (ReferenceEquals(data, _nullNode)) { + dirtyChild = null; return false; } if (data is Hash256) { + dirtyChild = null; return false; } - return ((TrieNode)data)!.IsDirty; + dirtyChild = (TrieNode)data; + return dirtyChild.IsDirty; } public TrieNode? this[int i] From 12b9e2a4a93161cf71b6737138c23006135abf61 Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Tue, 30 Dec 2025 18:29:03 +0800 Subject: [PATCH 146/255] Call prune persisted recursively on commit and on copy too (#10065) --- src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs | 1 + .../Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index c079db77353..1e3fbe021c4 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -230,6 +230,7 @@ private TrieNode CommitAndInsertToDirtyNodes(long blockNumber, Hash256? address, node = _commitBuffer.SaveOrReplaceInDirtyNodesCache(address, ref path, node, blockNumber); else node = SaveOrReplaceInDirtyNodesCache(address, ref path, node, blockNumber); + node.PrunePersistedRecursively(1); IncrementCommittedNodesCount(); } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs index b1604a1fd37..34268a8db49 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs @@ -508,7 +508,11 @@ public bool IsRoot() public void CopyTo(TrieStoreDirtyNodesCache otherCache) { - foreach (var kv in AllNodes) otherCache.GetOrAdd(kv.Key, kv.Value); + foreach (var kv in AllNodes) + { + kv.Value.Node.PrunePersistedRecursively(1); + otherCache.GetOrAdd(kv.Key, kv.Value); + } Clear(); } } From 0b7641eb598fb965c57868cbe3fdcff5285945c6 Mon Sep 17 00:00:00 2001 From: Daniil Ankushin Date: Tue, 30 Dec 2025 18:06:08 +0400 Subject: [PATCH 147/255] feat(abi): add support for fixed-size array element types (#10025) --- .../Nethermind.Abi.Test/AbiTests.cs | 51 +++++++++++++++++++ .../Json/AbiParameterConverterTests.cs | 2 + .../Nethermind.Abi/AbiParameterConverter.cs | 20 ++++++++ src/Nethermind/Nethermind.Abi/AbiType.cs | 37 ++++++++++---- 4 files changed, 100 insertions(+), 10 deletions(-) diff --git a/src/Nethermind/Nethermind.Abi.Test/AbiTests.cs b/src/Nethermind/Nethermind.Abi.Test/AbiTests.cs index 67ab6646d1b..1b95b5e1d91 100644 --- a/src/Nethermind/Nethermind.Abi.Test/AbiTests.cs +++ b/src/Nethermind/Nethermind.Abi.Test/AbiTests.cs @@ -348,6 +348,14 @@ public void Test_uint_exception(int length) Assert.Throws(() => _ = new AbiUInt(length)); } + [TestCase("uint64[abc]")] + [TestCase("bytes32[xyz]")] + [TestCase("address[!@#]")] + public void Test_invalid_array_syntax_exception(string type) + { + Assert.Throws(() => System.Text.Json.JsonSerializer.Deserialize($"\"{type}\"")); + } + [TestCase(AbiEncodingStyle.IncludeSignature)] [TestCase(AbiEncodingStyle.IncludeSignature | AbiEncodingStyle.Packed)] [TestCase(AbiEncodingStyle.Packed)] @@ -597,6 +605,49 @@ private class UserOperationAbi public byte[] Signature { get; set; } } + [TestCase(AbiEncodingStyle.IncludeSignature)] + [TestCase(AbiEncodingStyle.IncludeSignature | AbiEncodingStyle.Packed)] + [TestCase(AbiEncodingStyle.Packed)] + [TestCase(AbiEncodingStyle.None)] + public void Dynamic_array_of_fixed_array_of_uint64(AbiEncodingStyle encodingStyle) + { + AbiType type = new AbiArray(new AbiFixedLengthArray(new AbiUInt(64), 3)); + ulong[] element = [100UL, 200UL, 300UL]; + ulong[][] data = [element, [400UL, 500UL, 600UL]]; + AbiSignature signature = new("abc", type); + byte[] encoded = _abiEncoder.Encode(encodingStyle, signature, [data]); + object[] arguments = _abiEncoder.Decode(encodingStyle, signature, encoded); + Assert.That(arguments[0], Is.EqualTo(data)); + } + + [TestCase(AbiEncodingStyle.IncludeSignature)] + [TestCase(AbiEncodingStyle.IncludeSignature | AbiEncodingStyle.Packed)] + [TestCase(AbiEncodingStyle.Packed)] + [TestCase(AbiEncodingStyle.None)] + public void Dynamic_array_of_fixed_array_of_uint64_single_element(AbiEncodingStyle encodingStyle) + { + AbiType type = new AbiArray(new AbiFixedLengthArray(new AbiUInt(64), 3)); + ulong[][] data = [[1000000UL, 7UL, 3600UL]]; + AbiSignature signature = new("abc", type); + byte[] encoded = _abiEncoder.Encode(encodingStyle, signature, [data]); + object[] arguments = _abiEncoder.Decode(encodingStyle, signature, encoded); + Assert.That(arguments[0], Is.EqualTo(data)); + } + + [TestCase(AbiEncodingStyle.IncludeSignature)] + [TestCase(AbiEncodingStyle.IncludeSignature | AbiEncodingStyle.Packed)] + [TestCase(AbiEncodingStyle.Packed)] + [TestCase(AbiEncodingStyle.None)] + public void Dynamic_array_of_fixed_array_of_uint64_empty(AbiEncodingStyle encodingStyle) + { + AbiType type = new AbiArray(new AbiFixedLengthArray(new AbiUInt(64), 3)); + ulong[][] data = []; + AbiSignature signature = new("abc", type); + byte[] encoded = _abiEncoder.Encode(encodingStyle, signature, [data]); + object[] arguments = _abiEncoder.Decode(encodingStyle, signature, encoded); + Assert.That(arguments[0], Is.EqualTo(data)); + } + /// /// http://solidity.readthedocs.io/en/develop/abi-spec.html /// diff --git a/src/Nethermind/Nethermind.Abi.Test/Json/AbiParameterConverterTests.cs b/src/Nethermind/Nethermind.Abi.Test/Json/AbiParameterConverterTests.cs index fbc22718809..b95d067d2b7 100644 --- a/src/Nethermind/Nethermind.Abi.Test/Json/AbiParameterConverterTests.cs +++ b/src/Nethermind/Nethermind.Abi.Test/Json/AbiParameterConverterTests.cs @@ -46,6 +46,8 @@ object[] GetTestDataWithException(string type, Exception exception, object[] com yield return new TestCaseData(GetTestData("string", AbiType.String)); yield return new TestCaseData(GetTestData("int[]", new AbiArray(AbiType.Int256))); yield return new TestCaseData(GetTestData("string[5]", new AbiFixedLengthArray(AbiType.String, 5))); + yield return new TestCaseData(GetTestData("uint64[3]", new AbiFixedLengthArray(new AbiUInt(64), 3))); + yield return new TestCaseData(GetTestData("uint64[3][]", new AbiArray(new AbiFixedLengthArray(new AbiUInt(64), 3)))); yield return new TestCaseData(GetTestData("tuple", new AbiTuple([]))); yield return new TestCaseData(GetTestData("tuple", diff --git a/src/Nethermind/Nethermind.Abi/AbiParameterConverter.cs b/src/Nethermind/Nethermind.Abi/AbiParameterConverter.cs index 5f09bf4857f..9764f122202 100644 --- a/src/Nethermind/Nethermind.Abi/AbiParameterConverter.cs +++ b/src/Nethermind/Nethermind.Abi/AbiParameterConverter.cs @@ -93,6 +93,26 @@ private static string GetName(JsonElement token) => private AbiType GetParameterType(string type, JsonElement? components) { + if (type.Contains('[')) + { + int lastBracket = type.LastIndexOf('['); + string innerType = type[..lastBracket]; + string bracketPart = type[lastBracket..]; + + // Recursively parse the inner type + AbiType elementType = GetParameterType(innerType, components); + + // Parse array suffix: [] for dynamic, [N] for fixed + if (bracketPart == "[]") + return new AbiArray(elementType); + + if (!bracketPart.StartsWith('[') || !bracketPart.EndsWith(']')) + throw new ArgumentException($"Invalid contract ABI json. Unknown array type {type}."); + string sizeStr = bracketPart[1..^1]; + return int.TryParse(sizeStr, out int size) ? new AbiFixedLengthArray(elementType, size) + : throw new ArgumentException($"Invalid contract ABI json. Unknown array type {type}."); + } + var match = AbiParameterConverterStatics.TypeExpression.Match(type); if (match.Success) { diff --git a/src/Nethermind/Nethermind.Abi/AbiType.cs b/src/Nethermind/Nethermind.Abi/AbiType.cs index 11b73b2a13b..08562463273 100644 --- a/src/Nethermind/Nethermind.Abi/AbiType.cs +++ b/src/Nethermind/Nethermind.Abi/AbiType.cs @@ -91,17 +91,37 @@ public class AbiTypeConverter : JsonConverter static AbiType ParseAbiType(string type) { - bool isArray = false; - if (type.EndsWith("[]")) + if (type == "tuple" || type.StartsWith("tuple[")) { - isArray = true; - type = type[..^2]; + return new AbiTuple(); } - if (type == "tuple") + // Check for array suffix: [N] for fixed-size or [] for dynamic + int lastBracket = type.LastIndexOf('['); + if (lastBracket >= 0 && type.EndsWith(']')) { - return new AbiTuple(); + string bracketContent = type[(lastBracket + 1)..^1]; + string elementTypeStr = type[..lastBracket]; + + switch (bracketContent.Length) + { + case > 0 when int.TryParse(bracketContent, out int length): + { + // Fixed-size array: type[N] + AbiType elementType = ParseAbiType(elementTypeStr); + return new AbiFixedLengthArray(elementType, length); + } + case 0: + { + // Dynamic array: type[] + AbiType elementType = ParseAbiType(elementTypeStr); + return new AbiArray(elementType); + } + default: + throw new ArgumentException($"Invalid array syntax in ABI type '{type}'.", nameof(type)); + } } + if (type.StartsWith('(') && type.EndsWith(')')) { string[] types = type[1..^1].Split(','); @@ -113,10 +133,7 @@ static AbiType ParseAbiType(string type) return ParseTuple(types); } - AbiType value = GetType(type); - - return isArray ? new AbiArray(value) : value; - + return GetType(type); } static AbiType ParseTuple(string[] types) From 2f73ca33d1f87f6cb56469f18387ec788e7574b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carmen=20Irene=20Cabrera=20Rodr=C3=ADguez?= <49727740+cicr99@users.noreply.github.com> Date: Tue, 30 Dec 2025 17:02:51 +0200 Subject: [PATCH 148/255] XDC Reward handler (#9881) * calculator * state reader * masternode voting contract * fix * abi json * working load test * test * test * test getCandidates * cleanup * format * remove var * format * review comments * implement calculate rewards base flow and get signing txs * implement rewards per signer and distribution calculations * implement getCadidateOwner * refactors and add comments to the code * add block signer contract address to the configuration spec * implement reward module tests * implement hook for reward calculation in hotstuff pipeline * refactor and format * format * fix xdc test * wire IRewardClaculator in ConfigureContainer in XdcTestBlockchain * address review comments and add unit test with precalculated xdc reward values * add missing dependencies in Xdc module * fix resolving contract addresses from spec * fix error with WorldState after merge * add comments for reward tests with link to original source --------- Co-authored-by: ak88 Co-authored-by: ak88 --- src/Nethermind/Chains/xdc.json | 4 +- .../TransactionBuilderXdcExtensions.cs | 49 +++ .../Helpers/XdcTestBlockchain.cs | 31 +- .../ModuleTests/RewardTests.cs | 323 ++++++++++++++++++ .../Contracts/IMasternodeVotingContract.cs | 3 +- .../Contracts/MasternodeVotingContract.cs | 12 +- .../Spec/XdcChainSpecBasedSpecProvider.cs | 4 + .../Spec/XdcChainSpecEngineParameters.cs | 3 + .../Nethermind.Xdc/Spec/XdcReleaseSpec.cs | 9 + src/Nethermind/Nethermind.Xdc/XdcModule.cs | 23 ++ .../Nethermind.Xdc/XdcRewardCalculator.cs | 247 ++++++++++++++ 11 files changed, 701 insertions(+), 7 deletions(-) create mode 100644 src/Nethermind/Nethermind.Xdc.Test/Helpers/TransactionBuilderXdcExtensions.cs create mode 100644 src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs create mode 100644 src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs diff --git a/src/Nethermind/Chains/xdc.json b/src/Nethermind/Chains/xdc.json index d96bdac61bc..591e0f045b3 100644 --- a/src/Nethermind/Chains/xdc.json +++ b/src/Nethermind/Chains/xdc.json @@ -60,7 +60,9 @@ "TimeoutPeriod": 10, "MinePeriod": 2 } - ] + ], + "masternodeVotingContract": "0x0000000000000000000000000000000000000088", + "blockSignerContract": "0x0000000000000000000000000000000000000089" } } }, diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/TransactionBuilderXdcExtensions.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/TransactionBuilderXdcExtensions.cs new file mode 100644 index 00000000000..0de5fe077c0 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/TransactionBuilderXdcExtensions.cs @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test.Builders; +using Nethermind.Xdc.Spec; + +namespace Nethermind.Xdc.Test.Helpers; + +public static class TransactionBuilderXdcExtensions +{ + // function sign(uint256 _blockNumber, bytes32 _blockHash) + // selector = 0xe341eaa4 + private static ReadOnlySpan SignSelector => new byte[] { 0xE3, 0x41, 0xEA, 0xA4 }; + + /// Sets 'To' to the XDC block-signer contract from the spec. + public static TransactionBuilder ToBlockSignerContract( + this TransactionBuilder b, IXdcReleaseSpec spec) + => b.To(spec.BlockSignerContract); + + /// + /// Appends ABI-encoded calldata for sign(uint256 _blockNumber, bytes32 _blockHash). + /// Calldata = 4-byte selector + 32-byte big-endian uint + 32-byte bytes32 (68 bytes total). + /// + public static TransactionBuilder WithXdcSigningData( + this TransactionBuilder b, long blockNumber, Hash256 blockHash) + => b.WithData(CreateSigningCalldata(blockNumber, blockHash)); + + private static byte[] CreateSigningCalldata(long blockNumber, Hash256 blockHash) + { + Span data = stackalloc byte[68]; // 4 + 32 + 32 + + // 0..3: selector + SignSelector.CopyTo(data); + + // 4..35: uint256 blockNumber (big-endian, right-aligned in 32 bytes) + var be = BitConverter.GetBytes((ulong)blockNumber); + if (BitConverter.IsLittleEndian) Array.Reverse(be); + // last 8 bytes of that 32 are the ulong + for (int i = 0; i < 8; i++) data[4 + 24 + i] = be[i]; + + // 36..67: bytes32 blockHash + blockHash.Bytes.CopyTo(data.Slice(36, 32)); + + return data.ToArray(); + } +} diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs index 33f5e224e9d..179d8194013 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs @@ -10,6 +10,7 @@ using Nethermind.Consensus.Comparers; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Producers; +using Nethermind.Consensus.Rewards; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Core.Test.Blockchain; @@ -55,7 +56,7 @@ public static async Task Create(int blocksToAdd = 3, bool use if (testConfiguration.SuggestGenesisOnStart) { - // The block added event is not waited by genesis, but its needed to wait here so that `AddBlock` wait correctly. + // The block added event is not waited by genesis, but it's needed to wait here so that `AddBlock` waits correctly. Task newBlockWaiter = chain.BlockTree.WaitForNewBlock(chain.CancellationToken); chain.MainProcessingContext.GenesisLoader.Load(); await newBlockWaiter; @@ -173,7 +174,16 @@ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder, .AddSingleton() .AddSingleton() .AddSingleton() - .AddScoped() + .AddScoped(ctx => + new XdcTestGenesisBuilder( + ctx.Resolve(), + ctx.Resolve(), + ctx.Resolve(), + ctx.Resolve>().ToArray(), + ctx.Resolve(), + MasterNodeCandidates + ) + ) .AddSingleton() .AddSingleton((ctx) => new CandidateContainer(MasterNodeCandidates)) .AddSingleton(ctx => @@ -185,6 +195,7 @@ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder, }) .AddSingleton((_) => BlockProducer) //.AddSingleton((_) => BlockProducerRunner) + .AddSingleton() .AddSingleton() .AddSingleton(new ProcessExitSource(TestContext.CurrentContext.CancellationToken)) @@ -218,6 +229,7 @@ private IXdcReleaseSpec WrapReleaseSpec(IReleaseSpec spec) xdcSpec.LimitPenaltyEpoch = 2; xdcSpec.MinimumSigningTx = 1; xdcSpec.GasLimitBoundDivisor = 1024; + xdcSpec.BlockSignerContract = new Address("0x0000000000000000000000000000000000000089"); V2ConfigParams[] v2ConfigParams = [ new V2ConfigParams { @@ -263,6 +275,8 @@ private IXdcReleaseSpec WrapReleaseSpec(IReleaseSpec spec) ]; xdcSpec.V2Configs = v2ConfigParams.ToList(); + xdcSpec.ValidateChainId = false; + xdcSpec.Reward = 5000; return xdcSpec; } @@ -302,7 +316,8 @@ private class XdcTestGenesisBuilder( IWorldState state, ISnapshotManager snapshotManager, IGenesisPostProcessor[] postProcessors, - Configuration testConfiguration + Configuration testConfiguration, + List masterNodeCandidates ) : IGenesisBuilder { public Block Build() @@ -311,6 +326,11 @@ public Block Build() state.CreateAccount(TestItem.AddressB, testConfiguration.AccountInitialValue); state.CreateAccount(TestItem.AddressC, testConfiguration.AccountInitialValue); + foreach (PrivateKey candidate in masterNodeCandidates) + { + state.CreateAccount(candidate.Address, testConfiguration.AccountInitialValue); + } + IXdcReleaseSpec? finalSpec = (IXdcReleaseSpec)specProvider.GetFinalSpec(); XdcBlockHeaderBuilder xdcBlockHeaderBuilder = new(); @@ -335,6 +355,11 @@ public Block Build() } } + private class ZeroRewardCalculator : IRewardCalculator + { + public BlockReward[] CalculateRewards(Block block) => Array.Empty(); + } + public void ChangeReleaseSpec(Action reconfigure) { reconfigure((XdcReleaseSpec)SpecProvider.GetXdcSpec((XdcBlockHeader)BlockTree.Head!.Header)); diff --git a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs new file mode 100644 index 00000000000..08aaa236e43 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs @@ -0,0 +1,323 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using FluentAssertions; +using Nethermind.Blockchain; +using Nethermind.Consensus.Rewards; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; +using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; +using Nethermind.Int256; +using Nethermind.Xdc.Contracts; +using Nethermind.Xdc.Spec; +using Nethermind.Xdc.Test.Helpers; +using Nethermind.Xdc.Types; +using NSubstitute; +using NUnit.Framework; + +namespace Nethermind.Xdc.Test.ModuleTests; + +public class RewardTests +{ + // Test ported from XDC reward_test : + // https://github.com/XinFinOrg/XDPoSChain/blob/af4178b2c7f9d668d8ba1f3a0244606a20ce303d/consensus/tests/engine_v2_tests/reward_test.go#L18 + [Test] + public async Task TestHookRewardV2() + { + var chain = await XdcTestBlockchain.Create(); + var masternodeVotingContract = Substitute.For(); + var rc = new XdcRewardCalculator( + chain.EpochSwitchManager, + chain.SpecProvider, + chain.BlockTree, + masternodeVotingContract + ); + var head = (XdcBlockHeader)chain.BlockTree.Head!.Header; + IXdcReleaseSpec spec = chain.SpecProvider.GetXdcSpec(head, chain.XdcContext.CurrentRound); + var epochLength = spec.EpochLength; + + // Add blocks up to epochLength (E) + 15 and create a signing tx that will be inserted in the next block + await chain.AddBlocks(epochLength + 15 - 3); + var header915 = chain.BlockTree.Head!.Header as XdcBlockHeader; + Assert.That(header915, Is.Not.Null); + PrivateKey signer915 = GetSignerFromMasternodes(chain, header915, spec); + Address owner = signer915.Address; + masternodeVotingContract.GetCandidateOwner(Arg.Any(), signer915.Address).Returns(owner); + await chain.AddBlock(BuildSigningTx( + spec, + header915.Number, + header915.Hash ?? header915.CalculateHash().ToHash256(), + signer915)); + + // Add blocks up until 3E and evaluate rewards at this checkpoint + // Save block 3E - 15 for second part of the test + await chain.AddBlocks(2 * epochLength - 31); + var header2685 = chain.BlockTree.Head!.Header as XdcBlockHeader; + Assert.That(header2685, Is.Not.Null); + PrivateKey signer2685 = GetSignerFromMasternodes(chain, header2685, spec); + Address owner2 = signer2685.Address; + masternodeVotingContract.GetCandidateOwner(Arg.Any(), signer2685.Address).Returns(owner2); + // Continue adding blocks up until 3E + await chain.AddBlocks(15); + Block block2700 = chain.BlockTree.Head!; + var header2700 = block2700.Header as XdcBlockHeader; + Assert.That(header2700, Is.Not.Null); + + BlockReward[] rewardsAt2700 = rc.CalculateRewards(block2700); + + // Expect exactly 2 entries: one for the masternode owner and one for foundation + Address foundation = spec.FoundationWallet; + foundation.Should().NotBe(Address.Zero); + + Assert.That(rewardsAt2700, Has.Length.EqualTo(2)); + rewardsAt2700.Length.Should().Be(2); + + UInt256 total = rewardsAt2700.Aggregate(UInt256.Zero, (acc, r) => acc + r.Value); + UInt256 ownerReward = rewardsAt2700.Single(r => r.Address == owner).Value; + UInt256 foundationReward = rewardsAt2700.Single(r => r.Address == foundation).Value; + + // Check 90/10 split + Assert.That(foundationReward, Is.EqualTo(total / 10)); + Assert.That(ownerReward, Is.EqualTo(total * 90 / 100)); + + // === Second part of the test: signing hash in a different epoch still counts === + + Transaction signingTx2 = BuildSigningTx( + spec, + header2685.Number, + header2685.Hash!, + signer2685); + + // Place signingTx2 in block 3E + 16 (different epoch than the signed block) + await chain.AddBlocks(15); + await chain.AddBlock(signingTx2); + + // Add blocks up until 4E and check rewards + await chain.AddBlocks(epochLength - 16); + Block block3600 = chain.BlockTree.Head!; + var header3600 = block3600.Header as XdcBlockHeader; + Assert.That(header3600, Is.Not.Null); + BlockReward[] rewardsAt3600 = rc.CalculateRewards(block3600); + + // Same expectations: exactly two outputs with 90/10 split + // Since this only counts signing txs from 2E to 3E, only signingTx2 should get counted + Assert.That(rewardsAt3600, Has.Length.EqualTo(2)); + UInt256 total2 = rewardsAt3600.Aggregate(UInt256.Zero, (acc, r) => acc + r.Value); + UInt256 ownerReward2 = rewardsAt3600.Single(r => r.Address == owner2).Value; + UInt256 foundationReward2 = rewardsAt3600.Single(r => r.Address == foundation).Value; + + Assert.That(foundationReward2, Is.EqualTo(total2 / 10)); + Assert.That(ownerReward2, Is.EqualTo(total2 * 90 / 100)); + + // === Third part of the test: if no signing tx, reward should be empty === + + // Add blocks up to 5E and check rewards + await chain.AddBlocks(epochLength); + Block block4500 = chain.BlockTree.Head!; + BlockReward[] rewardsAt4500 = rc.CalculateRewards(block4500); + // If no valid signing txs were counted for that epoch, expect no rewards. + rewardsAt4500.Should().BeEmpty(); + } + + // Test ported from XDC reward_test : + // https://github.com/XinFinOrg/XDPoSChain/blob/af4178b2c7f9d668d8ba1f3a0244606a20ce303d/consensus/tests/engine_v2_tests/reward_test.go#L99 + [Test] + public async Task TestHookRewardV2SplitReward() + { + var chain = await XdcTestBlockchain.Create(); + var masternodeVotingContract = Substitute.For(); + var rc = new XdcRewardCalculator( + chain.EpochSwitchManager, + chain.SpecProvider, + chain.BlockTree, + masternodeVotingContract + ); + + var head = (XdcBlockHeader)chain.BlockTree.Head!.Header; + IXdcReleaseSpec spec = chain.SpecProvider.GetXdcSpec(head, chain.XdcContext.CurrentRound); + var epochLength = spec.EpochLength; + + // - Insert 1 signing tx for header (E + 15) signed by signerA into block (E + 16) + // - Insert 2 signing txs (one for header (E + 15), one for header (2E - 15)) signed by signerB into block (2E - 1) + // - Verify: rewards at (3E) split 1:2 between A:B with 90/10 owner/foundation + + // Move to block (E + 15) + await chain.AddBlocks(epochLength + 15 - 3); + var header915 = (XdcBlockHeader)chain.BlockTree.Head!.Header; + + EpochSwitchInfo? epochInfo = chain.EpochSwitchManager.GetEpochSwitchInfo(header915); + Assert.That(epochInfo, Is.Not.Null); + PrivateKey[] masternodes = chain.TakeRandomMasterNodes(spec, epochInfo); + PrivateKey signerA = masternodes.First(); + PrivateKey signerB = masternodes.Last(); + Address ownerA = signerA.Address; + Address ownerB = signerB.Address; + masternodeVotingContract.GetCandidateOwner(Arg.Any(), signerA.Address).Returns(ownerA); + masternodeVotingContract.GetCandidateOwner(Arg.Any(), signerB.Address).Returns(ownerB); + + // Insert 1 signing tx for header (E + 15) in block (E + 16) + Transaction txA = BuildSigningTx( + spec, + header915.Number, + header915.Hash ?? header915.CalculateHash().ToHash256(), + signerA); + await chain.AddBlock(txA); // advances to (E + 16) + + // Move to block (2E - 15) to capture that header as well + var currentNumber = chain.BlockTree.Head!.Number; + await chain.AddBlocks(epochLength - 31); + var header1785 = (XdcBlockHeader)chain.BlockTree.Head!.Header; + + // Prepare two signing txs signed by signerB: + // - for header (E + 15) + // - for header (2E - 15) + Transaction txB1 = BuildSigningTx( + spec, + header915.Number, + header915.Hash!, + signerB); + + Transaction txB2 = BuildSigningTx( + spec, + header1785.Number, + header1785.Hash!, + signerB, + 1); + + // Advance to (2E - 2), then add a block with both signerB txs to be at (2E - 1) + await chain.AddBlocks(13); + await chain.AddBlock(txB1, txB2); // now at (2E - 1) + + // Rewards at (3E) should exist with split 1:2 across A:B and 90/10 owner/foundation + await chain.AddBlocks(epochLength + 1); // from (2E - 1) to (3E) + Block block2700 = chain.BlockTree.Head!; + BlockReward[] rewards = rc.CalculateRewards(block2700); + + Address foundation = spec.FoundationWallet; + + // Expect exactly 3 entries: ownerA, ownerB, foundation. + Assert.That(rewards.Length, Is.EqualTo(3)); + + // Calculate exact rewards for each address + UInt256 totalRewards = (UInt256)spec.Reward * Unit.Ether; + UInt256 signerAReward = totalRewards / 3; + UInt256 ownerAReward = signerAReward * 90 / 100; + UInt256 foundationReward = signerAReward / 10; + UInt256 signerBReward = totalRewards * 2 / 3; + UInt256 ownerBReward = signerBReward * 90 / 100; + foundationReward += signerBReward / 10; + + foreach (BlockReward reward in rewards) + { + if (reward.Address == ownerA) Assert.That(reward.Value, Is.EqualTo(ownerAReward)); + if (reward.Address == ownerB) Assert.That(reward.Value, Is.EqualTo(ownerBReward)); + if (reward.Address == foundation) Assert.That(reward.Value, Is.EqualTo(foundationReward)); + } + } + + // Test to check calculated rewards against precalculated values from : + // https://github.com/XinFinOrg/XDPoSChain/blob/af4178b2c7f9d668d8ba1f3a0244606a20ce303d/consensus/tests/engine_v2_tests/reward_test.go#L147 + [Test] + public void RewardCalculator_SplitReward_MatchesRounding() + { + const long epoch = 45, reward = 250; + PrivateKey[] masternodes = XdcTestHelper.GeneratePrivateKeys(2); + PrivateKey signerA = masternodes.First(); + PrivateKey signerB = masternodes.Last(); + var foundationWalletAddr = new Address("0x0000000000000000000000000000000000000068"); + var blockSignerContract = new Address("0x0000000000000000000000000000000000000089"); + + IEpochSwitchManager epochSwitchManager = Substitute.For(); + epochSwitchManager.IsEpochSwitchAtBlock(Arg.Any()) + .Returns(ci => ((XdcBlockHeader)ci.Args()[0]!).Number % epoch == 0); + + IXdcReleaseSpec xdcSpec = Substitute.For(); + xdcSpec.EpochLength.Returns((int)epoch); + xdcSpec.FoundationWallet.Returns(foundationWalletAddr); + xdcSpec.BlockSignerContract.Returns(blockSignerContract); + xdcSpec.Reward.Returns(reward); + xdcSpec.SwitchBlock.Returns(0); + ISpecProvider specProvider = Substitute.For(); + specProvider.GetSpec(Arg.Any()).Returns(xdcSpec); + + IBlockTree tree = Substitute.For(); + long size = 2 * epoch + 1; + var blockHeaders = new XdcBlockHeader[size]; + var blocks = new Block[size]; + for (int i = 0; i <= epoch * 2; i++) + { + blockHeaders[i] = Build.A.XdcBlockHeader() + .WithNumber(i) + .WithValidators(masternodes.Select(m => m.Address).ToArray()) + .WithExtraConsensusData(new ExtraFieldsV2((ulong)i, Build.A.QuorumCertificate().TestObject)) + .TestObject; + blocks[i] = new Block(blockHeaders[i]); + } + + // SignerA signs blocks 15 and 30 + // SignerB signs blocks 15 + var txsBlock16 = new List(); + txsBlock16.Add(BuildSigningTx(xdcSpec, 15, blockHeaders[15].Hash!, signerA, 1)); + txsBlock16.Add(BuildSigningTx(xdcSpec, 15, blockHeaders[15].Hash!, signerB, 2)); + var txsBlock31 = new List(); + txsBlock31.Add(BuildSigningTx(xdcSpec, 30, blockHeaders[30].Hash!, signerA, 3)); + blocks[16] = new Block(blockHeaders[16], new BlockBody(txsBlock16.ToArray(), null, null)); + blocks[31] = new Block(blockHeaders[31], new BlockBody(txsBlock31.ToArray(), null, null)); + tree.FindHeader(Arg.Any(), Arg.Any()) + .Returns(ci => blockHeaders[(long)ci.Args()[1]]); + tree.FindBlock(Arg.Any()) + .Returns(ci => blocks[(long)ci.Args()[0]]); + + IMasternodeVotingContract votingContract = Substitute.For(); + votingContract.GetCandidateOwner(Arg.Any(), Arg.Any
()) + .Returns(ci => ci.Arg
()); + + var rewardCalculator = new XdcRewardCalculator(epochSwitchManager, specProvider, tree, votingContract); + BlockReward[] rewards = rewardCalculator.CalculateRewards(blocks.Last()); + + // Expect ownerA, ownerB, and foundation + Assert.That(rewards, Has.Length.EqualTo(3)); + + // Expected values from XDC repo: + // A gets 2/3 of total, then 90% owner, 10% foundation (flooring at each integer division step) + // B gets 1/3 of total, then 90% owner, 10% foundation + var aOwnerExpected = UInt256.Parse("149999999999999999999"); + var aFoundExpected = UInt256.Parse("16666666666666666666"); + var bOwnerExpected = UInt256.Parse("74999999999999999999"); + var bFoundExpected = UInt256.Parse("8333333333333333333"); + + UInt256 aOwnerReward = rewards.Single(r => r.Address == signerA.Address).Value; + UInt256 bOwnerReward = rewards.Single(r => r.Address == signerB.Address).Value; + UInt256 foundationReward = rewards.Single(r => r.Address == foundationWalletAddr).Value; + + Assert.That(foundationReward, Is.EqualTo(aFoundExpected + bFoundExpected)); + Assert.That(aOwnerReward, Is.EqualTo(aOwnerExpected)); + Assert.That(bOwnerReward, Is.EqualTo(bOwnerExpected)); + + } + + + private static Transaction BuildSigningTx(IXdcReleaseSpec spec, long blockNumber, Hash256 blockHash, PrivateKey signer, long nonce = 0) + { + return Build.A.Transaction + .WithChainId(0) + .WithNonce((UInt256)nonce) + .WithGasLimit(200000) + .WithXdcSigningData(blockNumber, blockHash) + .ToBlockSignerContract(spec) + .SignedAndResolved(signer) + .TestObject; + } + + private static PrivateKey GetSignerFromMasternodes(XdcTestBlockchain chain, XdcBlockHeader header, IXdcReleaseSpec spec) + { + EpochSwitchInfo? epochInfo = chain.EpochSwitchManager.GetEpochSwitchInfo(header); + Assert.That(epochInfo, Is.Not.Null); + return chain.TakeRandomMasterNodes(spec, epochInfo).First(); + } +} diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs index bb1945b2780..520f16b8db7 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs @@ -6,8 +6,9 @@ namespace Nethermind.Xdc.Contracts; -internal interface IMasternodeVotingContract +public interface IMasternodeVotingContract { Address[] GetCandidates(BlockHeader blockHeader); UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate); + Address GetCandidateOwner(BlockHeader blockHeader, Address candidate); } diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs index 8d3f7e6038f..4453087afd5 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -7,10 +7,8 @@ using Nethermind.Blockchain.Contracts.Json; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Core.Specs; using Nethermind.Evm.State; using Nethermind.Int256; -using Nethermind.State; using System; namespace Nethermind.Xdc.Contracts; @@ -47,6 +45,16 @@ public UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate) return (UInt256)result[0]!; } + public Address GetCandidateOwner(BlockHeader blockHeader, Address candidate) + { + CallInfo callInfo = new CallInfo(blockHeader, "getCandidateOwner", Address.SystemUser, candidate); + object[] result = _constant.Call(callInfo); + if (result.Length != 1) + throw new InvalidOperationException("Expected 'getCandidateOwner' to return exactly one result."); + + return (Address)result[0]!; + } + public Address[] GetCandidates(BlockHeader blockHeader) { CallInfo callInfo = new CallInfo(blockHeader, "getCandidates", Address.SystemUser); diff --git a/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecBasedSpecProvider.cs b/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecBasedSpecProvider.cs index bf343c85384..7552193e9a7 100644 --- a/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecBasedSpecProvider.cs +++ b/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecBasedSpecProvider.cs @@ -22,6 +22,10 @@ protected override ReleaseSpec CreateReleaseSpec(ChainSpec chainSpec, long relea releaseSpec.SwitchEpoch = chainSpecEngineParameters.SwitchEpoch; releaseSpec.SwitchBlock = chainSpecEngineParameters.SwitchBlock; releaseSpec.V2Configs = chainSpecEngineParameters.V2Configs; + releaseSpec.FoundationWallet = chainSpecEngineParameters.FoundationWalletAddr; + releaseSpec.Reward = chainSpecEngineParameters.Reward; + releaseSpec.MasternodeVotingContract = chainSpecEngineParameters.MasternodeVotingContract; + releaseSpec.BlockSignerContract = chainSpecEngineParameters.BlockSignerContract; releaseSpec.ApplyV2Config(0); diff --git a/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecEngineParameters.cs b/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecEngineParameters.cs index a0b51affa27..cefacaa8c16 100644 --- a/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecEngineParameters.cs +++ b/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecEngineParameters.cs @@ -21,6 +21,9 @@ public class XdcChainSpecEngineParameters : IChainSpecEngineParameters public int SwitchEpoch { get; set; } public long SwitchBlock { get; set; } + public Address MasternodeVotingContract { get; set; } + public Address BlockSignerContract { get; set; } + private List _v2Configs = new(); public List V2Configs diff --git a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs index bf0b7453dff..2c0f616fa8e 100644 --- a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs @@ -12,6 +12,7 @@ public class XdcReleaseSpec : ReleaseSpec, IXdcReleaseSpec { public int EpochLength { get; set; } public int Gap { get; set; } + public long Reward { get; set; } public int SwitchEpoch { get; set; } public long SwitchBlock { get; set; } public int MaxMasternodes { get; set; } // v2 max masternodes @@ -31,6 +32,9 @@ public class XdcReleaseSpec : ReleaseSpec, IXdcReleaseSpec public List V2Configs { get; set; } = new List(); public Address[] GenesisMasterNodes { get; set; } + public Address FoundationWallet { get; set; } + public Address MasternodeVotingContract { get; set; } + public Address BlockSignerContract { get; set; } public void ApplyV2Config(ulong round) { @@ -79,6 +83,7 @@ public interface IXdcReleaseSpec : IReleaseSpec { public int EpochLength { get; } public int Gap { get; } + public long Reward { get; } public int SwitchEpoch { get; set; } public long SwitchBlock { get; set; } public int MaxMasternodes { get; set; } // v2 max masternodes @@ -97,5 +102,9 @@ public interface IXdcReleaseSpec : IReleaseSpec public int MinimumSigningTx { get; set; } // Signing txs that a node needs to produce to get out of penalty, after `LimitPenaltyEpoch` public List V2Configs { get; set; } Address[] GenesisMasterNodes { get; set; } + Address FoundationWallet { get; set; } + Address MasternodeVotingContract { get; set; } + Address BlockSignerContract { get; set; } + public void ApplyV2Config(ulong round); } diff --git a/src/Nethermind/Nethermind.Xdc/XdcModule.cs b/src/Nethermind/Nethermind.Xdc/XdcModule.cs index 0676b10e9b7..b6742681ff8 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcModule.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcModule.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Autofac; using Autofac.Features.AttributeFilters; using Nethermind.Blockchain; @@ -8,6 +9,7 @@ using Nethermind.Blockchain.Headers; using Nethermind.Consensus; using Nethermind.Consensus.Processing; +using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Specs; @@ -15,6 +17,11 @@ using Nethermind.Init.Modules; using Nethermind.Specs.ChainSpecStyle; using Nethermind.Xdc.Spec; +using Nethermind.Xdc.Contracts; +using Nethermind.Abi; +using Nethermind.Evm.State; +using Nethermind.State; +using Nethermind.Logging; namespace Nethermind.Xdc; @@ -47,6 +54,8 @@ protected override void Load(ContainerBuilder builder) // penalty handler // reward handler + .AddSingleton() + .AddSingleton(CreateMasternodeVotingContract) // forensics handler @@ -74,4 +83,18 @@ private ISnapshotManager CreateSnapshotManager([KeyFilter(SnapshotDbName)] IDb d return new SnapshotManager(db, blockTree, penaltyHandler); } + private IMasternodeVotingContract CreateMasternodeVotingContract( + ISpecProvider specProvider, + IAbiEncoder abiEncoder, + IWorldStateManager worldStateManager, + IReadOnlyTxProcessingEnvFactory readOnlyTxProcessingEnvFactory, + ILogManager logManager) + { + var xdcSpec = specProvider.GenesisSpec as IXdcReleaseSpec; + IWorldStateScopeProvider scopeProvider = worldStateManager.CreateResettableWorldState(); + IWorldState worldState = new WorldState(scopeProvider, logManager); + IReadOnlyTxProcessorSource readOnlyTxProcessorSource = readOnlyTxProcessingEnvFactory.Create(); + return new MasternodeVotingContract(worldState, abiEncoder, xdcSpec.MasternodeVotingContract, readOnlyTxProcessorSource); + } + } diff --git a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs new file mode 100644 index 00000000000..3088ca79c6d --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs @@ -0,0 +1,247 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Blockchain; +using Nethermind.Consensus.Rewards; +using Nethermind.Core; +using Nethermind.Core.Caching; +using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; +using Nethermind.Int256; +using Nethermind.Xdc.Spec; +using System; +using System.Collections.Generic; +using System.Linq; +using Nethermind.Crypto; +using Nethermind.Xdc.Contracts; + +namespace Nethermind.Xdc +{ + /// + /// Reward model (current mainnet): + /// - Rewards are paid only at epoch checkpoints (number % EpochLength == 0). + /// - For now we **ignore** TIPUpgradeReward behavior because on mainnet + /// the upgrade activation is set far in the future (effectively “not active”). + /// When TIPUpgradeReward activates, protector/observer beneficiaries must be added. + /// - Current split implemented here: 90% to masternode owner, 10% to foundation. + /// + public class XdcRewardCalculator( + IEpochSwitchManager epochSwitchManager, + ISpecProvider specProvider, + IBlockTree blockTree, + IMasternodeVotingContract masternodeVotingContract) : IRewardCalculator + { + private LruCache _signingTxsCache = new(9000, "XDC Signing Txs Cache"); + private const long BlocksPerYear = 15768000; + // XDC rule: signing transactions are sampled/merged every N blocks (N=15 on XDC). + // Only block numbers that are multiples of MergeSignRange are considered when tallying signers. + private const long MergeSignRange = 15; + private static readonly EthereumEcdsa _ethereumEcdsa = new(0); + + /// + /// Calculates block rewards according to XDPoS consensus rules. + /// + /// For XDPoS, rewards are only distributed at epoch checkpoints (blocks where number % 900 == 0). + /// At these checkpoints, rewards are calculated based on masternode signature counts during + /// the previous epoch and distributed according to the 90/10 split model. + /// + /// The block to calculate rewards for + /// Array of BlockReward objects for all reward recipients + public BlockReward[] CalculateRewards(Block block) + { + if (block is null) + throw new ArgumentNullException(nameof(block)); + if (block.Header is not XdcBlockHeader xdcHeader) + throw new InvalidOperationException("Only supports XDC headers"); + + // Rewards in XDC are calculated only if it's an epoch switch block + if (!epochSwitchManager.IsEpochSwitchAtBlock(xdcHeader)) return Array.Empty(); + + var number = xdcHeader.Number; + IXdcReleaseSpec spec = specProvider.GetXdcSpec(xdcHeader, xdcHeader.ExtraConsensusData.BlockRound); + if (number == spec.SwitchBlock + 1) return Array.Empty(); + + Address foundationWalletAddr = spec.FoundationWallet; + if (foundationWalletAddr == Address.Zero) throw new InvalidOperationException("Foundation wallet address cannot be empty"); + + var (signers, count) = GetSigningTxCount(number, xdcHeader, spec); + + UInt256 chainReward = (UInt256)spec.Reward * Unit.Ether; + Dictionary rewardSigners = CalculateRewardForSigners(chainReward, signers, count); + + UInt256 totalFoundationWalletReward = UInt256.Zero; + var rewards = new List(); + foreach (var (signer, reward) in rewardSigners) + { + (BlockReward holderReward, UInt256 foundationWalletReward) = DistributeRewards(signer, reward, xdcHeader); + totalFoundationWalletReward += foundationWalletReward; + rewards.Add(holderReward); + } + if (totalFoundationWalletReward > UInt256.Zero) rewards.Add(new BlockReward(foundationWalletAddr, totalFoundationWalletReward)); + return rewards.ToArray(); + } + + private (Dictionary Signers, long Count) GetSigningTxCount(long number, XdcBlockHeader header, IXdcReleaseSpec spec) + { + var signers = new Dictionary(); + if (number == 0) return (signers, 0); + + long signEpochCount = 1, rewardEpochCount = 2, epochCount = 0, endBlockNumber = 0, startBlockNumber = 0, signingCount = 0; + var blockNumberToHash = new Dictionary(); + var hashToSigningAddress = new Dictionary>(); + var masternodes = new HashSet
(); + + XdcBlockHeader h = header; + for (long i = number - 1; i >= 0; i--) + { + Hash256 parentHash = h.ParentHash; + h = blockTree.FindHeader(parentHash!, i) as XdcBlockHeader; + if (h == null) throw new InvalidOperationException($"Header with hash {parentHash} not found"); + if (epochSwitchManager.IsEpochSwitchAtBlock(h) && i != spec.SwitchBlock + 1) + { + epochCount++; + if (epochCount == signEpochCount) endBlockNumber = i; + if (epochCount == rewardEpochCount) + { + startBlockNumber = i + 1; + // Get masternodes from epoch switch header + masternodes = new HashSet
(h.ValidatorsAddress!); + // TIPUpgradeReward path (protector/observer selection) is currently ignored, + // because on mainnet the upgrade height is set to an effectively unreachable block. + // If/when that changes, we must compute protector/observer sets here. + break; + } + } + + blockNumberToHash[i] = h.Hash; + if (!_signingTxsCache.TryGet(h.Hash, out Transaction[] signingTxs)) + { + Block? block = blockTree.FindBlock(i); + if (block == null) throw new InvalidOperationException($"Block with number {i} not found"); + Transaction[] txs = block.Transactions; + signingTxs = CacheSigningTxs(h.Hash!, txs, spec); + } + + foreach (Transaction tx in signingTxs) + { + Hash256 blockHash = ExtractBlockHashFromSigningTxData(tx.Data); + tx.SenderAddress ??= _ethereumEcdsa.RecoverAddress(tx); + if (!hashToSigningAddress.ContainsKey(blockHash)) + hashToSigningAddress[blockHash] = new HashSet
(); + hashToSigningAddress[blockHash].Add(tx.SenderAddress); + } + } + + // Only blocks at heights that are multiples of MergeSignRange are considered. + // Calculate start >= startBlockNumber so that start % MergeSignRange == 0 + long start = ((startBlockNumber + MergeSignRange - 1) / MergeSignRange) * MergeSignRange; + for (long i = start; i < endBlockNumber; i += MergeSignRange) + { + if (!blockNumberToHash.TryGetValue(i, out var blockHash)) continue; + if (!hashToSigningAddress.TryGetValue(blockHash, out var addrs)) continue; + foreach (Address addr in addrs) + { + if (!masternodes.Contains(addr)) continue; + if (!signers.ContainsKey(addr)) signers[addr] = 0; + signers[addr] += 1; + signingCount++; + } + } + return (signers, signingCount); + } + + private Transaction[] CacheSigningTxs(Hash256 hash, Transaction[] txs, IXdcReleaseSpec spec) + { + Transaction[] signingTxs = txs.Where(t => IsSigningTransaction(t, spec)).ToArray(); + _signingTxsCache.Set(hash, signingTxs); + return signingTxs; + } + + // Signing transaction ABI (Solidity): + // function sign(uint256 _blockNumber, bytes32 _blockHash) + // Calldata = 4-byte selector + 32-byte big-endian uint + 32-byte bytes32 = 68 bytes total. + private bool IsSigningTransaction(Transaction tx, IXdcReleaseSpec spec) + { + if (tx.To is null || tx.To != spec.BlockSignerContract) return false; + if (tx.Data.Length != 68) return false; + + return ExtractSelectorFromSigningTxData(tx.Data) == "0xe341eaa4"; + } + + private String ExtractSelectorFromSigningTxData(ReadOnlyMemory data) + { + ReadOnlySpan span = data.Span; + if (span.Length != 68) + throw new ArgumentException("Signing tx calldata must be exactly 68 bytes (4 + 32 + 32).", nameof(data)); + + // 0..3: selector + ReadOnlySpan selBytes = span.Slice(0, 4); + return "0x" + Convert.ToHexString(selBytes).ToLowerInvariant(); + } + + private Hash256 ExtractBlockHashFromSigningTxData(ReadOnlyMemory data) + { + ReadOnlySpan span = data.Span; + if (span.Length != 68) + throw new ArgumentException("Signing tx calldata must be exactly 68 bytes (4 + 32 + 32).", nameof(data)); + + // 36..67: bytes32 blockHash + ReadOnlySpan hashBytes = span.Slice(36, 32); + return new Hash256(hashBytes); + } + + private Dictionary CalculateRewardForSigners(UInt256 totalReward, + Dictionary signers, long totalSigningCount) + { + var rewardSigners = new Dictionary(); + foreach (var (signer, count) in signers) + { + UInt256 reward = CalculateProportionalReward(count, totalSigningCount, totalReward); + rewardSigners.Add(signer, reward); + } + return rewardSigners; + } + + /// + /// Calculates a proportional reward based on the number of signatures. + /// Uses UInt256 arithmetic to maintain precision with large Wei values. + /// + /// Formula: (signatureCount / totalSignatures) * totalReward + /// + private UInt256 CalculateProportionalReward( + long signatureCount, + long totalSignatures, + UInt256 totalReward) + { + if (signatureCount <= 0 || totalSignatures <= 0) + { + return UInt256.Zero; + } + + // Convert to UInt256 for precision + var signatures = (UInt256)signatureCount; + var total = (UInt256)totalSignatures; + + // Calculate: (signatures * totalReward) / total + // Order of operations matters to maintain precision + UInt256 numerator = signatures * totalReward; + UInt256 reward = numerator / total; + + return reward; + } + + private (BlockReward HolderReward, UInt256 FoundationWalletReward) DistributeRewards( + Address masternodeAddress, UInt256 reward, XdcBlockHeader header) + { + Address owner = masternodeVotingContract.GetCandidateOwner(header, masternodeAddress); + + // 90% of the reward goes to the masternode + UInt256 masterReward = reward * 90 / 100; + + // 10% of the reward goes to the foundation wallet + UInt256 foundationReward = reward / 10; + + return (new BlockReward(owner, masterReward), foundationReward); + } + } +} From 14d4a39103f3e4abfd2c570c3e2aefa2f8deb5af Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Wed, 31 Dec 2025 07:29:56 +0800 Subject: [PATCH 149/255] Use baseblock for tree visitor (#10066) --- .../FullPruning/CopyTreeVisitorTests.cs | 5 +++-- .../Nethermind.Blockchain/FullPruning/FullPruner.cs | 12 ++++++------ .../SpecificBlockReadOnlyStateProvider.cs | 10 ---------- .../Nethermind.Consensus/Processing/GenesisLoader.cs | 2 +- .../Nethermind.Consensus/Tracing/ITracer.cs | 2 +- .../Nethermind.Consensus/Tracing/Tracer.cs | 6 +++--- src/Nethermind/Nethermind.Facade/BlockchainBridge.cs | 4 ++-- .../Nethermind.Facade/IBlockchainBridge.cs | 2 +- .../Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs | 2 +- .../Modules/Proof/ProofRpcModule.cs | 6 +++--- .../Nethermind.State.Test/StateReaderTests.cs | 6 +++--- .../Nethermind.State.Test/StatsCollectorTests.cs | 6 +++--- .../Nethermind.State/BlockingVerifyTrie.cs | 3 +-- src/Nethermind/Nethermind.State/IStateReader.cs | 2 +- src/Nethermind/Nethermind.State/StateReader.cs | 4 ++-- .../Nethermind.State/StateReaderExtensions.cs | 8 ++++---- 16 files changed, 35 insertions(+), 45 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs index a20c7457677..7c5aae0c8b2 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs @@ -93,18 +93,19 @@ private IPruningContext CopyDb(IPruningContext pruningContext, CancellationToken // Use TestWorldStateFactory.CreateForTest() with the custom DbProvider (IWorldState worldState, IStateReader stateReader) = TestWorldStateFactory.CreateForTestWithStateReader(dbProvider, logManager); + BlockHeader? baseBlock = Build.A.BlockHeader.WithStateRoot(trie.RootHash).TestObject; if (_keyScheme == INodeStorage.KeyScheme.Hash) { NodeStorage nodeStorage = new NodeStorage(pruningContext, _keyScheme); using CopyTreeVisitor copyTreeVisitor = new(nodeStorage, writeFlags, logManager, cancellationToken); - stateReader.RunTreeVisitor(copyTreeVisitor, trie.RootHash, visitingOptions); + stateReader.RunTreeVisitor(copyTreeVisitor, baseBlock, visitingOptions); copyTreeVisitor.Finish(); } else { NodeStorage nodeStorage = new NodeStorage(pruningContext, _keyScheme); using CopyTreeVisitor copyTreeVisitor = new(nodeStorage, writeFlags, logManager, cancellationToken); - stateReader.RunTreeVisitor(copyTreeVisitor, trie.RootHash, visitingOptions); + stateReader.RunTreeVisitor(copyTreeVisitor, baseBlock, visitingOptions); copyTreeVisitor.Finish(); } diff --git a/src/Nethermind/Nethermind.Blockchain/FullPruning/FullPruner.cs b/src/Nethermind/Nethermind.Blockchain/FullPruning/FullPruner.cs index 01ee4f9cde9..89152d3de30 100644 --- a/src/Nethermind/Nethermind.Blockchain/FullPruning/FullPruner.cs +++ b/src/Nethermind/Nethermind.Blockchain/FullPruning/FullPruner.cs @@ -180,7 +180,7 @@ await WaitForMainChainChange((e) => } if (_logger.IsInfo) _logger.Info($"Full Pruning Ready to start: pruning garbage before state {stateToCopy} with root {header.StateRoot}"); - await CopyTrie(pruningContext, header.StateRoot!, cancellationToken); + await CopyTrie(pruningContext, header, cancellationToken); } private bool CanStartNewPruning() => _fullPruningDb.CanStartPruning; @@ -220,7 +220,7 @@ private void HandlePruningFinished(object? sender, PruningEventArgs e) } } - private Task CopyTrie(IPruningContext pruning, Hash256 stateRoot, CancellationToken cancellationToken) + private Task CopyTrie(IPruningContext pruning, BlockHeader? baseBlock, CancellationToken cancellationToken) { INodeStorage.KeyScheme originalKeyScheme = _nodeStorage.Scheme; ICopyTreeVisitor visitor = null; @@ -265,8 +265,8 @@ private Task CopyTrie(IPruningContext pruning, Hash256 stateRoot, CancellationTo if (_logger.IsInfo) _logger.Info($"Full pruning started with MaxDegreeOfParallelism: {visitingOptions.MaxDegreeOfParallelism} and FullScanMemoryBudget: {visitingOptions.FullScanMemoryBudget}"); visitor = targetNodeStorage.Scheme == INodeStorage.KeyScheme.Hash - ? CopyTree(stateRoot, targetNodeStorage, writeFlags, visitingOptions, cancellationToken) - : CopyTree(stateRoot, targetNodeStorage, writeFlags, visitingOptions, cancellationToken); + ? CopyTree(baseBlock, targetNodeStorage, writeFlags, visitingOptions, cancellationToken) + : CopyTree(baseBlock, targetNodeStorage, writeFlags, visitingOptions, cancellationToken); if (!cancellationToken.IsCancellationRequested) { @@ -296,7 +296,7 @@ private Task CopyTrie(IPruningContext pruning, Hash256 stateRoot, CancellationTo } private ICopyTreeVisitor CopyTree( - Hash256 stateRoot, + BlockHeader? baseBlock, INodeStorage targetNodeStorage, WriteFlags writeFlags, VisitingOptions visitingOptions, @@ -304,7 +304,7 @@ CancellationToken cancellationToken ) where TContext : struct, ITreePathContextWithStorage, INodeContext { CopyTreeVisitor copyTreeVisitor = new(targetNodeStorage, writeFlags, _logManager, cancellationToken); - _stateReader.RunTreeVisitor(copyTreeVisitor, stateRoot, visitingOptions); + _stateReader.RunTreeVisitor(copyTreeVisitor, baseBlock, visitingOptions); return copyTreeVisitor; } diff --git a/src/Nethermind/Nethermind.Blockchain/SpecificBlockReadOnlyStateProvider.cs b/src/Nethermind/Nethermind.Blockchain/SpecificBlockReadOnlyStateProvider.cs index 9fe0a072ecf..68ae8474ee4 100644 --- a/src/Nethermind/Nethermind.Blockchain/SpecificBlockReadOnlyStateProvider.cs +++ b/src/Nethermind/Nethermind.Blockchain/SpecificBlockReadOnlyStateProvider.cs @@ -31,18 +31,8 @@ public class SpecificBlockReadOnlyStateProvider(IStateReader stateReader, BlockH public byte[]? GetCode(in ValueHash256 codeHash) => _stateReader.GetCode(in codeHash); - public void Accept(ITreeVisitor visitor, Hash256 stateRoot, VisitingOptions? visitingOptions) where TCtx : struct, INodeContext - { - _stateReader.RunTreeVisitor(visitor, stateRoot, visitingOptions); - } - public bool AccountExists(Address address) => _stateReader.TryGetAccount(BaseBlock, address, out _); - [SkipLocalsInit] - public bool IsEmptyAccount(Address address) => TryGetAccount(address, out AccountStruct account) && account.IsEmpty; - - public bool HasStateForBlock(BlockHeader? header) => _stateReader.HasStateForBlock(header); - [SkipLocalsInit] public bool IsDeadAccount(Address address) => !TryGetAccount(address, out AccountStruct account) || account.IsEmpty; } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/GenesisLoader.cs b/src/Nethermind/Nethermind.Consensus/Processing/GenesisLoader.cs index d6b89a2eda1..50d14deb954 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/GenesisLoader.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/GenesisLoader.cs @@ -84,7 +84,7 @@ private void ValidateGenesisHash(Hash256? expectedGenesisHash, BlockHeader genes { if (expectedGenesisHash is not null && genesis.Hash != expectedGenesisHash) { - if (_logger.IsTrace) _logger.Trace(stateReader.DumpState(genesis.StateRoot!)); + if (_logger.IsTrace) _logger.Trace(stateReader.DumpState(genesis)); if (_logger.IsWarn) _logger.Warn(genesis.ToString(BlockHeader.Format.Full)); if (_logger.IsError) _logger.Error($"Unexpected genesis hash, expected {expectedGenesisHash}, but was {genesis.Hash}"); } diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs index 95478961c51..898c20c4496 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs @@ -27,6 +27,6 @@ public interface ITracer /// Trace to act on block processing events. void Execute(Block block, IBlockTracer tracer); - void Accept(ITreeVisitor visitor, Hash256 stateRoot) where TCtx : struct, INodeContext; + void Accept(ITreeVisitor visitor, BlockHeader? baseBlock) where TCtx : struct, INodeContext; } } diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs index 92e60ae2bdf..680e1495789 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs @@ -33,12 +33,12 @@ We also want to make it read only so the state is not modified persistently in a public void Execute(Block block, IBlockTracer tracer) => Process(block, tracer, executeProcessor, executeOptions); - public void Accept(ITreeVisitor visitor, Hash256 stateRoot) where TCtx : struct, INodeContext + public void Accept(ITreeVisitor visitor, BlockHeader? baseBlock) where TCtx : struct, INodeContext { ArgumentNullException.ThrowIfNull(visitor); - ArgumentNullException.ThrowIfNull(stateRoot); + ArgumentNullException.ThrowIfNull(baseBlock); - stateReader.RunTreeVisitor(visitor, stateRoot); + stateReader.RunTreeVisitor(visitor, baseBlock); } } } diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 2b03bd8dbfa..4fc16b67da6 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -378,9 +378,9 @@ public Hash256[] GetPendingTransactionFilterChanges(int filterId) => public Address? RecoverTxSender(Transaction tx) => ecdsa.RecoverAddress(tx); - public void RunTreeVisitor(ITreeVisitor treeVisitor, Hash256 stateRoot) where TCtx : struct, INodeContext + public void RunTreeVisitor(ITreeVisitor treeVisitor, BlockHeader? baseBlock) where TCtx : struct, INodeContext { - stateReader.RunTreeVisitor(treeVisitor, stateRoot); + stateReader.RunTreeVisitor(treeVisitor, baseBlock); } public bool HasStateForBlock(BlockHeader baseBlock) diff --git a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs index d4bed512d8d..6191d6bf06f 100644 --- a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs @@ -48,7 +48,7 @@ public interface IBlockchainBridge : ILogFinder IEnumerable GetLogs(BlockParameter fromBlock, BlockParameter toBlock, HashSet? addresses = null, IEnumerable? topics = null, CancellationToken cancellationToken = default); bool TryGetLogs(int filterId, out IEnumerable filterLogs, CancellationToken cancellationToken = default); - void RunTreeVisitor(ITreeVisitor treeVisitor, Hash256 stateRoot) where TCtx : struct, INodeContext; + void RunTreeVisitor(ITreeVisitor treeVisitor, BlockHeader? baseBlock) where TCtx : struct, INodeContext; bool HasStateForBlock(BlockHeader? baseBlock); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index db87edeed9d..6b70f928c7d 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -684,7 +684,7 @@ public ResultWrapper eth_getProof(Address accountAddress, HashSet< } AccountProofCollector accountProofCollector = new(accountAddress, storageKeys); - _blockchainBridge.RunTreeVisitor(accountProofCollector, header!.StateRoot!); + _blockchainBridge.RunTreeVisitor(accountProofCollector, header!); return ResultWrapper.Success(accountProofCollector.BuildResult()); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs index 6a816708016..4ba87a89e52 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs @@ -88,7 +88,7 @@ public ResultWrapper proof_call(TransactionForRpc tx, Block // we collect proofs from before execution (after learning which addresses will be touched) // if we wanted to collect post execution proofs then we would need to use BeforeRestore on the tracer - callResultWithProof.Accounts = CollectAccountProofs(scope.Component, sourceHeader.StateRoot, proofTxTracer); + callResultWithProof.Accounts = CollectAccountProofs(scope.Component, sourceHeader, proofTxTracer); return ResultWrapper.Success(callResultWithProof); } @@ -165,7 +165,7 @@ public ResultWrapper proof_getTransactionReceipt(Hash256 txHas return ResultWrapper.Success(receiptWithProof); } - private AccountProof[] CollectAccountProofs(ITracer tracer, Hash256 stateRoot, ProofTxTracer proofTxTracer) + private AccountProof[] CollectAccountProofs(ITracer tracer, BlockHeader? baseBlock, ProofTxTracer proofTxTracer) { List accountProofs = new(); foreach (Address address in proofTxTracer.Accounts) @@ -174,7 +174,7 @@ private AccountProof[] CollectAccountProofs(ITracer tracer, Hash256 stateRoot, P .Where(s => s.Address == address) .Select(s => s.Index).ToArray()); - tracer.Accept(collector, stateRoot); + tracer.Accept(collector, baseBlock); accountProofs.Add(collector.BuildResult()); } diff --git a/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs b/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs index 0eac67506d3..a9f3e8acfd2 100644 --- a/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs +++ b/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs @@ -249,7 +249,7 @@ public void Can_collect_stats() stateRoot = provider.StateRoot; } - var stats = stateReader.CollectStats(stateRoot, new MemDb(), Logger); + var stats = stateReader.CollectStats(Build.A.BlockHeader.WithStateRoot(stateRoot).WithNumber(0).TestObject, new MemDb(), Logger); stats.AccountCount.Should().Be(1); } @@ -382,7 +382,7 @@ public void Can_accepts_visitors() } TrieStatsCollector visitor = new(new MemDb(), LimboLogs.Instance); - reader.RunTreeVisitor(visitor, stateRoot); + reader.RunTreeVisitor(visitor, Build.A.BlockHeader.WithStateRoot(stateRoot).WithNumber(0).TestObject); } [Test] @@ -399,7 +399,7 @@ public void Can_dump_state() stateRoot = provider.StateRoot; } - string state = reader.DumpState(stateRoot); + string state = reader.DumpState(Build.A.BlockHeader.WithStateRoot(stateRoot).WithNumber(0).TestObject); state.Should().NotBeEmpty(); } } diff --git a/src/Nethermind/Nethermind.State.Test/StatsCollectorTests.cs b/src/Nethermind/Nethermind.State.Test/StatsCollectorTests.cs index 6690ce95da3..c8fd2b1b866 100644 --- a/src/Nethermind/Nethermind.State.Test/StatsCollectorTests.cs +++ b/src/Nethermind/Nethermind.State.Test/StatsCollectorTests.cs @@ -30,7 +30,7 @@ public void Can_collect_stats([Values(false, true)] bool parallel) TestRawTrieStore trieStore = new(nodeStorage); WorldState stateProvider = new(new TrieStoreScopeProvider(trieStore, codeDb, LimboLogs.Instance), LimboLogs.Instance); StateReader stateReader = new StateReader(trieStore, codeDb, LimboLogs.Instance); - Hash256 stateRoot; + BlockHeader baseBlock; using (var _ = stateProvider.BeginScope(IWorldState.PreGenesis)) { @@ -50,7 +50,7 @@ public void Can_collect_stats([Values(false, true)] bool parallel) stateProvider.CommitTree(0); stateProvider.CommitTree(1); - stateRoot = stateProvider.StateRoot; + baseBlock = Build.A.BlockHeader.WithNumber(1).WithStateRoot(stateProvider.StateRoot).TestObject; } codeDb.Delete(Keccak.Compute(new byte[] { 1, 2, 3, 4 })); // missing code @@ -67,7 +67,7 @@ public void Can_collect_stats([Values(false, true)] bool parallel) MaxDegreeOfParallelism = parallel ? 0 : 1 }; - stateReader.RunTreeVisitor(statsCollector, stateRoot, visitingOptions); + stateReader.RunTreeVisitor(statsCollector, baseBlock, visitingOptions); var stats = statsCollector.Stats; stats.CodeCount.Should().Be(1); diff --git a/src/Nethermind/Nethermind.State/BlockingVerifyTrie.cs b/src/Nethermind/Nethermind.State/BlockingVerifyTrie.cs index e7921cd9513..91f0ab31581 100644 --- a/src/Nethermind/Nethermind.State/BlockingVerifyTrie.cs +++ b/src/Nethermind/Nethermind.State/BlockingVerifyTrie.cs @@ -47,8 +47,7 @@ public bool VerifyTrie(BlockHeader stateAtBlock, CancellationToken cancellationT // This is to block processing as with halfpath old nodes will be removed using IDisposable _ = _trieStore.BeginScope(stateAtBlock); - Hash256 rootNode = stateAtBlock.StateRoot; - TrieStats stats = _stateReader.CollectStats(rootNode, _codeDb, _logManager, cancellationToken); + TrieStats stats = _stateReader.CollectStats(stateAtBlock, _codeDb, _logManager, cancellationToken); if (stats.MissingNodes > 0) { if (_logger.IsError) _logger.Error($"Missing node found!"); diff --git a/src/Nethermind/Nethermind.State/IStateReader.cs b/src/Nethermind/Nethermind.State/IStateReader.cs index a2d44d20eb6..f52f5f9b504 100644 --- a/src/Nethermind/Nethermind.State/IStateReader.cs +++ b/src/Nethermind/Nethermind.State/IStateReader.cs @@ -15,7 +15,7 @@ public interface IStateReader ReadOnlySpan GetStorage(BlockHeader? baseBlock, Address address, in UInt256 index); byte[]? GetCode(Hash256 codeHash); byte[]? GetCode(in ValueHash256 codeHash); - void RunTreeVisitor(ITreeVisitor treeVisitor, Hash256 stateRoot, VisitingOptions? visitingOptions = null) where TCtx : struct, INodeContext; + void RunTreeVisitor(ITreeVisitor treeVisitor, BlockHeader? baseBlock, VisitingOptions? visitingOptions = null) where TCtx : struct, INodeContext; bool HasStateForBlock(BlockHeader? baseBlock); } } diff --git a/src/Nethermind/Nethermind.State/StateReader.cs b/src/Nethermind/Nethermind.State/StateReader.cs index 1eac7ece078..f62975701d6 100644 --- a/src/Nethermind/Nethermind.State/StateReader.cs +++ b/src/Nethermind/Nethermind.State/StateReader.cs @@ -41,9 +41,9 @@ public ReadOnlySpan GetStorage(BlockHeader? baseBlock, Address address, in public byte[]? GetCode(Hash256 codeHash) => codeHash == Keccak.OfAnEmptyString ? [] : _codeDb[codeHash.Bytes]; - public void RunTreeVisitor(ITreeVisitor treeVisitor, Hash256 stateRoot, VisitingOptions? visitingOptions = null) where TCtx : struct, INodeContext + public void RunTreeVisitor(ITreeVisitor treeVisitor, BlockHeader? header, VisitingOptions? visitingOptions = null) where TCtx : struct, INodeContext { - _state.Accept(treeVisitor, stateRoot, visitingOptions); + _state.Accept(treeVisitor, header?.StateRoot ?? Keccak.EmptyTreeHash, visitingOptions); } public bool HasStateForBlock(BlockHeader? baseBlock) => trieStore.HasRoot(baseBlock?.StateRoot ?? Keccak.EmptyTreeHash); diff --git a/src/Nethermind/Nethermind.State/StateReaderExtensions.cs b/src/Nethermind/Nethermind.State/StateReaderExtensions.cs index 933ec39162b..22f7440e70d 100644 --- a/src/Nethermind/Nethermind.State/StateReaderExtensions.cs +++ b/src/Nethermind/Nethermind.State/StateReaderExtensions.cs @@ -44,10 +44,10 @@ public static ValueHash256 GetCodeHash(this IStateReader stateReader, BlockHeade return account.CodeHash; } - public static TrieStats CollectStats(this IStateReader stateProvider, Hash256 root, IKeyValueStore codeStorage, ILogManager logManager, CancellationToken cancellationToken = default) + public static TrieStats CollectStats(this IStateReader stateProvider, BlockHeader? baseBlock, IKeyValueStore codeStorage, ILogManager logManager, CancellationToken cancellationToken = default) { TrieStatsCollector collector = new(codeStorage, logManager, cancellationToken); - stateProvider.RunTreeVisitor(collector, root, new VisitingOptions + stateProvider.RunTreeVisitor(collector, baseBlock, new VisitingOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, FullScanMemoryBudget = 16.GiB(), // Gonna guess that if you are running this, you have a decent setup. @@ -55,10 +55,10 @@ public static TrieStats CollectStats(this IStateReader stateProvider, Hash256 ro return collector.Stats; } - public static string DumpState(this IStateReader stateReader, Hash256 root) + public static string DumpState(this IStateReader stateReader, BlockHeader? baseBlock) { TreeDumper dumper = new(); - stateReader.RunTreeVisitor(dumper, root); + stateReader.RunTreeVisitor(dumper, baseBlock); return dumper.ToString(); } } From 9229706ef556ba5f4eb8cd5ab41662753f6b5095 Mon Sep 17 00:00:00 2001 From: Diptanshu Kakwani Date: Wed, 31 Dec 2025 14:32:14 +0530 Subject: [PATCH 150/255] Surge: Fix Profitabilty Check Bypass (#10020) * add potential fix * nit: improve config description --- .../TxPoolContentListsTests.cs | 103 +++++++++++++----- .../Nethermind.Taiko/Config/ISurgeConfig.cs | 3 + .../Nethermind.Taiko/Config/SurgeConfig.cs | 1 + .../Rpc/TaikoEngineRpcModule.cs | 12 +- 4 files changed, 93 insertions(+), 26 deletions(-) diff --git a/src/Nethermind/Nethermind.Taiko.Test/TxPoolContentListsTests.cs b/src/Nethermind/Nethermind.Taiko.Test/TxPoolContentListsTests.cs index 786ab8f6185..3ace773efba 100644 --- a/src/Nethermind/Nethermind.Taiko.Test/TxPoolContentListsTests.cs +++ b/src/Nethermind/Nethermind.Taiko.Test/TxPoolContentListsTests.cs @@ -22,7 +22,6 @@ using Nethermind.Blockchain; using Nethermind.Merge.Plugin.Data; using Nethermind.Merge.Plugin.Handlers; -using Nethermind.Consensus.Processing; using Nethermind.Facade.Eth.RpcTransaction; using Nethermind.Serialization.Rlp; @@ -70,30 +69,7 @@ public int[][] Test_TxLists_AreConstructed( IShareableTxProcessorSource shareableTxProcessor = Substitute.For(); shareableTxProcessor.Build(Arg.Any()).Returns(scope); - TaikoEngineRpcModule taikoAuthRpcModule = new( - Substitute.For>(), - Substitute.For>(), - Substitute.For>(), - Substitute.For>(), - Substitute.For>(), - Substitute.For>(), - Substitute.For(), - Substitute.For, IEnumerable>>(), - Substitute.For(), - Substitute.For>(), - Substitute.For, IEnumerable>>(), - Substitute.For>>(), - Substitute.For?>>(), - Substitute.For(), - Substitute.For(), - null!, - Substitute.For(), - txPool, - blockFinder, - shareableTxProcessor, - TxDecoder.Instance, - Substitute.For() - ); + TaikoEngineRpcModule taikoAuthRpcModule = CreateRpcModule(txPool, blockFinder, shareableTxProcessor); ResultWrapper result = taikoAuthRpcModule.taikoAuth_txPoolContent( Address.Zero, @@ -156,4 +132,81 @@ static object[] MakeTestData(Dictionary txs, int[] localAccounts, ul }; } } + + [TestCase(10, 0)] + [TestCase(0, 1)] + public void MaxGasLimitRatio_FiltersHighGasLimitTransactions(int maxGasLimitRatio, int expectedTxCount) + { + Transaction tx = Build.A.Transaction + .WithType(TxType.EIP1559) + .WithMaxFeePerGas(100) + .WithGasLimit(2_100_000) // 100x the actual gas used for this transaction + .WithNonce(1) + .SignedAndResolved() + .TestObject; + + ITxPool txPool = Substitute.For(); + txPool.GetPendingTransactionsBySender().Returns(new Dictionary + { + { tx.SenderAddress!, [tx] } + }); + + IBlockFinder blockFinder = Substitute.For(); + Block block = Build.A.Block.WithHeader(Build.A.BlockHeader.WithGasLimit(30_000_000).TestObject).TestObject; + blockFinder.Head.Returns(block); + + ITransactionProcessor transactionProcessor = Substitute.For(); + transactionProcessor.Execute(Arg.Any(), Arg.Any()) + .Returns(call => + { + call.Arg().SpentGas = 21_000; + return TransactionResult.Ok; + }); + + IReadOnlyTxProcessingScope scope = Substitute.For(); + scope.TransactionProcessor.Returns(transactionProcessor); + + IShareableTxProcessorSource shareableTxProcessor = Substitute.For(); + shareableTxProcessor.Build(Arg.Any()).Returns(scope); + + TaikoEngineRpcModule rpcModule = CreateRpcModule(txPool, blockFinder, shareableTxProcessor, + new Config.SurgeConfig { MaxGasLimitRatio = maxGasLimitRatio }); + + ResultWrapper result = rpcModule.taikoAuth_txPoolContent( + Address.Zero, 1, 30_000_000, 100_000, null, 10); + + Assert.That(result.Result, Is.EqualTo(Result.Success)); + int totalTxCount = result.Data?.Sum(list => list.TxList.Length) ?? 0; + Assert.That(totalTxCount, Is.EqualTo(expectedTxCount)); + } + + private static TaikoEngineRpcModule CreateRpcModule( + ITxPool txPool, + IBlockFinder blockFinder, + IShareableTxProcessorSource shareableTxProcessor, + Config.ISurgeConfig? surgeConfig = null) => new( + Substitute.For>(), + Substitute.For>(), + Substitute.For>(), + Substitute.For>(), + Substitute.For>(), + Substitute.For>(), + Substitute.For(), + Substitute.For, IEnumerable>>(), + Substitute.For(), + Substitute.For>(), + Substitute.For, IEnumerable>>(), + Substitute.For>>(), + Substitute.For?>>(), + Substitute.For(), + Substitute.For(), + null!, + Substitute.For(), + txPool, + blockFinder, + shareableTxProcessor, + TxDecoder.Instance, + Substitute.For(), + surgeConfig ?? new Config.SurgeConfig() + ); } diff --git a/src/Nethermind/Nethermind.Taiko/Config/ISurgeConfig.cs b/src/Nethermind/Nethermind.Taiko/Config/ISurgeConfig.cs index a326d9e1356..684c683ae0d 100644 --- a/src/Nethermind/Nethermind.Taiko/Config/ISurgeConfig.cs +++ b/src/Nethermind/Nethermind.Taiko/Config/ISurgeConfig.cs @@ -45,4 +45,7 @@ public interface ISurgeConfig : IConfig [ConfigItem(Description = "Maximum time in seconds to use cached gas price estimates before forcing a refresh.", DefaultValue = "12")] int GasPriceRefreshTimeoutSeconds { get; set; } + + [ConfigItem(Description = "Filter transactions exceeding the max allowed ratio of gas limit to the actual gas used (e.g. 1, 2 etc.). Set to 0 to disable.", DefaultValue = "0")] + int MaxGasLimitRatio { get; set; } } diff --git a/src/Nethermind/Nethermind.Taiko/Config/SurgeConfig.cs b/src/Nethermind/Nethermind.Taiko/Config/SurgeConfig.cs index f9946e8abc0..9e8d4f3bcc8 100644 --- a/src/Nethermind/Nethermind.Taiko/Config/SurgeConfig.cs +++ b/src/Nethermind/Nethermind.Taiko/Config/SurgeConfig.cs @@ -18,4 +18,5 @@ public class SurgeConfig : ISurgeConfig public int SharingPercentage { get; set; } = 75; public int BoostBaseFeePercentage { get; set; } = 5; public int GasPriceRefreshTimeoutSeconds { get; set; } = 12; + public int MaxGasLimitRatio { get; set; } = 0; } diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs index a5f9452aca7..7560bc5750e 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs @@ -30,6 +30,7 @@ using Nethermind.Serialization.Rlp; using Nethermind.TxPool; using Nethermind.Evm.State; +using Nethermind.Taiko.Config; namespace Nethermind.Taiko.Rpc; @@ -54,7 +55,8 @@ public class TaikoEngineRpcModule(IAsyncHandler getPa IBlockFinder blockFinder, IShareableTxProcessorSource txProcessorSource, IRlpStreamDecoder txDecoder, - IL1OriginStore l1OriginStore) : + IL1OriginStore l1OriginStore, + ISurgeConfig surgeConfig) : EngineRpcModule(getPayloadHandlerV1, getPayloadHandlerV2, getPayloadHandlerV3, @@ -208,6 +210,14 @@ void CommitAndDisposeBatch(Batch batch) while (i < txSource.Length && txSource[i].SenderAddress == tx.SenderAddress) i++; continue; } + + // For Surge, filter out any transaction with very high gas limit + if (surgeConfig.MaxGasLimitRatio > 0 && tx.GasLimit > tx.SpentGas * surgeConfig.MaxGasLimitRatio) + { + worldState.Restore(snapshot); + while (i < txSource.Length && txSource[i].SenderAddress == tx.SenderAddress) i++; + continue; + } } catch { From 9ee55399f1416606cf8daa3f042aed8d134d532c Mon Sep 17 00:00:00 2001 From: Pavlo Rytikov Date: Wed, 31 Dec 2025 11:07:00 +0200 Subject: [PATCH 151/255] Skip SST file size checks when MaxOpenFiles is specified (#10002) * Skip SST file size checks when MaxOpenFiles is specified * Add config option, skip SST checks on MacOS if not configured otherwise * Remove obvious comment --- .../Nethermind.Db.Rocks/Config/DbConfig.cs | 1 + .../Nethermind.Db.Rocks/Config/IDbConfig.cs | 1 + .../Config/RocksDbConfigFactory.cs | 8 +++++++ .../RocksDbConfigFactoryTests.cs | 21 ++++++++++++++++++- 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs index f0efb6213da..6a2b42c0c30 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs @@ -18,6 +18,7 @@ public class DbConfig : IDbConfig public uint StatsDumpPeriodSec { get; set; } = 600; public int? MaxOpenFiles { get; set; } + public bool? SkipCheckingSstFileSizesOnDbOpen { get; set; } public ulong? ReadAheadSize { get; set; } = (ulong)256.KiB(); public string RocksDbOptions { get; set; } = diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs index bdd18bb3afd..fa7c8e2023b 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs @@ -25,6 +25,7 @@ public interface IDbConfig : IConfig int? MaxOpenFiles { get; set; } + bool? SkipCheckingSstFileSizesOnDbOpen { get; set; } bool WriteAheadLogSync { get; set; } ulong? ReadAheadSize { get; set; } string RocksDbOptions { get; set; } diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/RocksDbConfigFactory.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/RocksDbConfigFactory.cs index add67c9965d..a2c661824f6 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/RocksDbConfigFactory.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/RocksDbConfigFactory.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Runtime.InteropServices; using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Logging; @@ -36,6 +37,13 @@ public IRocksDbConfig GetForDatabase(string databaseName, string? columnName) dbConfig.MaxOpenFiles = perDbLimit; } + + bool skipSstChecks = dbConfig.SkipCheckingSstFileSizesOnDbOpen ?? RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + if (skipSstChecks) + { + if (_logger.IsTrace) _logger.Trace("Skipping SST file size checks on DB open for faster startup."); + dbConfig.RocksDbOptions += "skip_checking_sst_file_sizes_on_db_open=true;"; + } } IRocksDbConfig rocksDbConfig = new PerTableDbConfig(dbConfig, databaseName, columnName); diff --git a/src/Nethermind/Nethermind.Db.Test/RocksDbConfigFactoryTests.cs b/src/Nethermind/Nethermind.Db.Test/RocksDbConfigFactoryTests.cs index ad1d4d04c31..d79af859643 100644 --- a/src/Nethermind/Nethermind.Db.Test/RocksDbConfigFactoryTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/RocksDbConfigFactoryTests.cs @@ -23,7 +23,6 @@ public void CanFetchNormally() var dbConfig = new DbConfig(); var factory = new RocksDbConfigFactory(dbConfig, new PruningConfig(), new TestHardwareInfo(0), LimboLogs.Instance); IRocksDbConfig config = factory.GetForDatabase("State0", null); - Console.Error.WriteLine(config.RocksDbOptions); config.RocksDbOptions.Should().Be(dbConfig.RocksDbOptions + dbConfig.StateDbRocksDbOptions); } @@ -100,4 +99,24 @@ public void WillEnforceMinimumMaxOpenFiles() // With system limit of 1000, would be 1000 * 0.8 = 800 config.MaxOpenFiles.Should().Be(800); } + + [Test] + public void WillApplySkipSstFileSizeChecksWhenConfigExplicitlyEnabled() + { + var dbConfig = new DbConfig(); + dbConfig.SkipCheckingSstFileSizesOnDbOpen = true; + var factory = new RocksDbConfigFactory(dbConfig, new PruningConfig(), new TestHardwareInfo(0), LimboLogs.Instance); + IRocksDbConfig config = factory.GetForDatabase("State0", null); + config.RocksDbOptions.Should().Contain("skip_checking_sst_file_sizes_on_db_open=true;"); + } + + [Test] + public void WillNotApplySkipSstFileSizeChecksWhenConfigExplicitlyDisabled() + { + var dbConfig = new DbConfig(); + dbConfig.SkipCheckingSstFileSizesOnDbOpen = false; + var factory = new RocksDbConfigFactory(dbConfig, new PruningConfig(), new TestHardwareInfo(0), LimboLogs.Instance); + IRocksDbConfig config = factory.GetForDatabase("State0", null); + config.RocksDbOptions.Should().NotContain("skip_checking_sst_file_sizes_on_db_open"); + } } From 07d8de7174fd536874a192d3e75e6b80545c04a1 Mon Sep 17 00:00:00 2001 From: lupin17 <59-quanta.middle@icloud.com> Date: Wed, 31 Dec 2025 12:29:31 +0100 Subject: [PATCH 152/255] Fix: Correct memory access validation in TrySaveByte for MSTORE8 operation (#9970) * Update EvmPooledMemory.cs * Update src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs * Update src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs --------- Co-authored-by: Lukasz Rozmej Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs b/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs index df531b37ca6..043a12513fa 100644 --- a/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs +++ b/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs @@ -45,10 +45,10 @@ ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_memory), offset), public bool TrySaveByte(in UInt256 location, byte value) { - CheckMemoryAccessViolation(in location, WordSize, out _, out bool isViolation); + CheckMemoryAccessViolation(in location, 1, out ulong newLength, out bool isViolation); if (isViolation) return false; - UpdateSize(location.u0 + 1); + UpdateSize(newLength); _memory![(long)location] = value; return true; From 6778204bd5af54d9ac5da63648e3288f2037b2ad Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Thu, 1 Jan 2026 16:10:37 +0100 Subject: [PATCH 153/255] Update file header templates (#10077) --- .editorconfig | 2 +- CONTRIBUTING.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index b54df7ecd37..1b960db343d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,7 @@ indent_style = space insert_final_newline = true trim_trailing_whitespace = true -file_header_template = SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited\nSPDX-License-Identifier: LGPL-3.0-only +file_header_template = SPDX-FileCopyrightText: 2026 Demerzel Solutions Limited\nSPDX-License-Identifier: LGPL-3.0-only [*.py] indent_size = 4 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b9adeabc56d..53cf3198a30 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,7 +59,7 @@ Branch names must follow the `kebab-case` or `snake_case` pattern and be all low The following notice must be included as a header in all source files if possible. ``` -// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2026 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only ``` From 75a6d978c148a84fcd2b691413fe03eec7eaf015 Mon Sep 17 00:00:00 2001 From: Damian Orzechowski <114909782+damian-orzechowski@users.noreply.github.com> Date: Fri, 2 Jan 2026 15:00:34 +0100 Subject: [PATCH 154/255] Should update child if parent has empty keccak as well (#10073) * Should update child if parent has empty keccak as well * Combine conditions --- src/Nethermind/Nethermind.Trie/PatriciaTree.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs index e8638015ad4..65e57990dd1 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs @@ -718,8 +718,9 @@ internal bool ShouldUpdateChild(TrieNode? parent, TrieNode? oldChild, TrieNode? if (parent is null) return true; if (oldChild is null && newChild is null) return false; if (!ReferenceEquals(oldChild, newChild)) return true; - if (newChild.Keccak is null && parent.Keccak is not null) return true; // So that recalculate root knows to recalculate the parent root. - return false; + // So that recalculate root knows to recalculate the parent root. + // Parent's hash can also be null depending on nesting level - still need to update child, otherwise combine will remain original value + return newChild.Keccak is null; } /// From 9cf0d075d681a9d5454482ec0f859e309125a78e Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Fri, 2 Jan 2026 11:04:02 -0500 Subject: [PATCH 155/255] Improve FastHash quality (#10082) * Improve hash quality * formatting * Update src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Nethermind/Nethermind.Core/Bloom.cs | 10 +- .../Nethermind.Core/BloomConverter.cs | 2 +- .../Extensions/SpanExtensions.cs | 230 ++++++++++++++---- 3 files changed, 183 insertions(+), 59 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Bloom.cs b/src/Nethermind/Nethermind.Core/Bloom.cs index e3f2749e7cc..baeb3e75e16 100644 --- a/src/Nethermind/Nethermind.Core/Bloom.cs +++ b/src/Nethermind/Nethermind.Core/Bloom.cs @@ -54,6 +54,7 @@ public Bloom(ReadOnlySpan bytes) } public Span Bytes => _bloomData.AsSpan(); + public ReadOnlySpan ReadOnlyBytes => _bloomData.AsReadOnlySpan(); private Span ULongs => _bloomData.AsULongs(); public void Set(ReadOnlySpan sequence, Bloom? masterBloom = null) @@ -79,7 +80,7 @@ public void Set(ReadOnlySpan sequence, Bloom? masterBloom = null) public bool Matches(ReadOnlySpan sequence) => Matches(GetExtract(sequence)); - public override string ToString() => Bytes.ToHexString(); + public override string ToString() => ReadOnlyBytes.ToHexString(); public static bool operator !=(Bloom? a, Bloom? b) { @@ -101,7 +102,7 @@ public bool Equals(Bloom? other) if (other is null) return false; if (ReferenceEquals(this, other)) return true; - return Nethermind.Core.Extensions.Bytes.AreEqual(Bytes, other.Bytes); + return Nethermind.Core.Extensions.Bytes.AreEqual(ReadOnlyBytes, other.ReadOnlyBytes); } public override bool Equals(object? obj) @@ -112,7 +113,7 @@ public override bool Equals(object? obj) return Equals((Bloom)obj); } - public override int GetHashCode() => Bytes.FastHash(); + public override int GetHashCode() => ReadOnlyBytes.FastHash(); public void Add(LogEntry[] logEntries) { @@ -251,7 +252,7 @@ public readonly struct BloomExtract(ulong indexes) public Bloom Clone() { Bloom clone = new(); - Bytes.CopyTo(clone.Bytes); + ReadOnlyBytes.CopyTo(clone.Bytes); return clone; } @@ -259,6 +260,7 @@ public Bloom Clone() public struct BloomData { private byte _element0; + public ReadOnlySpan AsReadOnlySpan() => MemoryMarshal.CreateReadOnlySpan(ref _element0, ByteLength); public Span AsSpan() => MemoryMarshal.CreateSpan(ref _element0, ByteLength); public Span AsULongs() => MemoryMarshal.CreateSpan(ref Unsafe.As(ref _element0), ByteLength / sizeof(ulong)); } diff --git a/src/Nethermind/Nethermind.Core/BloomConverter.cs b/src/Nethermind/Nethermind.Core/BloomConverter.cs index c2b59492a3a..f58df98a53a 100644 --- a/src/Nethermind/Nethermind.Core/BloomConverter.cs +++ b/src/Nethermind/Nethermind.Core/BloomConverter.cs @@ -24,6 +24,6 @@ public override void Write( Bloom bloom, JsonSerializerOptions options) { - ByteArrayConverter.Convert(writer, bloom.Bytes, skipLeadingZeros: false); + ByteArrayConverter.Convert(writer, bloom.ReadOnlyBytes, skipLeadingZeros: false); } } diff --git a/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs index 0c9c08b282e..0f280e093e6 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs @@ -197,83 +197,205 @@ public static ArrayPoolListRef ToPooledListRef(this in ReadOnlySpan spa return newList; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int FastHash(this Span input) - => FastHash((ReadOnlySpan)input); - + /// + /// Computes a very fast, non-cryptographic 32-bit hash of the supplied bytes. + /// + /// The input bytes to hash. + /// + /// A 32-bit hash value for . Returns 0 when is empty. + /// Note that the value is returned as a signed (the underlying 32-bit pattern may appear negative). + /// + /// + /// + /// This routine is optimised for throughput and low overhead on modern CPUs. It is based on CRC32C (Castagnoli) + /// via and related overloads, and will use hardware acceleration + /// when the runtime and processor support it. + /// + /// + /// The hash is intended for in-memory data structures (for example, hash tables, caches, and quick bucketing). + /// It is not suitable for cryptographic purposes, integrity verification, or security-sensitive scenarios. + /// In particular, it is not collision resistant and should not be used as a MAC, signature, or authentication token. + /// + /// + /// The returned value is an implementation detail. It is seeded with an instance-random value and may be + /// platform and runtime dependent, so do not persist it or rely on it being stable across processes or versions. + /// + /// [SkipLocalsInit] public static int FastHash(this ReadOnlySpan input) { - // Very fast hardware accelerated non-cryptographic hash function - var length = input.Length; - if (length == 0) return 0; - - ref var b = ref MemoryMarshal.GetReference(input); - uint hash = s_instanceRandom + (uint)length; - if (length < sizeof(long)) + // Fast hardware-accelerated, non-cryptographic hash. + // Core idea: CRC32C is extremely cheap on CPUs with SSE4.2/ARM CRC, + // and gives good diffusion for hashing. We then optionally add extra + // mixing to reduce "CRC linearity" artefacts. + + int len = input.Length; + + // Contract choice: empty input hashes to 0. + // (Also avoids doing any ref work on an empty span.) + if (len == 0) return 0; + // Using ref + Unsafe.ReadUnaligned lets the JIT hoist bounds checks + // and keep the hot loop tight. + ref byte start = ref MemoryMarshal.GetReference(input); + + // Seed with an instance-random value so attackers cannot trivially + // engineer lots of same-bucket keys. Mixing in length makes "same prefix, + // different length" less correlated (CRC alone can be length-sensitive). + uint seed = s_instanceRandom + (uint)len; + + // Small: 1-7 bytes. + // Using the tail routine here avoids building a synthetic + // 64-bit value with shifts/byte-permute. + if (len < 8) { - goto Short; + uint small = CrcTailOrdered(seed, ref start, len); + // FinalMix breaks some remaining linearity and improves avalanche for tiny inputs. + return (int)FinalMix(small); } - // Start with instance random, length and first ulong as seed - hash = BitOperations.Crc32C(hash, Unsafe.ReadUnaligned(ref b)); - - // Calculate misalignment and move by it if needed. - // If no misalignment, advance by the size of ulong - uint misaligned = (uint)length & 7; - if (misaligned != 0) + // Medium: 8-31 bytes. + // A single CRC lane is usually fine here - overhead dominates, + // and latency hiding is less important. + if (len < 32) { - // Align by moving by the misaligned count - b = ref Unsafe.Add(ref b, misaligned); - length -= (int)misaligned; + uint h = seed; + ref byte p = ref start; + + // Process as many full qwords as possible. + // "& ~7" is a cheap round-down-to-multiple-of-8 (no division/mod). + int full = len & ~7; + int tail = len - full; + + // Streaming CRC over 8-byte chunks. + // ReadUnaligned keeps us safe for arbitrary input alignment. + for (int i = 0; i < full; i += 8) + { + h = BitOperations.Crc32C(h, Unsafe.ReadUnaligned(ref p)); + p = ref Unsafe.Add(ref p, 8); + } + + // Hash remaining 1-7 bytes in strict order (no over-read). + if (tail != 0) + h = CrcTailOrdered(h, ref p, tail); + + // Final mixing for better bit diffusion than raw CRC, + // especially for shorter payloads. + return (int)FinalMix(h); } - else + + // Large: 32+ bytes. + // Use multiple independent CRC accumulators ("lanes") to hide crc32 + // latency and increase ILP. CRC32C instructions have decent throughput + // but non-trivial latency; 4 lanes keeps the CPU busy. + uint h0 = seed; + uint h1 = seed ^ 0x9E3779B9u; // golden-ratio-ish constants to decorrelate lanes + uint h2 = seed ^ 0x85EBCA6Bu; // constants borrowed from common finalisers (good bit dispersion) + uint h3 = seed ^ 0xC2B2AE35u; + + ref byte q = ref start; + + // Consume all full qwords first. Tail (1-7 bytes) is handled later. + int aligned = len & ~7; + int remaining = aligned; + + // 64-byte unroll: + // - amortises loop branch/compare overhead + // - feeds enough independent work to keep OoO cores busy + // - maps nicely onto cache line sized chunks + while (remaining >= 64) { - // Already Crc'd first ulong so skip it - b = ref Unsafe.Add(ref b, sizeof(ulong)); - length -= sizeof(ulong); + h0 = BitOperations.Crc32C(h0, Unsafe.ReadUnaligned(ref q)); + h1 = BitOperations.Crc32C(h1, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 8))); + h2 = BitOperations.Crc32C(h2, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 16))); + h3 = BitOperations.Crc32C(h3, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 24))); + + h0 = BitOperations.Crc32C(h0, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 32))); + h1 = BitOperations.Crc32C(h1, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 40))); + h2 = BitOperations.Crc32C(h2, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 48))); + h3 = BitOperations.Crc32C(h3, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 56))); + + q = ref Unsafe.Add(ref q, 64); + remaining -= 64; } - // Length is fully aligned here and b is set in place - while (length >= sizeof(ulong) * 3) + // One more half-unroll for 32 bytes if present. + // Keeps the "drain" path short and avoids a smaller loop with more branches. + if (remaining >= 32) { - // Crc32C is 3 cycle latency, 1 cycle throughput - // So we us same initial 3 times to not create a dependency chain - uint hash0 = BitOperations.Crc32C(hash, Unsafe.ReadUnaligned(ref b)); - uint hash1 = BitOperations.Crc32C(hash, Unsafe.ReadUnaligned(ref Unsafe.Add(ref b, sizeof(ulong)))); - uint hash2 = BitOperations.Crc32C(hash, Unsafe.ReadUnaligned(ref Unsafe.Add(ref b, sizeof(ulong) * 2))); - b = ref Unsafe.Add(ref b, sizeof(ulong) * 3); - length -= sizeof(ulong) * 3; - // Combine the 3 hashes; performing the shift on first crc to calculate - hash = BitOperations.Crc32C(hash1, ((ulong)hash0 << (sizeof(uint) * 8)) | hash2); + h0 = BitOperations.Crc32C(h0, Unsafe.ReadUnaligned(ref q)); + h1 = BitOperations.Crc32C(h1, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 8))); + h2 = BitOperations.Crc32C(h2, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 16))); + h3 = BitOperations.Crc32C(h3, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 24))); + + q = ref Unsafe.Add(ref q, 32); + remaining -= 32; } - while (length > 0) + // Drain any remaining full qwords (0, 8, 16, or 24 bytes). + // This is branchy but only runs once, so it is cheaper than another loop. + if (remaining != 0) { - hash = BitOperations.Crc32C(hash, Unsafe.ReadUnaligned(ref b)); - b = ref Unsafe.Add(ref b, sizeof(ulong)); - length -= sizeof(ulong); + // remaining is a multiple of 8 here. + if (remaining >= 8) h0 = BitOperations.Crc32C(h0, Unsafe.ReadUnaligned(ref q)); + if (remaining >= 16) h1 = BitOperations.Crc32C(h1, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 8))); + if (remaining == 24) h2 = BitOperations.Crc32C(h2, Unsafe.ReadUnaligned(ref Unsafe.Add(ref q, 16))); } - return (int)hash; - Short: - ulong data = 0; - if ((length & sizeof(byte)) != 0) + // Fold lanes down to one 32-bit value. + // Rotates permute bit positions so each lane contributes differently. + // Adds (rather than XOR) deliberately introduce carries + // - CRC is linear over GF(2), and carry breaks that, making simple algebraic + // structure harder to exploit for collision clustering in hash tables. + h2 = BitOperations.RotateLeft(h2, 17) + BitOperations.RotateLeft(h3, 23); + h0 += BitOperations.RotateLeft(h1, 11); + uint hash = h2 + h0; + + // Handle tail bytes (1-7 bytes) that were not part of the qword-aligned stream. + // This is exact, in-order processing - no overlap and no over-read. + int tailBytes = len - aligned; + if (tailBytes != 0) { - data = b; - b = ref Unsafe.Add(ref b, sizeof(byte)); + ref byte tailRef = ref Unsafe.Add(ref start, aligned); + hash = CrcTailOrdered(hash, ref tailRef, tailBytes); } - if ((length & sizeof(ushort)) != 0) + + // FinalMix breaks some remaining linearity and improves avalanche + return (int)FinalMix(hash); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static uint CrcTailOrdered(uint hash, ref byte p, int length) { - data = (data << (sizeof(ushort) * 8)) | Unsafe.ReadUnaligned(ref b); - b = ref Unsafe.Add(ref b, sizeof(ushort)); + // length is 1..7 + // Process 4-2-1 bytes in natural order + if ((length & 4) != 0) + { + hash = BitOperations.Crc32C(hash, Unsafe.ReadUnaligned(ref p)); + p = ref Unsafe.Add(ref p, 4); + } + if ((length & 2) != 0) + { + hash = BitOperations.Crc32C(hash, Unsafe.ReadUnaligned(ref p)); + p = ref Unsafe.Add(ref p, 2); + } + if ((length & 1) != 0) + { + hash = BitOperations.Crc32C(hash, p); + } + return hash; } - if ((length & sizeof(uint)) != 0) + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static uint FinalMix(uint x) { - data = (data << (sizeof(uint) * 8)) | Unsafe.ReadUnaligned(ref b); + // A tiny finaliser to improve avalanche: + // - xor-fold high bits down + // - multiply by an odd constant to spread changes across bits + // - xor-fold again to propagate the multiply result + x ^= x >> 16; + x *= 0x9E3779B1u; + x ^= x >> 16; + return x; } - - return (int)BitOperations.Crc32C(hash, data); } } } From 3921649718412b10bf26a97c2b6019f745fcd264 Mon Sep 17 00:00:00 2001 From: James Niken <155266991+dizer-ti@users.noreply.github.com> Date: Sat, 3 Jan 2026 14:56:12 +0100 Subject: [PATCH 156/255] refactor: replace HexConvert.ToUInt256 with UInt256.Parse (#10085) Keep HexConvert.ToUInt64 as it handles both base 10 and 16 automatically. --- tools/SendBlobs/BlobSender.cs | 4 ++-- tools/SendBlobs/FundsDistributor.cs | 24 ++++++++++++------------ tools/SendBlobs/HexConvert.cs | 7 ------- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/tools/SendBlobs/BlobSender.cs b/tools/SendBlobs/BlobSender.cs index aaad1d6ab34..a4eb13dba9d 100644 --- a/tools/SendBlobs/BlobSender.cs +++ b/tools/SendBlobs/BlobSender.cs @@ -277,8 +277,8 @@ public async Task SendData( if (defaultMaxPriorityFeePerGas is null) { - string? maxPriorityFeePerGasRes = await _rpcClient.Post("eth_maxPriorityFeePerGas") ?? "1"; - result.maxPriorityFeePerGas = HexConvert.ToUInt256(maxPriorityFeePerGasRes); + string? maxPriorityFeePerGasRes = await _rpcClient.Post("eth_maxPriorityFeePerGas") ?? "0x1"; + result.maxPriorityFeePerGas = UInt256.Parse(maxPriorityFeePerGasRes); } else { diff --git a/tools/SendBlobs/FundsDistributor.cs b/tools/SendBlobs/FundsDistributor.cs index fe87fd76b3b..7a66867066d 100644 --- a/tools/SendBlobs/FundsDistributor.cs +++ b/tools/SendBlobs/FundsDistributor.cs @@ -48,15 +48,15 @@ public async Task> DitributeFunds(Signer distributeFrom, uin if (nonceString is null) throw new AccountException($"Unable to get nonce for {distributeFrom.Address}"); - string? gasPriceRes = await _rpcClient.Post("eth_gasPrice") ?? "1"; - UInt256 gasPrice = HexConvert.ToUInt256(gasPriceRes); + string? gasPriceRes = await _rpcClient.Post("eth_gasPrice") ?? "0x1"; + UInt256 gasPrice = UInt256.Parse(gasPriceRes); string? maxPriorityFeePerGasRes; UInt256 maxPriorityFeePerGas = maxPriorityFee; if (maxPriorityFee == 0) { - maxPriorityFeePerGasRes = await _rpcClient.Post("eth_maxPriorityFeePerGas") ?? "1"; - maxPriorityFeePerGas = HexConvert.ToUInt256(maxPriorityFeePerGasRes); + maxPriorityFeePerGasRes = await _rpcClient.Post("eth_maxPriorityFeePerGas") ?? "0x1"; + maxPriorityFeePerGas = UInt256.Parse(maxPriorityFeePerGasRes); } UInt256 balance = new UInt256(Bytes.FromHexString(balanceString)); @@ -100,11 +100,11 @@ public async Task> DitributeFunds(Signer distributeFrom, uin { if (maxFee == 0) { - gasPriceRes = await _rpcClient.Post("eth_gasPrice") ?? "1"; - gasPrice = HexConvert.ToUInt256(gasPriceRes); + gasPriceRes = await _rpcClient.Post("eth_gasPrice") ?? "0x1"; + gasPrice = UInt256.Parse(gasPriceRes); - maxPriorityFeePerGasRes = await _rpcClient.Post("eth_maxPriorityFeePerGas") ?? "1"; - maxPriorityFeePerGas = HexConvert.ToUInt256(maxPriorityFeePerGasRes); + maxPriorityFeePerGasRes = await _rpcClient.Post("eth_maxPriorityFeePerGas") ?? "0x1"; + maxPriorityFeePerGas = UInt256.Parse(maxPriorityFeePerGasRes); } Transaction tx = CreateTx(_chainId, @@ -163,14 +163,14 @@ public async Task> ReclaimFunds(Address beneficiary, UInt256 ulong nonce = HexConvert.ToUInt64(nonceString); - string? gasPriceRes = await _rpcClient.Post("eth_gasPrice") ?? "1"; - UInt256 gasPrice = HexConvert.ToUInt256(gasPriceRes); + string? gasPriceRes = await _rpcClient.Post("eth_gasPrice") ?? "0x1"; + UInt256 gasPrice = UInt256.Parse(gasPriceRes); UInt256 maxPriorityFeePerGas = maxPriorityFee; if (maxPriorityFee == 0) { - string? maxPriorityFeePerGasRes = await _rpcClient.Post("eth_maxPriorityFeePerGas") ?? "1"; - maxPriorityFeePerGas = HexConvert.ToUInt256(maxPriorityFeePerGasRes); + string? maxPriorityFeePerGasRes = await _rpcClient.Post("eth_maxPriorityFeePerGas") ?? "0x1"; + maxPriorityFeePerGas = UInt256.Parse(maxPriorityFeePerGasRes); } UInt256 approxGasFee = (gasPrice + maxPriorityFeePerGas) * GasCostOf.Transaction; diff --git a/tools/SendBlobs/HexConvert.cs b/tools/SendBlobs/HexConvert.cs index d68014b229c..d125a6153f9 100644 --- a/tools/SendBlobs/HexConvert.cs +++ b/tools/SendBlobs/HexConvert.cs @@ -1,16 +1,9 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Int256; - namespace SendBlobs; internal static class HexConvert { - public static UInt256 ToUInt256(string s) - { - return (UInt256)ToUInt64(s); - } - public static ulong ToUInt64(string s) { return Convert.ToUInt64(s, s.StartsWith("0x") ? 16 : 10); From 891d79d82a320ba5e2b5675ce4fd40dee332ba70 Mon Sep 17 00:00:00 2001 From: Ahmad Bitar <33181301+smartprogrammer93@users.noreply.github.com> Date: Sat, 3 Jan 2026 20:09:04 +0300 Subject: [PATCH 157/255] fix: ensure eth_getBlockByNumber enforces canonical block retrieval (#10024) * fix: ensure eth_getBlockByNumber enforces canonical block retrieval * fix tests * address comment * apply suggestion --- .../Find/BlockParameter.cs | 1 + .../Eth/Simulate/EthSimulateTestsHiveBase.cs | 10 +++--- .../Modules/BlockFinderExtensions.cs | 36 ++++++------------- 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs b/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs index ced17296aaa..884febc8cc8 100644 --- a/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs +++ b/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs @@ -45,6 +45,7 @@ public BlockParameter(BlockParameterType type) public BlockParameter(long number) { + RequireCanonical = true; Type = BlockParameterType.BlockNumber; BlockNumber = number; } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs index 93eae058322..209968e149c 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs @@ -11,6 +11,7 @@ using Nethermind.Core.Specs; using Nethermind.Core.Test.Blockchain; using Nethermind.Core.Test.Builders; +using Nethermind.Facade.Eth; using Nethermind.Facade.Eth.RpcTransaction; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Int256; @@ -128,9 +129,9 @@ public async Task TestSimulate_TimestampIsComputedCorrectly_WhenNoTimestampOverr } """; var serializer = new EthereumJsonSerializer(); - var payload = serializer.Deserialize>(data); + SimulatePayload? payload = serializer.Deserialize>(data); - var chain = await TestRpcBlockchain + TestRpcBlockchain chain = await TestRpcBlockchain .ForTest(new TestRpcBlockchain()) .WithBlocksConfig(new BlocksConfig { @@ -146,9 +147,8 @@ public async Task TestSimulate_TimestampIsComputedCorrectly_WhenNoTimestampOverr await chain.AddBlock(BuildSimpleTransaction.WithNonce(3).TestObject); await chain.AddBlock(BuildSimpleTransaction.WithNonce(4).TestObject, BuildSimpleTransaction.WithNonce(5).TestObject); - var blockParameter = new BlockParameter(blockNumber); - var parent = chain.EthRpcModule.eth_getBlockByNumber(blockParameter).Data; - var simulated = chain.EthRpcModule.eth_simulateV1(payload, blockParameter).Data[0]; + BlockForRpc parent = chain.EthRpcModule.eth_getBlockByNumber(new BlockParameter(blockNumber)).Data; + SimulateBlockResult simulated = chain.EthRpcModule.eth_simulateV1(payload, new BlockParameter(blockNumber)).Data[0]; simulated.ParentHash.Should().Be(parent.Hash); (simulated.Number - parent.Number).Should().Be(1); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs index 16d0a22526e..85b63ed25b5 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs @@ -35,23 +35,15 @@ public static SearchResult SearchForHeader(this IBlockFinder blockF blockParameter ??= BlockParameter.Latest; - BlockHeader header; - if (blockParameter.RequireCanonical) + BlockHeader header = blockFinder.FindHeader(blockParameter); + if (blockParameter.RequireCanonical && header is null && !allowNulls && blockParameter.BlockHash is not null) { - header = blockFinder.FindHeader(blockParameter.BlockHash, BlockTreeLookupOptions.RequireCanonical); - if (header is null && !allowNulls) + header = blockFinder.FindHeader(blockParameter.BlockHash); + if (header is not null) { - header = blockFinder.FindHeader(blockParameter.BlockHash); - if (header is not null) - { - return new SearchResult($"{blockParameter.BlockHash} block is not canonical", ErrorCodes.InvalidInput); - } + return new SearchResult($"{blockParameter.BlockHash} block is not canonical", ErrorCodes.InvalidInput); } } - else - { - header = blockFinder.FindHeader(blockParameter); - } return header is null && !allowNulls ? new SearchResult($"{blockParameter.BlockHash?.ToString() ?? blockParameter.BlockNumber?.ToString() ?? blockParameter.Type.ToString()} could not be found", ErrorCodes.ResourceNotFound) @@ -62,23 +54,15 @@ public static SearchResult SearchForBlock(this IBlockFinder blockFinder, { blockParameter ??= BlockParameter.Latest; - Block block; - if (blockParameter.RequireCanonical) + Block block = blockFinder.FindBlock(blockParameter); + if (blockParameter.RequireCanonical && block is null && !allowNulls && blockParameter.BlockHash is not null) { - block = blockFinder.FindBlock(blockParameter.BlockHash!, BlockTreeLookupOptions.RequireCanonical); - if (block is null && !allowNulls) + BlockHeader? header = blockFinder.FindHeader(blockParameter.BlockHash); + if (header is not null) { - BlockHeader? header = blockFinder.FindHeader(blockParameter.BlockHash); - if (header is not null) - { - return new SearchResult($"{blockParameter.BlockHash} block is not canonical", ErrorCodes.InvalidInput); - } + return new SearchResult($"{blockParameter.BlockHash} block is not canonical", ErrorCodes.InvalidInput); } } - else - { - block = blockFinder.FindBlock(blockParameter); - } if (block is null) { From 64e7f38baa0fc1bc43e2f90cb137e66168b15120 Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Sun, 4 Jan 2026 12:00:51 +0100 Subject: [PATCH 158/255] Auto-update fast sync settings (#10089) Co-authored-by: rubo --- src/Nethermind/Nethermind.Runner/configs/base-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/base-sepolia.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/chiado.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/gnosis.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/joc-testnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sepolia.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-mainnet.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-sepolia.json | 4 ++-- 14 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index 15b33ed0086..30f2e293146 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": 10000000000, - "PivotNumber": 40030000, - "PivotHash": "0x5c90880ea1e205ab07cc587b73760271ebbceedaf0c00a163e2bb60dac66cad9" + "PivotNumber": 40340000, + "PivotHash": "0x42aa9b1d248ba0173d76a00b4255528f8719ff92f1124c34ec1de7e993de61bb" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index 3cab4cce994..bcd13f9650c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": 10000000000, - "PivotNumber": 35540000, - "PivotHash": "0xc2502a90d5a1d21254bd4c613be06816e9a9d87719f74d3ea41714b30cc3098d" + "PivotNumber": 35850000, + "PivotHash": "0xd7006ba1950b68c00dfae913c0de97ac855be355573f15142bf269a77dd378cf" }, "Discovery": { "DiscoveryVersion": "V5" @@ -36,4 +36,4 @@ "Optimism": { "SequencerUrl": "https://sepolia-sequencer.base.org" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.json b/src/Nethermind/Nethermind.Runner/configs/chiado.json index 46f5eef1e28..49705e6ee74 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.json +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.json @@ -18,8 +18,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 19430000, - "PivotHash": "0xb7f24304de674835b2c056f26c872949152a66aab1844df60efdda986d4b7b36", + "PivotNumber": 19530000, + "PivotHash": "0x00ead99cab26fddc9804d697de2bc8e64e6fa85264ef4864a7b35989931ab665", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": 10000000000, "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.json b/src/Nethermind/Nethermind.Runner/configs/gnosis.json index d75db0f5215..ff43be86cdc 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.json +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.json @@ -14,8 +14,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 43850000, - "PivotHash": "0xf27984f12faa543ecaada2564b8fb66a3488abc4d4aebcd8d03c59accdb91c33", + "PivotNumber": 43970000, + "PivotHash": "0xdd75a603dd94638a2cd3bc5e8625e2e1b9e4fa976c698d8e011c8ae59db495ab", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000, diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json index b2a83375973..c24a040dcb3 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 21440000, - "PivotHash": "0x986a542bc4eda557266d001ea82b4d734446bc53b0b5b05dbb21cbef4dd5e8c1", - "PivotTotalDifficulty": "38655935" + "PivotNumber": 21560000, + "PivotHash": "0xba316a7a54faf7870506dfe4aa12138141dab2115bf9d3767bd13908bb922345", + "PivotTotalDifficulty": "38834019" }, "Metrics": { "NodeName": "JOC-Mainnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json index 552584682f4..156cb836607 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 15050000, - "PivotHash": "0xa76e62e7236f647246e47696bfbc8d3fcf2d8df1664d62197fc2f2fef3a2e472", - "PivotTotalDifficulty": "25060219" + "PivotNumber": 15170000, + "PivotHash": "0x63ef6fad18f2fb68ce4ea143265f585cf61691076f356316ce16cfead69beb2d", + "PivotTotalDifficulty": "25248307" }, "Metrics": { "NodeName": "JOC-Testnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json index 3a30f79acc4..40b55454e6b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 27130000, - "PivotHash": "0x01922d659e4fb8918d40febde2b9d26a71b2dec2f39b2b9ab90425628e33b442", + "PivotNumber": 27380000, + "PivotHash": "0x5e6870a0a2fc04bc795630ce13a9f3ecb91d33ebd86329d82ab9dfb9fba1e5db", "PivotTotalDifficulty": "0", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json index 8f427a8f31a..212ab068c23 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 22580000, - "PivotHash": "0x16c23c7588f52856a3422ea7e6b4052b9f0287017f01e05cda78f19a3c8f5a87", + "PivotNumber": 22880000, + "PivotHash": "0x8b327501ef7474ddc60f360f5d1ac9b635f950265d26d8ea58f1fa0b06aa6da9", "PivotTotalDifficulty": "37331807", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index 3d72b85c4ca..e36b29c1f84 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -10,8 +10,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 24106000, - "PivotHash": "0x2d2ac74ae7ca57ee08feef9e0cb6241f5c761e9408fa15fc0c9b944873a60895", + "PivotNumber": 24156000, + "PivotHash": "0xda6de49233e78a0aaf669fd880bd36aea98318e1cbccf0aeb3e5db464070ac30", "PivotTotalDifficulty": "58750003716598352816469", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 15537394, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index ae2bf0b44fd..941f4c478e6 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -15,8 +15,8 @@ "FastSyncCatchUpHeightDelta": 10000000000, "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, - "PivotNumber": 145630000, - "PivotHash": "0x8b3d9430308aa1586140f05826b351dc07b68205341bb4de9b0c0dd35765148b" + "PivotNumber": 145930000, + "PivotHash": "0x49b2334bc8fe69aaa9c1efdf5d32521e8eb55f770d57c22876bc5569cf929a25" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index dc37bc59914..deac9811813 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": 10000000000, - "PivotNumber": 37530000, - "PivotHash": "0x8db44f466e83096f4db5b65928ebddcc798200f510d26a41d4d10636582b0737" + "PivotNumber": 37830000, + "PivotHash": "0xf151fb33df6aa6acdf73b8043ba3d57483fe3e4ac48c56d5375535b063f9582f" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index 64769451266..b9d6b2620d4 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -17,8 +17,8 @@ "FastSync": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 9927000, - "PivotHash": "0x83b4469d7485dc6fde0be253ccc21b165d1eb5c76a4f7f0227c6d468730c5f27", + "PivotNumber": 9973000, + "PivotHash": "0x689761fe14abede25d4a22cec1b0fdc445b273a05f66635e1e2131632fffce77", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 1450409, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index 087836562d0..c838db016eb 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": 10000000000, - "PivotNumber": 23760000, - "PivotHash": "0x048798c8c100aa79c35588bf18358d90f340f8d9431b722de8e8d5c715e66dc3" + "PivotNumber": 24060000, + "PivotHash": "0xb20cd0979431e3a226ffab9ecfd5905b9d94093f07d43b234fd788cfab26d56d" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index b119d014b14..3b101034729 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": 10000000000, - "PivotNumber": 23150000, - "PivotHash": "0x9f91d2e4e3b632b3a5ef1ff64cbd691242f61cfaf30af7c4907ae54bc1a4cca8" + "PivotNumber": 23460000, + "PivotHash": "0xf633722e8fcceaa519564b79da80de4b7ed98d6ec455dad0cf0173cdc6389a21" }, "Discovery": { "DiscoveryVersion": "V5" From 2ae8737ec9acde9ab1df849762e55768c5dc3198 Mon Sep 17 00:00:00 2001 From: iPLAY888 <133153661+letmehateu@users.noreply.github.com> Date: Sun, 4 Jan 2026 14:06:20 +0300 Subject: [PATCH 159/255] fix: correct assertion variables in Cleans_invalid_blocks_before_starting test (#10086) Update BlockTreeTests.cs --- src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs index e873b4e5123..b697a2bf326 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs @@ -254,10 +254,10 @@ public void Cleans_invalid_blocks_before_starting() Assert.That(tree2.BestKnownNumber, Is.EqualTo(0L), "best known"); Assert.That(tree2.Head?.Number, Is.EqualTo(0), "head"); Assert.That(tree2.BestSuggestedHeader!.Number, Is.EqualTo(0L), "suggested"); - Assert.That(blockStore.Get(block2.Number, block2.Hash!), Is.Null, "block 1"); + Assert.That(blockStore.Get(block1.Number, block1.Hash!), Is.Null, "block 1"); Assert.That(blockStore.Get(block2.Number, block2.Hash!), Is.Null, "block 2"); Assert.That(blockStore.Get(block3.Number, block3.Hash!), Is.Null, "block 3"); - Assert.That(blockInfosDb.Get(2), Is.Null, "level 1"); + Assert.That(blockInfosDb.Get(1), Is.Null, "level 1"); Assert.That(blockInfosDb.Get(2), Is.Null, "level 2"); Assert.That(blockInfosDb.Get(3), Is.Null, "level 3"); } From 7ddb135f7489f60752a88cba76e2f431d6ff6940 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Sun, 4 Jan 2026 16:57:28 -0500 Subject: [PATCH 160/255] Drop eth66 and eth67 support, add eth69 as a default (#9938) * Drop eth66 and eth67 support * Fix tests * test * bump versions * Fix E2ESyncTests failures when isPostMerge=false - remove eth/69 from default capabilities (#10103) * Initial plan * Remove eth/69 from default capabilities - added dynamically by MergePlugin Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> * Fix test expecting eth/69 as highest default protocol version Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> * fix --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> --- .../Modules/Eth/EthRpcModuleTests.cs | 1 - .../P2P/P2PProtocolInfoProviderTests.cs | 2 +- .../ProtocolsManagerTests.cs | 14 +++++++------- .../Nethermind.Network/ProtocolsManager.cs | 2 -- .../FastSync/StateSyncFeedTestsBase.cs | 4 ++-- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index fa1030ce93a..8d75e4d3819 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -774,7 +774,6 @@ public async Task Eth_get_block_by_number_null() [Test] public async Task Eth_protocol_version() { - // TODO: test case when eth/69 is added dynamically using Context ctx = await Context.Create(); string serialized = await ctx.Test.TestEthRpc("eth_protocolVersion"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x44\",\"id\":67}")); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolInfoProviderTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolInfoProviderTests.cs index ddfc60643b0..354f992b048 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolInfoProviderTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolInfoProviderTests.cs @@ -14,7 +14,7 @@ public class P2PProtocolInfoProviderTests public void DefaultCapabilitiesToString_ReturnExpectedResult() { string result = P2PProtocolInfoProvider.DefaultCapabilitiesToString(); - Assert.That(result, Is.EqualTo("eth/68,eth/67,eth/66,nodedata/1")); + Assert.That(result, Is.EqualTo("eth/68,nodedata/1")); } } } diff --git a/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs b/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs index 9eba656ac38..19271cce2db 100644 --- a/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs @@ -219,7 +219,7 @@ public Context ReceiveStatus() msg.NetworkId = TestBlockchainIds.NetworkId; msg.GenesisHash = _blockTree.Genesis.Hash; msg.BestHash = _blockTree.Genesis.Hash; - msg.ProtocolVersion = 66; + msg.ProtocolVersion = 68; msg.ForkId = new ForkId(0, 0); return ReceiveStatus(msg); @@ -239,7 +239,7 @@ public Context VerifyEthInitialized() INodeStats stats = _nodeStatsManager.GetOrAdd(_currentSession.Node); Assert.That(stats.EthNodeDetails.NetworkId, Is.EqualTo(TestBlockchainIds.NetworkId)); Assert.That(stats.EthNodeDetails.GenesisHash, Is.EqualTo(_blockTree.Genesis.Hash)); - Assert.That(stats.EthNodeDetails.ProtocolVersion, Is.EqualTo(66)); + Assert.That(stats.EthNodeDetails.ProtocolVersion, Is.EqualTo(68)); Assert.That(stats.EthNodeDetails.TotalDifficulty, Is.EqualTo(BigInteger.One)); return this; } @@ -265,7 +265,7 @@ private Context ReceiveHello(HelloMessage msg) public Context ReceiveHello(byte p2pVersion = 5) { using HelloMessage msg = new(); - msg.Capabilities = new ArrayPoolList(1) { new("eth", 66) }; + msg.Capabilities = new ArrayPoolList(1) { new("eth", 68) }; msg.NodeId = TestItem.PublicKeyB; msg.ClientId = "other client v1"; msg.P2PVersion = p2pVersion; @@ -309,7 +309,7 @@ public Context ReceiveStatusWrongChain(ulong networkId) msg.NetworkId = networkId; msg.GenesisHash = TestItem.KeccakA; msg.BestHash = TestItem.KeccakA; - msg.ProtocolVersion = 66; + msg.ProtocolVersion = 68; return ReceiveStatus(msg); } @@ -321,7 +321,7 @@ public Context ReceiveStatusWrongGenesis() msg.NetworkId = TestBlockchainIds.NetworkId; msg.GenesisHash = TestItem.KeccakB; msg.BestHash = TestItem.KeccakB; - msg.ProtocolVersion = 66; + msg.ProtocolVersion = 68; return ReceiveStatus(msg); } @@ -474,7 +474,7 @@ public void Disconnects_on_wrong_genesis_hash() } [Test] - public void Initialized_with_eth66_only() + public void Initialized_with_eth68_only() { When .CreateIncomingSession() @@ -482,7 +482,7 @@ public void Initialized_with_eth66_only() .Handshake() .Init() .VerifyInitialized() - .ReceiveHelloEth(66) + .ReceiveHelloEth(68) .VerifyInitialized(); } diff --git a/src/Nethermind/Nethermind.Network/ProtocolsManager.cs b/src/Nethermind/Nethermind.Network/ProtocolsManager.cs index e0d7ccd228b..f1a0291cbde 100644 --- a/src/Nethermind/Nethermind.Network/ProtocolsManager.cs +++ b/src/Nethermind/Nethermind.Network/ProtocolsManager.cs @@ -41,8 +41,6 @@ public class ProtocolsManager : IProtocolsManager { public static readonly IEnumerable DefaultCapabilities = new Capability[] { - new(Protocol.Eth, 66), - new(Protocol.Eth, 67), new(Protocol.Eth, 68), new(Protocol.NodeData, 1) }; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs index 9a735cfe8bb..4e427df4f5e 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs @@ -81,7 +81,7 @@ protected IContainer PrepareDownloader(DbContext dbContext, Action { Node node = new Node(TestItem.PublicKeys[i], $"127.0.0.{i}", 30302, true) { - EthDetails = "eth66", + EthDetails = "eth68", }; SyncPeerMock mock = new SyncPeerMock(dbContext.RemoteStateDb, dbContext.RemoteCodeDb, node: node, maxRandomizedLatencyMs: defaultPeerMaxRandomLatency); mockMutator?.Invoke(mock); @@ -298,7 +298,7 @@ public SyncPeerMock( _codeDb = codeDb; _executorResultFunction = executorResultFunction; - Node = node ?? new Node(TestItem.PublicKeyA, "127.0.0.1", 30302, true) { EthDetails = "eth67" }; + Node = node ?? new Node(TestItem.PublicKeyA, "127.0.0.1", 30302, true) { EthDetails = "eth68" }; _maxRandomizedLatencyMs = maxRandomizedLatencyMs ?? 0; IStateReader alwaysAvailableRootTracker = Substitute.For(); From 18b62a14042336b653443adc955d793cbeb7905e Mon Sep 17 00:00:00 2001 From: Bashmunta Date: Mon, 5 Jan 2026 10:27:56 +0200 Subject: [PATCH 161/255] fix(network): shutdown rlpx executor group (#10087) --- src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs b/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs index 6e3e9af762b..e3795965fd0 100644 --- a/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs +++ b/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs @@ -168,7 +168,10 @@ public async Task Init() // Replacing to prevent double dispose which hangs var bossGroup = Interlocked.Exchange(ref _bossGroup, null); var workerGroup = Interlocked.Exchange(ref _workerGroup, null); - await Task.WhenAll(bossGroup?.ShutdownGracefullyAsync() ?? Task.CompletedTask, workerGroup?.ShutdownGracefullyAsync() ?? Task.CompletedTask); + await Task.WhenAll( + bossGroup?.ShutdownGracefullyAsync() ?? Task.CompletedTask, + workerGroup?.ShutdownGracefullyAsync() ?? Task.CompletedTask, + _group.ShutdownGracefullyAsync(_shutdownQuietPeriod, _shutdownCloseTimeout)); throw; } } @@ -289,7 +292,8 @@ public async Task Shutdown() Task closingTask = Task.WhenAll( _bossGroup is not null ? _bossGroup.ShutdownGracefullyAsync(_shutdownQuietPeriod, _shutdownCloseTimeout) : Task.CompletedTask, - _workerGroup is not null ? _workerGroup.ShutdownGracefullyAsync(_shutdownCloseTimeout, _shutdownCloseTimeout) : Task.CompletedTask); + _workerGroup is not null ? _workerGroup.ShutdownGracefullyAsync(_shutdownCloseTimeout, _shutdownCloseTimeout) : Task.CompletedTask, + _group.ShutdownGracefullyAsync(_shutdownQuietPeriod, _shutdownCloseTimeout)); // below comment may arise from not understanding the quiet period but the resolution is correct // we need to add additional timeout on our side as netty is not executing internal timeout properly, often it just hangs forever on closing From 0417aa401ad513d5f12c604d716b6be6eba00f83 Mon Sep 17 00:00:00 2001 From: Daniil Ankushin Date: Mon, 5 Jan 2026 14:08:51 +0400 Subject: [PATCH 162/255] feat (gas policy): add `ConsumeCodeCopyGas` method (#10068) --- .../Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs | 4 ++++ src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs | 11 +++++++++++ .../Instructions/EvmInstructions.CodeCopy.cs | 4 ++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs b/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs index d056b9cb965..d6c33db0e47 100644 --- a/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs +++ b/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs @@ -165,6 +165,10 @@ public static bool ConsumeLogEmission(ref EthereumGasPolicy gas, long topicCount return UpdateGas(ref gas, cost); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ConsumeDataCopyGas(ref EthereumGasPolicy gas, bool isExternalCode, long baseCost, long dataCost) + => UpdateGas(ref gas, baseCost + dataCost); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static EthereumGasPolicy Max(in EthereumGasPolicy a, in EthereumGasPolicy b) => a.Value >= b.Value ? a : b; diff --git a/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs b/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs index 40459a6200a..3277aa7ca42 100644 --- a/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs +++ b/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs @@ -205,4 +205,15 @@ static abstract bool UpdateMemoryCost(ref TSelf gas, /// The intrinsic gas to subtract. /// Available gas with preserved tracking data. static abstract TSelf CreateAvailableFromIntrinsic(long gasLimit, in TSelf intrinsicGas); + + /// + /// Consumes gas for code copy operations (CODECOPY, CALLDATACOPY, EXTCODECOPY, etc.). + /// Allows policies to categorize external code copy differently (state trie access). + /// + /// The gas state to update. + /// True for EXTCODECOPY (external account code). + /// Fixed opcode cost. + /// Per-word copy cost. + /// True if sufficient gas available. + static abstract bool ConsumeDataCopyGas(ref TSelf gas, bool isExternalCode, long baseCost, long dataCost); } diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs index 783f8d77039..658511bca8c 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.CodeCopy.cs @@ -68,7 +68,7 @@ public static EvmExceptionType InstructionCodeCopy( goto StackUnderflow; // Deduct gas cost: cost for external code access plus memory expansion cost. - TGasPolicy.Consume(ref gas, spec.GetExtCodeCost() + GasCostOf.Memory * EvmCalculations.Div32Ceiling(in result, out bool outOfGas)); + TGasPolicy.ConsumeDataCopyGas(ref gas, isExternalCode: true, spec.GetExtCodeCost(), GasCostOf.Memory * EvmCalculations.Div32Ceiling(in result, out bool outOfGas)); if (outOfGas) goto OutOfGas; // Charge gas for account access (considering hot/cold storage costs). From f2217da35c9184785f6f64be812f05ddc6c9716b Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Mon, 5 Jan 2026 06:54:24 -0500 Subject: [PATCH 163/255] Add Address recovery from PublicKey to KeccakCache (#10003) * Add Address recovery from PublicKey to KeccakCache * Improve comments * Feedback --- .../Nethermind.Core/Crypto/KeccakCache.cs | 18 ++++++++++++------ .../Nethermind.Core/Crypto/PublicKey.cs | 2 +- .../EcRecoverPrecompile.cs | 4 ++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Crypto/KeccakCache.cs b/src/Nethermind/Nethermind.Core/Crypto/KeccakCache.cs index 8574ebd169f..675bc8756ec 100644 --- a/src/Nethermind/Nethermind.Core/Crypto/KeccakCache.cs +++ b/src/Nethermind/Nethermind.Core/Crypto/KeccakCache.cs @@ -7,6 +7,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; using System.Threading; using Nethermind.Core.Extensions; @@ -15,7 +16,7 @@ namespace Nethermind.Core.Crypto; /// /// This is a minimalistic one-way set associative cache for Keccak values. /// -/// It allocates only 12MB of memory to store 128k of entries. +/// It allocates only 16MB of memory to store 128k of entries. /// No misaligned reads. Everything is aligned to both cache lines as well as to boundaries so no torn reads. /// Requires a single CAS to lock and to unlock. /// On a lock failure, it just moves on with execution. @@ -34,7 +35,7 @@ public static unsafe class KeccakCache private const int InputLengthOfKeccak = ValueHash256.MemorySize; private const int InputLengthOfAddress = Address.Size; - + private const int CacheLineSizeBytes = 64; private static readonly Entry* Memory; static KeccakCache() @@ -69,8 +70,14 @@ public static void ComputeTo(ReadOnlySpan input, out ValueHash256 keccak25 Debug.Assert(index < Count); ref Entry e = ref Unsafe.Add(ref Unsafe.AsRef(Memory), index); + if (Sse.IsSupported) + { + // This would be a GC hole if was managed memory, but it's native. + // Regardless, prefetch is non-faulting so it's safe. + Sse.PrefetchNonTemporal((byte*)Unsafe.AsPointer(ref e) + CacheLineSizeBytes); + } - // Half the hash his encoded in the bucket so we only need half of it and can use other half for length. + // Half the hash is encoded in the bucket so we only need half of it and can use other half for length. // This allows to create a combined value that represents a part of the hash, the input's length and the lock marker. uint combined = (HashMask & (uint)hashCode) | (uint)input.Length; @@ -174,10 +181,9 @@ public static void ComputeTo(ReadOnlySpan input, out ValueHash256 keccak25 private struct Entry { /// - /// The size will make it 1.5 CPU cache entry or 0.75 which may result in some collisions. - /// Still, it's better to save these 32 bytes per entry and have a bigger cache. + /// The size will make it 2 CPU cache entries. /// - public const int Size = 96; + public const int Size = 128; private const int PayloadStart = sizeof(uint); private const int ValueStart = Size - ValueHash256.MemorySize; diff --git a/src/Nethermind/Nethermind.Core/Crypto/PublicKey.cs b/src/Nethermind/Nethermind.Core/Crypto/PublicKey.cs index b176616eb2b..d6bcbc9cb64 100644 --- a/src/Nethermind/Nethermind.Core/Crypto/PublicKey.cs +++ b/src/Nethermind/Nethermind.Core/Crypto/PublicKey.cs @@ -76,7 +76,7 @@ public Hash256 Hash public static Address ComputeAddress(ReadOnlySpan publicKeyBytes) { - Span hash = ValueKeccak.Compute(publicKeyBytes).BytesAsSpan; + Span hash = KeccakCache.Compute(publicKeyBytes).BytesAsSpan; return new Address(hash[12..].ToArray()); } diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs index bf05bb4b396..ba809cc8a67 100644 --- a/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs @@ -72,10 +72,10 @@ private Result RunInternal(ReadOnlySpan inputDataSpan) } byte[] result = new byte[32]; - KeccakHash.ComputeHashBytesToSpan(publicKey.Slice(1, 64), result); - ref byte refResult = ref MemoryMarshal.GetArrayDataReference(result); + KeccakCache.ComputeTo(publicKey.Slice(1, 64), out Unsafe.As(ref refResult)); + // Clear first 12 bytes, as address is last 20 bytes of the hash Unsafe.InitBlockUnaligned(ref refResult, 0, 12); return result; From 4d7e0b3d20ba5394f43768bbf8531e0487c144a0 Mon Sep 17 00:00:00 2001 From: SashaMalysehko Date: Mon, 5 Jan 2026 15:16:39 +0200 Subject: [PATCH 164/255] refactor: remove unused Destroy change type from storage provider (#10106) --- .../Nethermind.State/PartialStorageProviderBase.cs | 1 - .../Nethermind.State/PersistentStorageProvider.cs | 6 ------ 2 files changed, 7 deletions(-) diff --git a/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs b/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs index a37cc2c3aed..0c8d1a3ad47 100644 --- a/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs +++ b/src/Nethermind/Nethermind.State/PartialStorageProviderBase.cs @@ -270,7 +270,6 @@ protected enum ChangeType Null = 0, JustCache, Update, - Destroy, } } } diff --git a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs index 2437a37db43..1f6c4af48de 100644 --- a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs +++ b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs @@ -171,12 +171,6 @@ protected override void CommitCore(IStorageTracer tracer) } _committedThisRound.Add(change.StorageCell); - - if (change.ChangeType == ChangeType.Destroy) - { - continue; - } - int forAssertion = _intraBlockCache[change.StorageCell].Pop(); if (forAssertion != currentPosition - i) { From 519aa4cf2cc5c59d6dbfe10cb642deaf29b581c7 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Mon, 5 Jan 2026 08:19:16 -0500 Subject: [PATCH 165/255] Update to UInt256 version 1.4.0 (#10107) * Update to UInt256 version 1.4.0 * Fix some div zero --- Directory.Packages.props | 4 +-- .../Nethermind.Core/BaseFeeCalculator.cs | 14 +++++----- .../Nethermind.Evm/BlobGasCalculator.cs | 4 +-- .../Nethermind.Optimism/OptimismCostHelper.cs | 18 +++++++------ .../Nethermind.Runner/packages.lock.json | 8 +++--- .../Rpc/SurgeGasPriceOracle.cs | 13 ++++++--- .../Nethermind.Taiko/TaikoHeaderValidator.cs | 27 ++++++++++++++----- 7 files changed, 57 insertions(+), 31 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 45b3f496737..065d95f8a88 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -59,7 +59,7 @@ - + @@ -89,4 +89,4 @@ - \ No newline at end of file + diff --git a/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs b/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs index 42b25af8cb7..6987630b47f 100644 --- a/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs +++ b/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs @@ -22,8 +22,6 @@ public UInt256 Calculate(BlockHeader parent, IEip1559Spec specFor1559) if (specFor1559.IsEip1559Enabled) { UInt256 parentBaseFee = parent.BaseFeePerGas; - long gasDelta; - UInt256 feeDelta; bool isForkBlockNumber = specFor1559.Eip1559TransitionBlock == parent.Number + 1; long parentGasTarget = parent.GasLimit / specFor1559.ElasticityMultiplier; if (isForkBlockNumber) @@ -33,18 +31,22 @@ public UInt256 Calculate(BlockHeader parent, IEip1559Spec specFor1559) { expectedBaseFee = parent.BaseFeePerGas; } + else if (parentGasTarget == 0 || specFor1559.BaseFeeMaxChangeDenominator.IsZero) + { + expectedBaseFee = parentBaseFee; + } else if (parent.GasUsed > parentGasTarget) { - gasDelta = parent.GasUsed - parentGasTarget; - feeDelta = UInt256.Max( + long gasDelta = parent.GasUsed - parentGasTarget; + UInt256 feeDelta = UInt256.Max( parentBaseFee * (UInt256)gasDelta / (UInt256)parentGasTarget / specFor1559.BaseFeeMaxChangeDenominator, UInt256.One); expectedBaseFee = parentBaseFee + feeDelta; } else { - gasDelta = parentGasTarget - parent.GasUsed; - feeDelta = parentBaseFee * (UInt256)gasDelta / (UInt256)parentGasTarget / specFor1559.BaseFeeMaxChangeDenominator; + long gasDelta = parentGasTarget - parent.GasUsed; + UInt256 feeDelta = parentBaseFee * (UInt256)gasDelta / (UInt256)parentGasTarget / specFor1559.BaseFeeMaxChangeDenominator; expectedBaseFee = UInt256.Max(parentBaseFee - feeDelta, 0); } diff --git a/src/Nethermind/Nethermind.Evm/BlobGasCalculator.cs b/src/Nethermind/Nethermind.Evm/BlobGasCalculator.cs index 7dbe87e1de8..4c3b4d6f5b1 100644 --- a/src/Nethermind/Nethermind.Evm/BlobGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/BlobGasCalculator.cs @@ -83,10 +83,10 @@ static bool FakeExponentialOverflow(UInt256 factor, UInt256 num, UInt256 denomin return true; } - accumulator = updatedAccumulator / multipliedDenominator; + accumulator = multipliedDenominator.IsZero ? default : updatedAccumulator / multipliedDenominator; } - feePerBlobGas = output / denominator; + feePerBlobGas = denominator.IsZero ? default : output / denominator; return false; } diff --git a/src/Nethermind/Nethermind.Optimism/OptimismCostHelper.cs b/src/Nethermind/Nethermind.Optimism/OptimismCostHelper.cs index 998fc542353..8d2ff036328 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismCostHelper.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismCostHelper.cs @@ -162,10 +162,12 @@ public UInt256 ComputeDaFootprint(Block block) continue; UInt256 flzLen = L1CostFastlzCoef * ComputeFlzCompressLen(tx); - UInt256 daUsageEstimate = UInt256.Max( - MinTransactionSizeScaled, - flzLen > L1CostInterceptNeg ? flzLen - L1CostInterceptNeg : 0 // avoid uint underflow - ) / DaFootprintScale; + UInt256 daUsageEstimate = DaFootprintScale.IsZero ? + default : + UInt256.Max( + MinTransactionSizeScaled, + flzLen > L1CostInterceptNeg ? flzLen - L1CostInterceptNeg : 0 // avoid uint underflow + ) / DaFootprintScale; footprint += daUsageEstimate * daFootprintScalar; } @@ -205,19 +207,19 @@ public static UInt256 ComputeL1CostFjord(UInt256 fastLzSize, UInt256 l1BaseFee, } estimatedSize = UInt256.Max(MinTransactionSizeScaled, fastLzCost); - return estimatedSize * l1FeeScaled / FjordDivisor; + return FjordDivisor.IsZero ? default : estimatedSize * l1FeeScaled / FjordDivisor; } // Ecotone formula: (dataGas) * (16 * l1BaseFee * l1BaseFeeScalar + l1BlobBaseFee*l1BlobBaseFeeScalar) / 16e6 public static UInt256 ComputeL1CostEcotone(UInt256 dataGas, UInt256 l1BaseFee, UInt256 blobBaseFee, UInt256 l1BaseFeeScalar, UInt256 l1BlobBaseFeeScalar) { - return dataGas * (PrecisionMultiplier * l1BaseFee * l1BaseFeeScalar + blobBaseFee * l1BlobBaseFeeScalar) / PrecisionDivisor; + return PrecisionDivisor.IsZero ? default : dataGas * (PrecisionMultiplier * l1BaseFee * l1BaseFeeScalar + blobBaseFee * l1BlobBaseFeeScalar) / PrecisionDivisor; } // Pre-Ecotone formula: (dataGas + overhead) * l1BaseFee * scalar / 1e6 public static UInt256 ComputeL1CostPreEcotone(UInt256 dataGasWithOverhead, UInt256 l1BaseFee, UInt256 feeScalar) { - return dataGasWithOverhead * l1BaseFee * feeScalar / BasicDivisor; + return BasicDivisor.IsZero ? default : dataGasWithOverhead * l1BaseFee * feeScalar / BasicDivisor; } // Based on: @@ -321,7 +323,7 @@ uint setNextHash(uint ip, ref Span ht) return FlzCompressLen(encoded); } - internal static UInt256 ComputeGasUsedFjord(UInt256 estimatedSize) => estimatedSize * GasCostOf.TxDataNonZeroEip2028 / BasicDivisor; + internal static UInt256 ComputeGasUsedFjord(UInt256 estimatedSize) => BasicDivisor.IsZero ? default : estimatedSize * GasCostOf.TxDataNonZeroEip2028 / BasicDivisor; // https://specs.optimism.io/protocol/jovian/exec-engine.html#scalar-loading // https://specs.optimism.io/protocol/jovian/l1-attributes.html diff --git a/src/Nethermind/Nethermind.Runner/packages.lock.json b/src/Nethermind/Nethermind.Runner/packages.lock.json index 333be533d51..7f71a26adc3 100644 --- a/src/Nethermind/Nethermind.Runner/packages.lock.json +++ b/src/Nethermind/Nethermind.Runner/packages.lock.json @@ -722,7 +722,7 @@ "Microsoft.IdentityModel.JsonWebTokens": "[8.15.0, )", "Nethermind.Crypto.SecP256k1": "[1.5.0, )", "Nethermind.Logging": "[1.37.0-unstable, )", - "Nethermind.Numerics.Int256": "[1.3.6, )", + "Nethermind.Numerics.Int256": "[1.4.0, )", "NonBlocking": "[2.1.2, )", "TestableIO.System.IO.Abstractions.Wrappers": "[22.1.0, )" } @@ -1489,9 +1489,9 @@ }, "Nethermind.Numerics.Int256": { "type": "CentralTransitive", - "requested": "[1.3.6, )", - "resolved": "1.3.6", - "contentHash": "Sk/CakMkQZuCUflJxYlj9gVTfxbTPJKsgDS5fsRWdzYA6hHVQipNJfyD6xnrF3u1X6XJadeyTTa3Rs80hJCMvQ==" + "requested": "[1.4.0, )", + "resolved": "1.4.0", + "contentHash": "w8HRMsdpX9fG9kcELJeJPEKIZgOUTCe47ebtejCvfBYQVlabA9blqba6QWIt5oG8cRSgnVlQ24DsdGsLzqFM+Q==" }, "Nito.Collections.Deque": { "type": "CentralTransitive", diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/SurgeGasPriceOracle.cs b/src/Nethermind/Nethermind.Taiko/Rpc/SurgeGasPriceOracle.cs index 691a1123374..00319c63307 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/SurgeGasPriceOracle.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/SurgeGasPriceOracle.cs @@ -110,9 +110,16 @@ public override async ValueTask GetGasPriceEstimate() Math.Max(averageGasUsage, _surgeConfig.L2GasPerL2Batch); // Adjust the gas price estimate with the config values. - UInt256 adjustedGasPriceEstimate = gasPriceEstimate + gasPriceEstimate * (UInt256)_surgeConfig.BoostBaseFeePercentage / 100; - adjustedGasPriceEstimate = adjustedGasPriceEstimate * 100 / (UInt256)_surgeConfig.SharingPercentage; - + UInt256 adjustedGasPriceEstimate; + if (_surgeConfig.SharingPercentage == 0) + { + adjustedGasPriceEstimate = default; + } + else + { + adjustedGasPriceEstimate = gasPriceEstimate + gasPriceEstimate * (UInt256)_surgeConfig.BoostBaseFeePercentage / 100; + adjustedGasPriceEstimate = adjustedGasPriceEstimate * 100 / (UInt256)_surgeConfig.SharingPercentage; + } // Update the cache and timestamp _gasPriceEstimation.Set(headBlockHash, adjustedGasPriceEstimate); _lastGasPriceCalculation = DateTime.UtcNow; diff --git a/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs b/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs index abbc1d4648c..b26cdbb1ff8 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs @@ -143,13 +143,20 @@ private static UInt256 CalculateEip4396BaseFee(BlockHeader parent, ulong parentB { // If the parent block used more gas than its target, the baseFee should increase // max(1, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator) - UInt256 gasUsedDelta = (ulong)parent.GasUsed - parentAdjustedGasTarget; - UInt256 feeDelta = parent.BaseFeePerGas * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator; - - if (feeDelta < 1) + UInt256 feeDelta; + if (parentGasTarget == 0 || baseFeeChangeDenominator.IsZero) { feeDelta = 1; } + else + { + UInt256 gasUsedDelta = (ulong)parent.GasUsed - parentAdjustedGasTarget; + feeDelta = parent.BaseFeePerGas * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator; + if (feeDelta < 1) + { + feeDelta = 1; + } + } baseFee = parent.BaseFeePerGas + feeDelta; } @@ -157,8 +164,16 @@ private static UInt256 CalculateEip4396BaseFee(BlockHeader parent, ulong parentB { // Otherwise if the parent block used less gas than its target, the baseFee should decrease // max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator) - UInt256 gasUsedDelta = parentAdjustedGasTarget - (ulong)parent.GasUsed; - UInt256 feeDelta = parent.BaseFeePerGas * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator; + UInt256 feeDelta; + if (parentGasTarget == 0 || baseFeeChangeDenominator.IsZero) + { + feeDelta = 0; + } + else + { + UInt256 gasUsedDelta = parentAdjustedGasTarget - (ulong)parent.GasUsed; + feeDelta = parent.BaseFeePerGas * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator; + } baseFee = parent.BaseFeePerGas > feeDelta ? parent.BaseFeePerGas - feeDelta : UInt256.Zero; } From 62f723093db7e4dca14f6b6689fe2c6219f0606a Mon Sep 17 00:00:00 2001 From: kurahin Date: Mon, 5 Jan 2026 15:20:59 +0200 Subject: [PATCH 166/255] chore: remove debug-only keccak keys from proof call storage test (#10104) --- .../Modules/Proof/ProofRpcModuleTests.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs index 24c3e30e824..bb6296d4993 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs @@ -843,19 +843,6 @@ private async Task TestCallWithStorageAndCode(byte[] code, UInt256 gasPrice, Add CallResultWithProof callResultWithProof = _proofRpcModule.proof_call(tx, new BlockParameter(blockOnTop.Number)).Data; Assert.That(callResultWithProof.Accounts.Length, Is.GreaterThan(0)); - // just the keys for debugging - byte[] span = new byte[32]; - new UInt256(0).ToBigEndian(span); - _ = Keccak.Compute(span); - - // just the keys for debugging - new UInt256(1).ToBigEndian(span); - _ = Keccak.Compute(span); - - // just the keys for debugging - new UInt256(2).ToBigEndian(span); - _ = Keccak.Compute(span); - foreach (AccountProof accountProof in callResultWithProof.Accounts) { // this is here for diagnostics - so you can read what happens in the test From ab9414e49651e5ec26ccc5ca656362f397abb6da Mon Sep 17 00:00:00 2001 From: Ragnar Date: Mon, 5 Jan 2026 15:37:34 +0200 Subject: [PATCH 167/255] fix: use parameter name in BloomStorage null check (#10096) --- src/Nethermind/Nethermind.Db/Blooms/BloomStorage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Db/Blooms/BloomStorage.cs b/src/Nethermind/Nethermind.Db/Blooms/BloomStorage.cs index 50fffb6da71..f21903dabf7 100644 --- a/src/Nethermind/Nethermind.Db/Blooms/BloomStorage.cs +++ b/src/Nethermind/Nethermind.Db/Blooms/BloomStorage.cs @@ -68,7 +68,7 @@ public BloomStorage(IBloomConfig config, [KeyFilter(DbNames.Bloom)] IDb bloomDb, long Get(Hash256 key, long defaultValue) => bloomDb.Get(key)?.ToLongFromBigEndianByteArrayWithoutLeadingZeros() ?? defaultValue; _config = config ?? throw new ArgumentNullException(nameof(config)); - _bloomInfoDb = bloomDb ?? throw new ArgumentNullException(nameof(_bloomInfoDb)); + _bloomInfoDb = bloomDb ?? throw new ArgumentNullException(nameof(bloomDb)); _fileStoreFactory = fileStoreFactory; _storageLevels = CreateStorageLevels(config); Levels = (byte)_storageLevels.Length; From 1e80301c24f89d3fa7bf82b4cc0af26fd3cdd61f Mon Sep 17 00:00:00 2001 From: Desant pivo Date: Mon, 5 Jan 2026 14:37:48 +0100 Subject: [PATCH 168/255] fix: correct ExampleResponse for admin_importHistory method (#10097) Update IEraAdminRpcModule.cs --- src/Nethermind/Nethermind.Era1/JsonRpc/IEraAdminRpcModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Era1/JsonRpc/IEraAdminRpcModule.cs b/src/Nethermind/Nethermind.Era1/JsonRpc/IEraAdminRpcModule.cs index c1591be7fe7..ebb021f0ef3 100644 --- a/src/Nethermind/Nethermind.Era1/JsonRpc/IEraAdminRpcModule.cs +++ b/src/Nethermind/Nethermind.Era1/JsonRpc/IEraAdminRpcModule.cs @@ -24,7 +24,7 @@ int to [JsonRpcMethod(Description = "Import a range of historic block from era1 directory.", EdgeCaseHint = "", - ExampleResponse = "\"Export task started.\"", + ExampleResponse = "\"Import task started.\"", IsImplemented = true)] Task> admin_importHistory( [JsonRpcParameter(Description = "Source path to import from.", ExampleValue = "/tmp/eradir")] From 0e8ec6e4dd65027e8dc9ee29c64e6e4a37e8b186 Mon Sep 17 00:00:00 2001 From: iPLAY888 <133153661+letmehateu@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:38:05 +0300 Subject: [PATCH 169/255] fix: remove redundant blockInfosDb assertions (#10099) Update BlockTreeTests.cs --- src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs index b697a2bf326..3d327872c84 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs @@ -1050,10 +1050,6 @@ public void When_deleting_invalid_block_deletes_its_descendants_even_if_not_firs Assert.That(blockInfosDb.Get(2), Is.Not.Null, "level 2"); Assert.That(blockInfosDb.Get(3), Is.Not.Null, "level 3"); - Assert.That(blockInfosDb.Get(1), Is.Not.Null, "level 1b"); - Assert.That(blockInfosDb.Get(2), Is.Not.Null, "level 2b"); - Assert.That(blockInfosDb.Get(3), Is.Not.Null, "level 3b"); - repository.LoadLevel(1)!.BlockInfos.Length.Should().Be(1); repository.LoadLevel(2)!.BlockInfos.Length.Should().Be(1); repository.LoadLevel(3)!.BlockInfos.Length.Should().Be(1); From 7514d24f64adeb5ad03893aa531b58c70d6e8225 Mon Sep 17 00:00:00 2001 From: Desant pivo Date: Mon, 5 Jan 2026 14:39:08 +0100 Subject: [PATCH 170/255] perf: reuse SimpleConsoleLogger instance in SimpleConsoleLogManager (#10070) Update SimpleConsoleLogManager.cs --- .../Nethermind.Logging/SimpleConsoleLogManager.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Logging/SimpleConsoleLogManager.cs b/src/Nethermind/Nethermind.Logging/SimpleConsoleLogManager.cs index db87f13ec7b..7409d29e114 100644 --- a/src/Nethermind/Nethermind.Logging/SimpleConsoleLogManager.cs +++ b/src/Nethermind/Nethermind.Logging/SimpleConsoleLogManager.cs @@ -8,21 +8,23 @@ namespace Nethermind.Logging { public class SimpleConsoleLogManager(LogLevel logLevel = LogLevel.Trace, string dateFormat = "yyyy-MM-dd HH-mm-ss.ffff|") : ILogManager { + private readonly SimpleConsoleLogger _logger = new(logLevel, dateFormat); + public static ILogManager Instance { get; } = new SimpleConsoleLogManager(); public ILogger GetClassLogger() { - return new(new SimpleConsoleLogger(logLevel, dateFormat)); + return new(_logger); } public ILogger GetClassLogger([CallerFilePath] string filePath = "") { - return new(new SimpleConsoleLogger(logLevel, dateFormat)); + return new(_logger); } public ILogger GetLogger(string loggerName) { - return new(new SimpleConsoleLogger(logLevel, dateFormat)); + return new(_logger); } } } From c748ed263e4e3e0b03946e54c739085baa6d07ff Mon Sep 17 00:00:00 2001 From: cui Date: Mon, 5 Jan 2026 22:10:10 +0800 Subject: [PATCH 171/255] optimize eth_gasPrice using kth algorithm (#10100) * optimize eth_gasPrice using kth algorithm * fix: review nethermind --------- Co-authored-by: weixie.cui --- .../Modules/GasPriceOracleTests.cs | 78 ++++++++++++++++--- .../Modules/Eth/GasPrice/GasPriceOracle.cs | 77 ++++++++++++++++-- 2 files changed, 141 insertions(+), 14 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GasPriceOracleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GasPriceOracleTests.cs index bf3fef65b98..ad5623d7f90 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GasPriceOracleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GasPriceOracleTests.cs @@ -24,6 +24,66 @@ namespace Nethermind.JsonRpc.Test.Modules [TestFixture] public class GasPriceOracleTests { + [TestCaseSource(nameof(SelectKthSmallestInPlace_Cases))] + public void SelectKthSmallestInPlace_ReturnsCorrectKthElement(uint[] values, int k) + { + List list = values.Select(static v => (UInt256)v).ToList(); + UInt256 expected = values.OrderBy(static v => v).Select(static v => (UInt256)v).ElementAt(k); + + UInt256 result = GasPriceOracle.SelectKthSmallestInPlace(list, k); + + result.Should().Be(expected); + list.Should().HaveCount(values.Length); + list.Should().BeEquivalentTo(values.Select(static v => (UInt256)v)); // ensures mutation doesn't lose/duplicate items + } + + [TestCaseSource(nameof(SelectKthSmallestInPlace_InvalidKCases))] + public void SelectKthSmallestInPlace_InvalidK_Throws(uint[] values, int k) + { + List list = values.Select(static v => (UInt256)v).ToList(); + + Action act = () => GasPriceOracle.SelectKthSmallestInPlace(list, k); + + act.Should().Throw(); + } + + private static IEnumerable SelectKthSmallestInPlace_Cases() + { + // single element + yield return new TestCaseData(new uint[] { 7 }, 0).SetName("SelectKthSmallestInPlace_SingleElement_k0"); + + // two elements + yield return new TestCaseData(new uint[] { 2, 1 }, 0).SetName("SelectKthSmallestInPlace_TwoElements_k0"); + yield return new TestCaseData(new uint[] { 2, 1 }, 1).SetName("SelectKthSmallestInPlace_TwoElements_kLast"); + + // already sorted + yield return new TestCaseData(new uint[] { 1, 2, 3, 4, 5 }, 0).SetName("SelectKthSmallestInPlace_Sorted_k0"); + yield return new TestCaseData(new uint[] { 1, 2, 3, 4, 5 }, 4).SetName("SelectKthSmallestInPlace_Sorted_kLast"); + yield return new TestCaseData(new uint[] { 1, 2, 3, 4, 5 }, 2).SetName("SelectKthSmallestInPlace_Sorted_kMid"); + + // reverse sorted (forces lots of swaps) + yield return new TestCaseData(new uint[] { 5, 4, 3, 2, 1 }, 0).SetName("SelectKthSmallestInPlace_Reverse_k0"); + yield return new TestCaseData(new uint[] { 5, 4, 3, 2, 1 }, 4).SetName("SelectKthSmallestInPlace_Reverse_kLast"); + yield return new TestCaseData(new uint[] { 5, 4, 3, 2, 1 }, 2).SetName("SelectKthSmallestInPlace_Reverse_kMid"); + + // duplicates (partition uses < pivot, so equal elements are a good edge case) + yield return new TestCaseData(new uint[] { 7, 7, 7, 7 }, 0).SetName("SelectKthSmallestInPlace_AllEqual_k0"); + yield return new TestCaseData(new uint[] { 7, 7, 7, 7 }, 3).SetName("SelectKthSmallestInPlace_AllEqual_kLast"); + yield return new TestCaseData(new uint[] { 5, 1, 5, 3, 5, 2 }, 2).SetName("SelectKthSmallestInPlace_Duplicates_kMid"); + + // pivot-in-the-middle style layouts (median-of-range pivot) + yield return new TestCaseData(new uint[] { 9, 1, 8, 2, 7, 3, 6, 4, 5 }, 4).SetName("SelectKthSmallestInPlace_ZigZag_kMid"); + yield return new TestCaseData(new uint[] { 100, 1, 50, 2, 49, 3, 48, 4 }, 3).SetName("SelectKthSmallestInPlace_ZigZagEven_kMid"); + } + + private static IEnumerable SelectKthSmallestInPlace_InvalidKCases() + { + yield return new TestCaseData(Array.Empty(), 0).SetName("SelectKthSmallestInPlace_Empty_Throws"); + yield return new TestCaseData(new uint[] { 1 }, -1).SetName("SelectKthSmallestInPlace_kNegative_Throws"); + yield return new TestCaseData(new uint[] { 1 }, 1).SetName("SelectKthSmallestInPlace_kEqualsCount_Throws"); + yield return new TestCaseData(new uint[] { 1, 2 }, 2).SetName("SelectKthSmallestInPlace_kGreaterThanLast_Throws"); + } + [Test] public async ValueTask GasPriceEstimate_NoChangeInHeadBlock_ReturnsPreviousGasPrice() { @@ -192,7 +252,7 @@ public void GetGasPricesFromRecentBlocks_IfBlockHasMoreThanThreeValidTx_AddOnlyT blockFinder.FindBlock(0).Returns(headBlock); GasPriceOracle testGasPriceOracle = new(blockFinder, Substitute.For(), LimboLogs.Instance); - IEnumerable results = testGasPriceOracle.GetSortedGasPricesFromRecentBlocks(0); + IEnumerable results = testGasPriceOracle.GetGasPricesFromRecentBlocks(0); results.Count().Should().Be(3); } @@ -206,7 +266,7 @@ public void GetGasPricesFromRecentBlocks_IfBlockHasMoreThanThreeValidTxs_OnlyAdd GasPriceOracle testGasPriceOracle = new(blockFinder, Substitute.For(), LimboLogs.Instance); List expected = new() { 2, 3, 4 }; - IEnumerable results = testGasPriceOracle.GetSortedGasPricesFromRecentBlocks(0); + IEnumerable results = testGasPriceOracle.GetGasPricesFromRecentBlocks(0); results.Should().BeEquivalentTo(expected); } @@ -240,7 +300,7 @@ public void GetGasPricesFromRecentBlocks_TxsSentByMiner_ShouldNotHaveGasPriceInT GasPriceOracle gasPriceOracle = new(blockFinder, Substitute.For(), LimboLogs.Instance); List expected = new() { 8, 9 }; - IEnumerable results = gasPriceOracle.GetSortedGasPricesFromRecentBlocks(0); + IEnumerable results = gasPriceOracle.GetGasPricesFromRecentBlocks(0); results.Should().BeEquivalentTo(expected); } @@ -258,7 +318,7 @@ public void AddValidTxAndReturnCount_GivenEip1559Txs_EffectiveGasPriceProperlyCa blockFinder.FindBlock(0).Returns(eip1559Block); GasPriceOracle gasPriceOracle = new(blockFinder, GetSpecProviderWithEip1559EnabledAs(eip1559Enabled), LimboLogs.Instance); - IEnumerable results = gasPriceOracle.GetSortedGasPricesFromRecentBlocks(0); + IEnumerable results = gasPriceOracle.GetGasPricesFromRecentBlocks(0); List expectedList = expected.Select(static n => (UInt256)n).ToList(); results.Should().BeEquivalentTo(expectedList); @@ -278,7 +338,7 @@ public void AddValidTxAndReturnCount_GivenNonEip1559Txs_EffectiveGasPriceProperl blockFinder.FindBlock(0).Returns(nonEip1559Block); GasPriceOracle gasPriceOracle = new(blockFinder, GetSpecProviderWithEip1559EnabledAs(eip1559Enabled), LimboLogs.Instance); - IEnumerable results = gasPriceOracle.GetSortedGasPricesFromRecentBlocks(0); + IEnumerable results = gasPriceOracle.GetGasPricesFromRecentBlocks(0); List expectedList = expected.Select(static n => (UInt256)n).ToList(); results.Should().BeEquivalentTo(expectedList); @@ -302,7 +362,7 @@ public void GetGasPricesFromRecentBlocks_IfNoValidTxsInABlock_DefaultPriceAddedT GasPriceOracle gasPriceOracle = new(blockFinder, Substitute.For(), LimboLogs.Instance) { _gasPriceEstimation = new(null, 7) }; List expected = new() { 7 }; - IEnumerable results = gasPriceOracle.GetSortedGasPricesFromRecentBlocks(0); + IEnumerable results = gasPriceOracle.GetGasPricesFromRecentBlocks(0); results.ToList().Should().BeEquivalentTo(expected); } @@ -317,7 +377,7 @@ public void AddValidTxAndReturnCount_IfNoTxsInABlock_DefaultPriceAddedToListInst GasPriceOracle gasPriceOracle = new(blockFinder, Substitute.For(), LimboLogs.Instance) { _gasPriceEstimation = new(null, 7) }; List expected = new() { 7 }; - IEnumerable results = gasPriceOracle.GetSortedGasPricesFromRecentBlocks(0); + IEnumerable results = gasPriceOracle.GetGasPricesFromRecentBlocks(0); results.ToList().Should().BeEquivalentTo(expected); } @@ -337,7 +397,7 @@ public void AddValidTxAndReturnCount_Eip1559NotEnabled_EffectiveGasPricesShouldB GasPriceOracle gasPriceOracle = new(blockFinder, GetSpecProviderWithEip1559EnabledAs(false), LimboLogs.Instance); List expected = new() { 2, 3 }; - IEnumerable results = gasPriceOracle.GetSortedGasPricesFromRecentBlocks(0); + IEnumerable results = gasPriceOracle.GetGasPricesFromRecentBlocks(0); results.Should().BeEquivalentTo(expected); } @@ -357,7 +417,7 @@ public void AddValidTxAndReturnCount_Eip1559Enabled_EffectiveGasPricesShouldBeMo GasPriceOracle gasPriceOracle = new(blockFinder, GetSpecProviderWithEip1559EnabledAs(true), LimboLogs.Instance); List expected = new() { 3, 4 }; - IEnumerable results = gasPriceOracle.GetSortedGasPricesFromRecentBlocks(0); + IEnumerable results = gasPriceOracle.GetGasPricesFromRecentBlocks(0); results.Should().BeEquivalentTo(expected); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/GasPrice/GasPriceOracle.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/GasPrice/GasPriceOracle.cs index 5dba25f2d09..ff517e18c4f 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/GasPrice/GasPriceOracle.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/GasPrice/GasPriceOracle.cs @@ -17,6 +17,8 @@ namespace Nethermind.JsonRpc.Modules.Eth.GasPrice { public class GasPriceOracle : IGasPriceOracle { + private static readonly IComparer UInt256Comparer = Comparer.Default; + protected readonly IBlockFinder _blockFinder; protected readonly ILogger _logger; protected readonly UInt256 _minGasPrice; @@ -55,14 +57,14 @@ public virtual ValueTask GetGasPriceEstimate() return ValueTask.FromResult(price!.Value); } - IEnumerable txGasPrices = GetSortedGasPricesFromRecentBlocks(headBlock.Number); + IEnumerable txGasPrices = GetGasPricesFromRecentBlocks(headBlock.Number); UInt256 gasPriceEstimate = GetGasPriceAtPercentile(txGasPrices.ToList()) ?? GetMinimumGasPrice(headBlock.BaseFeePerGas); gasPriceEstimate = UInt256.Min(gasPriceEstimate!, EthGasPriceConstants.MaxGasPrice); _gasPriceEstimation.Set(headBlockHash, gasPriceEstimate); return ValueTask.FromResult(gasPriceEstimate!); } - internal IEnumerable GetSortedGasPricesFromRecentBlocks(long blockNumber) => + internal IEnumerable GetGasPricesFromRecentBlocks(long blockNumber) => GetGasPricesFromRecentBlocks(blockNumber, BlockLimit, static (transaction, eip1559Enabled, baseFee) => transaction.CalculateEffectiveGasPrice(eip1559Enabled, baseFee)); @@ -106,8 +108,7 @@ IEnumerable GetBlocks(long currentBlockNumber) } } - return GetGasPricesFromRecentBlocks(GetBlocks(blockNumber), numberOfBlocks, calculateGasFromTransaction) - .OrderBy(gasPrice => gasPrice); + return GetGasPricesFromRecentBlocks(GetBlocks(blockNumber), numberOfBlocks, calculateGasFromTransaction); } private IEnumerable GetGasPricesFromRecentBlocks(IEnumerable blocks, int blocksToGoBack, CalculateGas calculateGasFromTransaction) @@ -161,7 +162,73 @@ private IEnumerable GetGasPricesFromRecentBlocks(IEnumerable blo return roundedIndex < 0 ? null - : txGasPriceList[roundedIndex]; + : SelectKthSmallestInPlace(txGasPriceList, roundedIndex); + } + + /// + /// Selects the kth smallest element (0-based) in-place using a Quickselect-style partitioning algorithm. + /// This mutates the input list order. + /// + internal static UInt256 SelectKthSmallestInPlace(List list, int k) + { + if ((uint)k >= (uint)list.Count) + { + throw new ArgumentOutOfRangeException(nameof(k), k, "k must be within [0, list.Count)."); + } + + int left = 0; + int right = list.Count - 1; + + while (true) + { + if (left == right) + { + return list[left]; + } + + // Deterministic pivot for stable perf/repro (median-of-range). + int pivotIndex = left + ((right - left) >> 1); + pivotIndex = Partition(list, left, right, pivotIndex, UInt256Comparer); + + if (k == pivotIndex) + { + return list[k]; + } + + if (k < pivotIndex) + { + right = pivotIndex - 1; + } + else + { + left = pivotIndex + 1; + } + } + } + + private static int Partition(List list, int left, int right, int pivotIndex, IComparer comparer) + { + UInt256 pivotValue = list[pivotIndex]; + Swap(list, pivotIndex, right); + + int storeIndex = left; + for (int i = left; i < right; i++) + { + if (comparer.Compare(list[i], pivotValue) < 0) + { + Swap(list, storeIndex, i); + storeIndex++; + } + } + + Swap(list, right, storeIndex); + return storeIndex; + } + + private static void Swap(List list, int a, int b) + { + if (a == b) return; + (list[a], list[b]) = (list[b], list[a]); } private static int GetRoundedIndexAtPercentile(int count) From 9d52d38d6bd08dddfa3b2c19a89ab63190d8792a Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Mon, 5 Jan 2026 20:04:46 -0500 Subject: [PATCH 172/255] Don't queue prunes (#10112) * Don't queue prunes * Add delay * Add Delay reasoning comment --- .../Pruning/TreeStoreTests.cs | 6 +- .../PruningScenariosTests.cs | 2 +- .../Nethermind.Trie/Pruning/TrieStore.cs | 111 ++++++++++++------ 3 files changed, 77 insertions(+), 42 deletions(-) diff --git a/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs b/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs index b1e3316a132..fd920defda1 100644 --- a/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs @@ -1306,7 +1306,7 @@ void VerifyAllTrie() // Persist sometimes testPruningStrategy.ShouldPruneEnabled = i % snapshotInterval == 0; testPruningStrategy.ShouldPrunePersistedEnabled = i % prunePersistedInterval == 0; - fullTrieStore.SyncPruneCheck(); + fullTrieStore.SyncPruneQueue(); testPruningStrategy.ShouldPruneEnabled = false; testPruningStrategy.ShouldPrunePersistedEnabled = false; @@ -1393,7 +1393,7 @@ void WriteRandomData(int seed) Task persistTask = Task.Run(() => { testPruningStrategy.ShouldPruneEnabled = true; - fullTrieStore.SyncPruneCheck(); + fullTrieStore.SyncPruneQueue(); testPruningStrategy.ShouldPruneEnabled = false; }); Thread.Sleep(100); @@ -1425,7 +1425,7 @@ void WriteRandomData(int seed) // Persisted nodes should be from block 12 testPruningStrategy.ShouldPruneEnabled = true; - fullTrieStore.SyncPruneCheck(); + fullTrieStore.SyncPruneQueue(); testPruningStrategy.ShouldPruneEnabled = false; fullTrieStore.LastPersistedBlockNumber.Should().Be(12); diff --git a/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs b/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs index 1e7bc90dd31..223282c6604 100644 --- a/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs @@ -431,7 +431,7 @@ public PruningContext CommitAndWaitForPruning() public PruningContext SyncPruneCheck() { - _trieStore.SyncPruneCheck(); + _trieStore.SyncPruneQueue(); return this; } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index 1e3fbe021c4..03b01088941 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -571,60 +571,95 @@ private TrieStoreState CaptureCurrentState() public void Prune() { - var state = CaptureCurrentState(); + TrieStoreState state = CaptureCurrentState(); if ((_pruningStrategy.ShouldPruneDirtyNode(state) || _pruningStrategy.ShouldPrunePersistedNode(state)) && _pruningTask.IsCompleted) { - _pruningTask = Task.Run(SyncPruneCheck); + _pruningTask = TrySyncPrune(); } } - internal void SyncPruneCheck() + private async Task TrySyncPrune() + { + // Delay for 3 things: + // 1. Move to background thread + // 2. Allow kick off (block processing) some time to finish before starting to prune (prune in block gap) + // 3. If we are n+1 Task passing the .IsCompleted check but not going to be first to pass lock, + // remain uncompleted for a time to prevent other tasks seeing .IsCompleted and also trying to queue. + await Task.Delay(10); + + if (!_pruningLock.TryEnter()) + { + // Do not want to queue on lock behind already ongoing pruning. + return; + } + + try + { + SyncPruneNonLocked(); + } + finally + { + _pruningLock.Exit(); + } + + TryExitCommitBufferMode(); + } + + // Testing purpose only + internal void SyncPruneQueue() { using (var _ = _pruningLock.EnterScope()) { - if (_pruningStrategy.ShouldPruneDirtyNode(CaptureCurrentState())) - { - PersistAndPruneDirtyCache(); - } + SyncPruneNonLocked(); + } + + TryExitCommitBufferMode(); + } + + private void SyncPruneNonLocked() + { + Debug.Assert(_pruningLock.IsHeldByCurrentThread, "Pruning lock must be held to perform sync prune."); + + if (_pruningStrategy.ShouldPruneDirtyNode(CaptureCurrentState())) + { + PersistAndPruneDirtyCache(); + } - if (_prunePersistedNodePortion > 0) + if (_prunePersistedNodePortion > 0) + { + try { - try + // When `_pruningLock` is held, the begin commit will check for _toBePersistedBlockNumber in order + // to decide which block to be used as the boundary for the commit buffer. This number was re-set + // to -1 in `PersistAndPruneDirtyCache`. So we need to re-set it here, otherwise `BeginScope` will hang + // until the prune persisted node loop is completed. + _toBePersistedBlockNumber = LastPersistedBlockNumber; + + // `PrunePersistedNodes` only work on part of the partition at any one time. With commit buffer, + // it is possible that the commit buffer once flushed will immediately trigger another prune, which + // mean `PrunePersistedNodes` was not able to re-trigger multiple time, which make the persisted node + // cache even bigger which causes longer prune which causes bigger commit buffer, etc. + // So we loop it here until `ShouldPrunePersistedNode` return false. + int startingShard = _lastPrunedShardIdx; + while (_lastPrunedShardIdx - startingShard < _shardedDirtyNodeCount && _pruningStrategy.ShouldPrunePersistedNode(CaptureCurrentState())) { - // When `_pruningLock` is held, the begin commit will check for _toBePersistedBlockNumber in order - // to decide which block to be used as the boundary for the commit buffer. This number was re-set - // to -1 in `PersistAndPruneDirtyCache`. So we need to re-set it here, otherwrise `BeginScope` will hang - // until the prune persisted node loop is completed. - _toBePersistedBlockNumber = LastPersistedBlockNumber; - - // `PrunePersistedNodes` only work on part of the partition at any one time. With commit buffer, - // it is possible that the commit buffer once flushed will immediately trigger another prune, which - // mean `PrunePersistedNodes` was not able to re-trigger multiple time, which make the persisted node - // cache even bigger which causes longer prune which causes bigger commit buffer, etc. - // So we loop it here until `ShouldPrunePersistedNode` return false. - int startingShard = _lastPrunedShardIdx; - while (_lastPrunedShardIdx - startingShard < _shardedDirtyNodeCount && _pruningStrategy.ShouldPrunePersistedNode(CaptureCurrentState())) - { - PrunePersistedNodes(); - } - - if (!IsInCommitBufferMode && _lastPrunedShardIdx - startingShard >= _shardedDirtyNodeCount && _pruningStrategy.ShouldPrunePersistedNode(CaptureCurrentState())) - { - // A persisted nodes that was recommitted and is still within pruning boundary cannot be pruned. - // This should be rare but can happen, notably in mainnet block 4500000 around there, But this - // does mean that it will keep retrying to prune persisted nodes. The solution is to either increase - // the memory budget or reduce the pruning boundary. - if (_logger.IsWarn) _logger.Warn($"Unable to completely prune persisted nodes. Consider increasing pruning cache limit or reducing pruning boundary"); - } + PrunePersistedNodes(); } - finally + + if (!IsInCommitBufferMode && _lastPrunedShardIdx - startingShard >= _shardedDirtyNodeCount && _pruningStrategy.ShouldPrunePersistedNode(CaptureCurrentState())) { - _toBePersistedBlockNumber = -1; + // A persisted nodes that was recommitted and is still within pruning boundary cannot be pruned. + // This should be rare but can happen, notably in mainnet block 4500000 around there, But this + // does mean that it will keep retrying to prune persisted nodes. The solution is to either increase + // the memory budget or reduce the pruning boundary. + if (_logger.IsWarn) _logger.Warn($"Unable to completely prune persisted nodes. Consider increasing pruning cache limit or reducing pruning boundary"); } } + finally + { + _toBePersistedBlockNumber = -1; + } } - - TryExitCommitBufferMode(); } internal void PersistAndPruneDirtyCache() From 5f117326ac2f2df9fb6b4e7be92019e35269ca17 Mon Sep 17 00:00:00 2001 From: ANtutov Date: Tue, 6 Jan 2026 11:44:13 +0200 Subject: [PATCH 173/255] refactor: simplify Avx2 branches for UInt256 shuffles (#10111) * refactor: simplify Avx2 branches for UInt256 shuffles * Update EvmStack.cs --- src/Nethermind/Nethermind.Core/Extensions/UInt256Extensions.cs | 2 +- src/Nethermind/Nethermind.Evm/EvmStack.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Extensions/UInt256Extensions.cs b/src/Nethermind/Nethermind.Core/Extensions/UInt256Extensions.cs index d28b523d305..92712f8af16 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/UInt256Extensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/UInt256Extensions.cs @@ -35,7 +35,7 @@ public static ValueHash256 ToValueHash(this in UInt256 value) Word data = Unsafe.As(ref Unsafe.AsRef(in value)); result = Avx512Vbmi.VL.PermuteVar32x8(data, shuffle); } - else if (Avx2.IsSupported) + else { Vector256 permute = Unsafe.As>(ref Unsafe.AsRef(in value)); Vector256 convert = Avx2.Permute4x64(permute, 0b_01_00_11_10); diff --git a/src/Nethermind/Nethermind.Evm/EvmStack.cs b/src/Nethermind/Nethermind.Evm/EvmStack.cs index a86286434ca..6f9aaa10940 100644 --- a/src/Nethermind/Nethermind.Evm/EvmStack.cs +++ b/src/Nethermind/Nethermind.Evm/EvmStack.cs @@ -319,7 +319,7 @@ public void PushUInt256(in UInt256 value) Word data = Unsafe.As(ref Unsafe.AsRef(in value)); head = Avx512Vbmi.VL.PermuteVar32x8(data, shuffle); } - else if (Avx2.IsSupported) + else { Vector256 permute = Unsafe.As>(ref Unsafe.AsRef(in value)); Vector256 convert = Avx2.Permute4x64(permute, 0b_01_00_11_10); From 49ee006d16c112242381b35940d8fb5c031048da Mon Sep 17 00:00:00 2001 From: Fallengirl <155266340+Fallengirl@users.noreply.github.com> Date: Tue, 6 Jan 2026 12:13:37 +0100 Subject: [PATCH 174/255] fix(kute): prevent null label crash in Prometheus metrics reporter (#10109) --- .../PrometheusPushGatewayMetricsReporter.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tools/Kute/Nethermind.Tools.Kute/Metrics/PrometheusPushGatewayMetricsReporter.cs b/tools/Kute/Nethermind.Tools.Kute/Metrics/PrometheusPushGatewayMetricsReporter.cs index fedfcc96ea3..d5c9985bddd 100644 --- a/tools/Kute/Nethermind.Tools.Kute/Metrics/PrometheusPushGatewayMetricsReporter.cs +++ b/tools/Kute/Nethermind.Tools.Kute/Metrics/PrometheusPushGatewayMetricsReporter.cs @@ -97,17 +97,23 @@ public Task Ignored(CancellationToken token = default) public Task Batch(JsonRpc.Request.Batch batch, TimeSpan elapsed, CancellationToken token = default) { - _batchDuration - .WithLabels(batch.Id) - .Observe(elapsed.TotalSeconds); + if (batch.Id is not null) + { + _batchDuration + .WithLabels(batch.Id) + .Observe(elapsed.TotalSeconds); + } return Task.CompletedTask; } public Task Single(JsonRpc.Request.Single single, TimeSpan elapsed, CancellationToken token = default) { - _singleDuration - .WithLabels(single.Id, single.MethodName) - .Observe(elapsed.TotalSeconds); + if (single.Id is not null && single.MethodName is not null) + { + _singleDuration + .WithLabels(single.Id, single.MethodName) + .Observe(elapsed.TotalSeconds); + } return Task.CompletedTask; } From e96d4ecceca05dcf6fefab6e78f72b339ada80d9 Mon Sep 17 00:00:00 2001 From: Daniil Ankushin Date: Tue, 6 Jan 2026 16:23:43 +0400 Subject: [PATCH 175/255] Fix #10068 regression (#10116) --- src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs | 4 ++-- src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs b/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs index d6c33db0e47..243840ccc2e 100644 --- a/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs +++ b/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs @@ -166,8 +166,8 @@ public static bool ConsumeLogEmission(ref EthereumGasPolicy gas, long topicCount } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool ConsumeDataCopyGas(ref EthereumGasPolicy gas, bool isExternalCode, long baseCost, long dataCost) - => UpdateGas(ref gas, baseCost + dataCost); + public static void ConsumeDataCopyGas(ref EthereumGasPolicy gas, bool isExternalCode, long baseCost, long dataCost) + => Consume(ref gas, baseCost + dataCost); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static EthereumGasPolicy Max(in EthereumGasPolicy a, in EthereumGasPolicy b) => diff --git a/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs b/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs index 3277aa7ca42..289b9959717 100644 --- a/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs +++ b/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs @@ -214,6 +214,5 @@ static abstract bool UpdateMemoryCost(ref TSelf gas, /// True for EXTCODECOPY (external account code). /// Fixed opcode cost. /// Per-word copy cost. - /// True if sufficient gas available. - static abstract bool ConsumeDataCopyGas(ref TSelf gas, bool isExternalCode, long baseCost, long dataCost); + static abstract void ConsumeDataCopyGas(ref TSelf gas, bool isExternalCode, long baseCost, long dataCost); } From 6cd4afa18b9231006b8a2da4b520b43e58caa09c Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Tue, 6 Jan 2026 16:16:26 +0100 Subject: [PATCH 176/255] Git/ignore claude config (#10118) * Ignore claude config in git * Ignore claude config in git --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index be433a3fc74..e1f4fb7b03b 100644 --- a/.gitignore +++ b/.gitignore @@ -438,3 +438,6 @@ FodyWeavers.xsd ## Nethermind keystore/ /.githooks + +# AI +**/.claude/** From 2526f4170285a0e5f29f253b59ce1beedcdd0592 Mon Sep 17 00:00:00 2001 From: iPLAY888 <133153661+letmehateu@users.noreply.github.com> Date: Wed, 7 Jan 2026 14:14:02 +0300 Subject: [PATCH 177/255] perf: use cached BlockInfo variable instead of redundant array access in BlockTree (#10125) Update BlockTree.cs --- src/Nethermind/Nethermind.Blockchain/BlockTree.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs index 74434364f79..76b21345fb4 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs @@ -767,7 +767,7 @@ as it does not require the step of resolving number -> hash */ for (int i = 0; i < level.BlockInfos.Length; i++) { BlockInfo current = level.BlockInfos[i]; - if (level.BlockInfos[i].TotalDifficulty >= bestDifficultySoFar) + if (current.TotalDifficulty >= bestDifficultySoFar) { bestDifficultySoFar = current.TotalDifficulty; bestHash = current.BlockHash; From 724b668f7ce95c89ddd016d066eb6908717452b2 Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Wed, 7 Jan 2026 12:23:44 +0100 Subject: [PATCH 178/255] Save space locally on builds (#10113) * Add Directory.Build.targets with: - Skip copying dependencies and native runtimes for library projects - Filter native runtimes to current OS only during local builds - Share native runtimes across projects during local builds with a shared location and junctions/symlinks * NethermindCopyAllRuntimes -> CI * Remove filtering native lib by os * Move Directory.Build.targets to src/Nethermind * Make mechanism opt-in with SlimBuild parameter Add Directory.Build.targets to Solution Items * SlimBuild can have any value to be enabled * Refactor Directory.Build.targets (#10122) --------- Co-authored-by: Ruben Buniatyan --- src/Nethermind/Directory.Build.targets | 28 ++++++++++++++++++++++++++ src/Nethermind/Nethermind.slnx | 1 + 2 files changed, 29 insertions(+) create mode 100644 src/Nethermind/Directory.Build.targets diff --git a/src/Nethermind/Directory.Build.targets b/src/Nethermind/Directory.Build.targets new file mode 100644 index 00000000000..4c920adb3cb --- /dev/null +++ b/src/Nethermind/Directory.Build.targets @@ -0,0 +1,28 @@ + + + + + <_SharedRuntimesDir>$(ArtifactsPath)\runtimes\$(Configuration) + + + + + + <_RuntimeFilesToShare Include="$(OutputPath)runtimes\**\*" /> + + + + + + + + + + + diff --git a/src/Nethermind/Nethermind.slnx b/src/Nethermind/Nethermind.slnx index e73865e7af3..c64f1a920b7 100644 --- a/src/Nethermind/Nethermind.slnx +++ b/src/Nethermind/Nethermind.slnx @@ -33,6 +33,7 @@ + From 811c27bd8c15d4d2f570302cb4b88b4c5af3feed Mon Sep 17 00:00:00 2001 From: Nurbakyt Madibek Date: Wed, 7 Jan 2026 17:21:36 +0500 Subject: [PATCH 179/255] Align Nethermind with the latest taiko-geth changes (#10127) --- .../Rpc/TaikoExtendedEthModule.cs | 33 ++------------- .../Nethermind.Taiko/TaikoBlockValidator.cs | 2 +- .../Nethermind.Taiko/TaikoHeaderHelper.cs | 40 +++++++++++++++---- .../Nethermind.Taiko/TaikoHeaderValidator.cs | 6 +-- .../TaikoTransactionProcessor.cs | 2 +- 5 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoExtendedEthModule.cs b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoExtendedEthModule.cs index 8ab244b3f56..db9b0c5f275 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoExtendedEthModule.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoExtendedEthModule.cs @@ -79,10 +79,9 @@ public class TaikoExtendedEthModule( } /// - /// Traverses the blockchain backwards to find the last Shasta block of the given Shasta batch ID. + /// Traverses the blockchain backwards to find the last Shasta block of the given batch ID. /// - /// The batch ID. - /// The last block ID. + /// The Shasta batch identifier for which to find the last corresponding block. private UInt256? GetLastBlockByBatchId(UInt256 batchId) { Block? currentBlock = blockFinder.Head; @@ -96,8 +95,7 @@ public class TaikoExtendedEthModule( break; } - UInt256? proposalId = ExtractAnchorV4ProposalId(currentBlock.Transactions[0].Data); - + UInt256? proposalId = currentBlock.Header.DecodeShastaProposalID(); if (proposalId is null) { return null; @@ -118,29 +116,4 @@ private static bool HasAnchorV4Prefix(ReadOnlyMemory data) { return data.Length >= 4 && AnchorV4Selector.AsSpan().SequenceEqual(data.Span[..4]); } - - private static UInt256? ExtractAnchorV4ProposalId(ReadOnlyMemory data) - { - // Calldata layout: 4-byte selector + ABI-encoded arguments. - // The first 32 bytes hold the offset (relative to args start) where the proposal id is stored. - const int selectorLength = 4; - const int dataLength = 32; - - if (data.Length <= selectorLength + dataLength) - { - return null; - } - - ReadOnlySpan args = data.Span[selectorLength..]; - var offset = new UInt256(args[..dataLength], true); - - // Check if the offset is invalid - if (offset > int.MaxValue || offset + dataLength > args.Length) - { - return null; - } - - ReadOnlySpan proposalIdBytes = args.Slice((int)offset, dataLength); - return new UInt256(proposalIdBytes, true); - } } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs b/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs index 4b2331e60d3..60526286547 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoBlockValidator.cs @@ -24,7 +24,7 @@ public class TaikoBlockValidator( private static readonly byte[] AnchorSelector = Keccak.Compute("anchor(bytes32,bytes32,uint64,uint32)").Bytes[..4].ToArray(); private static readonly byte[] AnchorV2Selector = Keccak.Compute("anchorV2(uint64,bytes32,uint32,(uint8,uint8,uint32,uint64,uint32))").Bytes[..4].ToArray(); private static readonly byte[] AnchorV3Selector = Keccak.Compute("anchorV3(uint64,bytes32,uint32,(uint8,uint8,uint32,uint64,uint32),bytes32[])").Bytes[..4].ToArray(); - public static readonly byte[] AnchorV4Selector = Keccak.Compute("anchorV4((uint48,address,bytes),(uint48,bytes32,bytes32))").Bytes[..4].ToArray(); + public static readonly byte[] AnchorV4Selector = Keccak.Compute("anchorV4((uint48,bytes32,bytes32))").Bytes[..4].ToArray(); public static readonly Address GoldenTouchAccount = new("0x0000777735367b36bC9B61C50022d9D0700dB4Ec"); diff --git a/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs b/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs index 1f73b6a20a6..8b4a63f9e99 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoHeaderHelper.cs @@ -3,18 +3,44 @@ using System; using Nethermind.Core; +using Nethermind.Int256; namespace Nethermind.Taiko; +/// +/// Helper methods for decoding Taiko block header extraData. +/// Shasta extraData layout: [basefeeSharingPctg (1 byte)][proposalId (6 bytes)] +/// internal static class TaikoHeaderHelper { - public const int ShastaExtraDataMinLen = 2; + public const int ShastaExtraDataBasefeeSharingPctgIndex = 0; + public const int ShastaExtraDataProposalIDIndex = 1; + public const int ShastaExtraDataProposalIDLength = 6; + public const int ShastaExtraDataLen = 1 + ShastaExtraDataProposalIDLength; - public static byte? DecodeOntakeExtraData(this BlockHeader header) => header.ExtraData is { Length: >= 32 } ? Math.Min(header.ExtraData[31], (byte)100) : null; + /// + /// Decodes Ontake/Pacaya extraData to get basefeeSharingPctg (last byte, capped at 100). + /// + public static byte? DecodeOntakeExtraData(this BlockHeader header) => + header.ExtraData is { Length: >= 32 } ? Math.Min(header.ExtraData[31], (byte)100) : null; - // Two bytes encoded in the extra data for Shasta - // - First byte: basefeeSharingPctg - // - Second byte: isLowBondProposal (lowest bit) - // Returns only the basefeeSharingPctg - public static byte? DecodeShastaExtraData(this BlockHeader header) => header.ExtraData is { Length: < ShastaExtraDataMinLen } ? null : header.ExtraData[0]; + /// + /// Decodes Shasta extraData to get basefeeSharingPctg (first byte). + /// + public static byte? DecodeShastaBasefeeSharingPctg(this BlockHeader header) => + header.ExtraData is { Length: < ShastaExtraDataLen } ? null : header.ExtraData[ShastaExtraDataBasefeeSharingPctgIndex]; + + /// + /// Decodes Shasta extraData to get proposalId (bytes 1-6). + /// + public static UInt256? DecodeShastaProposalID(this BlockHeader header) + { + if (header.ExtraData is null || header.ExtraData.Length < ShastaExtraDataLen) + { + return null; + } + + ReadOnlySpan proposalIdBytes = header.ExtraData.AsSpan(ShastaExtraDataProposalIDIndex, ShastaExtraDataProposalIDLength); + return new UInt256(proposalIdBytes, true); + } } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs b/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs index b26cdbb1ff8..72e481345eb 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoHeaderValidator.cs @@ -60,9 +60,9 @@ protected override bool ValidateExtraData(BlockHeader header, IReleaseSpec spec, { var taikoSpec = (ITaikoReleaseSpec)spec; - if (taikoSpec.IsShastaEnabled && header.ExtraData is { Length: < TaikoHeaderHelper.ShastaExtraDataMinLen }) + if (taikoSpec.IsShastaEnabled && header.ExtraData is { Length: < TaikoHeaderHelper.ShastaExtraDataLen }) { - error = $"ExtraData must be at least {TaikoHeaderHelper.ShastaExtraDataMinLen} bytes for Shasta, but got {header.ExtraData.Length}"; + error = $"ExtraData must be at least {TaikoHeaderHelper.ShastaExtraDataLen} bytes for Shasta, but got {header.ExtraData.Length}"; if (_logger.IsWarn) _logger.Warn($"Invalid block header ({header.Hash}) - {error}"); return false; } @@ -93,7 +93,7 @@ private bool ValidateEip4396Header(BlockHeader header, BlockHeader parent, IRele ulong parentBlockTime = 0; if (header.Number > 1) { - BlockHeader? grandParent = _blockTree?.FindHeader(parent.ParentHash!, BlockTreeLookupOptions.None); + BlockHeader? grandParent = _blockTree?.FindHeader(parent.ParentHash!, BlockTreeLookupOptions.None, blockNumber: parent.Number - 1); if (grandParent is null) { error = $"Ancestor block not found for parent {parent.ParentHash}"; diff --git a/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs b/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs index 11b6fa4962f..fc8e4972038 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs @@ -63,7 +63,7 @@ protected override void PayFees(Transaction tx, BlockHeader header, IReleaseSpec var taikoSpec = (ITaikoReleaseSpec)spec; if (taikoSpec.IsOntakeEnabled || taikoSpec.IsShastaEnabled) { - byte basefeeSharingPct = (taikoSpec.IsShastaEnabled ? header.DecodeShastaExtraData() : header.DecodeOntakeExtraData()) ?? 0; + byte basefeeSharingPct = (taikoSpec.IsShastaEnabled ? header.DecodeShastaBasefeeSharingPctg() : header.DecodeOntakeExtraData()) ?? 0; UInt256 feeCoinbase = baseFees * basefeeSharingPct / 100; From 40505c74e107b030274b61af945afc671dcbf5b0 Mon Sep 17 00:00:00 2001 From: Diptanshu Kakwani Date: Wed, 7 Jan 2026 18:01:18 +0530 Subject: [PATCH 180/255] Surge TDX Attestation (#9954) * initial changes for taiko tdx * fixes and refactoring * optimize attestation * simplify attestation, return block header and add tests * add two variants for attestation, remove quotes & instance id, add tests * remove docs * minor fix * modify header attestation to return both hash and header rlp * refactor * fix tests and address comments * nit: fix whitespace * undo tdx module change * modify signature to use blockhash+stateroot * fix new header serialization * address comments --------- Co-authored-by: smartprogrammer93 --- .../Tdx/TdxRpcModuleTests.cs | 201 +++++++++++++++ .../Tdx/TdxServiceTests.cs | 171 +++++++++++++ .../Nethermind.Taiko/Config/ISurgeConfig.cs | 3 + .../Nethermind.Taiko/Config/SurgeConfig.cs | 1 + .../Nethermind.Taiko/TaikoPlugin.cs | 4 + .../Nethermind.Taiko/Tdx/BlockHeaderForRpc.cs | 85 +++++++ .../Nethermind.Taiko/Tdx/ISurgeTdxConfig.cs | 16 ++ .../Nethermind.Taiko/Tdx/ITdxRpcModule.cs | 32 +++ .../Nethermind.Taiko/Tdx/ITdxService.cs | 33 +++ .../Nethermind.Taiko/Tdx/ITdxsClient.cs | 32 +++ .../Nethermind.Taiko/Tdx/SurgeTdxConfig.cs | 11 + .../Nethermind.Taiko/Tdx/TdxAttestation.cs | 32 +++ .../Nethermind.Taiko/Tdx/TdxModule.cs | 39 +++ .../Nethermind.Taiko/Tdx/TdxRpcModule.cs | 108 +++++++++ .../Nethermind.Taiko/Tdx/TdxService.cs | 228 ++++++++++++++++++ .../Nethermind.Taiko/Tdx/TdxsClient.cs | 92 +++++++ 16 files changed, 1088 insertions(+) create mode 100644 src/Nethermind/Nethermind.Taiko.Test/Tdx/TdxRpcModuleTests.cs create mode 100644 src/Nethermind/Nethermind.Taiko.Test/Tdx/TdxServiceTests.cs create mode 100644 src/Nethermind/Nethermind.Taiko/Tdx/BlockHeaderForRpc.cs create mode 100644 src/Nethermind/Nethermind.Taiko/Tdx/ISurgeTdxConfig.cs create mode 100644 src/Nethermind/Nethermind.Taiko/Tdx/ITdxRpcModule.cs create mode 100644 src/Nethermind/Nethermind.Taiko/Tdx/ITdxService.cs create mode 100644 src/Nethermind/Nethermind.Taiko/Tdx/ITdxsClient.cs create mode 100644 src/Nethermind/Nethermind.Taiko/Tdx/SurgeTdxConfig.cs create mode 100644 src/Nethermind/Nethermind.Taiko/Tdx/TdxAttestation.cs create mode 100644 src/Nethermind/Nethermind.Taiko/Tdx/TdxModule.cs create mode 100644 src/Nethermind/Nethermind.Taiko/Tdx/TdxRpcModule.cs create mode 100644 src/Nethermind/Nethermind.Taiko/Tdx/TdxService.cs create mode 100644 src/Nethermind/Nethermind.Taiko/Tdx/TdxsClient.cs diff --git a/src/Nethermind/Nethermind.Taiko.Test/Tdx/TdxRpcModuleTests.cs b/src/Nethermind/Nethermind.Taiko.Test/Tdx/TdxRpcModuleTests.cs new file mode 100644 index 00000000000..f2dd7f08324 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko.Test/Tdx/TdxRpcModuleTests.cs @@ -0,0 +1,201 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Threading.Tasks; +using FluentAssertions; +using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test.Builders; +using Nethermind.JsonRpc; +using Nethermind.Logging; +using Nethermind.Taiko.Config; +using Nethermind.Taiko.Tdx; +using NSubstitute; +using NUnit.Framework; + +namespace Nethermind.Taiko.Test.Tdx; + +public class TdxRpcModuleTests +{ + private ISurgeConfig _config = null!; + private ITdxService _tdxService = null!; + private IBlockFinder _blockFinder = null!; + private TdxRpcModule _rpcModule = null!; + + [SetUp] + public void Setup() + { + _config = Substitute.For(); + _tdxService = Substitute.For(); + _blockFinder = Substitute.For(); + + _rpcModule = new TdxRpcModule(_config, _tdxService, _blockFinder, LimboLogs.Instance); + } + + [Test] + public async Task SignBlockHeader_returns_error_when_disabled() + { + _config.TdxEnabled.Returns(false); + + ResultWrapper result = await _rpcModule.taiko_tdxSignBlockHeader(new BlockParameter(1)); + + result.Result.ResultType.Should().Be(ResultType.Failure); + result.Result.Error.Should().Contain("not enabled"); + } + + [Test] + public async Task SignBlockHeader_returns_error_when_not_bootstrapped() + { + _config.TdxEnabled.Returns(true); + _tdxService.IsBootstrapped.Returns(false); + + ResultWrapper result = await _rpcModule.taiko_tdxSignBlockHeader(new BlockParameter(1)); + + result.Result.ResultType.Should().Be(ResultType.Failure); + result.Result.Error.Should().Contain("not bootstrapped"); + } + + [Test] + public async Task SignBlockHeader_returns_error_when_block_not_found() + { + _config.TdxEnabled.Returns(true); + _tdxService.IsBootstrapped.Returns(true); + _blockFinder.FindHeader(Arg.Any(), Arg.Any()).Returns((BlockHeader?)null); + + ResultWrapper result = await _rpcModule.taiko_tdxSignBlockHeader(new BlockParameter(1)); + + result.Result.ResultType.Should().Be(ResultType.Failure); + result.Result.Error.Should().Contain("not found"); + } + + [Test] + public async Task SignBlockHeader_returns_signature_when_successful() + { + _config.TdxEnabled.Returns(true); + _tdxService.IsBootstrapped.Returns(true); + + BlockHeader header = Build.A.BlockHeader.WithStateRoot(TestItem.KeccakA).TestObject; + _blockFinder.FindHeader(Arg.Any(), Arg.Any()).Returns(header); + + var signature = new TdxBlockHeaderSignature + { + Signature = new byte[Signature.Size], + BlockHash = header.Hash!, + StateRoot = header.StateRoot!, + Header = new BlockHeaderForRpc(header) + }; + _tdxService.SignBlockHeader(header).Returns(signature); + + ResultWrapper result = await _rpcModule.taiko_tdxSignBlockHeader(new BlockParameter(1)); + + result.Result.ResultType.Should().Be(ResultType.Success); + result.Data.Should().NotBeNull(); + result.Data!.Header.Hash.Should().Be(header.Hash!); + } + + [Test] + public async Task SignBlockHeader_returns_error_on_signing_failure() + { + _config.TdxEnabled.Returns(true); + _tdxService.IsBootstrapped.Returns(true); + + BlockHeader header = Build.A.BlockHeader.TestObject; + _blockFinder.FindHeader(Arg.Any(), Arg.Any()).Returns(header); + _tdxService.SignBlockHeader(header).Returns(_ => throw new TdxException("Signing failed")); + + ResultWrapper result = await _rpcModule.taiko_tdxSignBlockHeader(new BlockParameter(1)); + + result.Result.ResultType.Should().Be(ResultType.Failure); + result.Result.Error.Should().Contain("Signing failed"); + } + + [Test] + public async Task GetTdxGuestInfo_returns_error_when_disabled() + { + _config.TdxEnabled.Returns(false); + + ResultWrapper result = await _rpcModule.taiko_getTdxGuestInfo(); + + result.Result.ResultType.Should().Be(ResultType.Failure); + result.Result.Error.Should().Contain("not enabled"); + } + + [Test] + public async Task GetTdxGuestInfo_returns_error_when_not_bootstrapped() + { + _config.TdxEnabled.Returns(true); + _tdxService.GetGuestInfo().Returns((TdxGuestInfo?)null); + + ResultWrapper result = await _rpcModule.taiko_getTdxGuestInfo(); + + result.Result.ResultType.Should().Be(ResultType.Failure); + result.Result.Error.Should().Contain("not bootstrapped"); + } + + [Test] + public async Task GetTdxGuestInfo_returns_info_when_available() + { + _config.TdxEnabled.Returns(true); + var info = new TdxGuestInfo + { + IssuerType = "test", + PublicKey = "0x1234", + Quote = "abcd", + Nonce = "1234" + }; + _tdxService.GetGuestInfo().Returns(info); + + ResultWrapper result = await _rpcModule.taiko_getTdxGuestInfo(); + + result.Result.ResultType.Should().Be(ResultType.Success); + result.Data.Should().NotBeNull(); + result.Data!.IssuerType.Should().Be("test"); + } + + [Test] + public async Task TdxBootstrap_returns_error_when_disabled() + { + _config.TdxEnabled.Returns(false); + + ResultWrapper result = await _rpcModule.taiko_tdxBootstrap(); + + result.Result.ResultType.Should().Be(ResultType.Failure); + result.Result.Error.Should().Contain("not enabled"); + } + + [Test] + public async Task TdxBootstrap_returns_info_when_successful() + { + _config.TdxEnabled.Returns(true); + var info = new TdxGuestInfo + { + IssuerType = "azure", + PublicKey = "0xabcd", + Quote = "quote", + Nonce = "nonce" + }; + _tdxService.Bootstrap().Returns(info); + + ResultWrapper result = await _rpcModule.taiko_tdxBootstrap(); + + result.Result.ResultType.Should().Be(ResultType.Success); + result.Data.Should().NotBeNull(); + result.Data!.IssuerType.Should().Be("azure"); + } + + [Test] + public async Task TdxBootstrap_returns_error_on_exception() + { + _config.TdxEnabled.Returns(true); + _tdxService.Bootstrap().Returns(_ => throw new TdxException("Connection failed")); + + ResultWrapper result = await _rpcModule.taiko_tdxBootstrap(); + + result.Result.ResultType.Should().Be(ResultType.Failure); + result.Result.Error.Should().Contain("Connection failed"); + } + +} + diff --git a/src/Nethermind/Nethermind.Taiko.Test/Tdx/TdxServiceTests.cs b/src/Nethermind/Nethermind.Taiko.Test/Tdx/TdxServiceTests.cs new file mode 100644 index 00000000000..1eaf9d1eed9 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko.Test/Tdx/TdxServiceTests.cs @@ -0,0 +1,171 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.IO; +using FluentAssertions; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test.Builders; +using Nethermind.Logging; +using Nethermind.Taiko.Tdx; +using NSubstitute; +using NUnit.Framework; + +namespace Nethermind.Taiko.Test.Tdx; + +public class TdxServiceTests +{ + private ISurgeTdxConfig _config = null!; + private ITdxsClient _client = null!; + private TdxService _service = null!; + private string _tempDir = null!; + + [SetUp] + public void Setup() + { + _tempDir = Path.Combine(Path.GetTempPath(), $"tdx_test_{Guid.NewGuid():N}"); + Directory.CreateDirectory(_tempDir); + + _config = Substitute.For(); + _config.SocketPath.Returns("/tmp/tdxs.sock"); + _config.ConfigPath.Returns(_tempDir); + + _client = Substitute.For(); + _client.GetMetadata().Returns(new TdxMetadata { IssuerType = "test", Metadata = null }); + _client.Issue(Arg.Any(), Arg.Any()).Returns(new byte[100]); + + _service = new TdxService(_config, _client, LimboLogs.Instance); + } + + [TearDown] + public void TearDown() + { + if (Directory.Exists(_tempDir)) + Directory.Delete(_tempDir, true); + } + + [Test] + public void IsBootstrapped_returns_false_before_bootstrap() + { + _service.IsBootstrapped.Should().BeFalse(); + } + + [Test] + public void Bootstrap_generates_keys_and_quote() + { + TdxGuestInfo info = _service.Bootstrap(); + + info.Should().NotBeNull(); + info.IssuerType.Should().Be("test"); + info.PublicKey.Should().NotBeNullOrEmpty(); + info.Quote.Should().NotBeNullOrEmpty(); + _service.IsBootstrapped.Should().BeTrue(); + } + + [Test] + public void Bootstrap_returns_same_info_when_called_twice() + { + TdxGuestInfo info1 = _service.Bootstrap(); + TdxGuestInfo info2 = _service.Bootstrap(); + + info1.PublicKey.Should().Be(info2.PublicKey); + info1.Quote.Should().Be(info2.Quote); + } + + [Test] + public void GetGuestInfo_returns_null_before_bootstrap() + { + _service.GetGuestInfo().Should().BeNull(); + } + + [Test] + public void GetGuestInfo_returns_info_after_bootstrap() + { + _service.Bootstrap(); + TdxGuestInfo? info = _service.GetGuestInfo(); + + info.Should().NotBeNull(); + info!.PublicKey.Should().NotBeNullOrEmpty(); + } + + [Test] + public void SignBlockHeader_throws_when_not_bootstrapped() + { + Block block = Build.A.Block.WithStateRoot(TestItem.KeccakA).TestObject; + + Action act = () => _service.SignBlockHeader(block.Header); + + act.Should().Throw().WithMessage("*not bootstrapped*"); + } + + [Test] + public void SignBlockHeader_generates_valid_signature() + { + _service.Bootstrap(); + Block block = Build.A.Block + .WithNumber(100) + .WithStateRoot(TestItem.KeccakA) + .WithParent(Build.A.BlockHeader.TestObject) + .TestObject; + + TdxBlockHeaderSignature signature = _service.SignBlockHeader(block.Header); + + signature.Should().NotBeNull(); + signature.Signature.Should().HaveCount(Signature.Size); + signature.BlockHash.Should().Be(block.Hash!); + signature.StateRoot.Should().Be(TestItem.KeccakA); + signature.Header.Hash.Should().Be(block.Hash!); + } + + [Test] + public void Bootstrap_persists_and_reloads_data() + { + TdxGuestInfo info1 = _service.Bootstrap(); + + var newService = new TdxService(_config, _client, LimboLogs.Instance); + + newService.IsBootstrapped.Should().BeTrue(); + TdxGuestInfo? info2 = newService.GetGuestInfo(); + info2.Should().NotBeNull(); + info2!.PublicKey.Should().Be(info1.PublicKey); + } + + [Test] + public void Signature_v_value_is_27_or_28() + { + _service.Bootstrap(); + Block block = Build.A.Block.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject; + + TdxBlockHeaderSignature signature = _service.SignBlockHeader(block.Header); + + byte v = signature.Signature[Signature.Size - 1]; + v.Should().BeOneOf((byte)27, (byte)28); + } + + [Test] + public void New_service_bootstrap_loads_existing_data() + { + TdxGuestInfo info1 = _service.Bootstrap(); + + var newService = new TdxService(_config, _client, LimboLogs.Instance); + TdxGuestInfo info2 = newService.Bootstrap(); + + info2.PublicKey.Should().Be(info1.PublicKey); + info2.Quote.Should().Be(info1.Quote); + } + + [Test] + public void New_service_sign_uses_persisted_keys() + { + _service.Bootstrap(); + Block block = Build.A.Block.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject; + TdxBlockHeaderSignature signature1 = _service.SignBlockHeader(block.Header); + + var newService = new TdxService(_config, _client, LimboLogs.Instance); + newService.Bootstrap(); + TdxBlockHeaderSignature signature2 = newService.SignBlockHeader(block.Header); + + signature2.Signature.Should().BeEquivalentTo(signature1.Signature); + } +} diff --git a/src/Nethermind/Nethermind.Taiko/Config/ISurgeConfig.cs b/src/Nethermind/Nethermind.Taiko/Config/ISurgeConfig.cs index 684c683ae0d..73ce005b672 100644 --- a/src/Nethermind/Nethermind.Taiko/Config/ISurgeConfig.cs +++ b/src/Nethermind/Nethermind.Taiko/Config/ISurgeConfig.cs @@ -48,4 +48,7 @@ public interface ISurgeConfig : IConfig [ConfigItem(Description = "Filter transactions exceeding the max allowed ratio of gas limit to the actual gas used (e.g. 1, 2 etc.). Set to 0 to disable.", DefaultValue = "0")] int MaxGasLimitRatio { get; set; } + + [ConfigItem(Description = "Enable TDX attestation support.", DefaultValue = "false")] + bool TdxEnabled { get; set; } } diff --git a/src/Nethermind/Nethermind.Taiko/Config/SurgeConfig.cs b/src/Nethermind/Nethermind.Taiko/Config/SurgeConfig.cs index 9e8d4f3bcc8..ee48b4d0d8d 100644 --- a/src/Nethermind/Nethermind.Taiko/Config/SurgeConfig.cs +++ b/src/Nethermind/Nethermind.Taiko/Config/SurgeConfig.cs @@ -19,4 +19,5 @@ public class SurgeConfig : ISurgeConfig public int BoostBaseFeePercentage { get; set; } = 5; public int GasPriceRefreshTimeoutSeconds { get; set; } = 12; public int MaxGasLimitRatio { get; set; } = 0; + public bool TdxEnabled { get; set; } = false; } diff --git a/src/Nethermind/Nethermind.Taiko/TaikoPlugin.cs b/src/Nethermind/Nethermind.Taiko/TaikoPlugin.cs index ffab0b121f3..ea38ee57e1c 100644 --- a/src/Nethermind/Nethermind.Taiko/TaikoPlugin.cs +++ b/src/Nethermind/Nethermind.Taiko/TaikoPlugin.cs @@ -36,6 +36,7 @@ using Nethermind.Taiko.BlockTransactionExecutors; using Nethermind.Taiko.Config; using Nethermind.Taiko.Rpc; +using Nethermind.Taiko.Tdx; using Nethermind.Taiko.TaikoSpec; namespace Nethermind.Taiko; @@ -196,6 +197,9 @@ protected override void Load(ContainerBuilder builder) .RegisterSingletonJsonRpcModule() .AddSingleton() + // TDX attestation (enabled with Surge.TdxEnabled) + .AddModule(new TdxModule()) + // Need to set the rlp globally .OnBuild(ctx => { diff --git a/src/Nethermind/Nethermind.Taiko/Tdx/BlockHeaderForRpc.cs b/src/Nethermind/Nethermind.Taiko/Tdx/BlockHeaderForRpc.cs new file mode 100644 index 00000000000..ac5942e1fd4 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko/Tdx/BlockHeaderForRpc.cs @@ -0,0 +1,85 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Buffers.Binary; +using System.Text.Json.Serialization; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Int256; + +namespace Nethermind.Taiko.Tdx; + +public class BlockHeaderForRpc +{ + public BlockHeaderForRpc() { } + + public BlockHeaderForRpc(BlockHeader header) + { + Hash = header.Hash; + ParentHash = header.ParentHash; + Sha3Uncles = header.UnclesHash; + Miner = header.Beneficiary; + StateRoot = header.StateRoot; + TransactionsRoot = header.TxRoot; + ReceiptsRoot = header.ReceiptsRoot; + LogsBloom = header.Bloom; + Difficulty = header.Difficulty; + Number = header.Number; + GasLimit = header.GasLimit; + GasUsed = header.GasUsed; + Timestamp = (UInt256)header.Timestamp; + ExtraData = header.ExtraData; + MixHash = header.MixHash; + + Nonce = new byte[8]; + BinaryPrimitives.WriteUInt64BigEndian(Nonce, header.Nonce); + + BaseFeePerGas = header.BaseFeePerGas; + WithdrawalsRoot = header.WithdrawalsRoot; + BlobGasUsed = header.BlobGasUsed; + ExcessBlobGas = header.ExcessBlobGas; + ParentBeaconBlockRoot = header.ParentBeaconBlockRoot; + RequestsHash = header.RequestsHash; + } + + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public Hash256? Hash { get; set; } + + public Hash256? ParentHash { get; set; } + public Hash256? Sha3Uncles { get; set; } + public Address? Miner { get; set; } + public Hash256? StateRoot { get; set; } + public Hash256? TransactionsRoot { get; set; } + public Hash256? ReceiptsRoot { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public Bloom? LogsBloom { get; set; } + public UInt256 Difficulty { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public long Number { get; set; } + + public long GasLimit { get; set; } + public long GasUsed { get; set; } + public UInt256 Timestamp { get; set; } + public byte[] ExtraData { get; set; } = []; + public Hash256? MixHash { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public byte[]? Nonce { get; set; } + public UInt256? BaseFeePerGas { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public Hash256? WithdrawalsRoot { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public ulong? BlobGasUsed { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public ulong? ExcessBlobGas { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public Hash256? ParentBeaconBlockRoot { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public Hash256? RequestsHash { get; set; } +} diff --git a/src/Nethermind/Nethermind.Taiko/Tdx/ISurgeTdxConfig.cs b/src/Nethermind/Nethermind.Taiko/Tdx/ISurgeTdxConfig.cs new file mode 100644 index 00000000000..0c86bff9795 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko/Tdx/ISurgeTdxConfig.cs @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Config; + +namespace Nethermind.Taiko.Tdx; + +public interface ISurgeTdxConfig : IConfig +{ + [ConfigItem(Description = "Path to the tdxs Unix socket.", DefaultValue = "/var/tdxs.sock")] + string SocketPath { get; set; } + + [ConfigItem(Description = "Path to store TDX bootstrap data and keys.", DefaultValue = "~/.config/nethermind/tdx")] + string ConfigPath { get; set; } +} + diff --git a/src/Nethermind/Nethermind.Taiko/Tdx/ITdxRpcModule.cs b/src/Nethermind/Nethermind.Taiko/Tdx/ITdxRpcModule.cs new file mode 100644 index 00000000000..6b1c514c7f5 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko/Tdx/ITdxRpcModule.cs @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Threading.Tasks; +using Nethermind.Blockchain.Find; +using Nethermind.JsonRpc; +using Nethermind.JsonRpc.Modules; + +namespace Nethermind.Taiko.Tdx; + +[RpcModule(ModuleType.Eth)] +public interface ITdxRpcModule : IRpcModule +{ + [JsonRpcMethod( + Description = "Returns TDX signed block header for the specified block.", + IsSharable = true, + IsImplemented = true)] + Task> taiko_tdxSignBlockHeader(BlockParameter blockParameter); + + [JsonRpcMethod( + Description = "Returns the TDX guest information for instance registration.", + IsSharable = true, + IsImplemented = true)] + Task> taiko_getTdxGuestInfo(); + + [JsonRpcMethod( + Description = "Bootstraps the TDX service (generates key, gets initial quote).", + IsSharable = false, + IsImplemented = true)] + Task> taiko_tdxBootstrap(); +} + diff --git a/src/Nethermind/Nethermind.Taiko/Tdx/ITdxService.cs b/src/Nethermind/Nethermind.Taiko/Tdx/ITdxService.cs new file mode 100644 index 00000000000..753f1dbde4b --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko/Tdx/ITdxService.cs @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core; + +namespace Nethermind.Taiko.Tdx; + +/// +/// Service for generating TDX attestations for blocks. +/// +public interface ITdxService +{ + /// + /// Whether the service is bootstrapped. + /// + bool IsBootstrapped { get; } + + /// + /// Bootstrap the TDX service: generate key, get initial quote. + /// + TdxGuestInfo Bootstrap(); + + /// + /// Get guest info if already bootstrapped. + /// + TdxGuestInfo? GetGuestInfo(); + + /// + /// Generate a TDX signature for the given block header. + /// + /// The block header to sign. + TdxBlockHeaderSignature SignBlockHeader(BlockHeader blockHeader); +} diff --git a/src/Nethermind/Nethermind.Taiko/Tdx/ITdxsClient.cs b/src/Nethermind/Nethermind.Taiko/Tdx/ITdxsClient.cs new file mode 100644 index 00000000000..d05dc3b12a9 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko/Tdx/ITdxsClient.cs @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Text.Json; + +namespace Nethermind.Taiko.Tdx; + +/// +/// Client for communicating with the tdxs daemon via Unix socket. +/// +public interface ITdxsClient +{ + /// + /// Issues a TDX attestation quote. + /// + /// User data to embed in the quote (typically 32 bytes). + /// Random nonce for freshness. + /// The attestation document (quote) bytes. + byte[] Issue(byte[] userData, byte[] nonce); + + /// + /// Gets metadata about the TDX environment. + /// + TdxMetadata GetMetadata(); +} + +public class TdxMetadata +{ + public required string IssuerType { get; init; } + public JsonElement? Metadata { get; init; } +} + diff --git a/src/Nethermind/Nethermind.Taiko/Tdx/SurgeTdxConfig.cs b/src/Nethermind/Nethermind.Taiko/Tdx/SurgeTdxConfig.cs new file mode 100644 index 00000000000..1edaaa04ad2 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko/Tdx/SurgeTdxConfig.cs @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +namespace Nethermind.Taiko.Tdx; + +public class SurgeTdxConfig : ISurgeTdxConfig +{ + public string SocketPath { get; set; } = "/var/tdxs.sock"; + public string ConfigPath { get; set; } = "~/.config/nethermind/tdx"; +} + diff --git a/src/Nethermind/Nethermind.Taiko/Tdx/TdxAttestation.cs b/src/Nethermind/Nethermind.Taiko/Tdx/TdxAttestation.cs new file mode 100644 index 00000000000..3e5d4b4d659 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko/Tdx/TdxAttestation.cs @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Text.Json; +using Nethermind.Core.Crypto; + +namespace Nethermind.Taiko.Tdx; + +/// +/// TDX signed block header containing the signature, block hash, state root and header. +/// Signature is over keccak(). +/// +public class TdxBlockHeaderSignature +{ + public required byte[] Signature { get; init; } + public required Hash256 BlockHash { get; init; } + public required Hash256 StateRoot { get; init; } + public required BlockHeaderForRpc Header { get; init; } +} + +/// +/// TDX guest information for instance registration and bootstrap persistence. +/// +public class TdxGuestInfo +{ + public required string IssuerType { get; init; } + public required string PublicKey { get; init; } + public required string Quote { get; init; } + public required string Nonce { get; init; } + public JsonElement? Metadata { get; init; } +} + diff --git a/src/Nethermind/Nethermind.Taiko/Tdx/TdxModule.cs b/src/Nethermind/Nethermind.Taiko/Tdx/TdxModule.cs new file mode 100644 index 00000000000..dcc8f651444 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko/Tdx/TdxModule.cs @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Autofac; +using Nethermind.Core; +using Nethermind.JsonRpc.Modules; +using Nethermind.Logging; +using Nethermind.Taiko.Config; + +namespace Nethermind.Taiko.Tdx; + +/// +/// Autofac module for TDX attestation services. +/// Services are registered regardless of config; RPC checks config at runtime. +/// +public class TdxModule : Module +{ + protected override void Load(ContainerBuilder builder) + { + base.Load(builder); + + builder.AddSingleton(); + + // Register TDX service - returns NullTdxService when disabled + builder.Register(ctx => + { + ISurgeConfig surgeConfig = ctx.Resolve(); + if (!surgeConfig.TdxEnabled) + return NullTdxService.Instance; + + return new TdxService( + ctx.Resolve(), + ctx.Resolve(), + ctx.Resolve()); + }).SingleInstance(); + + builder.RegisterSingletonJsonRpcModule(); + } +} diff --git a/src/Nethermind/Nethermind.Taiko/Tdx/TdxRpcModule.cs b/src/Nethermind/Nethermind.Taiko/Tdx/TdxRpcModule.cs new file mode 100644 index 00000000000..38de08a61a7 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko/Tdx/TdxRpcModule.cs @@ -0,0 +1,108 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Threading.Tasks; +using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; +using Nethermind.Core; +using Nethermind.JsonRpc; +using Nethermind.Logging; +using Nethermind.Taiko.Config; + +namespace Nethermind.Taiko.Tdx; + +public class TdxRpcModule( + ISurgeConfig config, + ITdxService tdxService, + IBlockFinder blockFinder, + ILogManager logManager) : ITdxRpcModule +{ + private static readonly ResultWrapper TdxDisabledInfo = + ResultWrapper.Fail("TDX is not enabled. Set Surge.TdxEnabled=true in configuration."); + + private readonly ILogger _logger = logManager.GetClassLogger(); + + public Task> taiko_tdxSignBlockHeader(BlockParameter blockParameter) + { + string? availabilityError = VerifyTdxAvailability(); + if (availabilityError is not null) + return Task.FromResult(ResultWrapper.Fail(availabilityError)); + + BlockHeader? blockHeader = FindBlockHeader(blockParameter); + if (blockHeader is null) + return Task.FromResult(ResultWrapper.Fail("Block not found")); + + try + { + TdxBlockHeaderSignature signature = tdxService.SignBlockHeader(blockHeader); + return Task.FromResult(ResultWrapper.Success(signature)); + } + catch (Exception ex) + { + _logger.Error($"Failed to sign block header: {ex.Message}", ex); + return Task.FromResult(ResultWrapper.Fail($"Signing failed: {ex.Message}")); + } + } + + private string? VerifyTdxAvailability() + { + if (!config.TdxEnabled) + return "TDX is not enabled. Set Surge.TdxEnabled=true in configuration."; + + return !tdxService.IsBootstrapped ? "TDX service not bootstrapped. Call taiko_tdxBootstrap first." : null; + } + + private BlockHeader? FindBlockHeader(BlockParameter blockParameter) + { + // Only allow valid canonical blocks for TDX attestation + BlockHeader? blockHeader; + BlockTreeLookupOptions options = BlockTreeLookupOptions.RequireCanonical + | BlockTreeLookupOptions.TotalDifficultyNotNeeded + | BlockTreeLookupOptions.ExcludeTxHashes; + + if (blockParameter.BlockHash is { } blockHash) + { + blockHeader = blockFinder.FindHeader(blockHash, options); + } + else if (blockParameter.BlockNumber is { } blockNumber) + { + blockHeader = blockFinder.FindHeader(blockNumber, options); + } + else + { + BlockHeader? header = blockFinder.FindHeader(blockParameter); + blockHeader = header is null ? null : blockFinder.FindHeader(header.Hash!, options); + } + + return blockHeader; + } + + public Task> taiko_getTdxGuestInfo() + { + if (!config.TdxEnabled) + return Task.FromResult(TdxDisabledInfo); + + TdxGuestInfo? info = tdxService.GetGuestInfo(); + return info is null + ? Task.FromResult(ResultWrapper.Fail("TDX service not bootstrapped. Call taiko_tdxBootstrap first.")) + : Task.FromResult(ResultWrapper.Success(info)); + } + + public Task> taiko_tdxBootstrap() + { + if (!config.TdxEnabled) + return Task.FromResult(TdxDisabledInfo); + + try + { + TdxGuestInfo info = tdxService.Bootstrap(); + return Task.FromResult(ResultWrapper.Success(info)); + } + catch (Exception ex) + { + _logger.Error($"Failed to bootstrap TDX: {ex.Message}", ex); + return Task.FromResult(ResultWrapper.Fail($"Bootstrap failed: {ex.Message}")); + } + } +} diff --git a/src/Nethermind/Nethermind.Taiko/Tdx/TdxService.cs b/src/Nethermind/Nethermind.Taiko/Tdx/TdxService.cs new file mode 100644 index 00000000000..192cb3ec241 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko/Tdx/TdxService.cs @@ -0,0 +1,228 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text.Json; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Crypto; +using Nethermind.Logging; +using Nethermind.Serialization.Rlp; + +namespace Nethermind.Taiko.Tdx; + +/// +/// Service for TDX signing operations. +/// +public class TdxService : ITdxService +{ + + private readonly ISurgeTdxConfig _config; + private readonly ITdxsClient _client; + private readonly ILogger _logger; + private readonly Ecdsa _ecdsa = new(); + + private TdxGuestInfo? _guestInfo; + private PrivateKey? _privateKey; + + public TdxService( + ISurgeTdxConfig config, + ITdxsClient client, + ILogManager logManager) + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + throw new PlatformNotSupportedException("TDX attestation is only supported on Linux"); + } + + _config = config; + _client = client; + _logger = logManager.GetClassLogger(); + + TryLoadBootstrap(); + } + + public bool IsBootstrapped => _guestInfo is not null && _privateKey is not null; + + public TdxGuestInfo Bootstrap() + { + if (IsBootstrapped) + { + _logger.Info("Already bootstrapped, returning existing data"); + return _guestInfo!; + } + + _logger.Info("Bootstrapping TDX service"); + + // Generate private key + using var keyGenerator = new PrivateKeyGenerator(); + _privateKey = keyGenerator.Generate(); + Address address = _privateKey.Address; + + _logger.Info($"Generated TDX instance address: {address}"); + + // Get TDX quote with address as user data (padded to 32 bytes) + byte[] userData = new byte[32]; + address.Bytes.CopyTo(userData.AsSpan(12)); + + byte[] nonce = new byte[32]; + new CryptoRandom().GenerateRandomBytes(nonce); + + byte[] quote = _client.Issue(userData, nonce); + TdxMetadata metadata = _client.GetMetadata(); + + _guestInfo = new TdxGuestInfo + { + IssuerType = metadata.IssuerType, + PublicKey = address.ToString(), + Quote = Convert.ToHexString(quote).ToLowerInvariant(), + Nonce = Convert.ToHexString(nonce).ToLowerInvariant(), + Metadata = metadata.Metadata + }; + + SaveBootstrap(_guestInfo); + _logger.Info($"TDX bootstrap complete. Quote length: {quote.Length} bytes"); + + return _guestInfo; + } + + public TdxGuestInfo? GetGuestInfo() + { + return _guestInfo; + } + + public TdxBlockHeaderSignature SignBlockHeader(BlockHeader blockHeader) + { + if (!IsBootstrapped) + throw new TdxException("TDX service not bootstrapped"); + + blockHeader.Hash ??= blockHeader.CalculateHash(); + + if (blockHeader.StateRoot is null) + throw new TdxException("Block header state root is null"); + + // Concatenate blockHash and stateRoot, then hash for signing + byte[] dataToHash = new byte[64]; + blockHeader.Hash.Bytes.CopyTo(dataToHash.AsSpan(0, 32)); + blockHeader.StateRoot.Bytes.CopyTo(dataToHash.AsSpan(32, 32)); + Hash256 signedHash = Keccak.Compute(dataToHash); + + Signature signature = _ecdsa.Sign(_privateKey!, signedHash); + + return new TdxBlockHeaderSignature + { + Signature = GetSignatureBytes(signature), + BlockHash = blockHeader.Hash, + StateRoot = blockHeader.StateRoot, + Header = new BlockHeaderForRpc(blockHeader) + }; + } + + /// + /// Get 65-byte signature in format [r:32][s:32][v:1] where v = 27 + recovery_id + /// + private static byte[] GetSignatureBytes(Signature signature) + { + byte[] result = new byte[Signature.Size]; + signature.Bytes.CopyTo(result.AsSpan(0, Signature.Size - 1)); // r + s + result[Signature.Size - 1] = (byte)signature.V; + return result; + } + + private bool TryLoadBootstrap() + { + string path = GetBootstrapPath(); + string keyPath = GetKeyPath(); + + if (!File.Exists(path) || !File.Exists(keyPath)) + return false; + + try + { + string json = File.ReadAllText(path); + _guestInfo = JsonSerializer.Deserialize(json); + + byte[] keyBytes = File.ReadAllBytes(keyPath); + _privateKey = new PrivateKey(keyBytes); + + if (IsBootstrapped) + { + _logger.Info($"Loaded TDX bootstrap data. Address: {_privateKey.Address}"); + return true; + } + + _logger.Warn("Failed to load TDX bootstrap data, invalid data"); + return false; + } + catch (Exception ex) + { + _logger.Warn($"Failed to load bootstrap data: {ex.Message}"); + _guestInfo = null; + _privateKey = null; + } + + return false; + } + + private void SaveBootstrap(TdxGuestInfo data) + { + string dir = GetConfigDir(); + string secretsDir = Path.Combine(dir, "secrets"); + Directory.CreateDirectory(secretsDir); + + // Save bootstrap data + string path = GetBootstrapPath(); + File.WriteAllText(path, JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true })); + + // Save key with 0600 file permissions + string keyPath = GetKeyPath(); + if (OperatingSystem.IsLinux()) + { + using var fs = new FileStream(keyPath, new FileStreamOptions + { + Mode = FileMode.Create, + Access = FileAccess.Write, + Share = FileShare.None, + UnixCreateMode = UnixFileMode.UserRead | UnixFileMode.UserWrite // 0600 + }); + fs.Write(_privateKey!.KeyBytes); + } + else + { + throw new PlatformNotSupportedException("TDX attestation is only supported on Linux"); + } + + _logger.Debug($"Saved TDX key to {keyPath}"); + } + + private string GetConfigDir() + { + string configPath = _config.ConfigPath; + if (configPath.StartsWith("~/")) + { + configPath = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + configPath[2..]); + } + return configPath; + } + + private string GetBootstrapPath() => Path.Combine(GetConfigDir(), "bootstrap.json"); + private string GetKeyPath() => Path.Combine(GetConfigDir(), "secrets", "priv.key"); +} + +/// +/// Null implementation of ITdxService for when TDX is disabled. +/// +internal sealed class NullTdxService : ITdxService +{ + public static readonly NullTdxService Instance = new(); + private NullTdxService() { } + + public bool IsBootstrapped => false; + public TdxGuestInfo? GetGuestInfo() => null; + public TdxGuestInfo Bootstrap() => throw new TdxException("TDX is not enabled"); + public TdxBlockHeaderSignature SignBlockHeader(BlockHeader blockHeader) => throw new TdxException("TDX is not enabled"); +} diff --git a/src/Nethermind/Nethermind.Taiko/Tdx/TdxsClient.cs b/src/Nethermind/Nethermind.Taiko/Tdx/TdxsClient.cs new file mode 100644 index 00000000000..081e3326219 --- /dev/null +++ b/src/Nethermind/Nethermind.Taiko/Tdx/TdxsClient.cs @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.IO; +using System.Net.Sockets; +using System.Text; +using System.Text.Json; +using Nethermind.Logging; + +namespace Nethermind.Taiko.Tdx; + +/// +/// Client for communicating with the tdxs daemon via Unix socket. +/// Protocol: JSON request/response over Unix socket. +/// +public class TdxsClient(ISurgeTdxConfig config, ILogManager logManager) : ITdxsClient +{ + private readonly ILogger _logger = logManager.GetClassLogger(); + + public byte[] Issue(byte[] userData, byte[] nonce) + { + var request = new + { + method = "issue", + data = new + { + userData = Convert.ToHexString(userData).ToLowerInvariant(), + nonce = Convert.ToHexString(nonce).ToLowerInvariant() + } + }; + + JsonElement response = SendRequest(request); + + if (response.TryGetProperty("error", out JsonElement error) && error.ValueKind != JsonValueKind.Null) + { + throw new TdxException($"Attestation service error: {error.GetString()}"); + } + + if (!response.TryGetProperty("data", out JsonElement data) || + !data.TryGetProperty("document", out JsonElement document)) + { + throw new TdxException("Invalid response: missing document"); + } + + return Convert.FromHexString(document.GetString()!); + } + + public TdxMetadata GetMetadata() + { + var request = new { method = "metadata", data = new { } }; + JsonElement response = SendRequest(request); + + if (response.TryGetProperty("error", out JsonElement error) && error.ValueKind != JsonValueKind.Null) + { + throw new TdxException($"Attestation service error: {error.GetString()}"); + } + + if (!response.TryGetProperty("data", out JsonElement data)) + { + throw new TdxException("Invalid response: missing data"); + } + + return new TdxMetadata + { + IssuerType = data.GetProperty("issuerType").GetString()!, + Metadata = data.TryGetProperty("metadata", out JsonElement meta) ? meta.Clone() : null + }; + } + + private JsonElement SendRequest(object request) + { + string socketPath = config.SocketPath; + + if (!File.Exists(socketPath)) + throw new TdxException($"TDX socket not found at {socketPath}"); + + using var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); + socket.Connect(new UnixDomainSocketEndPoint(socketPath)); + + using var stream = new NetworkStream(socket, ownsSocket: false); + + string requestJson = JsonSerializer.Serialize(request); + socket.Send(Encoding.UTF8.GetBytes(requestJson)); + socket.Shutdown(SocketShutdown.Send); + + return JsonSerializer.Deserialize(stream); + } +} + +public class TdxException(string message, Exception? innerException = null) + : Exception(message, innerException); From e5e4624dba42dac5a796994f7596fffc77c0c20b Mon Sep 17 00:00:00 2001 From: emmmm <155267286+eeemmmmmm@users.noreply.github.com> Date: Wed, 7 Jan 2026 13:24:11 -0500 Subject: [PATCH 181/255] Remove redundant `File.Delete` after `File.Move` (#10128) --- tools/DocGen/ConfigGenerator.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/DocGen/ConfigGenerator.cs b/tools/DocGen/ConfigGenerator.cs index 8810540e3da..4ef93e62645 100644 --- a/tools/DocGen/ConfigGenerator.cs +++ b/tools/DocGen/ConfigGenerator.cs @@ -68,7 +68,6 @@ internal static void Generate(string path) writeStream.Close(); File.Move(tempFileName, fileName, true); - File.Delete(tempFileName); AnsiConsole.MarkupLine($"[green]Updated[/] {fileName}"); } From fa474637be8aea77352f8f979513eca15c3440bc Mon Sep 17 00:00:00 2001 From: strmfos <155266597+strmfos@users.noreply.github.com> Date: Wed, 7 Jan 2026 20:20:06 +0100 Subject: [PATCH 182/255] refactor: simplify conditional returns in FeeTooLowFilter (#10129) --- .../Nethermind.TxPool/Filters/FeeTooLowFilter.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Nethermind/Nethermind.TxPool/Filters/FeeTooLowFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/FeeTooLowFilter.cs index 1ab5ab76a3b..dee9638a68f 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/FeeTooLowFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/FeeTooLowFilter.cs @@ -48,9 +48,7 @@ public AcceptTxResult Accept(Transaction tx, ref TxFilteringState state, TxHandl { Metrics.PendingTransactionsTooLowFee++; if (_logger.IsTrace) _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, too low payable gas price with options {handlingOptions} from {new StackTrace()}"); - return !isLocal ? - AcceptTxResult.FeeTooLow : - AcceptTxResult.FeeTooLow.WithMessage("Affordable gas price is 0"); + return AcceptTxResult.FeeTooLow; } TxDistinctSortedPool relevantPool = (tx.SupportsBlobs ? _blobTxs : _txs); @@ -63,10 +61,7 @@ public AcceptTxResult Accept(Transaction tx, ref TxFilteringState state, TxHandl _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, too low payable gas price with options {handlingOptions} from {new StackTrace()}"); } - return !isLocal ? - AcceptTxResult.FeeTooLow : - AcceptTxResult.FeeTooLow.WithMessage($"FeePerGas needs to be higher than {lastTx.GasBottleneck.Value} to be added to the TxPool. FeePerGas of rejected tx: {affordableGasPrice}."); - + return AcceptTxResult.FeeTooLow; } return AcceptTxResult.Accepted; From 32dc74a5c84fa0d3404928e78c866d39b5eac322 Mon Sep 17 00:00:00 2001 From: Bashmunta Date: Wed, 7 Jan 2026 21:20:26 +0200 Subject: [PATCH 183/255] refactor: remove unused finalization manager field in Optimism plugin (#10130) --- src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs index 0e0615b52e4..18854588d55 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs @@ -55,8 +55,6 @@ public class OptimismPlugin(ChainSpec chainSpec) : IConsensusPlugin private OptimismNethermindApi? _api; private ILogger _logger; - private ManualBlockFinalizationManager? _blockFinalizationManager; - private OptimismCL? _cl; public bool Enabled => chainSpec.SealEngineType == SealEngineType; @@ -108,7 +106,7 @@ public Task Init(INethermindApi api) ArgumentNullException.ThrowIfNull(_api.SpecProvider); - _api.FinalizationManager = _blockFinalizationManager = new ManualBlockFinalizationManager(); + _api.FinalizationManager = new ManualBlockFinalizationManager(); _api.GossipPolicy = ShouldNotGossip.Instance; @@ -127,7 +125,7 @@ public Task InitRpcModules() ArgumentNullException.ThrowIfNull(_api.RpcModuleProvider); ArgumentNullException.ThrowIfNull(_api.BlockProducer); - ArgumentNullException.ThrowIfNull(_blockFinalizationManager); + ArgumentNullException.ThrowIfNull(_api.FinalizationManager); IEngineRpcModule engineRpcModule = _api.Context.Resolve(); From cba46c22d49670adce3c918bb5d7b72e4507d8e8 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Thu, 8 Jan 2026 11:25:24 +0300 Subject: [PATCH 184/255] Optimize discv5 (#10081) * Update schema * Fix schema * No need in type cast * Use improved discv5; refactor * Update PierTwo.Lantern.Discv5.WireProtocol * Less errors * Pooled --- Directory.Packages.props | 2 +- .../Discv5/DiscoveryV5App.cs | 37 +++++++++++-------- .../Discv5/NettyDiscoveryV5Handler.cs | 11 ++++-- .../configs/base-sepolia.json | 2 +- .../Nethermind.Runner/packages.lock.json | 22 +++++------ 5 files changed, 42 insertions(+), 32 deletions(-) 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": { From 5420e7e51568b62f2af676f0cebc22fd0ef32f43 Mon Sep 17 00:00:00 2001 From: yyhrnk Date: Thu, 8 Jan 2026 12:02:30 +0200 Subject: [PATCH 185/255] refactor: remove unused `_pushEnabled` from MonitoringService (#10135) refactor: remove unused _pushEnabled from MonitoringService --- src/Nethermind/Nethermind.Monitoring/MonitoringService.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Monitoring/MonitoringService.cs b/src/Nethermind/Nethermind.Monitoring/MonitoringService.cs index 1ee91ac12db..a4d23fa75f0 100644 --- a/src/Nethermind/Nethermind.Monitoring/MonitoringService.cs +++ b/src/Nethermind/Nethermind.Monitoring/MonitoringService.cs @@ -22,7 +22,6 @@ public class MonitoringService : IMonitoringService, IStoppableService private readonly string _exposeHost; private readonly int? _exposePort; private readonly string _nodeName; - private readonly bool _pushEnabled; private readonly string _pushGatewayUrl; private readonly int _intervalSeconds; @@ -34,7 +33,6 @@ public MonitoringService(IMetricsController metricsController, IMetricsConfig me int? exposePort = metricsConfig.ExposePort; string nodeName = metricsConfig.NodeName; string pushGatewayUrl = metricsConfig.PushGatewayUrl; - bool pushEnabled = metricsConfig.Enabled; int intervalSeconds = metricsConfig.IntervalSeconds; _exposeHost = exposeHost; @@ -43,7 +41,6 @@ public MonitoringService(IMetricsController metricsController, IMetricsConfig me ? throw new ArgumentNullException(nameof(nodeName)) : nodeName; _pushGatewayUrl = pushGatewayUrl; - _pushEnabled = pushEnabled; _intervalSeconds = intervalSeconds <= 0 ? throw new ArgumentException($"Invalid monitoring push interval: {intervalSeconds}s") : intervalSeconds; From f1fc64a22294bf0b523a07b6be84df27e5563b79 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Thu, 8 Jan 2026 13:58:00 +0300 Subject: [PATCH 186/255] Add some guards to RetryCache (#10134) * Add some guards to RetryCache Co-authored-by: Lukasz Rozmej --------- Co-authored-by: Lukasz Rozmej Co-authored-by: Marcos Antonio Maceo <35319980+stdevMac@users.noreply.github.com> --- Directory.Packages.props | 1 - .../V66/PooledTransactionsRequestingTests.cs | 3 +- .../Eth/V65/Eth65ProtocolHandler.cs | 2 +- .../Eth/V68/Eth68ProtocolHandler.cs | 2 +- .../Nethermind.Runner/packages.lock.json | 8 +- .../Nethermind.TxPool.Test/RetryCacheTests.cs | 26 ++- src/Nethermind/Nethermind.TxPool/ITxPool.cs | 2 +- .../Nethermind.TxPool.csproj | 2 +- .../Nethermind.TxPool/NullTxPool.cs | 2 +- .../Nethermind.TxPool/RetryCache.cs | 158 ++++++++++++++---- src/Nethermind/Nethermind.TxPool/TxPool.cs | 9 +- 11 files changed, 157 insertions(+), 58 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index de1da8ae56d..689a8550a51 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,6 @@ - diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsRequestingTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsRequestingTests.cs index 65667733805..3e7b97e6b71 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsRequestingTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsRequestingTests.cs @@ -77,11 +77,10 @@ public void Setup() new BlobTxStorage(), new ChainHeadInfoProvider( new ChainHeadSpecProvider(specProvider, blockTree), blockTree, TestWorldStateFactory.CreateForTestWithStateReader(TestMemDbProvider.Init(), LimboLogs.Instance).Item2), - new TxPoolConfig(), + new TxPoolConfig() { AcceptTxWhenNotSynced = true }, new TxValidator(specProvider.ChainId), LimboLogs.Instance, new TransactionComparerProvider(specProvider, blockTree).GetDefaultComparer()); - ISyncServer syncManager = Substitute.For(); syncManager.Head.Returns(_genesisBlock.Header); syncManager.Genesis.Returns(_genesisBlock.Header); diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs index 7accd12689d..2442a438221 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs @@ -229,7 +229,7 @@ private ArrayPoolList AddMarkUnknownHashes(ReadOnlySpan hashes Hash256 hash = hashes[i]; if (!_txPool.IsKnown(hash)) { - if (_txPool.AnnounceTx(hash, this) is AnnounceResult.New) + if (_txPool.NoitifyAboutTx(hash, this) is AnnounceResult.RequestRequired) { discoveredTxHashesAndSizes.Add(hash); } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs index 22e2f6a5903..bb628264ecc 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs @@ -171,7 +171,7 @@ private ArrayPoolListRef AddMarkUnknownHashes(ReadOnlySpan hashes) Hash256 hash = hashes[i]; if (!_txPool.IsKnown(hash)) { - if (_txPool.AnnounceTx(hash, this) is AnnounceResult.New) + if (_txPool.NoitifyAboutTx(hash, this) is AnnounceResult.RequestRequired) { discoveredTxHashesAndSizes.Add(i); } diff --git a/src/Nethermind/Nethermind.Runner/packages.lock.json b/src/Nethermind/Nethermind.Runner/packages.lock.json index b4dd4eabb03..31ec3ddbf6b 100644 --- a/src/Nethermind/Nethermind.Runner/packages.lock.json +++ b/src/Nethermind/Nethermind.Runner/packages.lock.json @@ -1156,7 +1156,7 @@ "nethermind.txpool": { "type": "Project", "dependencies": { - "Collections.Pooled": "[1.0.82, )", + "ConcurrentHashSet": "[1.3.0, )", "Nethermind.Config": "[1.37.0-unstable, )", "Nethermind.Core": "[1.37.0-unstable, )", "Nethermind.Crypto": "[1.37.0-unstable, )", @@ -1240,12 +1240,6 @@ "resolved": "2.1.5.1544", "contentHash": "xKg/UV2QpE7A2Oe8Ipry2BLRxDSM0sRsKL5INwGkrNmrRkZbdVCjfbSg7Nubvtw2/c7OTGHeMh4gg35rd9MqOA==" }, - "Collections.Pooled": { - "type": "CentralTransitive", - "requested": "[1.0.82, )", - "resolved": "1.0.82", - "contentHash": "o14V0k8bg+EPMwaVJcFbLNrkyDPaqNx6fWTTjJLgVWJLu939kVIAAWKaV5lCwZ7LM/tv59igi65rVWRyjILc0Q==" - }, "CommunityToolkit.HighPerformance": { "type": "CentralTransitive", "requested": "[8.4.0, )", diff --git a/src/Nethermind/Nethermind.TxPool.Test/RetryCacheTests.cs b/src/Nethermind/Nethermind.TxPool.Test/RetryCacheTests.cs index 8cd47a0a4e7..9b09028feda 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/RetryCacheTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/RetryCacheTests.cs @@ -48,8 +48,8 @@ public void Announced_SameResourceDifferentNode_ReturnsEnqueued() AnnounceResult result1 = _cache.Announced(1, Substitute.For()); AnnounceResult result2 = _cache.Announced(1, Substitute.For()); - Assert.That(result1, Is.EqualTo(AnnounceResult.New)); - Assert.That(result2, Is.EqualTo(AnnounceResult.Enqueued)); + Assert.That(result1, Is.EqualTo(AnnounceResult.RequestRequired)); + Assert.That(result2, Is.EqualTo(AnnounceResult.Delayed)); } [Test] @@ -91,7 +91,7 @@ public void Received_RemovesResourceFromRetryQueue() _cache.Received(1); AnnounceResult result = _cache.Announced(1, Substitute.For()); - Assert.That(result, Is.EqualTo(AnnounceResult.New)); + Assert.That(result, Is.EqualTo(AnnounceResult.RequestRequired)); } [Test] @@ -109,6 +109,24 @@ public async Task Received_BeforeTimeout_PreventsRetryExecution() request.DidNotReceive().HandleMessage(ResourceRequestMessage.New(1)); } + [Test] + public async Task Clear_cache_after_timeout() + { + Parallel.For(0, 100, (i) => + { + Parallel.For(0, 100, (j) => + { + ITestHandler request = Substitute.For(); + + _cache.Announced(i, request); + }); + }); + + await Task.Delay(Timeout * 2, _cancellationTokenSource.Token); + + Assert.That(_cache.ResourcesInRetryQueue, Is.Zero); + } + [Test] public void RetryExecution_HandlesExceptions() { @@ -143,7 +161,7 @@ public async Task Announced_AfterRetryInProgress_ReturnsNew() await Task.Delay(Timeout, _cancellationTokenSource.Token); - Assert.That(() => _cache.Announced(1, Substitute.For()), Is.EqualTo(AnnounceResult.New).After(Timeout, 100)); + Assert.That(() => _cache.Announced(1, Substitute.For()), Is.EqualTo(AnnounceResult.RequestRequired).After(Timeout, 100)); } [Test] diff --git a/src/Nethermind/Nethermind.TxPool/ITxPool.cs b/src/Nethermind/Nethermind.TxPool/ITxPool.cs index bdee1f2f448..a8f4507b8d1 100644 --- a/src/Nethermind/Nethermind.TxPool/ITxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/ITxPool.cs @@ -39,7 +39,7 @@ public interface ITxPool void AddPeer(ITxPoolPeer peer); void RemovePeer(PublicKey nodeId); bool ContainsTx(Hash256 hash, TxType txType); - AnnounceResult AnnounceTx(ValueHash256 txhash, IMessageHandler retryHandler); + AnnounceResult NoitifyAboutTx(Hash256 txhash, IMessageHandler retryHandler); AcceptTxResult SubmitTx(Transaction tx, TxHandlingOptions handlingOptions); bool RemoveTransaction(Hash256? hash); Transaction? GetBestTx(); diff --git a/src/Nethermind/Nethermind.TxPool/Nethermind.TxPool.csproj b/src/Nethermind/Nethermind.TxPool/Nethermind.TxPool.csproj index 2f5a3bab0bf..a229c249e60 100644 --- a/src/Nethermind/Nethermind.TxPool/Nethermind.TxPool.csproj +++ b/src/Nethermind/Nethermind.TxPool/Nethermind.TxPool.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/Nethermind/Nethermind.TxPool/NullTxPool.cs b/src/Nethermind/Nethermind.TxPool/NullTxPool.cs index 49d519cc02c..40a6855a4b3 100644 --- a/src/Nethermind/Nethermind.TxPool/NullTxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/NullTxPool.cs @@ -87,7 +87,7 @@ public bool TryGetBlobAndProofV1(byte[] blobVersionedHash, public UInt256 GetLatestPendingNonce(Address address) => 0; - public AnnounceResult AnnounceTx(ValueHash256 txhash, IMessageHandler retryHandler) => AnnounceResult.New; + public AnnounceResult NoitifyAboutTx(Hash256 txhash, IMessageHandler retryHandler) => AnnounceResult.RequestRequired; public event EventHandler NewDiscovered { diff --git a/src/Nethermind/Nethermind.TxPool/RetryCache.cs b/src/Nethermind/Nethermind.TxPool/RetryCache.cs index e4d918f7227..24c979ce1f6 100644 --- a/src/Nethermind/Nethermind.TxPool/RetryCache.cs +++ b/src/Nethermind/Nethermind.TxPool/RetryCache.cs @@ -1,7 +1,8 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Collections.Pooled; +using ConcurrentCollections; +using Microsoft.Extensions.ObjectPool; using Nethermind.Core; using Nethermind.Core.Caching; using Nethermind.Logging; @@ -12,109 +13,194 @@ namespace Nethermind.TxPool; -public class RetryCache +public sealed class RetryCache : IAsyncDisposable where TMessage : INew where TResourceId : struct, IEquatable { private readonly int _timeoutMs; + private readonly CancellationToken _token; private readonly int _checkMs; - - private readonly ConcurrentDictionary>> _retryRequests = new(); + private readonly int _expiringQueueLimit; + private readonly int _maxRetryRequests; + private readonly Task _mainLoopTask; + private static readonly ObjectPool>> _handlerBagsPool = new DefaultObjectPool>>(new ConcurrentBagPolicy>()); + private readonly ConcurrentDictionary>> _retryRequests = new(); private readonly ConcurrentQueue<(TResourceId ResourceId, DateTimeOffset ExpiresAfter)> _expiringQueue = new(); + private int _expiringQueueCounter = 0; private readonly ClockKeyCache _requestingResources; private readonly ILogger _logger; - public RetryCache(ILogManager logManager, int timeoutMs = 2500, int requestingCacheSize = 1024, CancellationToken token = default) + internal int ResourcesInRetryQueue => _expiringQueueCounter; + + public RetryCache(ILogManager logManager, int timeoutMs = 2500, int requestingCacheSize = 1024, int expiringQueueLimit = 10000, int maxRetryRequests = 8, CancellationToken token = default) { _logger = logManager.GetClassLogger(); _timeoutMs = timeoutMs; + _token = token; _checkMs = _timeoutMs / 5; _requestingResources = new(requestingCacheSize); + _expiringQueueLimit = expiringQueueLimit; + _maxRetryRequests = maxRetryRequests; - Task.Run(async () => + _mainLoopTask = Task.Run(async () => { PeriodicTimer timer = new(TimeSpan.FromMilliseconds(_checkMs)); while (await timer.WaitForNextTickAsync(token)) { - while (!token.IsCancellationRequested && _expiringQueue.TryPeek(out (TResourceId ResourceId, DateTimeOffset ExpiresAfter) item) && item.ExpiresAfter <= DateTimeOffset.UtcNow) + try { - _expiringQueue.TryDequeue(out item); - - if (_retryRequests.TryRemove(item.ResourceId, out PooledSet>? requests)) + while (!token.IsCancellationRequested && _expiringQueue.TryPeek(out (TResourceId ResourceId, DateTimeOffset ExpiresAfter) item) && item.ExpiresAfter <= DateTimeOffset.UtcNow) { - using (requests) + if (_expiringQueue.TryDequeue(out item)) { - if (requests.Count > 0) - { - _requestingResources.Set(item.ResourceId); - } - - if (_logger.IsTrace) _logger.Trace($"Sending retry requests for {item.ResourceId} after timeout"); + Interlocked.Decrement(ref _expiringQueueCounter); - - foreach (IMessageHandler retryHandler in requests) + if (_retryRequests.TryRemove(item.ResourceId, out ConcurrentHashSet>? requests)) { try { - retryHandler.HandleMessage(TMessage.New(item.ResourceId)); + bool set = false; + + foreach (IMessageHandler retryHandler in requests) + { + if (!set) + { + _requestingResources.Set(item.ResourceId); + set = true; + + if (_logger.IsTrace) _logger.Trace($"Sending retry requests for {item.ResourceId} after timeout"); + } + + try + { + retryHandler.HandleMessage(TMessage.New(item.ResourceId)); + } + catch (Exception ex) + { + if (_logger.IsTrace) _logger.Error($"Failed to send retry request to {retryHandler} for {item.ResourceId}", ex); + } + } } - catch (Exception ex) + finally { - if (_logger.IsTrace) _logger.Error($"Failed to send retry request to {retryHandler} for {item.ResourceId}", ex); + _handlerBagsPool.Return(requests); } } } } } + catch (Exception ex) + { + if (_logger.IsError) _logger.Error($"Unexpected error in {nameof(TResourceId)} retry cache loop", ex); + Clear(); + } } + + if (_logger.IsDebug) _logger.Debug($"{nameof(TResourceId)} retry cache stopped"); }, token); } - public AnnounceResult Announced(TResourceId resourceId, IMessageHandler retryHandler) + public AnnounceResult Announced(in TResourceId resourceId, IMessageHandler retryHandler) { + if (_token.IsCancellationRequested) + { + return AnnounceResult.RequestRequired; + } + + if (_expiringQueueCounter > _expiringQueueLimit) + { + if (_logger.IsDebug) _logger.Warn($"{nameof(TResourceId)} retry queue is full"); + + return AnnounceResult.RequestRequired; + } + if (!_requestingResources.Contains(resourceId)) { - bool added = false; + AnnounceResult result = AnnounceResult.Delayed; _retryRequests.AddOrUpdate(resourceId, (resourceId) => { if (_logger.IsTrace) _logger.Trace($"Announced {resourceId} by {retryHandler}: NEW"); _expiringQueue.Enqueue((resourceId, DateTimeOffset.UtcNow.AddMilliseconds(_timeoutMs))); - added = true; + Interlocked.Increment(ref _expiringQueueCounter); + + result = AnnounceResult.RequestRequired; - return []; - }, (resourceId, dict) => + return _handlerBagsPool.Get(); + }, (resourceId, requests) => { if (_logger.IsTrace) _logger.Trace($"Announced {resourceId} by {retryHandler}: UPDATE"); - dict.Add(retryHandler); - return dict; + if (requests.Count < _maxRetryRequests) + { + requests.Add(retryHandler); + } + + return requests; }); - return added ? AnnounceResult.New : AnnounceResult.Enqueued; + return result; } if (_logger.IsTrace) _logger.Trace($"Announced {resourceId} by {retryHandler}, but a retry is in progress already, immediately firing"); - return AnnounceResult.New; + return AnnounceResult.RequestRequired; } - public void Received(TResourceId resourceId) + public void Received(in TResourceId resourceId) { if (_logger.IsTrace) _logger.Trace($"Received {resourceId}"); - _retryRequests.TryRemove(resourceId, out PooledSet>? _); + if (_retryRequests.TryRemove(resourceId, out ConcurrentHashSet>? item)) + { + _handlerBagsPool.Return(item); + } + _requestingResources.Delete(resourceId); } + + private void Clear() + { + _expiringQueueCounter = 0; + _expiringQueue.Clear(); + _requestingResources.Clear(); + + foreach (ConcurrentHashSet> requests in _retryRequests.Values) + { + _handlerBagsPool.Return(requests); + } + + _retryRequests.Clear(); + } + + public async ValueTask DisposeAsync() + { + try + { + await _mainLoopTask; + } + catch (OperationCanceledException) { } + + Clear(); + } } public enum AnnounceResult { - New, - Enqueued, - PendingRequest + RequestRequired, + Delayed } +internal class ConcurrentBagPolicy : IPooledObjectPolicy> +{ + public ConcurrentHashSet Create() => []; + + public bool Return(ConcurrentHashSet obj) + { + obj.Clear(); + return true; + } +} diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index 98b8fd4da1e..b5596680f02 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -493,7 +493,6 @@ public AcceptTxResult SubmitTx(Transaction tx, TxHandlingOptions handlingOptions // If local tx allow it to be accepted even when syncing !startBroadcast) { - _retryCache.Received(tx.Hash!); return AcceptTxResult.Syncing; } @@ -577,7 +576,10 @@ private void TryConvertProofVersion(Transaction tx) } } - public AnnounceResult AnnounceTx(ValueHash256 txhash, IMessageHandler retryHandler) => _retryCache.Announced(txhash, retryHandler); + public AnnounceResult NoitifyAboutTx(Hash256 hash, IMessageHandler retryHandler) => + (!AcceptTxWhenNotSynced && _headInfo.IsSyncing) || _hashCache.Get(hash) ? + AnnounceResult.Delayed : + _retryCache.Announced(hash, retryHandler); private AcceptTxResult FilterTransactions(Transaction tx, TxHandlingOptions handlingOptions, ref TxFilteringState state) { @@ -958,13 +960,14 @@ public async ValueTask DisposeAsync() if (_isDisposed) return; _isDisposed = true; _timer?.Dispose(); - _cts.Cancel(); + await _cts.CancelAsync(); TxPoolHeadChanged -= _broadcaster.OnNewHead; _broadcaster.Dispose(); _headInfo.HeadChanged -= OnHeadChange; _headBlocksChannel.Writer.Complete(); _transactions.Removed -= OnRemovedTx; + await _retryCache.DisposeAsync(); await _headProcessing; } From 868bdcdb81a19a8a59d038ac8c5ccc69e4995510 Mon Sep 17 00:00:00 2001 From: ak88 Date: Thu, 8 Jan 2026 13:30:38 +0100 Subject: [PATCH 187/255] XDC save snapshot on gap block (#9774) * start * state reader * state reader * masternode voting contract * fix * blocktree saves snapshot on gap * abi json * working load test * test * test * test getCandidates * cleanup * format * update masternodes * hooked up with deposit contract * remove var * format * review comments * format * test rewrite * test fix * format * test save snapshot on head block * merge fix * cleanup * merge fix * merge fix * merge fix * remove using * remove class * fix MasternodeVotingContract IOC --- src/Nethermind/Chains/xdc.json | 23 ++++--- .../Nethermind.Blockchain/BlockTree.cs | 24 +++---- .../MasternodeVotingContractTests.cs | 14 +++- .../Helpers/XdcModuleTestOverrides.cs | 4 ++ .../Helpers/XdcTestBlockchain.cs | 20 ------ .../Helpers/XdcTestDepositContract.cs | 34 ++++++++++ .../ModuleTests/MineModuleTests.cs | 4 +- .../SnapshotManagerTests.cs | 41 ++++++++--- .../TimeoutCertificateManagerTests.cs | 6 +- .../Contracts/CandidateStake.cs | 13 ++++ .../Contracts/IMasternodeVotingContract.cs | 2 + .../Contracts/MasternodeVotingContract.cs | 68 +++++++++++++++---- .../Nethermind.Xdc/ISnapshotManager.cs | 2 +- .../Nethermind.Xdc/SnapshotManager.cs | 59 ++++++++++++++-- .../TimeoutCertificateManager.cs | 4 +- src/Nethermind/Nethermind.Xdc/VotesManager.cs | 2 +- src/Nethermind/Nethermind.Xdc/XdcBlockTree.cs | 4 +- src/Nethermind/Nethermind.Xdc/XdcModule.cs | 40 +++++------ 18 files changed, 259 insertions(+), 105 deletions(-) create mode 100644 src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestDepositContract.cs create mode 100644 src/Nethermind/Nethermind.Xdc/Contracts/CandidateStake.cs diff --git a/src/Nethermind/Chains/xdc.json b/src/Nethermind/Chains/xdc.json index 591e0f045b3..45908962ee4 100644 --- a/src/Nethermind/Chains/xdc.json +++ b/src/Nethermind/Chains/xdc.json @@ -45,20 +45,20 @@ "MinePeriod": 2 }, { - "MaxMasternodes": 108, - "SwitchRound": 460000, - "CertThreshold": 0.667, + "MaxMasternodes": 108, + "SwitchRound": 460000, + "CertThreshold": 0.667, "TimeoutSyncThreshold": 2, - "TimeoutPeriod": 20, - "MinePeriod": 2 + "TimeoutPeriod": 20, + "MinePeriod": 2 }, { - "MaxMasternodes": 108, - "SwitchRound": 3200000, - "CertThreshold": 0.667, + "MaxMasternodes": 108, + "SwitchRound": 3200000, + "CertThreshold": 0.667, "TimeoutSyncThreshold": 3, - "TimeoutPeriod": 10, - "MinePeriod": 2 + "TimeoutPeriod": 10, + "MinePeriod": 2 } ], "masternodeVotingContract": "0x0000000000000000000000000000000000000088", @@ -73,7 +73,8 @@ "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "eip155Block": 3, "eip158Block": 3, - "byzantiumBlock": 4 + "byzantiumBlock": 4, + "depositContractAddress": "0x0000000000000000000000000000000000000088" }, "genesis": { "nonce": "0x0", diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs index 76b21345fb4..a9ccc310da6 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs @@ -49,7 +49,7 @@ public partial class BlockTree : IBlockTree new(128, 128, "invalid blocks"); protected readonly ILogger Logger; - private readonly ISpecProvider _specProvider; + protected readonly ISpecProvider SpecProvider; private readonly IBloomStorage _bloomStorage; private readonly ISyncConfig _syncConfig; private readonly IChainLevelInfoRepository _chainLevelInfoRepository; @@ -94,9 +94,9 @@ public BlockHeader? LowestInsertedBeaconHeader public long BestKnownBeaconNumber { get; private set; } - public ulong NetworkId => _specProvider.NetworkId; + public ulong NetworkId => SpecProvider.NetworkId; - public ulong ChainId => _specProvider.ChainId; + public ulong ChainId => SpecProvider.ChainId; private int _canAcceptNewBlocksCounter; public bool CanAcceptNewBlocks => _canAcceptNewBlocksCounter == 0; @@ -126,7 +126,7 @@ public BlockTree( _blockInfoDb = blockInfoDb ?? throw new ArgumentNullException(nameof(blockInfoDb)); _metadataDb = metadataDb ?? throw new ArgumentNullException(nameof(metadataDb)); _badBlockStore = badBlockStore ?? throw new ArgumentNullException(nameof(badBlockStore)); - _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); + SpecProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _bloomStorage = bloomStorage ?? throw new ArgumentNullException(nameof(bloomStorage)); _syncConfig = syncConfig ?? throw new ArgumentNullException(nameof(syncConfig)); _chainLevelInfoRepository = chainLevelInfoRepository ?? @@ -1132,7 +1132,7 @@ public void UpdateBeaconMainChain(BlockInfo[]? blockInfos, long clearBeaconMainC public bool IsBetterThanHead(BlockHeader? header) => header is not null // null is never better && ((header.IsGenesis && Genesis is null) // is genesis - || header.TotalDifficulty >= _specProvider.TerminalTotalDifficulty // is post-merge block, we follow engine API + || header.TotalDifficulty >= SpecProvider.TerminalTotalDifficulty // is post-merge block, we follow engine API || header.TotalDifficulty > (Head?.TotalDifficulty ?? 0) // pre-merge rules || (header.TotalDifficulty == Head?.TotalDifficulty // when in doubt on difficulty && ((Head?.Number ?? 0L).CompareTo(header.Number) > 0 // pick longer chain @@ -1210,15 +1210,15 @@ protected virtual bool HeadImprovementRequirementsSatisfied(BlockHeader header) // before merge TD requirements are satisfied only if TD > block head bool preMergeImprovementRequirementSatisfied = header.TotalDifficulty > (Head?.TotalDifficulty ?? 0) && (header.TotalDifficulty < - _specProvider.TerminalTotalDifficulty - || _specProvider.TerminalTotalDifficulty is null); + SpecProvider.TerminalTotalDifficulty + || SpecProvider.TerminalTotalDifficulty is null); // after the merge, we will accept only the blocks with Difficulty = 0. However, during the transition process // we can have terminal PoW blocks with Difficulty > 0. That is why we accept everything greater or equal // than current head and header.TD >= TTD. - bool postMergeImprovementRequirementSatisfied = _specProvider.TerminalTotalDifficulty is not null && + bool postMergeImprovementRequirementSatisfied = SpecProvider.TerminalTotalDifficulty is not null && header.TotalDifficulty >= - _specProvider.TerminalTotalDifficulty; + SpecProvider.TerminalTotalDifficulty; return preMergeImprovementRequirementSatisfied || postMergeImprovementRequirementSatisfied; } @@ -1226,11 +1226,11 @@ private bool BestSuggestedImprovementRequirementsSatisfied(BlockHeader header) { if (BestSuggestedHeader is null) return true; - bool reachedTtd = header.IsPostTTD(_specProvider); + bool reachedTtd = header.IsPostTTD(SpecProvider); bool isPostMerge = header.IsPoS(); bool tdImproved = header.TotalDifficulty > (BestSuggestedBody?.TotalDifficulty ?? 0); bool preMergeImprovementRequirementSatisfied = tdImproved && !reachedTtd; - bool terminalBlockRequirementSatisfied = tdImproved && reachedTtd && header.IsTerminalBlock(_specProvider) && !Head.IsPoS(); + bool terminalBlockRequirementSatisfied = tdImproved && reachedTtd && header.IsTerminalBlock(SpecProvider) && !Head.IsPoS(); bool postMergeImprovementRequirementSatisfied = reachedTtd && (BestSuggestedBody?.Number ?? 0) <= header.Number && isPostMerge; return preMergeImprovementRequirementSatisfied || terminalBlockRequirementSatisfied || postMergeImprovementRequirementSatisfied; @@ -1498,7 +1498,7 @@ private bool IsTotalDifficultyAlwaysZero() { // In some Ethereum tests and possible testnets difficulty of all blocks might be zero // We also checking TTD is zero to ensure that block after genesis have zero difficulty - return Genesis?.Difficulty == 0 && _specProvider.TerminalTotalDifficulty == 0; + return Genesis?.Difficulty == 0 && SpecProvider.TerminalTotalDifficulty == 0; } private void SetTotalDifficultyFromBlockInfo(BlockHeader header, BlockInfo blockInfo) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs index fd9801cfef6..359111e4158 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs @@ -5,6 +5,7 @@ using FluentAssertions; using Nethermind.Abi; using Nethermind.Blockchain; +using Nethermind.Consensus.Processing; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -66,10 +67,19 @@ public void GetCandidatesAndStake_GenesisSetup_CanReadExpectedCandidates() } EthereumCodeInfoRepository codeInfoRepository = new(stateProvider); - EthereumVirtualMachine virtualMachine = new(new TestBlockhashProvider(specProvider), specProvider, LimboLogs.Instance); + VirtualMachine virtualMachine = new(new TestBlockhashProvider(specProvider), specProvider, LimboLogs.Instance); EthereumTransactionProcessor transactionProcessor = new(BlobBaseFeeCalculator.Instance, specProvider, stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); - MasternodeVotingContract masterVoting = new(stateProvider, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(transactionProcessor, stateProvider, Substitute.For())); + AutoReadOnlyTxProcessingEnv autoReadOnlyTxProcessingEnv = new AutoReadOnlyTxProcessingEnv(transactionProcessor, stateProvider, Substitute.For()); + + IReadOnlyTxProcessingEnvFactory readOnlyTxProcessingEnvFactory = Substitute.For(); + + readOnlyTxProcessingEnvFactory.Create().Returns(autoReadOnlyTxProcessingEnv); + //EthereumCodeInfoRepository codeInfoRepository = new(stateProvider); + //EthereumVirtualMachine virtualMachine = new(new TestBlockhashProvider(specProvider), specProvider, LimboLogs.Instance); + //EthereumTransactionProcessor transactionProcessor = new(BlobBaseFeeCalculator.Instance, specProvider, stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + + MasternodeVotingContract masterVoting = new(new AbiEncoder(), codeSource, readOnlyTxProcessingEnvFactory); Address[] candidates = masterVoting.GetCandidates(genesis); candidates.Length.Should().Be(3); diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcModuleTestOverrides.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcModuleTestOverrides.cs index 4adfbfcd4f1..fb2b1b0edad 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcModuleTestOverrides.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcModuleTestOverrides.cs @@ -10,6 +10,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Core.Test.Modules; +using Nethermind.Init.Modules; using Nethermind.JsonRpc; using Nethermind.KeyStore; using Nethermind.Logging; @@ -18,6 +19,7 @@ using Nethermind.Serialization.Rlp; using Nethermind.TxPool; using Nethermind.Wallet; +using Nethermind.Xdc.Contracts; using Nethermind.Xdc.Spec; using Nethermind.Xdc.Types; using NSubstitute; @@ -48,6 +50,8 @@ protected override void Load(ContainerBuilder builder) .AddModule(new PseudoNetworkModule()) .AddModule(new TestBlockProcessingModule()) + .AddSingleton() + // add missing components .AddSingleton() .AddSingleton() diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs index 179d8194013..f4b27d472f4 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs @@ -178,7 +178,6 @@ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder, new XdcTestGenesisBuilder( ctx.Resolve(), ctx.Resolve(), - ctx.Resolve(), ctx.Resolve>().ToArray(), ctx.Resolve(), MasterNodeCandidates @@ -314,7 +313,6 @@ protected override IBlockProducerRunner CreateBlockProducerRunner() private class XdcTestGenesisBuilder( ISpecProvider specProvider, IWorldState state, - ISnapshotManager snapshotManager, IGenesisPostProcessor[] postProcessors, Configuration testConfiguration, List masterNodeCandidates @@ -350,7 +348,6 @@ public Block Build() state.CommitTree(0); genesisBlock.Header.StateRoot = state.StateRoot; genesisBlock.Header.Hash = genesisBlock.Header.CalculateHash(); - snapshotManager.StoreSnapshot(new Types.Snapshot(genesisBlock.Number, genesisBlock.Hash!, finalSpec.GenesisMasterNodes)); return genesisBlock; } } @@ -396,16 +393,12 @@ public override async Task AddBlock(params Transaction[] transactions) { var b = await AddBlockWithoutCommitQc(transactions); CreateAndCommitQC((XdcBlockHeader)b.Header); - return b; } public override async Task AddBlockFromParent(BlockHeader parent, params Transaction[] transactions) { var b = await base.AddBlockFromParent(parent, transactions); - - CheckIfTimeForSnapshot(); - CreateAndCommitQC((XdcBlockHeader)b.Header); return b; @@ -414,22 +407,9 @@ public override async Task AddBlockFromParent(BlockHeader parent, params public async Task AddBlockWithoutCommitQc(params Transaction[] txs) { await base.AddBlock(txs); - - CheckIfTimeForSnapshot(); - return BlockTree.Head!; } - private void CheckIfTimeForSnapshot() - { - var head = (XdcBlockHeader)BlockTree.Head!.Header; - var headSpec = SpecProvider.GetXdcSpec(head, XdcContext.CurrentRound); - if (ISnapshotManager.IsTimeforSnapshot(head.Number, headSpec)) - { - SnapshotManager.StoreSnapshot(new Types.Snapshot(head.Number, head.Hash!, MasterNodeCandidates.Select(k => k.Address).ToArray())); - } - } - public async Task TriggerAndSimulateBlockProposalAndVoting() { await TriggerBlockProposal(); diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestDepositContract.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestDepositContract.cs new file mode 100644 index 00000000000..2d032653521 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestDepositContract.cs @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core; +using Nethermind.Core.Extensions; +using Nethermind.Int256; +using Nethermind.Xdc.Contracts; +using System.Linq; + +namespace Nethermind.Xdc.Test.Helpers; + +internal class XdcTestDepositContract(CandidateContainer candidateContainer) : IMasternodeVotingContract +{ + public Address[] GetCandidatesByStake(BlockHeader blockHeader) + { + //We fake ordering by returning addresses instead of stake in descending order + return candidateContainer.MasternodeCandidates.Select(m => m.Address).OrderByDescending(a => a).ToArray(); + } + + public Address[] GetCandidates(BlockHeader blockHeader) + { + return candidateContainer.MasternodeCandidates.Select(m => m.Address).ToArray(); + } + + public UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate) + { + return 10_000_000.Ether(); + } + + public Address GetCandidateOwner(BlockHeader blockHeader, Address candidate) + { + throw new System.NotImplementedException(); + } +} diff --git a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/MineModuleTests.cs b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/MineModuleTests.cs index 575d4067ae4..846b0c0c9d1 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/MineModuleTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/MineModuleTests.cs @@ -61,7 +61,7 @@ public async Task TestUpdateMultipleMasterNodes() var newHead = (XdcBlockHeader)tree.Head!.Header!; Assert.That(newHead.Number, Is.EqualTo(gapBlock.Number)); - var snapshotAfter = blockchain.SnapshotManager.GetSnapshotByGapNumber((ulong)newHead.Number); + var snapshotAfter = blockchain.SnapshotManager.GetSnapshotByGapNumber(newHead.Number); Assert.That(snapshotAfter, Is.Not.Null); Assert.That(snapshotAfter.BlockNumber, Is.EqualTo(gapBlock.Number)); @@ -136,7 +136,7 @@ public async Task TestUpdateMasterNodes() header = (XdcBlockHeader)gapBlock.Header!; spec = blockchain.SpecProvider.GetXdcSpec(header); - snapshot = blockchain.SnapshotManager.GetSnapshotByGapNumber((ulong)header.Number); + snapshot = blockchain.SnapshotManager.GetSnapshotByGapNumber(header.Number); Assert.That(snapshot, Is.Not.Null); Assert.That(snapshot.BlockNumber, Is.EqualTo(gapBlock.Number)); diff --git a/src/Nethermind/Nethermind.Xdc.Test/SnapshotManagerTests.cs b/src/Nethermind/Nethermind.Xdc.Test/SnapshotManagerTests.cs index 2061e9efa5d..4a8516e2dde 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/SnapshotManagerTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/SnapshotManagerTests.cs @@ -4,8 +4,10 @@ using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Core; +using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Db; +using Nethermind.Xdc.Contracts; using Nethermind.Xdc.Spec; using Nethermind.Xdc.Types; using NSubstitute; @@ -29,16 +31,16 @@ public void Setup() _snapshotDb = new MemDb(); - IPenaltyHandler penaltyHandler = NSubstitute.Substitute.For(); + IPenaltyHandler penaltyHandler = Substitute.For(); _blockTree = Substitute.For(); - _snapshotManager = new SnapshotManager(_snapshotDb, _blockTree, penaltyHandler); + _snapshotManager = new SnapshotManager(_snapshotDb, _blockTree, penaltyHandler, Substitute.For(), Substitute.For()); } [Test] public void GetSnapshot_ShouldReturnNullForNonExistentSnapshot() { // Act - var result = _snapshotManager.GetSnapshotByBlockNumber(0, _xdcReleaseSpec); + Snapshot? result = _snapshotManager.GetSnapshotByBlockNumber(0, _xdcReleaseSpec); // Assert result.Should().BeNull(); @@ -55,7 +57,7 @@ public void GetSnapshot_ShouldRetrieveFromIfFound() _blockTree.FindHeader(gapBlock).Returns(header); // Act - var result = _snapshotManager.GetSnapshotByGapNumber(gapBlock); + Snapshot? result = _snapshotManager.GetSnapshotByGapNumber(gapBlock); // assert that it was retrieved from cache result.Should().BeEquivalentTo(snapshot); @@ -65,7 +67,7 @@ public void GetSnapshot_ShouldRetrieveFromIfFound() public void GetSnapshot_ShouldReturnNullForEmptyDb() { // Act - var result = _snapshotManager.GetSnapshotByBlockNumber(0, _xdcReleaseSpec); + Snapshot? result = _snapshotManager.GetSnapshotByBlockNumber(0, _xdcReleaseSpec); // Assert result.Should().BeNull(); } @@ -81,7 +83,7 @@ public void GetSnapshot_ShouldRetrieveFromDbIfNotInCache() _blockTree.FindHeader(gapBlock).Returns(header); // Act - var saved = _snapshotManager.GetSnapshotByGapNumber(gapBlock); + Snapshot? saved = _snapshotManager.GetSnapshotByGapNumber(gapBlock); // Assert saved.Should().BeEquivalentTo(snapshot); @@ -98,7 +100,7 @@ public void StoreSnapshot_ShouldStoreSnapshotInDb() // Act _snapshotManager.StoreSnapshot(snapshot); - var fromDb = _snapshotManager.GetSnapshotByGapNumber(gapBlock); + Snapshot? fromDb = _snapshotManager.GetSnapshotByGapNumber(gapBlock); // Assert fromDb.Should().BeEquivalentTo(snapshot); @@ -113,7 +115,7 @@ public void GetSnapshot_ShouldReturnSnapshotIfExists() var snapshot1 = new Snapshot(gapBlock1, header.Hash!, [Address.FromNumber(1)]); _snapshotManager.StoreSnapshot(snapshot1); _blockTree.FindHeader(gapBlock1).Returns(header); - var result = _snapshotManager.GetSnapshotByGapNumber(gapBlock1); + Snapshot? result = _snapshotManager.GetSnapshotByGapNumber(gapBlock1); // assert that it was retrieved from db result.Should().BeEquivalentTo(snapshot1); @@ -146,9 +148,30 @@ public void GetSnapshot_DifferentBlockNumbers_ReturnsSnapshotFromCorrectGapNumbe var snapshot = new Snapshot(expectedGapNumber, header.Hash!, [Address.FromNumber(1)]); _snapshotManager.StoreSnapshot(snapshot); _blockTree.FindHeader(expectedGapNumber).Returns(header); - var result = _snapshotManager.GetSnapshotByBlockNumber(blockNumber, _xdcReleaseSpec); + Snapshot? result = _snapshotManager.GetSnapshotByBlockNumber(blockNumber, _xdcReleaseSpec); // assert that it was retrieved from db result.Should().BeEquivalentTo(snapshot); } + + [TestCase(450)] + [TestCase(1350)] + public void NewHeadBlock_(int gapNumber) + { + IXdcReleaseSpec releaseSpec = Substitute.For(); + releaseSpec.EpochLength.Returns(900); + releaseSpec.Gap.Returns(450); + IBlockTree blockTree = Substitute.For(); + ISpecProvider specProvider = Substitute.For(); + specProvider.GetSpec(Arg.Any()).Returns(releaseSpec); + SnapshotManager snapshotManager = new SnapshotManager(new MemDb(), blockTree, Substitute.For(), Substitute.For(), specProvider); + + XdcBlockHeader header = Build.A.XdcBlockHeader() + .WithGeneratedExtraConsensusData(1) + .WithNumber(gapNumber).TestObject; + blockTree.FindHeader(Arg.Any()).Returns(header); + + blockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(new Block(header))); + snapshotManager.GetSnapshotByGapNumber(header.Number)!.HeaderHash.Should().Be(header.Hash!); + } } diff --git a/src/Nethermind/Nethermind.Xdc.Test/TimeoutCertificateManagerTests.cs b/src/Nethermind/Nethermind.Xdc.Test/TimeoutCertificateManagerTests.cs index 9de3ee988df..8901c83aca3 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/TimeoutCertificateManagerTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/TimeoutCertificateManagerTests.cs @@ -43,7 +43,7 @@ public void VerifyTC_SnapshotMissing_ReturnsFalse() { var tc = new TimeoutCertificate(1, Array.Empty(), 0); ISnapshotManager snapshotManager = Substitute.For(); - snapshotManager.GetSnapshotByGapNumber(Arg.Any()) + snapshotManager.GetSnapshotByGapNumber(Arg.Any()) .Returns((Snapshot?)null); IBlockTree blockTree = Substitute.For(); XdcBlockHeader header = Build.A.XdcBlockHeader().TestObject; @@ -69,7 +69,7 @@ public void VerifyTC_EmptyCandidates_ReturnsFalse() { var tc = new TimeoutCertificate(1, Array.Empty(), 0); ISnapshotManager snapshotManager = Substitute.For(); - snapshotManager.GetSnapshotByGapNumber(Arg.Any()) + snapshotManager.GetSnapshotByGapNumber(Arg.Any()) .Returns(new Snapshot(0, Hash256.Zero, Array.Empty
())); IBlockTree blockTree = Substitute.For(); XdcBlockHeader header = Build.A.XdcBlockHeader().TestObject; @@ -120,7 +120,7 @@ public void VerifyTCWithDifferentParameters_ReturnsExpected(TimeoutCertificate t { Address[] masternodes = masternodesList.ToArray(); ISnapshotManager snapshotManager = Substitute.For(); - snapshotManager.GetSnapshotByGapNumber(Arg.Any()) + snapshotManager.GetSnapshotByGapNumber(Arg.Any()) .Returns(new Snapshot(0, Hash256.Zero, masternodes)); IEpochSwitchManager epochSwitchManager = Substitute.For(); diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/CandidateStake.cs b/src/Nethermind/Nethermind.Xdc/Contracts/CandidateStake.cs new file mode 100644 index 00000000000..3ab5ef5e656 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc/Contracts/CandidateStake.cs @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core; +using Nethermind.Int256; + +namespace Nethermind.Xdc.Contracts; + +internal struct CandidateStake +{ + public Address Address; + public UInt256 Stake; +} diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs index 520f16b8db7..2af469cf419 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs @@ -3,11 +3,13 @@ using Nethermind.Core; using Nethermind.Int256; +using System; namespace Nethermind.Xdc.Contracts; public interface IMasternodeVotingContract { + Address[] GetCandidatesByStake(BlockHeader blockHeader); Address[] GetCandidates(BlockHeader blockHeader); UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate); Address GetCandidateOwner(BlockHeader blockHeader, Address candidate); diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs index 4453087afd5..e3d0c87e358 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -5,28 +5,30 @@ using Nethermind.Blockchain; using Nethermind.Blockchain.Contracts; using Nethermind.Blockchain.Contracts.Json; +using Nethermind.Consensus.Processing; using Nethermind.Core; +using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Evm.State; using Nethermind.Int256; +using Nethermind.State; +using Nethermind.Xdc.Contracts; using System; +using System.Linq; namespace Nethermind.Xdc.Contracts; internal class MasternodeVotingContract : Contract, IMasternodeVotingContract { - private readonly IWorldState _worldState; - private IConstantContract _constant; + private readonly IReadOnlyTxProcessingEnvFactory readOnlyTxProcessingEnvFactory; public MasternodeVotingContract( - IWorldState worldState, IAbiEncoder abiEncoder, Address contractAddress, - IReadOnlyTxProcessorSource readOnlyTxProcessorSource) + IReadOnlyTxProcessingEnvFactory readOnlyTxProcessingEnvFactory) : base(abiEncoder, contractAddress ?? throw new ArgumentNullException(nameof(contractAddress)), CreateAbiDefinition()) { - _constant = GetConstant(readOnlyTxProcessorSource); - _worldState = worldState; + this.readOnlyTxProcessingEnvFactory = readOnlyTxProcessingEnvFactory; } private static AbiDefinition CreateAbiDefinition() @@ -38,7 +40,8 @@ private static AbiDefinition CreateAbiDefinition() public UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate) { CallInfo callInfo = new CallInfo(blockHeader, "getCandidateCap", Address.SystemUser, candidate); - object[] result = _constant.Call(callInfo); + IConstantContract constant = GetConstant(readOnlyTxProcessingEnvFactory.Create()); + object[] result = constant.Call(callInfo); if (result.Length != 1) throw new InvalidOperationException("Expected 'getCandidateCap' to return exactly one result."); @@ -48,7 +51,8 @@ public UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate) public Address GetCandidateOwner(BlockHeader blockHeader, Address candidate) { CallInfo callInfo = new CallInfo(blockHeader, "getCandidateOwner", Address.SystemUser, candidate); - object[] result = _constant.Call(callInfo); + IConstantContract constant = GetConstant(readOnlyTxProcessingEnvFactory.Create()); + object[] result = constant.Call(callInfo); if (result.Length != 1) throw new InvalidOperationException("Expected 'getCandidateOwner' to return exactly one result."); @@ -58,7 +62,8 @@ public Address GetCandidateOwner(BlockHeader blockHeader, Address candidate) public Address[] GetCandidates(BlockHeader blockHeader) { CallInfo callInfo = new CallInfo(blockHeader, "getCandidates", Address.SystemUser); - object[] result = _constant.Call(callInfo); + IConstantContract constant = GetConstant(readOnlyTxProcessingEnvFactory.Create()); + object[] result = constant.Call(callInfo); return (Address[])result[0]!; } @@ -71,24 +76,57 @@ public Address[] GetCandidatesFromState(BlockHeader header) { CandidateContractSlots variableSlot = CandidateContractSlots.Candidates; Span input = [(byte)variableSlot]; - var slot = new UInt256(Keccak.Compute(input).Bytes); - using IDisposable state = _worldState.BeginScope(header); - ReadOnlySpan storageCell = _worldState.Get(new StorageCell(ContractAddress, slot)); - UInt256 length = new UInt256(storageCell); + UInt256 slot = new UInt256(Keccak.Compute(input).Bytes); + IReadOnlyTxProcessorSource txProcessorSource = readOnlyTxProcessingEnvFactory.Create(); + using IReadOnlyTxProcessingScope source = txProcessorSource.Build(header); + IWorldState worldState = source.WorldState; + ReadOnlySpan storageCell = worldState.Get(new StorageCell(ContractAddress, slot)); + var length = new UInt256(storageCell); Address[] candidates = new Address[(ulong)length]; for (int i = 0; i < length; i++) { UInt256 key = CalculateArrayKey(slot, (ulong)i, 1); - candidates[i] = new Address(_worldState.Get(new StorageCell(ContractAddress, key))); + candidates[i] = new Address(worldState.Get(new StorageCell(ContractAddress, key))); } return candidates; } - private static UInt256 CalculateArrayKey(UInt256 slot, ulong index, ulong size) + private UInt256 CalculateArrayKey(UInt256 slot, ulong index, ulong size) { return slot + new UInt256(index * size); } + /// + /// Returns an array of masternode candidates sorted by stake + /// + /// + /// + public Address[] GetCandidatesByStake(BlockHeader blockHeader) + { + Address[] candidates = GetCandidates(blockHeader); + + using var candidatesAndStake = new ArrayPoolList(candidates.Length); + foreach (Address candidate in candidates) + { + if (candidate == Address.Zero) + continue; + + candidatesAndStake.Add(new CandidateStake() + { + Address = candidate, + Stake = GetCandidateStake(blockHeader, candidate) + }); + } + candidatesAndStake.Sort((x, y) => y.Stake.CompareTo(x.Stake)); + + Address[] sortedCandidates = new Address[candidatesAndStake.Count]; + for (int i = 0; i < candidatesAndStake.Count; i++) + { + sortedCandidates[i] = candidatesAndStake[i].Address; + } + return sortedCandidates; + } + private enum CandidateContractSlots : byte { WithdrawsState, diff --git a/src/Nethermind/Nethermind.Xdc/ISnapshotManager.cs b/src/Nethermind/Nethermind.Xdc/ISnapshotManager.cs index 3ec43a6b740..f43abe604d7 100644 --- a/src/Nethermind/Nethermind.Xdc/ISnapshotManager.cs +++ b/src/Nethermind/Nethermind.Xdc/ISnapshotManager.cs @@ -16,7 +16,7 @@ static bool IsTimeforSnapshot(long blockNumber, IXdcReleaseSpec spec) return true; return blockNumber % spec.EpochLength == spec.EpochLength - spec.Gap; } - Snapshot? GetSnapshotByGapNumber(ulong gapNumber); + Snapshot? GetSnapshotByGapNumber(long gapNumber); Snapshot? GetSnapshotByBlockNumber(long blockNumber, IXdcReleaseSpec spec); void StoreSnapshot(Snapshot snapshot); (Address[] Masternodes, Address[] PenalizedNodes) CalculateNextEpochMasternodes(long blockNumber, Hash256 parentHash, IXdcReleaseSpec spec); diff --git a/src/Nethermind/Nethermind.Xdc/SnapshotManager.cs b/src/Nethermind/Nethermind.Xdc/SnapshotManager.cs index 330c884936f..6b406a8fab5 100644 --- a/src/Nethermind/Nethermind.Xdc/SnapshotManager.cs +++ b/src/Nethermind/Nethermind.Xdc/SnapshotManager.cs @@ -5,8 +5,10 @@ using Nethermind.Core; using Nethermind.Core.Caching; using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Serialization.Rlp; +using Nethermind.Xdc.Contracts; using Nethermind.Xdc.RLP; using Nethermind.Xdc.Spec; using Nethermind.Xdc.Types; @@ -15,14 +17,29 @@ namespace Nethermind.Xdc; -internal class SnapshotManager(IDb snapshotDb, IBlockTree blockTree, IPenaltyHandler penaltyHandler) : ISnapshotManager +internal class SnapshotManager : ISnapshotManager { private readonly LruCache _snapshotCache = new(128, 128, "XDC Snapshot cache"); private readonly SnapshotDecoder _snapshotDecoder = new(); + private readonly IDb snapshotDb; + private readonly IBlockTree blockTree; + private readonly IMasternodeVotingContract votingContract; + private readonly ISpecProvider specProvider; + private readonly IPenaltyHandler penaltyHandler; - public Snapshot? GetSnapshotByGapNumber(ulong gapNumber) + public SnapshotManager(IDb snapshotDb, IBlockTree blockTree, IPenaltyHandler penaltyHandler, IMasternodeVotingContract votingContract, ISpecProvider specProvider) + { + blockTree.NewHeadBlock += OnNewHeadBlock; + this.snapshotDb = snapshotDb; + this.blockTree = blockTree; + this.votingContract = votingContract; + this.specProvider = specProvider; + this.penaltyHandler = penaltyHandler; + } + + public Snapshot? GetSnapshotByGapNumber(long gapNumber) { var gapBlockHeader = blockTree.FindHeader((long)gapNumber) as XdcBlockHeader; @@ -42,7 +59,7 @@ internal class SnapshotManager(IDb snapshotDb, IBlockTree blockTree, IPenaltyHan if (value.IsEmpty) return null; - var decoded = _snapshotDecoder.Decode(value); + Snapshot decoded = _snapshotDecoder.Decode(value); snapshot = decoded; _snapshotCache.Set(gapBlockHeader.Hash, snapshot); return snapshot; @@ -51,7 +68,7 @@ internal class SnapshotManager(IDb snapshotDb, IBlockTree blockTree, IPenaltyHan public Snapshot? GetSnapshotByBlockNumber(long blockNumber, IXdcReleaseSpec spec) { var gapBlockNum = Math.Max(0, blockNumber - blockNumber % spec.EpochLength - spec.Gap); - return GetSnapshotByGapNumber((ulong)gapBlockNum); + return GetSnapshotByGapNumber(gapBlockNum); } public void StoreSnapshot(Snapshot snapshot) @@ -61,20 +78,21 @@ public void StoreSnapshot(Snapshot snapshot) if (snapshotDb.KeyExists(key)) return; - var rlpEncodedSnapshot = _snapshotDecoder.Encode(snapshot); + Rlp rlpEncodedSnapshot = _snapshotDecoder.Encode(snapshot); snapshotDb.Set(key, rlpEncodedSnapshot.Bytes); + _snapshotCache.Set(snapshot.HeaderHash, snapshot); } public (Address[] Masternodes, Address[] PenalizedNodes) CalculateNextEpochMasternodes(long blockNumber, Hash256 parentHash, IXdcReleaseSpec spec) { int maxMasternodes = spec.MaxMasternodes; - var previousSnapshot = GetSnapshotByBlockNumber(blockNumber, spec); + Snapshot previousSnapshot = GetSnapshotByBlockNumber(blockNumber, spec); if (previousSnapshot is null) throw new InvalidOperationException($"No snapshot found for header #{blockNumber}"); - var candidates = previousSnapshot.NextEpochCandidates; + Address[] candidates = previousSnapshot.NextEpochCandidates; if (blockNumber == spec.SwitchBlock + 1) { @@ -96,4 +114,31 @@ public void StoreSnapshot(Snapshot snapshot) return (candidates, penalties); } + + private void OnNewHeadBlock(object? sender, BlockEventArgs e) + { + UpdateMasterNodes((XdcBlockHeader)e.Block.Header); + } + + private void UpdateMasterNodes(XdcBlockHeader header) + { + ulong round; + if (header.IsGenesis) + round = 0; + else + round = header.ExtraConsensusData.BlockRound; + // Could consider dropping the round parameter here, since the consensus parameters used here should not change + IXdcReleaseSpec spec = specProvider.GetXdcSpec(header, round); + if (!ISnapshotManager.IsTimeforSnapshot(header.Number, spec)) + return; + + Address[] candidates; + if (header.IsGenesis) + candidates = spec.GenesisMasterNodes; + else + candidates = votingContract.GetCandidatesByStake(header); + + Snapshot snapshot = new(header.Number, header.Hash, candidates); + StoreSnapshot(snapshot); + } } diff --git a/src/Nethermind/Nethermind.Xdc/TimeoutCertificateManager.cs b/src/Nethermind/Nethermind.Xdc/TimeoutCertificateManager.cs index ed06c548673..83f6224378d 100644 --- a/src/Nethermind/Nethermind.Xdc/TimeoutCertificateManager.cs +++ b/src/Nethermind/Nethermind.Xdc/TimeoutCertificateManager.cs @@ -104,7 +104,7 @@ public bool VerifyTimeoutCertificate(TimeoutCertificate timeoutCertificate, out if (timeoutCertificate is null) throw new ArgumentNullException(nameof(timeoutCertificate)); if (timeoutCertificate.Signatures is null) throw new ArgumentNullException(nameof(timeoutCertificate.Signatures)); - Snapshot snapshot = _snapshotManager.GetSnapshotByGapNumber(timeoutCertificate.GapNumber); + Snapshot snapshot = _snapshotManager.GetSnapshotByGapNumber((long)timeoutCertificate.GapNumber); if (snapshot is null) { errorMessage = $"Failed to get snapshot using gap number {timeoutCertificate.GapNumber}"; @@ -196,7 +196,7 @@ public Task OnReceiveTimeout(Timeout timeout) internal bool FilterTimeout(Timeout timeout) { if (timeout.Round < _consensusContext.CurrentRound) return false; - Snapshot snapshot = _snapshotManager.GetSnapshotByGapNumber(timeout.GapNumber); + Snapshot snapshot = _snapshotManager.GetSnapshotByGapNumber((long)timeout.GapNumber); if (snapshot is null || snapshot.NextEpochCandidates.Length == 0) return false; // Verify msg signature diff --git a/src/Nethermind/Nethermind.Xdc/VotesManager.cs b/src/Nethermind/Nethermind.Xdc/VotesManager.cs index c3774d821db..5687caed3be 100644 --- a/src/Nethermind/Nethermind.Xdc/VotesManager.cs +++ b/src/Nethermind/Nethermind.Xdc/VotesManager.cs @@ -187,7 +187,7 @@ internal bool FilterVote(Vote vote) { if (vote.ProposedBlockInfo.Round < _ctx.CurrentRound) return false; - Snapshot snapshot = _snapshotManager.GetSnapshotByGapNumber(vote.GapNumber); + Snapshot snapshot = _snapshotManager.GetSnapshotByGapNumber((long)vote.GapNumber); if (snapshot is null) return false; // Verify message signature vote.Signer ??= _ethereumEcdsa.RecoverVoteSigner(vote); diff --git a/src/Nethermind/Nethermind.Xdc/XdcBlockTree.cs b/src/Nethermind/Nethermind.Xdc/XdcBlockTree.cs index b9af6d8fd01..9d97cd0fb87 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcBlockTree.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcBlockTree.cs @@ -12,6 +12,8 @@ using Nethermind.Db.Blooms; using Nethermind.Logging; using Nethermind.State.Repositories; +using Nethermind.Xdc.Contracts; +using Nethermind.Xdc.Types; namespace Nethermind.Xdc; @@ -39,7 +41,7 @@ public XdcBlockTree( protected override AddBlockResult Suggest(Block? block, BlockHeader header, BlockTreeSuggestOptions options = BlockTreeSuggestOptions.ShouldProcess) { - Types.BlockRoundInfo finalizedBlockInfo = _xdcConsensus.HighestCommitBlock; + BlockRoundInfo finalizedBlockInfo = _xdcConsensus.HighestCommitBlock; if (finalizedBlockInfo is null) return base.Suggest(block, header, options); if (finalizedBlockInfo.Hash == header.Hash) diff --git a/src/Nethermind/Nethermind.Xdc/XdcModule.cs b/src/Nethermind/Nethermind.Xdc/XdcModule.cs index b6742681ff8..ac8b642b78c 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcModule.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcModule.cs @@ -4,6 +4,7 @@ using System; using Autofac; using Autofac.Features.AttributeFilters; +using Nethermind.Abi; using Nethermind.Blockchain; using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Headers; @@ -14,13 +15,13 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Db; +using Nethermind.Evm; +using Nethermind.Evm.State; using Nethermind.Init.Modules; using Nethermind.Specs.ChainSpecStyle; -using Nethermind.Xdc.Spec; -using Nethermind.Xdc.Contracts; -using Nethermind.Abi; -using Nethermind.Evm.State; using Nethermind.State; +using Nethermind.Xdc.Contracts; +using Nethermind.Xdc.Spec; using Nethermind.Logging; namespace Nethermind.Xdc; @@ -48,6 +49,14 @@ protected override void Load(ContainerBuilder builder) .AddSingleton() .AddSingleton() + // Sys contracts + //TODO this might not be wired correctly + .AddSingleton< + IMasternodeVotingContract, + IAbiEncoder, + ISpecProvider, + IReadOnlyTxProcessingEnvFactory>(CreateVotingContract) + // sealer .AddSingleton() @@ -55,7 +64,6 @@ protected override void Load(ContainerBuilder builder) // reward handler .AddSingleton() - .AddSingleton(CreateMasternodeVotingContract) // forensics handler @@ -71,30 +79,24 @@ protected override void Load(ContainerBuilder builder) .AddSingleton() .AddSingleton() .AddDatabase(SnapshotDbName) - .AddSingleton(CreateSnapshotManager) + .AddSingleton(CreateSnapshotManager) .AddSingleton() .AddSingleton() .AddSingleton() ; } - private ISnapshotManager CreateSnapshotManager([KeyFilter(SnapshotDbName)] IDb db, IBlockTree blockTree, IPenaltyHandler penaltyHandler) + private ISnapshotManager CreateSnapshotManager([KeyFilter(SnapshotDbName)] IDb db, IBlockTree blockTree, IPenaltyHandler penaltyHandler, IMasternodeVotingContract votingContract, ISpecProvider specProvider) { - return new SnapshotManager(db, blockTree, penaltyHandler); + return new SnapshotManager(db, blockTree, penaltyHandler, votingContract, specProvider); } - private IMasternodeVotingContract CreateMasternodeVotingContract( - ISpecProvider specProvider, + private IMasternodeVotingContract CreateVotingContract( IAbiEncoder abiEncoder, - IWorldStateManager worldStateManager, - IReadOnlyTxProcessingEnvFactory readOnlyTxProcessingEnvFactory, - ILogManager logManager) + ISpecProvider specProvider, + IReadOnlyTxProcessingEnvFactory readOnlyTxProcessingEnv) { - var xdcSpec = specProvider.GenesisSpec as IXdcReleaseSpec; - IWorldStateScopeProvider scopeProvider = worldStateManager.CreateResettableWorldState(); - IWorldState worldState = new WorldState(scopeProvider, logManager); - IReadOnlyTxProcessorSource readOnlyTxProcessorSource = readOnlyTxProcessingEnvFactory.Create(); - return new MasternodeVotingContract(worldState, abiEncoder, xdcSpec.MasternodeVotingContract, readOnlyTxProcessorSource); + IXdcReleaseSpec spec = (XdcReleaseSpec)specProvider.GetFinalSpec(); + return new MasternodeVotingContract(abiEncoder, spec.MasternodeVotingContract, readOnlyTxProcessingEnv); } - } From 6756b54d09db406f6826d0e3717ebd1e210d7194 Mon Sep 17 00:00:00 2001 From: lupin17 <59-quanta.middle@icloud.com> Date: Fri, 9 Jan 2026 09:30:32 +0100 Subject: [PATCH 188/255] perf: Remove redundant allocations in NettyDiscoveryHandlerTests (#10155) Update NettyDiscoveryHandlerTests.cs --- .../NettyDiscoveryHandlerTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Network.Discovery.Test/NettyDiscoveryHandlerTests.cs b/src/Nethermind/Nethermind.Network.Discovery.Test/NettyDiscoveryHandlerTests.cs index 554a31ecbde..b9d241ea87f 100644 --- a/src/Nethermind/Nethermind.Network.Discovery.Test/NettyDiscoveryHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Discovery.Test/NettyDiscoveryHandlerTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Linq; using System.Net; @@ -137,7 +138,7 @@ public async Task FindNodeSentReceivedTest() [Test] public async Task NeighborsSentReceivedTest() { - NeighborsMsg msg = new(_privateKey2.PublicKey, Timestamper.Default.UnixTime.SecondsLong + 1200, new List().ToArray()) + NeighborsMsg msg = new(_privateKey2.PublicKey, Timestamper.Default.UnixTime.SecondsLong + 1200, Array.Empty()) { FarAddress = _address2 }; @@ -146,7 +147,7 @@ public async Task NeighborsSentReceivedTest() await SleepWhileWaiting(); _discoveryManagersMocks[1].Received(1).OnIncomingMsg(Arg.Is(static x => x.MsgType == MsgType.Neighbors)); - NeighborsMsg msg2 = new(_privateKey.PublicKey, Timestamper.Default.UnixTime.SecondsLong + 1200, new List().ToArray()) + NeighborsMsg msg2 = new(_privateKey.PublicKey, Timestamper.Default.UnixTime.SecondsLong + 1200, Array.Empty()) { FarAddress = _address, }; From c5f04013d19ec93b55738318f3f7606e3cde0208 Mon Sep 17 00:00:00 2001 From: iPLAY888 <133153661+letmehateu@users.noreply.github.com> Date: Fri, 9 Jan 2026 11:41:52 +0300 Subject: [PATCH 189/255] fix: correct header range logging in PoW forward sync (#10140) Update PowForwardHeaderProvider.cs --- .../Blocks/PowForwardHeaderProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Synchronization/Blocks/PowForwardHeaderProvider.cs b/src/Nethermind/Nethermind.Synchronization/Blocks/PowForwardHeaderProvider.cs index ac0020b155b..9db02fb7c01 100644 --- a/src/Nethermind/Nethermind.Synchronization/Blocks/PowForwardHeaderProvider.cs +++ b/src/Nethermind/Nethermind.Synchronization/Blocks/PowForwardHeaderProvider.cs @@ -73,7 +73,7 @@ private IOwnedReadOnlyList? LastResponseBatch IOwnedReadOnlyList? headers = AssembleResponseFromLastResponseBatch(); if (headers is not null) { - if (_logger.IsTrace) _logger.Trace($"PoW header info from last response from {headers[0].ToString(BlockHeader.Format.Short)} to {headers[1].ToString(BlockHeader.Format.Short)}"); + if (_logger.IsTrace) _logger.Trace($"PoW header info from last response from {headers[0].ToString(BlockHeader.Format.Short)} to {headers[^1].ToString(BlockHeader.Format.Short)}"); return headers; } From 1536e816a421b86a5c7693e7a3fc96490551ffe4 Mon Sep 17 00:00:00 2001 From: Forostovec Date: Fri, 9 Jan 2026 10:47:48 +0200 Subject: [PATCH 190/255] fix: avoid GetReceiptData when hash lookup unsupported (#10023) Co-authored-by: Lukasz Rozmej --- .../Receipts/PersistentReceiptStorage.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs index 8658cb93301..2db303f9dd8 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs @@ -223,7 +223,12 @@ public bool TryGetReceiptsIterator(long blockNumber, Hash256 blockHash, out Rece return true; } - var result = CanGetReceiptsByHash(blockNumber); + if (!CanGetReceiptsByHash(blockNumber)) + { + iterator = new ReceiptsIterator(); + return false; + } + Span receiptsData = GetReceiptData(blockNumber, blockHash); Func recoveryContextFactory = () => null; @@ -245,8 +250,8 @@ public bool TryGetReceiptsIterator(long blockNumber, Hash256 blockHash, out Rece IReceiptRefDecoder refDecoder = _storageDecoder.GetRefDecoder(receiptsData); - iterator = result ? new ReceiptsIterator(receiptsData, _receiptsDb, recoveryContextFactory, refDecoder) : new ReceiptsIterator(); - return result; + iterator = new ReceiptsIterator(receiptsData, _receiptsDb, recoveryContextFactory, refDecoder); + return true; } public void Insert(Block block, TxReceipt[]? txReceipts, bool ensureCanonical = true, WriteFlags writeFlags = WriteFlags.None, long? lastBlockNumber = null) From 13dd512e368391c03127323f819107e2eb88bfa2 Mon Sep 17 00:00:00 2001 From: Alex Pikme <30472093+reject-i@users.noreply.github.com> Date: Fri, 9 Jan 2026 09:12:12 +0000 Subject: [PATCH 191/255] fix: correct slice index in Address.TryParseVariableLength (#9902) * fix: correct slice index in Address.TryParseVariableLength * test * update test Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.Core.Test/AddressTests.cs --------- Co-authored-by: Lukasz Rozmej --- src/Nethermind/Nethermind.Core.Test/AddressTests.cs | 2 ++ src/Nethermind/Nethermind.Core/Address.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Core.Test/AddressTests.cs b/src/Nethermind/Nethermind.Core.Test/AddressTests.cs index bb029f46be5..74452b57e29 100644 --- a/src/Nethermind/Nethermind.Core.Test/AddressTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/AddressTests.cs @@ -183,6 +183,8 @@ public bool Is_PointEvaluationPrecompile_properly_activated(IReleaseSpec spec) = [TestCase(Address.SystemUserHex, false)] [TestCase("2" + Address.SystemUserHex, false)] [TestCase("2" + Address.SystemUserHex, true)] + [TestCase("0x00" + Address.SystemUserHex, true)] + [TestCase("0x00" + "fffffffffffffffffffffffffffffffffffffffe", true)] public void Parse_variable_length(string addressHex, bool allowOverflow) { var result = Address.TryParseVariableLength(addressHex, out Address? address, allowOverflow); diff --git a/src/Nethermind/Nethermind.Core/Address.cs b/src/Nethermind/Nethermind.Core/Address.cs index d20e96be38d..0bad6dd8360 100644 --- a/src/Nethermind/Nethermind.Core/Address.cs +++ b/src/Nethermind/Nethermind.Core/Address.cs @@ -109,7 +109,7 @@ public static bool TryParseVariableLength(string? value, out Address? address, b { if (allowOverflow) { - span = span[(value.Length - size)..]; + span = span[(span.Length - size)..]; } else { From 7e1dcb3fcba6b463fdbe5d49d08ca1dbece771d2 Mon Sep 17 00:00:00 2001 From: Snezhkko Date: Fri, 9 Jan 2026 11:12:26 +0200 Subject: [PATCH 192/255] perf(facade): optimize SimulateDictionaryHeaderStore.Get for cache hits (#9903) --- .../Simulate/SimulateDictionaryHeaderStore.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryHeaderStore.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryHeaderStore.cs index 0876b9d3084..b68e7a21707 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryHeaderStore.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryHeaderStore.cs @@ -36,17 +36,13 @@ public void BulkInsert(IReadOnlyList headers) public BlockHeader? Get(Hash256 blockHash, bool shouldCache = false, long? blockNumber = null) { - blockNumber ??= GetBlockNumber(blockHash); - - if (blockNumber.HasValue && _headerDict.TryGetValue(blockHash, out BlockHeader? header)) + if (_headerDict.TryGetValue(blockHash, out BlockHeader? header)) { - if (shouldCache) - { - Cache(header!); - } return header; } + blockNumber ??= GetBlockNumber(blockHash); + header = readonlyBaseHeaderStore.Get(blockHash, false, blockNumber); if (header is not null && shouldCache) { From 5ac98832d39f3c5075e7d17109b5082897b6655f Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 9 Jan 2026 10:12:36 +0100 Subject: [PATCH 193/255] fix: add informative message to block processing timeout exception (#9912) Update HiveRunner.cs --- src/Nethermind/Nethermind.Hive/HiveRunner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Hive/HiveRunner.cs b/src/Nethermind/Nethermind.Hive/HiveRunner.cs index 4f876371342..a31cd0ae88f 100644 --- a/src/Nethermind/Nethermind.Hive/HiveRunner.cs +++ b/src/Nethermind/Nethermind.Hive/HiveRunner.cs @@ -185,7 +185,7 @@ private static async Task WaitForBlockProcessing(SemaphoreSlim semaphore) { if (!await semaphore.WaitAsync(5000)) { - throw new InvalidOperationException(); + throw new InvalidOperationException("Block processing timeout after 5000ms. The block may not have been processed in time."); } } From 54d1c5c227b57d4444f06e161fdd08d57622bcc4 Mon Sep 17 00:00:00 2001 From: phrwlk Date: Fri, 9 Jan 2026 12:31:36 +0200 Subject: [PATCH 194/255] fix: Remove invalid eth_getTransactionByHash call (#9784) --- tools/SendBlobs/BlobSender.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/SendBlobs/BlobSender.cs b/tools/SendBlobs/BlobSender.cs index a4eb13dba9d..e652fce7cec 100644 --- a/tools/SendBlobs/BlobSender.cs +++ b/tools/SendBlobs/BlobSender.cs @@ -362,8 +362,6 @@ private async static Task WaitForBlobInclusion(IJsonRpcClient rpcClient, Hash256 if (txHash is not null && blockResult.Transactions.Contains(txHash)) { - string? receipt = await rpcClient.Post("eth_getTransactionByHash", txHash.ToString(), true); - Console.WriteLine($"Found blob transaction in block {blockResult.Number}"); return; } From dc0194047bad5045621421abcf0206579d8b3706 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Sat, 10 Jan 2026 01:06:12 +0300 Subject: [PATCH 195/255] Fix typos 2 (#10162) * Few typos fixed * Check in the pipeline * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Remove * Some fixes * Test --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/code-formatting.yml | 2 + cspell.json | 764 ++++++++++++++++++ .../Evm/Blake2Benchmark.cs | 2 +- .../BlockchainTestsBugHunter.cs | 8 +- .../StateTestsBugHunter.cs | 8 +- .../BlockhashCacheTests.cs | 2 +- .../Blocks/BlockStoreTests.cs | 2 +- .../Data/JSTracers/prestateTracer_legacy.js | 2 +- ...figProvider_FindIncorrectSettings_Tests.cs | 2 +- .../Nethermind.Core.Test/AddressTests.cs | 2 +- .../Encoding/HeaderDecoderTests.cs | 2 +- ...redComponentsContainerBuilderExtensions.cs | 2 +- .../Extensions/SpanExtensions.cs | 20 +- .../Nethermind.Core/TypeDiscovery.cs | 6 +- .../Nethermind.Crypto/KeccakRlpStream.cs | 8 +- .../Nethermind.Db.Rocks/Config/DbConfig.cs | 4 +- .../Nethermind.Db.Rocks/DbOnTheRocks.cs | 10 +- .../FullPruning/FullPruningDb.cs | 2 +- src/Nethermind/Nethermind.Db/Metrics.cs | 2 +- .../AdminEraServiceTests.cs | 2 +- .../E2StoreWriterTests.cs | 2 +- src/Nethermind/Nethermind.Era1/EraStore.cs | 4 +- .../Bls/G1MSMPrecompile.cs | 2 +- .../Bls/G2MSMPrecompile.cs | 2 +- .../BytecodeBuilderExtensionsTests.cs | 2 +- .../Nethermind.Evm.Test/CoinbaseTests.cs | 2 +- .../Nethermind.Evm.Test/Eip1153Tests.cs | 2 +- .../CodeAnalysis/JumpDestinationAnalyzer.cs | 4 +- .../EvmObjectFormat/Handlers/EofV1.cs | 4 +- .../Tracing/Debugger/DebugTracer.cs | 2 +- .../TransactionProcessor.cs | 2 +- .../Nethermind.Evm/VirtualMachine.cs | 4 +- .../Eth/EthSyncingInfoTests.cs | 4 +- .../SimulateReadOnlyBlocksProcessingEnv.cs | 2 +- ...ulateReadOnlyBlocksProcessingEnvFactory.cs | 4 +- .../HealthChecksWebhookInfo.cs | 2 +- .../IHealthChecksConfig.cs | 4 +- .../Nethermind.History/HistoryPruner.cs | 2 +- src/Nethermind/Nethermind.Hive/HiveRunner.cs | 2 +- .../PruningTrieStateFactory.cs | 4 +- .../Data/Base64ConverterTests.cs | 1 + .../Data/IdConverterTests.cs | 2 +- .../TransactionForRpcDeserializationTests.cs | 2 +- .../JsonRpcUrlCollectionTests.cs | 2 +- ...DebugSimulateTestsBlocksAndTransactions.cs | 6 +- .../Eth/EthRpcModuleTests.FeeHistory.cs | 2 +- .../EthSimulateTestsBlocksAndTransactions.cs | 10 +- .../Eth/Simulate/EthSimulateTestsHiveBase.cs | 2 +- .../AccessListTransactionForRpcTests.cs | 2 +- ...aritySimulateTestsBlocksAndTransactions.cs | 6 +- .../Nethermind.JsonRpc/ErrorCodes.cs | 4 +- .../Modules/DebugModule/DebugModuleFactory.cs | 6 +- .../Modules/DebugModule/IDebugRpcModule.cs | 2 +- .../Modules/Eth/IEthRpcModule.cs | 2 +- .../Modules/Personal/IPersonalRpcModule.cs | 2 +- .../Subscribe/PeerMsgSendRecvResponse.cs | 4 +- .../Nethermind.Logging.NLog/NLogManager.cs | 4 +- .../AuRaMergeEngineModuleTests.cs | 2 +- .../Nethermind.Merge.AuRa/AuRaMergePlugin.cs | 2 +- .../Nethermind.Merge.Plugin.Test/JwtTest.cs | 1 + .../Nethermind.Merge.Plugin/MergePlugin.cs | 6 +- .../Nethermind.Merkleization/MerkleTree.cs | 2 +- .../MetricsTests.cs | 2 +- .../Metrics/MetricsController.cs | 2 +- .../EnrTreeParserTests.cs | 1 + .../Nethermind.Network.Test/ForkInfoTests.cs | 2 +- .../Eth/V63/GetReceiptsMessageTests.cs | 2 +- .../Nethermind.Network.Test/PacketTests.cs | 2 +- .../PeerManagerTests.cs | 2 +- .../EncryptionHandshakeServiceTests.cs | 2 +- .../Rlpx/ZeroNettyFrameEncodeDecodeTests.cs | 8 +- .../Eth/V65/Eth65ProtocolHandler.cs | 2 +- .../Eth/V68/Eth68ProtocolHandler.cs | 2 +- .../Utils/BackgroundTaskSchedulerWrapper.cs | 8 +- .../Nethermind.Network/ProtocolsManager.cs | 10 +- .../Rlpx/ZeroFrameDecoder.cs | 2 +- .../CL/BatchDecoderTests.cs | 2 +- .../CL/Decoding/BatchDecoder.cs | 6 +- .../CL/Decoding/BatchV1.cs | 8 +- .../OptimismLegacyTxDecoder.cs | 2 +- .../OptimismSynchronizerModule.cs | 2 +- .../Ethereum/ContextWithMocks.cs | 2 +- .../Steps/EthereumStepsManagerTests.cs | 2 +- .../EthereumRunnerTests.cs | 4 +- .../Module/MainProcessingContextTests.cs | 6 +- src/Nethermind/Nethermind.Runner/NLog.config | 4 +- .../Nethermind.Shutter/ShutterEon.cs | 2 +- .../ChainSpecBasedSpecProviderTests.cs | 2 +- .../Pruning/OverlayTrieStore.cs | 2 +- src/Nethermind/Nethermind.TxPool/ITxPool.cs | 2 +- .../Nethermind.TxPool/NullTxPool.cs | 2 +- .../Nethermind.TxPool/RetryCache.cs | 4 +- src/Nethermind/Nethermind.TxPool/TxPool.cs | 2 +- .../Helpers/XdcModuleTestOverrides.cs | 4 +- .../Helpers/XdcTestBlockchain.cs | 4 +- .../Helpers/XdcTestHelper.cs | 4 +- .../ModuleTests/HeaderVerificationTests.cs | 10 +- .../ModuleTests/MineModuleTests.cs | 6 +- .../ModuleTests/ProposedBlockTests.cs | 12 +- .../ModuleTests/XdcReorgModuleTests.cs | 12 +- .../SnapshotDecoderTests.cs | 2 +- .../XdcSealValidatorTests.cs | 6 +- .../Nethermind.Xdc.Test/XdcTestExtentions.cs | 2 +- .../Nethermind.Xdc/EpochSwitchManager.cs | 6 +- .../Nethermind.Xdc/ISnapshotManager.cs | 2 +- .../QuorumCertificateManager.cs | 2 +- .../Nethermind.Xdc/SnapshotManager.cs | 2 +- .../Nethermind.Xdc/XdcRewardCalculator.cs | 4 +- src/Nethermind/cspell.json | 95 --- tools/Kute/Nethermind.Tools.Kute/Config.cs | 2 +- tools/Kute/README.md | 2 +- tools/SendBlobs/BlobSender.cs | 4 +- tools/SendBlobs/FundsDistributor.cs | 2 +- tools/SendBlobs/SetupCli.cs | 2 +- 114 files changed, 969 insertions(+), 297 deletions(-) create mode 100644 cspell.json delete mode 100644 src/Nethermind/cspell.json diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index f2029c97af7..578e0543042 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -17,3 +17,5 @@ jobs: uses: actions/setup-dotnet@v5 - name: Format run: dotnet format whitespace src/Nethermind/ --folder --verify-no-changes + - name: Check spelling + uses: streetsidesoftware/cspell-action@v7 diff --git a/cspell.json b/cspell.json new file mode 100644 index 00000000000..053b4563bcd --- /dev/null +++ b/cspell.json @@ -0,0 +1,764 @@ +{ + "version": "0.2", + "language": "en", + "files": [ + "**/*.{cs,csproj,props,targets,sln,config,json,yml,yaml,md,txt,ps1,psm1,sh}", + "**/*.{ts,tsx,js,jsx,html,css,scss,xml}", + "**/*.proto" + ], + "ignorePaths": [ + "**/.git/**", + "**/.vs/**", + "**/*.json", + "**/*.zst", + "**/bin/**", + "**/node_modules/**", + "**/obj/**", + "**/wwwroot/**", + "src/bench_precompiles", + "src/Nethermind/artifacts/**", + "src/Nethermind/BenchmarkDotNet.Artifacts/**", + "src/Nethermind/Chains/**", + "src/Nethermind/Nethermind.Runner/configs/**", + "src/Nethermind/TestResults/**", + "src/tests" + ], + "ignoreRegExpList": [ + "/0x[0-9a-fA-F]+/g", + "/\"[0-9a-fA-F]{64}\"/g", + "/https?:\\/\\/\\S+/g" + ], + "words": [ + "accesslist", + "accnt", + "adab", + "addmod", + "affinitize", + "akhunov", + "alethia", + "alexey", + "analysed", + "apikey", + "argjson", + "asmv", + "aspnet", + "aspnetcore", + "assertoor", + "autofac", + "auxdata", + "badreq", + "barebone", + "baseblock", + "basefee", + "basefeepergas", + "beaverbuild", + "behaviour", + "behaviours", + "benchmarkdotnet", + "bendian", + "beregszaszi", + "besu", + "bigrams", + "bilinearity", + "bitarray", + "bitfield", + "bitlist", + "bitlists", + "bitmask", + "bitvec", + "bitvector", + "bitvectors", + "bloatnet", + "blobbasefee", + "blobgasperblob", + "blobgasused", + "blobhash", + "blobhashes", + "bloboptions", + "blobpool", + "blobtransactions", + "blobversionedhashes", + "blockhash", + "blockhashes", + "blocknr", + "blocksconfig", + "blocksdb", + "blocktest", + "blocktree", + "blom", + "bloomconfig", + "bloomfilter", + "blsg", + "blsmapfp", + "blsmapfptog", + "blspairingcheck", + "bnadd", + "bnmul", + "bnpair", + "bootnode", + "bootnodes", + "bottlenecked", + "browsable", + "btcs", + "buildtransitive", + "bulkset", + "bursty", + "buterin", + "bylica", + "bytecodes", + "callcode", + "calldatacopy", + "calldataload", + "calldatasize", + "callf", + "callme", + "callvalue", + "cand", + "canonicality", + "castagnoli", + "chainid", + "chainspec", + "chiado", + "cipherparams", + "ciphertext", + "ckzg", + "cloneable", + "cmix", + "codecopy", + "codehash", + "codesection", + "codesize", + "coef", + "collectd", + "colour", + "commitset", + "comparand", + "concurrenc", + "configurer", + "configurers", + "conflictor's", + "containersection", + "contentfiles", + "corechart", + "cpufrequency", + "crummey", + "cryptosuite", + "cryptotests", + "datacopy", + "datagram", + "dataloadn", + "datasection", + "datasize", + "dbdir", + "dbsize", + "deadlined", + "deauthorized", + "debhelper", + "decommit", + "decompiled", + "decompiler", + "deconfigure", + "deconfigured's", + "decryptor", + "defaultable", + "delegatecall", + "delegatecode", + "demerzel", + "deque", + "deserialised", + "dests", + "devirtualize", + "devnet", + "devnets", + "devp2p", + "diagnoser", + "diagnosers", + "disappearer's", + "discontiguous", + "discport", + "discv", + "distros", + "divmod", + "dklen", + "dont", + "dontneed", + "dotmemory", + "dotnetty's", + "dottrace", + "dpapi", + "dpkg", + "dupn", + "ecies", + "ecrec", + "edgecase", + "efbbbf", + "eips", + "emojize", + "emptish", + "emptystep", + "emptystring", + "encrypter", + "encryptor", + "energi", + "energyweb", + "enginehost", + "engineport", + "enode", + "enodes", + "enrs", + "enrtree", + "eofcall", + "eofcreate", + "eofdelegatecall", + "eofstaticcall", + "eoftest", + "ephem", + "eradir", + "eraexportdir", + "erigon", + "esac", + "ethash", + "ethdisco", + "ethermine", + "ethpool", + "ethrex", + "ethstats", + "ethxx", + "evmdis", + "ewasm", + "extcall", + "extcode", + "extcodecopy", + "extcodehash", + "extcopycode", + "extdelegatecall", + "extopcodes", + "extradata", + "extstaticcall", + "fastbin", + "fastlz", + "fastmod", + "fastsync", + "feemultiplier", + "finalizer", + "finalizers", + "findnode", + "firepool", + "flashbots", + "flatdb", + "flushoptions", + "fmap", + "forkchoice", + "forkhash", + "forkid", + "fusaka", + "gasrefund", + "gbps", + "gcdump", + "geoff", + "getblobs", + "getnull", + "getpayloadv", + "getrlimit", + "gettrie", + "gopherium", + "gwat", + "halfpath", + "hardfork", + "hardforks", + "hashas", + "hashcode", + "hashdb", + "hashimoto", + "hashkey", + "hashlib", + "hashrate", + "hashtable", + "hashtables", + "hbrns", + "headp", + "healthchecks", + "hellothere", + "hexary", + "hexencodetest", + "hexroot", + "highbits", + "hiveon", + "hmac", + "holesky", + "hoodi", + "hostnames", + "hotstuff", + "hyperthreading", + "idxs", + "iface", + "ikvp", + "immediates", + "includable", + "initcode", + "initcodes", + "inited", + "initialized", + "insens", + "insize", + "installdeb", + "instart", + "internaltype", + "interp", + "invalidblockhash", + "isnull", + "iszero", + "ivalidatorregistrycontract", + "ivle", + "jemalloc", + "jimbojones", + "jitted", + "jitting", + "jmps", + "jsonrpcconfig", + "jumpdest", + "jumpdestpush", + "jumpf", + "jumpi", + "jumps", + "jumptable", + "jumpv", + "justcache", + "kademlia", + "karalabe", + "kdfparams", + "keccak", + "keccaks", + "keepalive", + "keyaddrtest", + "keyper", + "keypers", + "kneth", + "kute", + "kychash", + "lanfranchi", + "langdale", + "lastmemline", + "ldarg", + "ldfld", + "lemire's", + "libc", + "libdl", + "libp", + "libsnappy", + "limbologs", + "limitmeterinitcode", + "linea", + "liskov", + "logicalcpu", + "longdate", + "lukasz", + "machdep", + "machinename", + "madv", + "maiboroda", + "mainchain", + "mallopt", + "mapg", + "marshallers", + "maskz", + "masternode", + "masternodes", + "masterodes", + "maxcandidatepeercount", + "maxcandidatepercount", + "maxfee", + "maxfeeperblobgas", + "maxfeeperdatagas", + "maxheaders", + "maxlevel", + "maxpriorityfee", + "mclbn", + "mcmc", + "mcopy", + "mellor", + "memberwise", + "memin", + "meminstart", + "meminsz", + "memmove", + "memout", + "memoutsz", + "mempoool", + "memtable", + "merkle", + "merkleization", + "merkleize", + "merkleizer", + "mgas", + "microsecs", + "midnib", + "millis", + "mingas", + "minlevel", + "mintable", + "misbehaviour", + "mklink", + "mload", + "mmap", + "modexp", + "modexpprecompile", + "morden", + "movbe", + "movzx", + "mres", + "mscorlib", + "msgrecv", + "msgsend", + "msize", + "msm", + "msms", + "msquic", + "mstore", + "mula", + "mulmod", + "mult", + "multiaddress", + "multicall", + "multidim", + "multiexp", + "multifeed", + "multiformats", + "mvid", + "mycryptowallet", + "nada", + "nameof", + "nananana", + "nanopool", + "neighbour", + "neighbours", + "netcore", + "netframework", + "netheofparse", + "nethermind's", + "nethermind", + "nethermindeth", + "nethtest", + "netstandard", + "nettrace", + "networkconfig", + "networkconfigmaxcandidatepeercount", + "networkid", + "newtonsoft", + "nito", + "nlog", + "nodedata", + "nodelay", + "nodestore", + "nodetype", + "nofile", + "nonposdao", + "nonstring", + "nops", + "nostack", + "nowal", + "npoints", + "npushes", + "nsubstitute", + "nugettest", + "numfiles", + "oand", + "offchain", + "ommer", + "ommers", + "ontake", + "opcodeswith", + "opcount", + "openethereum", + "opinfo", + "opstack", + "opstr", + "optane", + "overwriter", + "owlf", + "pacaya", + "parallelizable", + "paweł", + "pctg", + "pearce", + "pectra", + "pendingtxs", + "perfnet", + "perfolizer", + "permissioned", + "pgrep", + "physicalcpu", + "piechart", + "pinnable", + "pinnableslice", + "pkcs", + "pmsg", + "poacore", + "poaps", + "podc", + "popcnt", + "posdao", + "postinst", + "postrm", + "poststate", + "powm", + "preconf", + "preconfirmation", + "predeploy", + "prefixedf", + "prefund", + "preimage", + "preimages", + "preinstallation", + "prestate", + "prevop", + "prevrandao", + "prewarmer", + "prioritise", + "protoc", + "prysm", + "ptree", + "pushgateway", + "pwas", + "pwgen", + "pyroscope", + "pyspec", + "quickselect", + "qwords", + "randao", + "randomexists", + "rawblock", + "rblob", + "rbuilder", + "rcvbuf", + "reada", + "readahead", + "readded", + "readhead", + "readonlycolumndb", + "readoptions", + "receiveraddress", + "recents", + "recid", + "recognises", + "reconfig", + "redownloading", + "reencoding", + "refint", + "refstruct", + "regenesis", + "reitwiessner", + "reorganisation", + "reorganisations", + "reorganised", + "resettables", + "retesteth", + "retf", + "returncode", + "returndata", + "returndatacopy", + "returndataload", + "returndatasize", + "ripemd", + "rjump", + "rjumpi", + "rjumpv", + "rlim", + "rlimit", + "rlps", + "rlptest", + "rlpx", + "rlpxhost", + "rocksdb", + "ronin", + "roothash", + "rormask", + "rpcurl", + "runtimeconfig", + "rustc", + "ryzen", + "samplenewpayload", + "sankey", + "sbrk", + "scopable", + "sdiv", + "secp", + "securetrie", + "segmentations", + "selfbalance", + "selfdestruct", + "serialised", + "setcode", + "sete", + "shamir", + "shlibs", + "shouldly", + "shutterized", + "sig₁", + "sig₂", + "signextend", + "sizeinbase", + "skiplastn", + "slnx", + "sload", + "smod", + "somelabel", + "spaceneth", + "spammy", + "sparkline", + "spinlocks", + "squarify", + "ssse", + "sstfiles", + "sstore", + "sswu", + "stackoverflow", + "starthash", + "statediff", + "stateroot", + "statetest", + "staticcall", + "stddev", + "stelem", + "stfld", + "stoppables", + "storagefuzz", + "stree", + "strs", + "stylesheet", + "subcall", + "subcalls", + "subchain", + "subcompaction", + "subcompactions", + "subcontainer", + "subcontext", + "subfolders", + "substate", + "subtrace", + "subtraces", + "superchain", + "swapn", + "swende", + "synchronised", + "synclag", + "syscall", + "szalay", + "taiko", + "taskkill", + "tdxs", + "teku", + "testdata", + "testdb", + "testenvironments", + "testpassword", + "testpuppeth", + "testsimulate", + "testspec", + "testspecdir", + "threadid", + "threadlocal", + "threadpool", + "threadsafe", + "timestamper", + "titanbuilder", + "tload", + "toobig", + "trambabamba", + "treemap", + "trieanyorder", + "trieexception", + "trienode", + "triestore", + "trietest", + "trietestnextprev", + "triggerable", + "tstore", + "tukey", + "tupleception", + "txcreate", + "txns", + "txpointer", + "txpool", + "txps", + "txtest", + "typesection", + "ufixed", + "uleypool", + "ulongs", + "unalign", + "unbonded", + "uncast", + "uncompacted", + "unconfigured", + "underflowed", + "underflows", + "undiagonalize", + "unfinalized", + "unflushed", + "unimpacted", + "unkeyed", + "unlocker", + "unmarshalling", + "unmetered", + "unpad", + "unpooled", + "unreferred", + "unrequested", + "unresolve", + "unsub", + "unsubscription", + "unsynchronized", + "unvote", + "upnp", + "upto", + "upvoting", + "vbmi", + "vitalik", + "vmovups", + "vmtrace", + "vote₁", + "vote₂", + "vote₃", + "voteₙ", + "vpcbr", + "vpor", + "vptest", + "vzeroupper", + "wamp", + "warmcoinbase", + "wblob", + "winget", + "winsvega", + "wnew", + "wojciech", + "worklet", + "worklist", + "worldchain", + "worldstate", + "writebatch", + "writeoptions", + "wwwroot", + "wycheproof", + "xdai", + "xmlstarlet", + "xnpool", + "yellowpaper", + "ymmword", + "yparity", + "zcompressor", + "zdecompressor", + "zhizhu", + "zstandard", + "zstd", + "zwcm" + ], + "overrides": [ + { + "filename": "**/*.json", + "ignoreRegExpList": [ + "/\\\\u[0-9a-fA-F]{4}/g" + ] + } + ] +} diff --git a/src/Nethermind/Nethermind.Benchmark/Evm/Blake2Benchmark.cs b/src/Nethermind/Nethermind.Benchmark/Evm/Blake2Benchmark.cs index 2bbfe76480c..55ce475eb35 100644 --- a/src/Nethermind/Nethermind.Benchmark/Evm/Blake2Benchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Evm/Blake2Benchmark.cs @@ -20,7 +20,7 @@ public void Setup() { if (!Bytes.AreEqual(Current(), Improved())) { - throw new InvalidBenchmarkDeclarationException("blakes"); + throw new InvalidBenchmarkDeclarationException("blake2 mismatch"); } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test.Runner/BlockchainTestsBugHunter.cs b/src/Nethermind/Nethermind.Blockchain.Test.Runner/BlockchainTestsBugHunter.cs index eba2ada07de..73a57efc392 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test.Runner/BlockchainTestsBugHunter.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test.Runner/BlockchainTestsBugHunter.cs @@ -14,12 +14,12 @@ namespace Nethermind.Blockchain.Test.Runner public class BlockchainTestsBugHunter : BlockchainTestBase, IBlockchainTestRunner { private ITestSourceLoader _testsSource; - private ConsoleColor _defaultColour; + private ConsoleColor _defaultColor; public BlockchainTestsBugHunter(ITestSourceLoader testsSource) { _testsSource = testsSource ?? throw new ArgumentNullException(nameof(testsSource)); - _defaultColour = Console.ForegroundColor; + _defaultColor = Console.ForegroundColor; } public async Task> RunTestsAsync() @@ -67,14 +67,14 @@ private void WriteRed(string text) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(text); - Console.ForegroundColor = _defaultColour; + Console.ForegroundColor = _defaultColor; } private void WriteGreen(string text) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(text); - Console.ForegroundColor = _defaultColour; + Console.ForegroundColor = _defaultColor; } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test.Runner/StateTestsBugHunter.cs b/src/Nethermind/Nethermind.Blockchain.Test.Runner/StateTestsBugHunter.cs index dc13573519c..6b34eab9585 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test.Runner/StateTestsBugHunter.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test.Runner/StateTestsBugHunter.cs @@ -14,12 +14,12 @@ namespace Nethermind.Blockchain.Test.Runner public class StateTestsBugHunter : GeneralStateTestBase, IStateTestRunner { private ITestSourceLoader _testsSource; - private ConsoleColor _defaultColour; + private ConsoleColor _defaultColor; public StateTestsBugHunter(ITestSourceLoader testsSource) { _testsSource = testsSource ?? throw new ArgumentNullException(nameof(testsSource)); - _defaultColour = Console.ForegroundColor; + _defaultColor = Console.ForegroundColor; } public IEnumerable RunTests() @@ -68,14 +68,14 @@ private void WriteRed(string text) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(text); - Console.ForegroundColor = _defaultColour; + Console.ForegroundColor = _defaultColor; } private void WriteGreen(string text) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(text); - Console.ForegroundColor = _defaultColour; + Console.ForegroundColor = _defaultColor; } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs index f1732833707..17d1363095a 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockhashCacheTests.cs @@ -330,7 +330,7 @@ public async Task DoesNot_cache_cancelled_searches() } [Test] - public void Doesnt_cache_null_hashes() + public void DoesNot_cache_null_hashes() { (BlockTree tree, BlockhashCache cache) = BuildTest(100); BlockHeader head = tree.FindHeader(99, BlockTreeLookupOptions.None)!; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs index 525a99c5353..46c3d9da71c 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs @@ -37,7 +37,7 @@ public void Test_can_insert_get_and_remove_blocks(bool cached) } [Test] - public void Test_insert_would_pass_in_writeflag() + public void Test_insert_would_pass_in_write_flag() { TestMemDb db = new(); BlockStore store = new(db); diff --git a/src/Nethermind/Nethermind.Blockchain/Data/JSTracers/prestateTracer_legacy.js b/src/Nethermind/Nethermind.Blockchain/Data/JSTracers/prestateTracer_legacy.js index 3d293fd14dd..24a92d6ab9e 100644 --- a/src/Nethermind/Nethermind.Blockchain/Data/JSTracers/prestateTracer_legacy.js +++ b/src/Nethermind/Nethermind.Blockchain/Data/JSTracers/prestateTracer_legacy.js @@ -67,7 +67,7 @@ // Decrement the caller's nonce, and remove empty create targets this.prestate[toHex(ctx.from)].nonce--; if (ctx.type == 'CREATE') { - // We can blibdly delete the contract prestate, as any existing state would + // We can blindly delete the contract prestate, as any existing state would // have caused the transaction to be rejected as invalid in the first place. delete this.prestate[toHex(ctx.to)]; } diff --git a/src/Nethermind/Nethermind.Config.Test/ConfigProvider_FindIncorrectSettings_Tests.cs b/src/Nethermind/Nethermind.Config.Test/ConfigProvider_FindIncorrectSettings_Tests.cs index e06da50a042..87ccec88703 100644 --- a/src/Nethermind/Nethermind.Config.Test/ConfigProvider_FindIncorrectSettings_Tests.cs +++ b/src/Nethermind/Nethermind.Config.Test/ConfigProvider_FindIncorrectSettings_Tests.cs @@ -61,7 +61,7 @@ public void NoCategorySettings() { "NETHERMIND_CLI_SWITCH_LOCAL", "http://localhost:80" }, { "NETHERMIND_CONFIG", "test2.json" }, { "NETHERMIND_XYZ", "xyz" }, // not existing, should get error - { "QWER", "qwerty" } // not Nethermind setting, no error + { "QWERTY", "qwerty" } // not Nethermind setting, no error }); EnvConfigSource? envSource = new(_env); diff --git a/src/Nethermind/Nethermind.Core.Test/AddressTests.cs b/src/Nethermind/Nethermind.Core.Test/AddressTests.cs index 74452b57e29..1eee046ad3c 100644 --- a/src/Nethermind/Nethermind.Core.Test/AddressTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/AddressTests.cs @@ -184,7 +184,7 @@ public bool Is_PointEvaluationPrecompile_properly_activated(IReleaseSpec spec) = [TestCase("2" + Address.SystemUserHex, false)] [TestCase("2" + Address.SystemUserHex, true)] [TestCase("0x00" + Address.SystemUserHex, true)] - [TestCase("0x00" + "fffffffffffffffffffffffffffffffffffffffe", true)] + [TestCase("0x00fffffffffffffffffffffffffffffffffffffffe", true)] public void Parse_variable_length(string addressHex, bool allowOverflow) { var result = Address.TryParseVariableLength(addressHex, out Address? address, allowOverflow); diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs index c60d4e76442..e4942c21b16 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs @@ -192,7 +192,7 @@ public void Can_encode_decode_with_ValidatorExitRoot_equals_to_null() } [Test] - public void Can_encode_decode_with_missing_excess_blob_gass() + public void Can_encode_decode_with_missing_excess_blob_gas() { BlockHeader header = Build.A.BlockHeader .WithHash(new Hash256("0x3d8b9cc98eee58243461bd5a83663384b50293cd1e459a6841cb005296305590")) diff --git a/src/Nethermind/Nethermind.Core/Container/OrderedComponentsContainerBuilderExtensions.cs b/src/Nethermind/Nethermind.Core/Container/OrderedComponentsContainerBuilderExtensions.cs index be286cedbe8..e4f64bfb89c 100644 --- a/src/Nethermind/Nethermind.Core/Container/OrderedComponentsContainerBuilderExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Container/OrderedComponentsContainerBuilderExtensions.cs @@ -36,7 +36,7 @@ public static ContainerBuilder AddFirst(this ContainerBuilder builder, Func(this ContainerBuilder builder) { - string registeredMarker = $"Registerd OrderedComponents For {typeof(T).Name}"; + string registeredMarker = $"Registered OrderedComponents For {typeof(T).Name}"; if (!builder.Properties.TryAdd(registeredMarker, null)) { return builder; diff --git a/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs index 0f280e093e6..5118ea293bb 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs @@ -207,7 +207,7 @@ public static ArrayPoolListRef ToPooledListRef(this in ReadOnlySpan spa /// /// /// - /// This routine is optimised for throughput and low overhead on modern CPUs. It is based on CRC32C (Castagnoli) + /// This routine is optimized for throughput and low overhead on modern CPUs. It is based on CRC32C (Castagnoli) /// via and related overloads, and will use hardware acceleration /// when the runtime and processor support it. /// @@ -227,7 +227,7 @@ public static int FastHash(this ReadOnlySpan input) // Fast hardware-accelerated, non-cryptographic hash. // Core idea: CRC32C is extremely cheap on CPUs with SSE4.2/ARM CRC, // and gives good diffusion for hashing. We then optionally add extra - // mixing to reduce "CRC linearity" artefacts. + // mixing to reduce "CRC linearity" artifacts. int len = input.Length; @@ -261,7 +261,7 @@ public static int FastHash(this ReadOnlySpan input) uint h = seed; ref byte p = ref start; - // Process as many full qwords as possible. + // Process as many full 64-bit words as possible. // "& ~7" is a cheap round-down-to-multiple-of-8 (no division/mod). int full = len & ~7; int tail = len - full; @@ -288,18 +288,18 @@ public static int FastHash(this ReadOnlySpan input) // latency and increase ILP. CRC32C instructions have decent throughput // but non-trivial latency; 4 lanes keeps the CPU busy. uint h0 = seed; - uint h1 = seed ^ 0x9E3779B9u; // golden-ratio-ish constants to decorrelate lanes - uint h2 = seed ^ 0x85EBCA6Bu; // constants borrowed from common finalisers (good bit dispersion) + uint h1 = seed ^ 0x9E3779B9u; // golden-ratio-ish constants to separate lanes + uint h2 = seed ^ 0x85EBCA6Bu; // constants borrowed from common finalizers (good bit dispersion) uint h3 = seed ^ 0xC2B2AE35u; ref byte q = ref start; - // Consume all full qwords first. Tail (1-7 bytes) is handled later. + // Consume all full 64-bit words first. Tail (1-7 bytes) is handled later. int aligned = len & ~7; int remaining = aligned; // 64-byte unroll: - // - amortises loop branch/compare overhead + // - amortizes loop branch/compare overhead // - feeds enough independent work to keep OoO cores busy // - maps nicely onto cache line sized chunks while (remaining >= 64) @@ -331,7 +331,7 @@ public static int FastHash(this ReadOnlySpan input) remaining -= 32; } - // Drain any remaining full qwords (0, 8, 16, or 24 bytes). + // Drain any remaining full 64-bit words (0, 8, 16, or 24 bytes). // This is branchy but only runs once, so it is cheaper than another loop. if (remaining != 0) { @@ -350,7 +350,7 @@ public static int FastHash(this ReadOnlySpan input) h0 += BitOperations.RotateLeft(h1, 11); uint hash = h2 + h0; - // Handle tail bytes (1-7 bytes) that were not part of the qword-aligned stream. + // Handle tail bytes (1-7 bytes) that were not part of the 64-bit-aligned stream. // This is exact, in-order processing - no overlap and no over-read. int tailBytes = len - aligned; if (tailBytes != 0) @@ -387,7 +387,7 @@ static uint CrcTailOrdered(uint hash, ref byte p, int length) [MethodImpl(MethodImplOptions.AggressiveInlining)] static uint FinalMix(uint x) { - // A tiny finaliser to improve avalanche: + // A tiny finalizer to improve avalanche: // - xor-fold high bits down // - multiply by an odd constant to spread changes across bits // - xor-fold again to propagate the multiply result diff --git a/src/Nethermind/Nethermind.Core/TypeDiscovery.cs b/src/Nethermind/Nethermind.Core/TypeDiscovery.cs index fcd0dce56bb..0cdd6b87931 100644 --- a/src/Nethermind/Nethermind.Core/TypeDiscovery.cs +++ b/src/Nethermind/Nethermind.Core/TypeDiscovery.cs @@ -19,7 +19,7 @@ public static class TypeDiscovery public static void Initialize(Type? pluginType = null) { - // Early return if initialised + // Early return if initialized if (Volatile.Read(ref _allLoaded) == 1) return; if (pluginType is not null) @@ -34,7 +34,7 @@ private static void LoadAllImpl() { lock (_lock) { - // Early return if initialised while waiting for lock + // Early return if initialized while waiting for lock if (Volatile.Read(ref _allLoaded) == 1) return; List loadedAssemblies = new(capacity: 48); @@ -78,7 +78,7 @@ private static void LoadAllImpl() _assembliesWithNethermindTypes.Add(kv.Value); } - // Mark initialised before releasing lock + // Mark initialized before releasing lock Volatile.Write(ref _allLoaded, 1); } } diff --git a/src/Nethermind/Nethermind.Crypto/KeccakRlpStream.cs b/src/Nethermind/Nethermind.Crypto/KeccakRlpStream.cs index ae039b12582..636a56cbb8f 100644 --- a/src/Nethermind/Nethermind.Crypto/KeccakRlpStream.cs +++ b/src/Nethermind/Nethermind.Crypto/KeccakRlpStream.cs @@ -65,12 +65,12 @@ protected override void SkipBytes(int length) public override int Position { - get => throw new NotSupportedException("Cannot read form Keccak"); - set => throw new NotSupportedException("Cannot read form Keccak"); + get => throw new NotSupportedException("Cannot read from Keccak"); + set => throw new NotSupportedException("Cannot read from Keccak"); } - public override int Length => throw new NotSupportedException("Cannot read form Keccak"); + public override int Length => throw new NotSupportedException("Cannot read from Keccak"); - protected override string Description => "|KeccakRlpSTream|description missing|"; + protected override string Description => "|KeccakRlpStream|description missing|"; } } diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs index 6a2b42c0c30..c6004bcfc71 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs @@ -25,7 +25,7 @@ public class DbConfig : IDbConfig // This section affect the write buffer, or memtable. Note, the size of write buffer affect the size of l0 // file which affect compactions. The options here does not effect how the sst files are read... probably. - // But read does go through the write buffer first, before going through the rowcache (or is it before memtable?) + // But read does go through the write buffer first, before going through the row cache (or is it before memtable?) // block cache and then finally the LSM/SST files. "min_write_buffer_number_to_merge=1;" + "write_buffer_size=16000000;" + @@ -66,7 +66,7 @@ public class DbConfig : IDbConfig "block_based_table_factory.format_version=5;" + // Two level index split the index into two level. First index point to second level index, which actually - // point to the block, which get bsearched to the value. This means potentially two iop instead of one per + // point to the block, which get binary searched to the value. This means potentially two iop instead of one per // read, and probably more processing overhead. But it significantly reduces memory usage and make block // processing time more consistent. So its enabled by default. That said, if you got the RAM, maybe disable // this. diff --git a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs index a69d62475f0..d1d326ef1ac 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs @@ -222,7 +222,7 @@ private void WarmupFile(string basePath, RocksDb db) { long availableMemory = GC.GetGCMemoryInfo().TotalAvailableMemoryBytes; _logger.Info($"Warming up database {Name} assuming {availableMemory} bytes of available memory"); - List<(FileMetadata metadata, DateTime creationTime)> fileMetadatas = new(); + List<(FileMetadata metadata, DateTime creationTime)> fileMetadataEntries = new(); foreach (LiveFileMetadata liveFileMetadata in db.GetLiveFilesMetadata()) { @@ -230,7 +230,7 @@ private void WarmupFile(string basePath, RocksDb db) try { DateTime creationTime = File.GetCreationTimeUtc(fullPath); - fileMetadatas.Add((liveFileMetadata.FileMetadata, creationTime)); + fileMetadataEntries.Add((liveFileMetadata.FileMetadata, creationTime)); } catch (IOException) { @@ -238,7 +238,7 @@ private void WarmupFile(string basePath, RocksDb db) } } - fileMetadatas.Sort((item1, item2) => + fileMetadataEntries.Sort((item1, item2) => { // Sort them by level so that lower level get priority int levelDiff = item1.metadata.FileLevel - item2.metadata.FileLevel; @@ -249,7 +249,7 @@ private void WarmupFile(string basePath, RocksDb db) }); long totalSize = 0; - fileMetadatas = fileMetadatas.TakeWhile(metadata => + fileMetadataEntries = fileMetadataEntries.TakeWhile(metadata => { availableMemory -= (long)metadata.metadata.FileSize; bool take = availableMemory > 0; @@ -265,7 +265,7 @@ private void WarmupFile(string basePath, RocksDb db) .ToList(); long totalRead = 0; - Parallel.ForEach(fileMetadatas, (task) => + Parallel.ForEach(fileMetadataEntries, (task) => { string fullPath = Path.Join(basePath, task.metadata.FileName); _logger.Info($"{(totalRead * 100 / (double)totalSize):00.00}% Warming up file {fullPath}"); diff --git a/src/Nethermind/Nethermind.Db/FullPruning/FullPruningDb.cs b/src/Nethermind/Nethermind.Db/FullPruning/FullPruningDb.cs index f79c010c988..142eae0379e 100755 --- a/src/Nethermind/Nethermind.Db/FullPruning/FullPruningDb.cs +++ b/src/Nethermind/Nethermind.Db/FullPruning/FullPruningDb.cs @@ -17,7 +17,7 @@ namespace Nethermind.Db.FullPruning /// Allows to start pruning with in a thread safe way. /// When pruning is started it duplicates all writes to current DB as well as the new one for full pruning, this includes write batches. /// When returned in is d it will delete the pruning DB if the pruning was not successful. - /// It uses to create new pruning DB's. Check to see how inner sub DB's are organised. + /// It uses to create new pruning DB's. Check to see how inner sub DB's are organized. /// public class FullPruningDb : IDb, IFullPruningDb, ITunableDb { diff --git a/src/Nethermind/Nethermind.Db/Metrics.cs b/src/Nethermind/Nethermind.Db/Metrics.cs index b4889866ab9..296b1a5eb63 100644 --- a/src/Nethermind/Nethermind.Db/Metrics.cs +++ b/src/Nethermind/Nethermind.Db/Metrics.cs @@ -85,7 +85,7 @@ public static class Metrics internal static void IncrementStorageSkippedWrites(long value) => Interlocked.Add(ref _storageSkippedWrites, value); [GaugeMetric] - [Description("Indicator if StadeDb is being pruned.")] + [Description("Indicator if StateDb is being pruned.")] public static int StateDbPruning { get; set; } [GaugeMetric] diff --git a/src/Nethermind/Nethermind.Era1.Test/AdminEraServiceTests.cs b/src/Nethermind/Nethermind.Era1.Test/AdminEraServiceTests.cs index 7a0f245b705..461f0ff4a51 100644 --- a/src/Nethermind/Nethermind.Era1.Test/AdminEraServiceTests.cs +++ b/src/Nethermind/Nethermind.Era1.Test/AdminEraServiceTests.cs @@ -10,7 +10,7 @@ namespace Nethermind.Era1.Test; public class AdminEraServiceTests { [Test] - public void CanCallcExport() + public void CanCallImport() { IEraImporter importer = Substitute.For(); AdminEraService adminEraService = new AdminEraService( diff --git a/src/Nethermind/Nethermind.Era1.Test/E2StoreWriterTests.cs b/src/Nethermind/Nethermind.Era1.Test/E2StoreWriterTests.cs index 174bed9663a..9be200e2fb9 100644 --- a/src/Nethermind/Nethermind.Era1.Test/E2StoreWriterTests.cs +++ b/src/Nethermind/Nethermind.Era1.Test/E2StoreWriterTests.cs @@ -43,7 +43,7 @@ public async Task WriteEntry_WritingAnEntry_WritesCorrectLengthInHeader(int leng [TestCase(1)] [TestCase(5)] [TestCase(12)] - public async Task WriteEntry_WritingAnEntry_ReturnCorrectNumberofBytesWritten(int length) + public async Task WriteEntry_WritingAnEntry_ReturnCorrectNumberOfBytesWritten(int length) { using MemoryStream stream = new MemoryStream(); using E2StoreWriter sut = new E2StoreWriter(stream); diff --git a/src/Nethermind/Nethermind.Era1/EraStore.cs b/src/Nethermind/Nethermind.Era1/EraStore.cs index 9086fcd4b06..e2a0d0da9ac 100644 --- a/src/Nethermind/Nethermind.Era1/EraStore.cs +++ b/src/Nethermind/Nethermind.Era1/EraStore.cs @@ -81,14 +81,14 @@ public EraStore( IFileSystem fileSystem, string networkName, int maxEraSize, - ISet? trustedAcccumulators, + ISet? trustedAccumulators, string directory, int verifyConcurrency = 0 ) { _specProvider = specProvider; _blockValidator = blockValidator; - _trustedAccumulators = trustedAcccumulators; + _trustedAccumulators = trustedAccumulators; _maxEraFile = maxEraSize; _maxOpenFile = Environment.ProcessorCount * 2; if (_verifyConcurrency == 0) _verifyConcurrency = Environment.ProcessorCount; diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G1MSMPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G1MSMPrecompile.cs index 2880ab0a3e2..8b8018f557e 100644 --- a/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G1MSMPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G1MSMPrecompile.cs @@ -48,7 +48,7 @@ public Result Run(ReadOnlyMemory inputData, IReleaseSpec releaseSp return Errors.InvalidInputLength; } - // use Mul to optimise single point multiplication + // use Mul to optimize single point multiplication int nItems = inputData.Length / ItemSize; return nItems == 1 ? Mul(inputData) : MSM(inputData, nItems); } diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G2MSMPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G2MSMPrecompile.cs index 54879d48471..87681710ba4 100644 --- a/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G2MSMPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G2MSMPrecompile.cs @@ -45,7 +45,7 @@ public Result Run(ReadOnlyMemory inputData, IReleaseSpec releaseSp if (inputData.Length % ItemSize > 0 || inputData.Length == 0) return Errors.InvalidInputLength; - // use Mul to optimise single point multiplication + // use Mul to optimize single point multiplication int nItems = inputData.Length / ItemSize; return nItems == 1 ? Mul(inputData) : MSM(inputData, nItems); } diff --git a/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs b/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs index 3a50b711b49..993f303edf1 100644 --- a/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs @@ -604,7 +604,7 @@ public static IEnumerable FluentBuilderTestCases } [Test] - public void code_emited_by_fluent_is_same_as_expected([ValueSource(nameof(FluentBuilderTestCases))] TestCase test) + public void code_emitted_by_fluent_is_same_as_expected([ValueSource(nameof(FluentBuilderTestCases))] TestCase test) { test.FluentCodes.Should().BeEquivalentTo(test.ResultCodes, test.Description); } diff --git a/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs b/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs index 621fa480743..1f84f9e6fba 100644 --- a/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs @@ -13,7 +13,7 @@ public class CoinbaseTests : VirtualMachineTestsBase { private bool _setAuthor; - protected override Block BuildBlock(ForkActivation activation, SenderRecipientAndMiner senderRecipientAndMiner, Transaction transaction, long blockGasLimit = DefaultBlockGasLimit, ulong exessBlobGas = 0) + protected override Block BuildBlock(ForkActivation activation, SenderRecipientAndMiner senderRecipientAndMiner, Transaction transaction, long blockGasLimit = DefaultBlockGasLimit, ulong excessBlobGas = 0) { senderRecipientAndMiner ??= new SenderRecipientAndMiner(); Block block = base.BuildBlock(activation, senderRecipientAndMiner, transaction, blockGasLimit); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs index 9ce12f75464..158ec5da763 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs @@ -409,7 +409,7 @@ public void revert_resets_all_transient_state() /// Revert undoes transient storage writes from inner calls that successfully returned ///
[Test] - public void revert_resets_transient_state_from_succesful_calls() + public void revert_resets_transient_state_from_successful_calls() { // If caller is self, TLOAD and return value (break recursion) // Else, TSTORE and call self, return the response diff --git a/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpDestinationAnalyzer.cs b/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpDestinationAnalyzer.cs index 118595a3d99..2ceca978a1b 100644 --- a/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpDestinationAnalyzer.cs +++ b/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpDestinationAnalyzer.cs @@ -108,7 +108,7 @@ private long[] CreateJumpDestinationBitmap() Metrics.IncrementContractsAnalysed(); ReadOnlySpan code = MachineCode.Span; - // If code is empty or starts with STOP, then we don't need to analyse + // If code is empty or starts with STOP, then we don't need to analyze if ((uint)code.Length < (uint)1 || code[0] == (byte)Instruction.STOP) return _emptyJumpDestinationBitmap; long[] bitmap = CreateBitmap(code.Length); @@ -305,7 +305,7 @@ internal static long[] PopulateJumpDestinationBitmap_Vector128(long[] bitmap, Re else if ((sbyte)op > PUSHx) { // Fast forward programCounter by the amount of data the push - // represents as don't need to analyse data for Jump Destinations. + // represents as don't need to analyze data for Jump Destinations. move = op - PUSH1 + 2; } diff --git a/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs b/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs index 9953e46c9e4..55a156b3f30 100644 --- a/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs +++ b/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs @@ -785,7 +785,7 @@ private static bool ValidateDataSection(in EofHeader header, ValidationStrategy } // When trailing bytes are not allowed, the DataSection cannot exceed the stated size data. - // Undeflow cases were checked above as they don't apply in all cases + // Underflow cases were checked above as they don't apply in all cases if (!strategy.HasFlag(ValidationStrategy.AllowTrailingBytes) && strategy.HasFlag(ValidationStrategy.ValidateFullBody) && header.DataSection.Size < dataBody.Length) @@ -1083,7 +1083,7 @@ private static bool ValidateInstructions( return false; } - // JUMPF is only returnig when the target is returning + // JUMPF is only returning when the target is returning if (!isTargetSectionNonReturning) { hasRequiredSectionExit = true; diff --git a/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs index ec77b92b666..a8b35aca16c 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs @@ -64,7 +64,7 @@ public DebugTracer(ITxTracer tracer) public bool IsTracingLogs => InnerTracer.IsTracingLogs; - public bool IsBreakpoitnSet(int depth, int programCounter) => _breakPoints.ContainsKey((depth, programCounter)); + public bool IsBreakpointSet(int depth, int programCounter) => _breakPoints.ContainsKey((depth, programCounter)); public void SetBreakPoint((int depth, int pc) point, Func, bool> condition = null) { diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index ce337d50f1c..8a2d3cd2652 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -379,7 +379,7 @@ private static void UpdateMetrics(ExecutionOptions opts, UInt256 effectiveGasPri } /// - /// Validates the transaction, in a static manner (i.e. without accesing state/storage). + /// Validates the transaction, in a static manner (i.e. without accessing state/storage). /// It basically ensures the transaction is well formed (i.e. no null values where not allowed, no overflows, etc). /// As a part of validating the transaction the premium per gas will be calculated, to save computation this /// is returned in an out parameter. diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index f4d8202ec38..f3cdf0db249 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -1159,8 +1159,8 @@ protected CallResult ExecuteCall( // Dispatch the bytecode interpreter. // The second generic parameter is selected based on whether the transaction tracer is cancelable: - // - OffFlag is used when cancelation is not needed. - // - OnFlag is used when cancelation is enabled. + // - OffFlag is used when cancellation is not needed. + // - OnFlag is used when cancellation is enabled. // This leverages the compile-time evaluation of TTracingInst to optimize away runtime checks. return _txTracer.IsCancelable switch { diff --git a/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs b/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs index 9ca570581b6..fb58a49c2e9 100644 --- a/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs @@ -84,7 +84,7 @@ public void IsSyncing_ReturnsExpectedResult(long bestHeader, long currentHead, b [TestCase(false, false, true)] [TestCase(true, true, false)] public void IsSyncing_AncientBarriers(bool resolverDownloadingBodies, - bool resolverDownloadingreceipts, bool expectedResult) + bool resolverDownloadingReceipts, bool expectedResult) { ISyncConfig syncConfig = new SyncConfig { @@ -102,7 +102,7 @@ public void IsSyncing_AncientBarriers(bool resolverDownloadingBodies, ISyncPointers syncPointers = Substitute.For(); ISyncProgressResolver syncProgressResolver = Substitute.For(); syncProgressResolver.IsFastBlocksBodiesFinished().Returns(resolverDownloadingBodies); - syncProgressResolver.IsFastBlocksReceiptsFinished().Returns(resolverDownloadingreceipts); + syncProgressResolver.IsFastBlocksReceiptsFinished().Returns(resolverDownloadingReceipts); blockTree.FindBestSuggestedHeader().Returns(Build.A.BlockHeader.WithNumber(6178001L).TestObject); blockTree.Head.Returns(Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(6178000L).TestObject).TestObject); diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs index 73a52a531f5..ba3e5d28c08 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs @@ -15,7 +15,7 @@ namespace Nethermind.Facade.Simulate; /// -/// This is an env for eth simulater. It is constructed by . +/// This is an env for eth simulator. It is constructed by . /// It is not thread safe and is meant to be reused. must be called and the returned /// must be disposed once done or there may be some memory leak. /// diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnvFactory.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnvFactory.cs index 74a6a426cb1..43593715743 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnvFactory.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnvFactory.cs @@ -73,10 +73,10 @@ private static BlockTree CreateTempBlockTree( IReadOnlyDbProvider editableDbProvider, SimulateDictionaryHeaderStore tmpHeaderStore) { - IBlockStore mainblockStore = new BlockStore(editableDbProvider.BlocksDb); + IBlockStore mainBlockStore = new BlockStore(editableDbProvider.BlocksDb); const int badBlocksStored = 1; - SimulateDictionaryBlockStore tmpBlockStore = new(mainblockStore); + SimulateDictionaryBlockStore tmpBlockStore = new(mainBlockStore); IBadBlockStore badBlockStore = new BadBlockStore(editableDbProvider.BadBlocksDb, badBlocksStored); return new(tmpBlockStore, diff --git a/src/Nethermind/Nethermind.HealthChecks/HealthChecksWebhookInfo.cs b/src/Nethermind/Nethermind.HealthChecks/HealthChecksWebhookInfo.cs index 3314176be13..3b1e4fb9d8c 100644 --- a/src/Nethermind/Nethermind.HealthChecks/HealthChecksWebhookInfo.cs +++ b/src/Nethermind/Nethermind.HealthChecks/HealthChecksWebhookInfo.cs @@ -1,4 +1,4 @@ -/* Class to provide useful information in healh checks' webhook notifications */ +/* Class to provide useful information in health checks' webhook notifications */ using System.Net; using System; diff --git a/src/Nethermind/Nethermind.HealthChecks/IHealthChecksConfig.cs b/src/Nethermind/Nethermind.HealthChecks/IHealthChecksConfig.cs index eac6efa88bd..14733d674f5 100644 --- a/src/Nethermind/Nethermind.HealthChecks/IHealthChecksConfig.cs +++ b/src/Nethermind/Nethermind.HealthChecks/IHealthChecksConfig.cs @@ -19,7 +19,7 @@ public interface IHealthChecksConfig : IConfig [ConfigItem(Description = "The web hook URL.", DefaultValue = "null")] public string WebhooksUri { get; set; } - [ConfigItem(Description = "An escaped JSON paylod to be sent to the web hook on failure.", + [ConfigItem(Description = "An escaped JSON payload to be sent to the web hook on failure.", DefaultValue = """ ```json { @@ -46,7 +46,7 @@ public interface IHealthChecksConfig : IConfig """)] public string WebhooksPayload { get; set; } - [ConfigItem(Description = "An escaped JSON paylod to be sent to the web hook on recovery.", + [ConfigItem(Description = "An escaped JSON payload to be sent to the web hook on recovery.", DefaultValue = """ ```json { diff --git a/src/Nethermind/Nethermind.History/HistoryPruner.cs b/src/Nethermind/Nethermind.History/HistoryPruner.cs index ed703a60923..0e82890ee05 100644 --- a/src/Nethermind/Nethermind.History/HistoryPruner.cs +++ b/src/Nethermind/Nethermind.History/HistoryPruner.cs @@ -437,7 +437,7 @@ private void PruneBlocksAndReceipts(ulong? cutoffTimestamp, CancellationToken ca // should never happen if (number == 0 || number >= _blockTree.SyncPivot.BlockNumber) { - if (_logger.IsWarn) _logger.Warn($"Encountered unexepected block #{number} while pruning history, this block will not be deleted. Should be in range (0, {_blockTree.SyncPivot.BlockNumber})."); + if (_logger.IsWarn) _logger.Warn($"Encountered unexpected block #{number} while pruning history, this block will not be deleted. Should be in range (0, {_blockTree.SyncPivot.BlockNumber})."); continue; } diff --git a/src/Nethermind/Nethermind.Hive/HiveRunner.cs b/src/Nethermind/Nethermind.Hive/HiveRunner.cs index a31cd0ae88f..ba67b9d840c 100644 --- a/src/Nethermind/Nethermind.Hive/HiveRunner.cs +++ b/src/Nethermind/Nethermind.Hive/HiveRunner.cs @@ -69,7 +69,7 @@ private void ListEnvironmentVariables() // # - HIVE_TESTNET whether testnet nonces (2^20) are needed // # - HIVE_NODETYPE sync and pruning selector (archive, full, light) // # - HIVE_FORK_HOMESTEAD block number of the DAO hard-fork transition - // # - HIVE_FORK_DAO_BLOCK block number of the DAO hard-fork transitionnsition + // # - HIVE_FORK_DAO_BLOCK block number of the DAO hard-fork transition // # - HIVE_FORK_DAO_VOTE whether the node support (or opposes) the DAO fork // # - HIVE_FORK_TANGERINE block number of TangerineWhistle // # - HIVE_FORK_SPURIOUS block number of SpuriousDragon diff --git a/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs b/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs index 3857c679cff..9b8e0542617 100644 --- a/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs +++ b/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs @@ -256,7 +256,7 @@ private void AdviseConfig(IPruningConfig pruningConfig, IDbConfig dbConfig, IHar } } - // On a 7950x (32 logical coree), assuming write buffer is large enough, the pruning time is about 3 second + // On a 7950x (32 logical cores), assuming write buffer is large enough, the pruning time is about 3 second // with 8GB of pruning cache. Lets assume that this is a safe estimate as the ssd can be a limitation also. long maximumDirtyCacheMb = Environment.ProcessorCount * 250; // It must be at least 1GB as on mainnet at least 500MB will remain to support snap sync. So pruning cache only drop to about 500MB after pruning. @@ -264,7 +264,7 @@ private void AdviseConfig(IPruningConfig pruningConfig, IDbConfig dbConfig, IHar if (pruningConfig.DirtyCacheMb > maximumDirtyCacheMb) { // The user can also change `--Db.StateDbWriteBufferSize`. - // Which may or may not be better as each read will need to go through eacch write buffer. + // Which may or may not be better as each read will need to go through each write buffer. // So having less of them is probably better.. if (_logger.IsWarn) _logger.Warn($"Detected {pruningConfig.DirtyCacheMb}MB of dirty pruning cache config. Dirty cache more than {maximumDirtyCacheMb}MB is not recommended with {Environment.ProcessorCount} logical core as it may cause long memory pruning time which affect attestation."); } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Base64ConverterTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Base64ConverterTests.cs index 5c166c2c636..e72256dada9 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Base64ConverterTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Base64ConverterTests.cs @@ -1,5 +1,6 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +/* cSpell:disable */ using Nethermind.Serialization.Json; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/IdConverterTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/IdConverterTests.cs index f447c6cd77b..6f5a8238378 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/IdConverterTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/IdConverterTests.cs @@ -69,7 +69,7 @@ public void Can_do_roundtrip_long() [Test] public void Can_do_roundtrip_string() { - TestRoundtrip("{\"id\":\"asdasdasd\"}"); + TestRoundtrip("{\"id\":\"test\"}"); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/TransactionForRpcDeserializationTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/TransactionForRpcDeserializationTests.cs index 6da4e0606c2..b79672c487a 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/TransactionForRpcDeserializationTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/TransactionForRpcDeserializationTests.cs @@ -31,7 +31,7 @@ public static IEnumerable TxJsonTestCases { get { - static TestCaseData Make(TxType expectedTxType, string json) => new(json) { TestName = $"Deserilizes into {expectedTxType} from {json}", ExpectedResult = expectedTxType }; + static TestCaseData Make(TxType expectedTxType, string json) => new(json) { TestName = $"Deserializes into {expectedTxType} from {json}", ExpectedResult = expectedTxType }; yield return Make(TxType.Legacy, """{"nonce":"0x0","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null}"""); yield return Make(TxType.Legacy, """{"nonce":"0x0","to":null,"gasPrice":"0x0","gas":"0x0","input":null}"""); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcUrlCollectionTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcUrlCollectionTests.cs index 7ace8f6392f..714a083672e 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcUrlCollectionTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcUrlCollectionTests.cs @@ -132,7 +132,7 @@ public void Clears_flag_on_additional_ws_urls_when_ws_disabled() } [Test] - public void Skips_additional_urls_with_port_conficts() + public void Skips_additional_urls_with_port_conflicts() { JsonRpcConfig jsonRpcConfig = new JsonRpcConfig() { diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs index 615f684eda1..b468009e9f1 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs @@ -28,7 +28,7 @@ public async Task Test_debug_simulate_serialization() { TestRpcBlockchain chain = await EthRpcSimulateTestsBase.CreateChain(); - SimulatePayload payload = EthSimulateTestsBlocksAndTransactions.CreateSerialisationPayload(chain); + SimulatePayload payload = EthSimulateTestsBlocksAndTransactions.CreateSerializationPayload(chain); //Force persistence of head block in main chain chain.BlockTree.UpdateMainChain(new List { chain.BlockFinder.Head! }, true, true); @@ -67,7 +67,7 @@ public async Task Test_debug_simulate_eth_moved() chain.Bridge.GetReceipt(txMainnetAtoB.Hash!); - //Force persistancy of head block in main chain + //Force persistence of head block in main chain chain.BlockTree.UpdateMainChain(new List { chain.BlockFinder.Head! }, true, true); chain.BlockTree.UpdateHeadBlock(chain.BlockFinder.Head!.Hash!); @@ -105,7 +105,7 @@ public async Task Test_debug_simulate_transactions_forced_fail() chain.Bridge.GetReceipt(txMainnetAtoB.Hash!); - //Force persistancy of head block in main chain + //Force persistence of head block in main chain chain.BlockTree.UpdateMainChain(new List { chain.BlockFinder.Head! }, true, true); chain.BlockTree.UpdateHeadBlock(chain.BlockFinder.Head!.Hash!); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.FeeHistory.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.FeeHistory.cs index 0109a2beec6..aa61625cdf4 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.FeeHistory.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.FeeHistory.cs @@ -108,7 +108,7 @@ public static IEnumerable FeeHistoryBlobTestCases yield return new TestCaseData(new ulong?[] { 49152, 1 }, new ulong?[] { 0, 49152 }) { - TestName = "Blocks with arbitary values", + TestName = "Blocks with arbitrary values", ExpectedResult = (new UInt256?[] { 1, 1, 1 }, new double?[] { 0.0, 0.0625 }) }; } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs index b49a681eea0..c883b835da6 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs @@ -25,7 +25,7 @@ namespace Nethermind.JsonRpc.Test.Modules.Eth; public class EthSimulateTestsBlocksAndTransactions { - public static SimulatePayload CreateSerialisationPayload(TestRpcBlockchain chain) + public static SimulatePayload CreateSerializationPayload(TestRpcBlockchain chain) { UInt256 nonceA = chain.ReadOnlyState.GetNonce(TestItem.AddressA); Transaction txToFail = GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 10_000_000); @@ -160,11 +160,11 @@ public static Transaction GetTransferTxData(UInt256 nonce, IEthereumEcdsa ethere } [Test] - public async Task Test_eth_simulate_serialisation() + public async Task Test_eth_simulate_serialization() { TestRpcBlockchain chain = await EthRpcSimulateTestsBase.CreateChain(); - SimulatePayload payload = CreateSerialisationPayload(chain); + SimulatePayload payload = CreateSerializationPayload(chain); //Force persistence of head block in main chain chain.BlockTree.UpdateMainChain(new List { chain.BlockFinder.Head! }, true, true); @@ -205,7 +205,7 @@ public async Task Test_eth_simulate_eth_moved() chain.Bridge.GetReceipt(txMainnetAtoB.Hash!); - //Force persistancy of head block in main chain + //Force persistence of head block in main chain chain.BlockTree.UpdateMainChain(new List { chain.BlockFinder.Head! }, true, true); chain.BlockTree.UpdateHeadBlock(chain.BlockFinder.Head!.Hash!); @@ -246,7 +246,7 @@ public async Task Test_eth_simulate_transactions_forced_fail() chain.Bridge.GetReceipt(txMainnetAtoB.Hash!); - //Force persistancy of head block in main chain + //Force persistence of head block in main chain chain.BlockTree.UpdateMainChain(new List { chain.BlockFinder.Head! }, true, true); chain.BlockTree.UpdateHeadBlock(chain.BlockFinder.Head!.Hash!); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs index 209968e149c..45e931f91e8 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsHiveBase.cs @@ -45,7 +45,7 @@ public class EthSimulateTestsHiveBase new object[] {"multicall-eth-send-should-produce-more-logs-on-forward", true, "{\"blockStateCalls\": [{\"stateOverrides\": {\"0xc000000000000000000000000000000000000000\": {\"balance\": \"0x7d0\"}, \"0xc100000000000000000000000000000000000000\": {\"code\": \"0x60806040526004361061001e5760003560e01c80634b64e49214610023575b600080fd5b61003d6004803603810190610038919061011f565b61003f565b005b60008173ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050509050806100b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100af906101a9565b60405180910390fd5b5050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100ec826100c1565b9050919050565b6100fc816100e1565b811461010757600080fd5b50565b600081359050610119816100f3565b92915050565b600060208284031215610135576101346100bc565b5b60006101438482850161010a565b91505092915050565b600082825260208201905092915050565b7f4661696c656420746f2073656e64204574686572000000000000000000000000600082015250565b600061019360148361014c565b915061019e8261015d565b602082019050919050565b600060208201905081810360008301526101c281610186565b905091905056fea2646970667358221220563acd6f5b8ad06a3faf5c27fddd0ecbc198408b99290ce50d15c2cf7043694964736f6c63430008120033\"}}, \"calls\": [{\"from\": \"0xc000000000000000000000000000000000000000\", \"to\": \"0xc100000000000000000000000000000000000000\", \"value\": \"0x3e8\", \"input\": \"0x4b64e4920000000000000000000000000000000000000000000000000000000000000100\"}]}], \"traceTransfers\": true}"}, new object[] {"multicall-eth-send-should-produce-no-logs-on-forward-revert", true, "{\"blockStateCalls\": [{\"stateOverrides\": {\"0xc000000000000000000000000000000000000000\": {\"balance\": \"0x7d0\"}, \"0xc100000000000000000000000000000000000000\": {\"code\": \"0x60806040526004361061001e5760003560e01c80634b64e49214610023575b600080fd5b61003d6004803603810190610038919061011f565b61003f565b005b60008173ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050509050806100b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100af906101a9565b60405180910390fd5b5050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100ec826100c1565b9050919050565b6100fc816100e1565b811461010757600080fd5b50565b600081359050610119816100f3565b92915050565b600060208284031215610135576101346100bc565b5b60006101438482850161010a565b91505092915050565b600082825260208201905092915050565b7f4661696c656420746f2073656e64204574686572000000000000000000000000600082015250565b600061019360148361014c565b915061019e8261015d565b602082019050919050565b600060208201905081810360008301526101c281610186565b905091905056fea2646970667358221220563acd6f5b8ad06a3faf5c27fddd0ecbc198408b99290ce50d15c2cf7043694964736f6c63430008120033\"}, \"0xc200000000000000000000000000000000000000\": {\"code\": \"0x608060405260006042576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401603990609d565b60405180910390fd5b005b600082825260208201905092915050565b7f416c7761797320726576657274696e6720636f6e747261637400000000000000600082015250565b600060896019836044565b91506092826055565b602082019050919050565b6000602082019050818103600083015260b481607e565b905091905056fea264697066735822122005cbbbc709291f66fadc17416c1b0ed4d72941840db11468a21b8e1a0362024c64736f6c63430008120033\"}}, \"calls\": [{\"from\": \"0xc000000000000000000000000000000000000000\", \"to\": \"0xc100000000000000000000000000000000000000\", \"value\": \"0x3e8\", \"input\": \"0x4b64e492c200000000000000000000000000000000000000000000000000000000000000\"}]}], \"traceTransfers\": true}"}, new object[] {"multicall-get-block-properties", true, "{\"blockStateCalls\": [{\"stateOverrides\": {\"0xc100000000000000000000000000000000000000\": {\"code\": \"0x608060405234801561001057600080fd5b506000366060484641444543425a3a60014361002c919061009b565b406040516020016100469a99989796959493929190610138565b6040516020818303038152906040529050915050805190602001f35b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006100a682610062565b91506100b183610062565b92508282039050818111156100c9576100c861006c565b5b92915050565b6100d881610062565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610109826100de565b9050919050565b610119816100fe565b82525050565b6000819050919050565b6101328161011f565b82525050565b60006101408201905061014e600083018d6100cf565b61015b602083018c6100cf565b610168604083018b610110565b610175606083018a6100cf565b61018260808301896100cf565b61018f60a08301886100cf565b61019c60c08301876100cf565b6101a960e08301866100cf565b6101b76101008301856100cf565b6101c5610120830184610129565b9b9a505050505050505050505056fea26469706673582212205139ae3ba8d46d11c29815d001b725f9840c90e330884ed070958d5af4813d8764736f6c63430008120033\"}}, \"calls\": [{\"from\": \"0xc000000000000000000000000000000000000000\", \"to\": \"0xc100000000000000000000000000000000000000\", \"input\": \"0x\"}]}]}"}, -new object[] {"multicall-instrict-gas-38013", false, "{\"blockStateCalls\": [{\"calls\": [{\"from\": \"0xc100000000000000000000000000000000000000\", \"to\": \"0xc100000000000000000000000000000000000000\", \"gas\": \"0x0\"}]}]}"}, +new object[] {"multicall-insufficient-gas-38013", false, "{\"blockStateCalls\": [{\"calls\": [{\"from\": \"0xc100000000000000000000000000000000000000\", \"to\": \"0xc100000000000000000000000000000000000000\", \"gas\": \"0x0\"}]}]}"}, new object[] {"multicall-logs", true, "{\"blockStateCalls\": [{\"stateOverrides\": {\"0xc200000000000000000000000000000000000000\": {\"code\": \"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80600080a1600080f3\"}}, \"calls\": [{\"from\": \"0xc000000000000000000000000000000000000000\", \"to\": \"0xc200000000000000000000000000000000000000\", \"input\": \"0x6057361d0000000000000000000000000000000000000000000000000000000000000005\"}]}]}"}, new object[] {"multicall-move-precompile-twice", true, "{\"blockStateCalls\": [{\"stateOverrides\": {\"0xc000000000000000000000000000000000000000\": {\"balance\": \"0x3e8\"}, \"0xc200000000000000000000000000000000000000\": {\"balance\": \"0x7d0\"}, \"0xc300000000000000000000000000000000000000\": {\"balance\": \"0xbb8\"}, \"0xc400000000000000000000000000000000000000\": {\"code\": \"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033\"}}}, {\"stateOverrides\": {\"0x0000000000000000000000000000000000000001\": {\"balance\": \"0xbb8\", \"MovePrecompileToAddress\": \"0xc200000000000000000000000000000000000000\"}, \"0xc200000000000000000000000000000000000000\": {\"balance\": \"0xfa0\", \"MovePrecompileToAddress\": \"0xc300000000000000000000000000000000000000\"}}, \"calls\": [{\"from\": \"0xc000000000000000000000000000000000000000\", \"to\": \"0xc400000000000000000000000000000000000000\", \"input\": \"0xf8b2cb4f000000000000000000000000c000000000000000000000000000000000000000\"}, {\"from\": \"0xc000000000000000000000000000000000000000\", \"to\": \"0xc400000000000000000000000000000000000000\", \"input\": \"0xf8b2cb4f000000000000000000000000c200000000000000000000000000000000000000\"}, {\"from\": \"0xc000000000000000000000000000000000000000\", \"to\": \"0xc400000000000000000000000000000000000000\", \"input\": \"0xf8b2cb4f000000000000000000000000c300000000000000000000000000000000000000\"}]}]}"}, new object[] {"multicall-move-ecrecover-and-call", true, "{\"blockStateCalls\": [{\"calls\": [{\"from\": \"0xc100000000000000000000000000000000000000\", \"to\": \"0x0000000000000000000000000000000000000001\", \"input\": \"0x4554480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b45544800000000000000000000000000000000000000000000000000000000004554480000000000000000000000000000000000000000000000000000000000\"}, {\"from\": \"0xc100000000000000000000000000000000000000\", \"to\": \"0x0000000000000000000000000000000000000001\", \"input\": \"0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8000000000000000000000000000000000000000000000000000000000000001cb7cf302145348387b9e69fde82d8e634a0f8761e78da3bfa059efced97cbed0d2a66b69167cafe0ccfc726aec6ee393fea3cf0e4f3f9c394705e0f56d9bfe1c9\"}]}, {\"stateOverrides\": {\"0x0000000000000000000000000000000000000001\": {\"MovePrecompileToAddress\": \"0x0000000000000000000000000000000000123456\"}}, \"calls\": [{\"from\": \"0xc100000000000000000000000000000000000000\", \"to\": \"0x0000000000000000000000000000000000123456\", \"input\": \"0x4554480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b45544800000000000000000000000000000000000000000000000000000000004554480000000000000000000000000000000000000000000000000000000000\"}, {\"from\": \"0xc100000000000000000000000000000000000000\", \"to\": \"0x0000000000000000000000000000000000123456\", \"input\": \"0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8000000000000000000000000000000000000000000000000000000000000001cb7cf302145348387b9e69fde82d8e634a0f8761e78da3bfa059efced97cbed0d2a66b69167cafe0ccfc726aec6ee393fea3cf0e4f3f9c394705e0f56d9bfe1c9\"}]}]}"}, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcTransaction/AccessListTransactionForRpcTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcTransaction/AccessListTransactionForRpcTests.cs index fe7adfe2e48..d69dca748a3 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcTransaction/AccessListTransactionForRpcTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcTransaction/AccessListTransactionForRpcTests.cs @@ -81,7 +81,7 @@ public static void ValidateSchema(JsonElement json) json.GetProperty("value").GetString().Should().MatchRegex("^0x([1-9a-f]+[0-9a-f]*|0)$"); json.GetProperty("input").GetString().Should().MatchRegex("^0x[0-9a-f]*$"); json.GetProperty("gasPrice").GetString().Should().MatchRegex("^0x([1-9a-f]+[0-9a-f]*|0)$"); - // Suprising inconsistency in `FluentAssertions` where `AllSatisfy` fails on empty collections. + // Surprising inconsistency in `FluentAssertions` where `AllSatisfy` fails on empty collections. // This requires wrapping the assertion in a condition. // See: https://github.com/fluentassertions/fluentassertions/discussions/2143#discussioncomment-9677309 var accessList = json.GetProperty("accessList").EnumerateArray(); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParitySimulateTestsBlocksAndTransactions.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParitySimulateTestsBlocksAndTransactions.cs index fb5fd892d3f..cbd96f3430f 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParitySimulateTestsBlocksAndTransactions.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParitySimulateTestsBlocksAndTransactions.cs @@ -25,7 +25,7 @@ public async Task Test_trace_simulate_serialization() { TestRpcBlockchain chain = await EthRpcSimulateTestsBase.CreateChain(); - SimulatePayload payload = EthSimulateTestsBlocksAndTransactions.CreateSerialisationPayload(chain); + SimulatePayload payload = EthSimulateTestsBlocksAndTransactions.CreateSerializationPayload(chain); //Force persistence of head block in main chain chain.BlockTree.UpdateMainChain(new List { chain.BlockFinder.Head! }, true, true); @@ -63,7 +63,7 @@ public async Task Test_trace_simulate_eth_moved() chain.Bridge.GetReceipt(txMainnetAtoB.Hash!); - //Force persistancy of head block in main chain + //Force persistence of head block in main chain chain.BlockTree.UpdateMainChain(new List { chain.BlockFinder.Head! }, true, true); chain.BlockTree.UpdateHeadBlock(chain.BlockFinder.Head!.Hash!); @@ -101,7 +101,7 @@ public async Task Test_trace_simulate_transactions_forced_fail() chain.Bridge.GetReceipt(txMainnetAtoB.Hash!); - //Force persistancy of head block in main chain + //Force persistence of head block in main chain chain.BlockTree.UpdateMainChain(new List { chain.BlockFinder.Head! }, true, true); chain.BlockTree.UpdateHeadBlock(chain.BlockFinder.Head!.Hash!); diff --git a/src/Nethermind/Nethermind.JsonRpc/ErrorCodes.cs b/src/Nethermind/Nethermind.JsonRpc/ErrorCodes.cs index 71e4190e423..cea92a933c0 100644 --- a/src/Nethermind/Nethermind.JsonRpc/ErrorCodes.cs +++ b/src/Nethermind/Nethermind.JsonRpc/ErrorCodes.cs @@ -123,7 +123,7 @@ public static class ErrorCodes public const int ClientLimitExceededError = -38026; /// - /// Block is not available due to history expirty policy + /// Block is not available due to history expiry policy /// public const int PrunedHistoryUnavailable = 4444; @@ -178,7 +178,7 @@ public static class ErrorCodes public const int MaxInitCodeSizeExceeded = -38025; /// - /// Transaction reverted. Geth sets it to -32000 in simulate but suppose to 3. We kepp it as geth for now + /// Transaction reverted. Geth sets it to -32000 in simulate but supposed to be 3. We keep it as Geth for now /// public const int RevertedSimulate = -32000; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs index 7ae8f672122..2f0dca1873b 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs @@ -32,7 +32,7 @@ public IDebugRpcModule Create() { IOverridableEnv env = envFactory.Create(); - ILifetimeScope tracerLifecyccle = rootLifetimeScope.BeginLifetimeScope((builder) => + ILifetimeScope tracerLifecycle = rootLifetimeScope.BeginLifetimeScope((builder) => ConfigureTracerContainer(builder) .AddModule(env)); @@ -40,9 +40,9 @@ public IDebugRpcModule Create() // This is to prevent leaking processor or world state accidentally. // `GethStyleTracer` must be very careful to always dispose overridable env. ILifetimeScope debugRpcModuleLifetime = rootLifetimeScope.BeginLifetimeScope((builder) => builder - .AddScoped(tracerLifecyccle.Resolve())); + .AddScoped(tracerLifecycle.Resolve())); - debugRpcModuleLifetime.Disposer.AddInstanceForAsyncDisposal(tracerLifecyccle); + debugRpcModuleLifetime.Disposer.AddInstanceForAsyncDisposal(tracerLifecycle); rootLifetimeScope.Disposer.AddInstanceForAsyncDisposal(debugRpcModuleLifetime); return debugRpcModuleLifetime.Resolve(); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs index d5f2d5f3939..72f8ee4af0b 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs @@ -103,7 +103,7 @@ public interface IDebugRpcModule : IRpcModule [JsonRpcMethod(Description = "Get Raw Transaction format.")] ResultWrapper debug_getRawTransaction(Hash256 transactionHash); - [JsonRpcMethod(Description = "Retrives Nethermind Sync Stage, With extra Metadata")] + [JsonRpcMethod(Description = "Retrieves Nethermind Sync Stage, With extra Metadata")] Task> debug_getSyncStage(); [JsonRpcMethod(Description = "Writes to a file the full stack trace of all invoked opcodes of the transaction specified (or all transactions if not specified) that was included in the block specified. The parent of the block must be present or it will fail.", diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs index 1c486bf41fe..fd6ca2c2770 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs @@ -95,7 +95,7 @@ public interface IEthRpcModule : IRpcModule ResultWrapper eth_getStorageAt([JsonRpcParameter(ExampleValue = "[\"0x000000000000000000000000c666d239cbda32aa7ebca894b6dc598ddb881285\",\"0x2\"]")] Address address, UInt256 positionIndex, BlockParameter? blockParameter = null); [JsonRpcMethod(IsImplemented = true, - Description = "Returns account nonce (number of trnsactions from the account since genesis) at the given block number", + Description = "Returns account nonce (number of transactions from the account since genesis) at the given block number", IsSharable = true, ExampleResponse = "0x3e")] Task> eth_getTransactionCount([JsonRpcParameter(ExampleValue = "[\"0xae3ed7a6ccdddf2914133d0669b5f02ff6fa8ad2\"]")] Address address, BlockParameter? blockParameter = null); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Personal/IPersonalRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Personal/IPersonalRpcModule.cs index cb6350d5e1d..eb63b3bbf43 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Personal/IPersonalRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Personal/IPersonalRpcModule.cs @@ -34,7 +34,7 @@ public interface IPersonalRpcModule : IRpcModule ExampleResponse = "0x1ddea39c8b8a2202cd9f56bc9a6ecdbf1cf3d5f5")] ResultWrapper
personal_ecRecover([JsonRpcParameter(ExampleValue = "[\"0xdeadbeaf\", \"0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b\"]")] byte[] message, byte[] signature); - [JsonRpcMethod(Description = "The sign method calculates an Ethereum specific signature with: sign(keccack256(\"\x19Ethereum Signed Message:\n\" + len(message) + message))).", + [JsonRpcMethod(Description = "The sign method calculates an Ethereum specific signature with: sign(keccak256(\"\x19Ethereum Signed Message:\n\" + len(message) + message))).", IsImplemented = false, ExampleResponse = "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b")] ResultWrapper personal_sign([JsonRpcParameter(ExampleValue = "[\"0xdeadbeaf\", \"0x9b2055d370f73ec7d8a03e965129118dc8f5bf83\"]")] byte[] message, Address address, string passphrase = null); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerMsgSendRecvResponse.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerMsgSendRecvResponse.cs index f5afa80c503..9c5a37062de 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerMsgSendRecvResponse.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/PeerMsgSendRecvResponse.cs @@ -15,9 +15,9 @@ protected PeerMsgSendRecvResponse() } - public PeerMsgSendRecvResponse(EventArgs eventArgs, string subscripionType, string? e) + public PeerMsgSendRecvResponse(EventArgs eventArgs, string subscriptionType, string? e) { - Type = subscripionType; + Type = subscriptionType; Error = e; } diff --git a/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs b/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs index 150e27b716b..02060ce14fa 100644 --- a/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs +++ b/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs @@ -113,10 +113,10 @@ private static Target[] GetTargets(IList configurationLoggingRules) private static void RemoveOverriddenRules(IList configurationLoggingRules, LoggingRule loggingRule) { - string reqexPattern = $"^{loggingRule.LoggerNamePattern.Replace(".", "\\.").Replace("*", ".*")}$"; + string regexPattern = $"^{loggingRule.LoggerNamePattern.Replace(".", "\\.").Replace("*", ".*")}$"; for (int j = 0; j < configurationLoggingRules.Count;) { - if (Regex.IsMatch(configurationLoggingRules[j].LoggerNamePattern, reqexPattern)) + if (Regex.IsMatch(configurationLoggingRules[j].LoggerNamePattern, regexPattern)) { configurationLoggingRules.RemoveAt(j); } diff --git a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs index bb9b788da75..07dd1df0b51 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs @@ -84,7 +84,7 @@ public override Task processing_block_should_serialize_valid_responses(string bl public override Task forkchoiceUpdatedV1_should_communicate_with_boost_relay_through_http(string blockHash, string parentHash) => base.forkchoiceUpdatedV1_should_communicate_with_boost_relay_through_http(blockHash, parentHash); - [Ignore("Withdrawals are not withdrawan due to lack of Aura contract in tests")] + [Ignore("Withdrawals are not withdrawn due to lack of Aura contract in tests")] public override Task Can_apply_withdrawals_correctly((Withdrawal[][] Withdrawals, (Address Account, UInt256 BalanceIncrease)[] ExpectedAccountIncrease) input) { return base.Can_apply_withdrawals_correctly(input); diff --git a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs index 07e945056a2..56e2615e47b 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs @@ -63,7 +63,7 @@ protected override PostMergeBlockProducerFactory CreateBlockProducerFactory() _blocksConfig, _api.LogManager); - protected override IBlockFinalizationManager InitializeMergeFinilizationManager() + protected override IBlockFinalizationManager InitializeMergeFinalizationManager() { return new AuRaMergeFinalizationManager(_api.Context.Resolve(), _auraApi!.FinalizationManager ?? diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/JwtTest.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/JwtTest.cs index de53c5116f4..f111b2197bc 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/JwtTest.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/JwtTest.cs @@ -1,5 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +/* cSpell:disable */ using System; using System.Threading.Tasks; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs index a6a37aa8e2a..2262888457d 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs @@ -155,7 +155,7 @@ private void EnsureReceiptAvailable() private void EnsureJsonRpcUrl() { - if (HasTtd() == false) // by default we have Merge.Enabled = true, for chains that are not post-merge, wwe can skip this check, but we can still working with MergePlugin + if (HasTtd() == false) // by default we have Merge.Enabled = true, for chains that are not post-merge, we can skip this check, but we can still working with MergePlugin return; IJsonRpcConfig jsonRpcConfig = _api.Config(); @@ -214,7 +214,7 @@ public Task InitNetworkProtocol() _mergeBlockProductionPolicy = new MergeBlockProductionPolicy(_api.BlockProductionPolicy); _api.BlockProductionPolicy = _mergeBlockProductionPolicy; - _api.FinalizationManager = InitializeMergeFinilizationManager(); + _api.FinalizationManager = InitializeMergeFinalizationManager(); if (_poSSwitcher.TransitionFinished) { @@ -236,7 +236,7 @@ private void AddEth69() _api.ProtocolsManager!.AddSupportedCapability(new(Protocol.Eth, 69)); } - protected virtual IBlockFinalizationManager InitializeMergeFinilizationManager() + protected virtual IBlockFinalizationManager InitializeMergeFinalizationManager() { return new MergeFinalizationManager(_api.Context.Resolve(), _api.FinalizationManager, _poSSwitcher); } diff --git a/src/Nethermind/Nethermind.Merkleization/MerkleTree.cs b/src/Nethermind/Nethermind.Merkleization/MerkleTree.cs index f5f0c4f7317..aef4d5bd102 100644 --- a/src/Nethermind/Nethermind.Merkleization/MerkleTree.cs +++ b/src/Nethermind/Nethermind.Merkleization/MerkleTree.cs @@ -301,7 +301,7 @@ public IList GetProof(in uint leafIndex) { if (leafIndex >= Count) { - throw new InvalidOperationException("Unpexected query for a proof for a value beyond Count"); + throw new InvalidOperationException("Unexpected query for a proof for a value beyond Count"); } Index index = new Index(LeafRow, leafIndex); diff --git a/src/Nethermind/Nethermind.Monitoring.Test/MetricsTests.cs b/src/Nethermind/Nethermind.Monitoring.Test/MetricsTests.cs index 3da65ed5080..f152b18ab00 100644 --- a/src/Nethermind/Nethermind.Monitoring.Test/MetricsTests.cs +++ b/src/Nethermind/Nethermind.Monitoring.Test/MetricsTests.cs @@ -43,7 +43,7 @@ public static class TestMetrics [SummaryMetric] public static IMetricObserver SomeObservation { get; set; } = NoopMetricObserver.Instance; - [System.ComponentModel.Description("Histograrm metric")] + [System.ComponentModel.Description("Histogram metric")] [ExponentialPowerHistogramMetric(Start = 1, Factor = 2, Count = 10)] public static IMetricObserver HistogramObservation { get; set; } = NoopMetricObserver.Instance; diff --git a/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs b/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs index e8b139e4f4f..a0a0b6a0cba 100644 --- a/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs +++ b/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs @@ -205,7 +205,7 @@ private static string GetStaticMemberInfo(Type givenInformer, string givenName) Type type = givenInformer; PropertyInfo[] tagsData = type.GetProperties(BindingFlags.Static | BindingFlags.Public); PropertyInfo info = tagsData.FirstOrDefault(info => info.Name == givenName) ?? throw new NotSupportedException("Developer error: a requested static description field was not implemented!"); - object value = info.GetValue(null) ?? throw new NotSupportedException("Developer error: a requested static description field was not initialised!"); + object value = info.GetValue(null) ?? throw new NotSupportedException("Developer error: a requested static description field was not initialized!"); return value.ToString()!; } diff --git a/src/Nethermind/Nethermind.Network.Dns.Test/EnrTreeParserTests.cs b/src/Nethermind/Nethermind.Network.Dns.Test/EnrTreeParserTests.cs index 2131e3e2c4d..bd7ff19ab82 100644 --- a/src/Nethermind/Nethermind.Network.Dns.Test/EnrTreeParserTests.cs +++ b/src/Nethermind/Nethermind.Network.Dns.Test/EnrTreeParserTests.cs @@ -1,5 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +/* cSpell:disable */ using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs index 8e33c0c7324..c0c78ea903a 100644 --- a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs @@ -116,7 +116,7 @@ public void Fork_id_and_hash_as_expected_with_merge_fork_id(long head, ulong hea } [TestCase(0, 0ul, "0xFE3366E7", 1735371ul, "Sepolia genesis")] - [TestCase(1735370, 0ul, "0xFE3366E7", 1_735_371ul, "Sepolia Last block before MergeForkIdTranstion")] + [TestCase(1735370, 0ul, "0xFE3366E7", 1_735_371ul, "Sepolia Last block before MergeForkIdTransition")] [TestCase(1735371, 0ul, "0xb96cbd13", 1_677_557_088ul, "First block - Sepolia MergeForkIdTransition")] [TestCase(1735372, 1_677_557_088ul, "0xf7f9bc08", 1_706_655_072ul, "Shanghai")] [TestCase(1735372, 1_706_655_071ul, "0xf7f9bc08", 1_706_655_072ul, "Future Shanghai")] diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/GetReceiptsMessageTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/GetReceiptsMessageTests.cs index b6bde3d62e7..c12998f398d 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/GetReceiptsMessageTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/GetReceiptsMessageTests.cs @@ -14,7 +14,7 @@ namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V63 public class GetReceiptsMessageTests { [Test] - public void Sets_values_from_contructor_argument() + public void Sets_values_from_constructor_argument() { ArrayPoolList hashes = new(2) { TestItem.KeccakA, TestItem.KeccakB }; using GetReceiptsMessage message = new(hashes); diff --git a/src/Nethermind/Nethermind.Network.Test/PacketTests.cs b/src/Nethermind/Nethermind.Network.Test/PacketTests.cs index 7d04dd64766..d48385292c8 100644 --- a/src/Nethermind/Nethermind.Network.Test/PacketTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/PacketTests.cs @@ -11,7 +11,7 @@ namespace Nethermind.Network.Test public class PacketTests { [Test] - public void Asggins_values_from_constructor() + public void Assigns_values_from_constructor() { byte[] data = { 3, 4, 5 }; Packet packet = new("eth", 2, data); diff --git a/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs b/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs index e75041eec31..3121523f1e0 100644 --- a/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs @@ -63,7 +63,7 @@ public async Task Can_start_and_stop() "enode://3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333b@52.141.78.53:12345?discport=6789"; private const string enode8String = - "enode://3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333b@52.141.78.53:12345?somethingwrong=6789"; + "enode://3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333b@52.141.78.53:12345?somethingWrong=6789"; private const string enode9String = "enode://3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333b@52.141.78.53:12345?discport=6789?discport=67899"; diff --git a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EncryptionHandshakeServiceTests.cs b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EncryptionHandshakeServiceTests.cs index c791e5a10b2..01e47e33d52 100644 --- a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EncryptionHandshakeServiceTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EncryptionHandshakeServiceTests.cs @@ -29,7 +29,7 @@ public void SetUp() SerializerInfo.Create(new AckEip8MessageSerializer(new Eip8MessagePad(_testRandom))) ); - _eciesCipher = new EciesCipher(_trueCryptoRandom); // TODO: provide a separate test random with specific IV and epehemeral key for testing + _eciesCipher = new EciesCipher(_trueCryptoRandom); // TODO: provide a separate test random with specific IV and ephemeral key for testing _initiatorService = new HandshakeService(_messageSerializationService, _eciesCipher, _testRandom, _ecdsa, NetTestVectors.StaticKeyA, LimboLogs.Instance); _recipientService = new HandshakeService(_messageSerializationService, _eciesCipher, _testRandom, _ecdsa, NetTestVectors.StaticKeyB, LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyFrameEncodeDecodeTests.cs b/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyFrameEncodeDecodeTests.cs index bd779c7c5e6..571f6bced6c 100644 --- a/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyFrameEncodeDecodeTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyFrameEncodeDecodeTests.cs @@ -85,9 +85,9 @@ private IChannelHandlerContext PipeWriteToChannel(IChannelHandler channelHandler pipeWrite.When((it) => it.WriteAsync(Arg.Any())) .Do((info => { - if (info[0] is IReferenceCounted refc) + if (info[0] is IReferenceCounted refCount) { - refc.Retain(); + refCount.Retain(); } channelHandler.WriteAsync(nextContext, info[0]).Wait(); })); @@ -101,9 +101,9 @@ private IChannelHandlerContext PipeWriteToChannelRead(IChannelHandler channelHan pipeWrite.When((it) => it.WriteAsync(Arg.Any())) .Do((info => { - if (info[0] is IReferenceCounted refc) + if (info[0] is IReferenceCounted refCount) { - refc.Retain(); + refCount.Retain(); } channelHandler.ChannelRead(nextContext, info[0]); })); diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs index 2442a438221..de56ae1be6d 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs @@ -229,7 +229,7 @@ private ArrayPoolList AddMarkUnknownHashes(ReadOnlySpan hashes Hash256 hash = hashes[i]; if (!_txPool.IsKnown(hash)) { - if (_txPool.NoitifyAboutTx(hash, this) is AnnounceResult.RequestRequired) + if (_txPool.NotifyAboutTx(hash, this) is AnnounceResult.RequestRequired) { discoveredTxHashesAndSizes.Add(hash); } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs index bb628264ecc..512ef7f38e6 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs @@ -171,7 +171,7 @@ private ArrayPoolListRef AddMarkUnknownHashes(ReadOnlySpan hashes) Hash256 hash = hashes[i]; if (!_txPool.IsKnown(hash)) { - if (_txPool.NoitifyAboutTx(hash, this) is AnnounceResult.RequestRequired) + if (_txPool.NotifyAboutTx(hash, this) is AnnounceResult.RequestRequired) { discoveredTxHashesAndSizes.Add(i); } diff --git a/src/Nethermind/Nethermind.Network/P2P/Utils/BackgroundTaskSchedulerWrapper.cs b/src/Nethermind/Nethermind.Network/P2P/Utils/BackgroundTaskSchedulerWrapper.cs index 47a4836becc..f2fcc398c21 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Utils/BackgroundTaskSchedulerWrapper.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Utils/BackgroundTaskSchedulerWrapper.cs @@ -31,16 +31,16 @@ internal bool TryScheduleBackgroundTask(TReq request, Func( - (TReq Request, Func> FullfillFunc) input, CancellationToken cancellationToken) where TRes : P2PMessage + (TReq Request, Func> FulfillFunc) input, CancellationToken cancellationToken) where TRes : P2PMessage { - TRes response = await input.FullfillFunc(input.Request, cancellationToken); + TRes response = await input.FulfillFunc(input.Request, cancellationToken); handler.Send(response); } private async ValueTask BackgroundSyncSenderValueTask( - (TReq Request, Func> FullfillFunc) input, CancellationToken cancellationToken) where TRes : P2PMessage + (TReq Request, Func> FulfillFunc) input, CancellationToken cancellationToken) where TRes : P2PMessage { - TRes response = await input.FullfillFunc(input.Request, cancellationToken); + TRes response = await input.FulfillFunc(input.Request, cancellationToken); handler.Send(response); } diff --git a/src/Nethermind/Nethermind.Network/ProtocolsManager.cs b/src/Nethermind/Nethermind.Network/ProtocolsManager.cs index f1a0291cbde..562731cce69 100644 --- a/src/Nethermind/Nethermind.Network/ProtocolsManager.cs +++ b/src/Nethermind/Nethermind.Network/ProtocolsManager.cs @@ -64,7 +64,7 @@ public class ProtocolsManager : IProtocolsManager private readonly IGossipPolicy _gossipPolicy; private readonly ITxGossipPolicy _txGossipPolicy; private readonly ILogManager _logManager; - private readonly ITxPoolConfig _txPoolConfdig; + private readonly ITxPoolConfig _txPoolConfig; private readonly ISpecProvider _specProvider; private readonly ILogger _logger; private readonly IDictionary> _protocolFactories; @@ -87,7 +87,7 @@ public ProtocolsManager( IGossipPolicy gossipPolicy, IWorldStateManager worldStateManager, ILogManager logManager, - ITxPoolConfig txPoolConfdig, + ITxPoolConfig txPoolConfig, ISpecProvider specProvider, ITxGossipPolicy? transactionsGossipPolicy = null) { @@ -105,7 +105,7 @@ public ProtocolsManager( _gossipPolicy = gossipPolicy ?? throw new ArgumentNullException(nameof(gossipPolicy)); _txGossipPolicy = transactionsGossipPolicy ?? ShouldGossip.Instance; _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); - _txPoolConfdig = txPoolConfdig; + _txPoolConfig = txPoolConfig; _specProvider = specProvider; _snapServer = worldStateManager.SnapServer; _logger = _logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); @@ -223,8 +223,8 @@ private IDictionary> GetProtocolFa { 66 => new Eth66ProtocolHandler(session, _serializer, _stats, _syncServer, _backgroundTaskScheduler, _txPool, _gossipPolicy, _forkInfo, _logManager, _txGossipPolicy), 67 => new Eth67ProtocolHandler(session, _serializer, _stats, _syncServer, _backgroundTaskScheduler, _txPool, _gossipPolicy, _forkInfo, _logManager, _txGossipPolicy), - 68 => new Eth68ProtocolHandler(session, _serializer, _stats, _syncServer, _backgroundTaskScheduler, _txPool, _gossipPolicy, _forkInfo, _logManager, _txPoolConfdig, _specProvider, _txGossipPolicy), - 69 => new Eth69ProtocolHandler(session, _serializer, _stats, _syncServer, _backgroundTaskScheduler, _txPool, _gossipPolicy, _forkInfo, _logManager, _txPoolConfdig, _specProvider, _txGossipPolicy), + 68 => new Eth68ProtocolHandler(session, _serializer, _stats, _syncServer, _backgroundTaskScheduler, _txPool, _gossipPolicy, _forkInfo, _logManager, _txPoolConfig, _specProvider, _txGossipPolicy), + 69 => new Eth69ProtocolHandler(session, _serializer, _stats, _syncServer, _backgroundTaskScheduler, _txPool, _gossipPolicy, _forkInfo, _logManager, _txPoolConfig, _specProvider, _txGossipPolicy), _ => throw new NotSupportedException($"Eth protocol version {version} is not supported.") }; diff --git a/src/Nethermind/Nethermind.Network/Rlpx/ZeroFrameDecoder.cs b/src/Nethermind/Nethermind.Network/Rlpx/ZeroFrameDecoder.cs index 6d78a09b414..9829661df65 100644 --- a/src/Nethermind/Nethermind.Network/Rlpx/ZeroFrameDecoder.cs +++ b/src/Nethermind/Nethermind.Network/Rlpx/ZeroFrameDecoder.cs @@ -37,7 +37,7 @@ protected override void Decode(IChannelHandlerContext context, IByteBuffer input // Note that ByteToMessageDecoder handles input.Release calls for us. // In fact, we receive here a potentially surviving _internalBuffer of the base class - // that is being built by its cumulator. + // that is being built by its accumulator. // Output buffers that we create will be released by the next handler in the pipeline. while (input.ReadableBytes >= Frame.BlockSize) diff --git a/src/Nethermind/Nethermind.Optimism.Test/CL/BatchDecoderTests.cs b/src/Nethermind/Nethermind.Optimism.Test/CL/BatchDecoderTests.cs index 012c9487377..6c9e36734f0 100644 --- a/src/Nethermind/Nethermind.Optimism.Test/CL/BatchDecoderTests.cs +++ b/src/Nethermind/Nethermind.Optimism.Test/CL/BatchDecoderTests.cs @@ -45,7 +45,7 @@ public void DecodeSingleSpanBatch() new Address("0xa76fc24d4649325a236811710bd6ffe6c2d2cce4"), new Address("0x0f8570abb559266670ddcbc3fc995326b2f981b9"), ], - Datas = [ + Data = [ Bytes.FromHexString("0xf9032e8853444835ec58000088743dc13203ffb2eab90319485515d488227c969b561a04d56bec5d080c18cb61178511068ef972f059c5c4e91f7025af950e43af9288534c4aa7358ec0a1c769cff1d7d3d0dc64d68c997cb2e0f86d8228ea806645a57a196f669e5a075de1144153dbdfd5392a50ab79b226cf2b4fe3a80270dc784874246d1eb2f0c3bb458f94ccf129d9b8b8a3ba5fb1cde16f5de7a214c718a84c5a8d75e00d13d8d658e7a3db5d4d06c172d0f582b31ebdd9485cabe8aaba2fd4dc56f737f10a182f4cb352d641b8ff13e3d2601796f036159222314a73d8d19b183a4389fa4a74b4c5028596eec95f7d8f17afac441f074a1b4da6689f8ab1532a1f90586bdedff0e6ebf70fe5d1c26ac977a3ae9696ea4bf8009e0ee073e800db98783eab20a69d1b38de60e6dc1c20759863f4e8150504ae02b89c040d83befba021da4ee7031a924af56448349105c8c8e6e2e2f424133e5b3cd87cafc1083867e5543bd5fe8f35083d0fab1c43c499d445e50dc1b81adfc9b6b4bb6f64884467c4877a65d50f4faa6ba9dd6c81e07f1ef4783ed5cfcf4bfafedb5917e6163b5b17a3adb9145d0c9c8f3d0ca24188b3db1787cdb35c06315ea5d91f7f3d7c80e03c6cc80199b7277962a0d345a952784443b6ea695ff4e3ea5ce12728e6237b5e5206a72b7933db4991fbeff815f6bdff37c0fe0d86acccbb8756c580805dc97fab68d5bd4b9fdcf0e869ad693e3f23510a3c471cb94aefedbac5cd61a227d2a86eff1dbbc89ab34c1dc7a3c0a934fc3b6f70ced9a4c05029d7a4273dcddc9998fb825b8f1a93e772b8a11e250405aac197b2b10d432154f12d46e5aaf83dd7a38c38f61bac02b8348ae983d8d6d2d10a7a71ec98564f015910bb077d9324c550a1440592bf9c1bdfe1635440c6aee23e755f222bcdb8067efc1b6527db2247bf224da6055588e3674a5c30a0521147743a7d89421b7cdc0a5bc9f718eab3ab38a5e1baebc04621513a5d00199cfa25ea946a107adbd453a904298eebc0e5760777a6051099fe94fe6151b4ff2f04a80113788a2f9eb2e26613aa32bb0267362805aa6c7e535fbd6612d6951ea5bdde84c05be2d902793c8bc01a4455215c371a74c2f8cfa3f35b7a0302e572"), Bytes.FromHexString("0xf901e6886124fee993bc000088947902a97a7abf0bb901d15c5b0f5a62c90e175f998ee98115fa6ee1a0b9f708704902235345770e065ac4d3d43e6f66482b1f3488f38fbe158d2ed04f0d81a865bae80bd957d2fb1228fcc335afe1fc171ca17ff296415f2c7895a6ec3561bf71a34c40f2c6baf066ad4f41b5c89cecc91d44f517f1a0449ddc250873005a7f0cbca904b6176853218c63dd77758f2eeaced5da39a6ae2aaf9358c6268edfe91e7f161ba69a564fa81093b0c463b49bac1dad9c70df9c1622451a20c1c3ef225aed40f1db90d225eefe906a86938510267761d3fc518c11ab11f35e3f66feb784b8c8b84a2e3cd93bcf9c964a407a54bdcf9e594d81bab533cdcd659969543d75dbb2ce2411daccaf2675523a0f0f49bad0f26cc3cff853411f66c661a8ead90211081306838cc18c6e1aedb8df78f533a605edcbe4e24bd6404843d8b79c4a3cbb98c318378d990db39acb8154cecd1e5251bd258de852a2c5b4292a6bbce8383bb894e141ec80a78e51f1448850af993f18e5315c4cb4c8d397921608733a81370d7b803ba019a08ad75a25035f09ac53a89f3573282623b1e31d4829dafd3d801b04ca2d0aa2043e10bfe21619ec93fb3bddeac27f4a7ea969d6bf2a0563f3e7ed5df2e41f97308f21633b86fe4f44664cb65f225de096905a36"), Bytes.FromHexString("0xf90328880de0b6b3a764000088ce04f894f6dff6efb90312a1a85e158c277bebf76ffbdfbf0950af2a731471d53f18cdc3213621d648299a1309ec3fb66fcc871678003b370bd2c4f7763eb6ba56c525906496e979b20cbcd21254b44d7d3dea1d3b34d286e398b7529ff3a38b0b8ab7b9ab5fc9e3f04dd2f9a7ab7d9df3323f2211fb41352f03d4f74377df9621992ebfc376d6f85662e98e2fa440284bede4d4617a83cab8142b74dcd327b0177478bc4a156f557fb947ef45495b9041f86d2a247d5f1212a8b088ae5baa2b1dc7a829e0a3d2a0e766acb8a2a9bf674fd511756a8088843c2c8daabe10a652d44b546b9d0374e8daf3ead390f622ae286f0c664eecf567c415cf22e25aa69d8209444194c7d53aca10ad12d3f905a9511dca9445768063f18a08a6dcdb69e865ffcaff1f5a210c4b2bbbe4017eba33a0abe12cba2c99eced5dc42473ba6964dd58aebdb794d8203888c372c965c3b0bcc727e651823ea7d36e2c77378c6b00de06d640e5c87e0d2ff8d68585b56686a9d4ce02a00233e8181688f8a75f31803292942351c7156f0a6600a1ab2b206786969c33568d916cb1b404fa19d97b0e9b2e1fd282367d145777a2d451cbe94667b6025636caf49d4e37660467ca66cb2863c58254bf95023d36a4e3ebfe1294f95495a9348cd7f68bfd70a8368fb516a5bede14af5c98a3b0a61e95187eca74d09984c0ea8365aa8e0a870a9da1ad3049065ca20cf15799337366a915e12cca2cb5f3f557794dbc4bb0b66f6301fe0b07d06cbb58a610587813a116ad3a0262a2b167afb2919452acd26d2c4ca0b1cc54b0dcfb24017e1d5f86ae769664cdb327651ffcfcdd8108a798d50eaf2172e56d2737d318543e02f5575e3425dd8c5ad77dbbb3e196c0ab4a9f5a7e30b698819fbe95e66c608ba1eb70b3223c8654f44d04dd90a1e6e15b8f6b7d0f714b582f67584f59c49d497b34d8d084cf6d6b87937f198f50e79e4054f5a16f0d86e2dd2636c3aec9193a54d79f608bb5ebaef0240bee0fb35e4d5cc87602b99a45773d217265b402d8dc2c1eef10851a4163588f7c28b9548de8fab0db630e14bc491f28e7c61194c8e3a9490324e4c58116ba82b1f8ca2f9b3234964660a8aac0"), diff --git a/src/Nethermind/Nethermind.Optimism/CL/Decoding/BatchDecoder.cs b/src/Nethermind/Nethermind.Optimism/CL/Decoding/BatchDecoder.cs index e9d97865ef2..49f9381bff6 100644 --- a/src/Nethermind/Nethermind.Optimism/CL/Decoding/BatchDecoder.cs +++ b/src/Nethermind/Nethermind.Optimism/CL/Decoding/BatchDecoder.cs @@ -89,12 +89,12 @@ private static BatchV1 DecodeSpanBatch(BinaryMemoryReader reader) tos[i] = new Address(reader.Take(Address.Size).Span); } - var datas = new ReadOnlyMemory[(int)totalTxCount]; + var data = new ReadOnlyMemory[(int)totalTxCount]; var types = new TxType[(int)totalTxCount]; ulong legacyTxCnt = 0; for (var i = 0; i < (int)totalTxCount; ++i) { - (datas[i], types[i]) = reader.Read(TxParser.Data); + (data[i], types[i]) = reader.Read(TxParser.Data); if (types[i] == TxType.Legacy) { legacyTxCnt++; @@ -130,7 +130,7 @@ private static BatchV1 DecodeSpanBatch(BinaryMemoryReader reader) YParityBits = yParityBits, Signatures = signatures, Tos = tos, - Datas = datas, + Data = data, Types = types, TotalLegacyTxCount = legacyTxCnt, Nonces = nonces, diff --git a/src/Nethermind/Nethermind.Optimism/CL/Decoding/BatchV1.cs b/src/Nethermind/Nethermind.Optimism/CL/Decoding/BatchV1.cs index 875aa9be288..c94d04d4318 100644 --- a/src/Nethermind/Nethermind.Optimism/CL/Decoding/BatchV1.cs +++ b/src/Nethermind/Nethermind.Optimism/CL/Decoding/BatchV1.cs @@ -32,7 +32,7 @@ public sealed class Transactions public required BigInteger YParityBits; public required IReadOnlyList<(UInt256 R, UInt256 S)> Signatures; // TODO: Do we want to use `Nethermind.Core.Crypto.Signature`? public required IReadOnlyList
Tos; - public required IReadOnlyList> Datas; + public required IReadOnlyList> Data; public required IReadOnlyList Types; public required ulong TotalLegacyTxCount; public required IReadOnlyList Nonces; @@ -115,20 +115,20 @@ public IEnumerable ToSingularBatches(ulong chainId, ulong genesis v = 27u + (parityBit ? 1u : 0u); } - (tx.Value, tx.GasPrice, tx.Data) = DecodeLegacyTransaction(Txs.Datas[(int)txIdx].Span); + (tx.Value, tx.GasPrice, tx.Data) = DecodeLegacyTransaction(Txs.Data[(int)txIdx].Span); break; } case TxType.AccessList: { v = EthereumEcdsaExtensions.CalculateV(chainId, parityBit); - (tx.Value, tx.GasPrice, tx.Data, tx.AccessList) = DecodeAccessListTransaction(Txs.Datas[(int)txIdx].Span); + (tx.Value, tx.GasPrice, tx.Data, tx.AccessList) = DecodeAccessListTransaction(Txs.Data[(int)txIdx].Span); break; } case TxType.EIP1559: { v = EthereumEcdsaExtensions.CalculateV(chainId, parityBit); (tx.Value, tx.GasPrice, tx.DecodedMaxFeePerGas, tx.Data, tx.AccessList) = - DecodeEip1559Transaction(Txs.Datas[(int)txIdx].Span); + DecodeEip1559Transaction(Txs.Data[(int)txIdx].Span); break; } default: diff --git a/src/Nethermind/Nethermind.Optimism/OptimismLegacyTxDecoder.cs b/src/Nethermind/Nethermind.Optimism/OptimismLegacyTxDecoder.cs index 73c69369e5c..d892fa8795c 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismLegacyTxDecoder.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismLegacyTxDecoder.cs @@ -41,7 +41,7 @@ public ValidationResult IsWellFormed(Transaction transaction, IReleaseSpec relea var isPreBedrock = !releaseSpec.IsEip1559Enabled; if (isPreBedrock) { - // Pre-Bedrock we peform no validation at all + // Pre-Bedrock we perform no validation at all return ValidationResult.Success; } diff --git a/src/Nethermind/Nethermind.Optimism/OptimismSynchronizerModule.cs b/src/Nethermind/Nethermind.Optimism/OptimismSynchronizerModule.cs index d331fbbaaae..29ecf1e047d 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismSynchronizerModule.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismSynchronizerModule.cs @@ -10,7 +10,7 @@ namespace Nethermind.Optimism; /// -/// In Optimism Mainnet, the gets resetted to 0 in the Bedrock block unlike other chains that went through The Merge fork. +/// In Optimism Mainnet, the gets reset to 0 in the Bedrock block unlike other chains that went through The Merge fork. /// Calculation is still the same: the current block's is the parent's plus the current block's . /// /// diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs index e0013891a0c..608216b70a3 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs @@ -86,7 +86,7 @@ public IEnumerable RegistrationsFor(Service service, Fun return []; } - // Dynamically resolve any interface with nsubstitue + // Dynamically resolve any interface with nsubstitute ComponentRegistration registration = new ComponentRegistration( Guid.NewGuid(), new DelegateActivator(swt.ServiceType, (c, p) => diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs index 953abe1a301..88222c13a19 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs @@ -112,7 +112,7 @@ public async Task With_constructor_without_nethermind_api() } [Test] - public async Task With_ambigious_steps() + public async Task With_ambiguous_steps() { await using IContainer container = CreateNethermindEnvironment( new StepInfo(typeof(StepWithLogManagerInConstructor)), diff --git a/src/Nethermind/Nethermind.Runner.Test/EthereumRunnerTests.cs b/src/Nethermind/Nethermind.Runner.Test/EthereumRunnerTests.cs index 06645e64121..1b9fd323b01 100644 --- a/src/Nethermind/Nethermind.Runner.Test/EthereumRunnerTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/EthereumRunnerTests.cs @@ -203,12 +203,12 @@ public async Task Smoke_CanResolveAllSteps((string file, ConfigProvider configPr INethermindApi api = runner.Api; - // They normally need the api to be populated by steps, so we mock ouf nethermind api here. + // They normally need the api to be populated by steps, so we mock out nethermind api here. Build.MockOutNethermindApi((NethermindApi)api); api.Config().LocalIp = "127.0.0.1"; api.Config().ExternalIp = "127.0.0.1"; - _ = api.Config(); // Randomly fail type disccovery if not resolved early. + _ = api.Config(); // Randomly fail type discovery if not resolved early. api.NodeKey = new InsecureProtectedPrivateKey(TestItem.PrivateKeyA); api.BlockProducerRunner = Substitute.For(); diff --git a/src/Nethermind/Nethermind.Runner.Test/Module/MainProcessingContextTests.cs b/src/Nethermind/Nethermind.Runner.Test/Module/MainProcessingContextTests.cs index 516f65a0bc8..bc895664665 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Module/MainProcessingContextTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Module/MainProcessingContextTests.cs @@ -22,7 +22,7 @@ public class MainProcessingContextTests { [Test] [CancelAfter(10000)] - public async Task Test_TransactionProcessed_EventIsFired(CancellationToken cancelationToken) + public async Task Test_TransactionProcessed_EventIsFired(CancellationToken cancellationToken) { await using IContainer ctx = new ContainerBuilder() .AddModule(new TestNethermindModule(Cancun.Instance)) @@ -36,8 +36,8 @@ public async Task Test_TransactionProcessed_EventIsFired(CancellationToken cance int totalTransactionProcessed = 0; mainProcessingContext.TransactionProcessed += (_, _) => totalTransactionProcessed++; - await ctx.Resolve().StartBlockProcessing(cancelationToken); - await ctx.Resolve().AddBlockAndWaitForHead(false, cancelationToken, + await ctx.Resolve().StartBlockProcessing(cancellationToken); + await ctx.Resolve().AddBlockAndWaitForHead(false, cancellationToken, Build.A.Transaction .WithGasLimit(100_000) .WithSenderAddress(TestItem.AddressA) diff --git a/src/Nethermind/Nethermind.Runner/NLog.config b/src/Nethermind/Nethermind.Runner/NLog.config index 59c90820b85..17d3b6cd2a8 100644 --- a/src/Nethermind/Nethermind.Runner/NLog.config +++ b/src/Nethermind/Nethermind.Runner/NLog.config @@ -78,7 +78,7 @@ - + @@ -137,7 +137,7 @@ - You can also use wilcards + You can also use wildcards --> diff --git a/src/Nethermind/Nethermind.Shutter/ShutterEon.cs b/src/Nethermind/Nethermind.Shutter/ShutterEon.cs index 20e3f24b8bb..c41e3f0f037 100644 --- a/src/Nethermind/Nethermind.Shutter/ShutterEon.cs +++ b/src/Nethermind/Nethermind.Shutter/ShutterEon.cs @@ -66,7 +66,7 @@ public void Update(BlockHeader header) } else if (_logger.IsError) { - _logger.Error("Cannot use unfinalised Shutter keyper set contract."); + _logger.Error("Cannot use unfinalized Shutter keyper set contract."); } } } diff --git a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs index 25e2158cc4e..a8de14b0ec5 100644 --- a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs @@ -239,7 +239,7 @@ private static void VerifyPragueSpecificsForMainnetHoodiAndSepolia(ulong chainId expectedDepositContractAddress = Eip6110Constants.SepoliaDepositContractAddress; break; default: - Assert.Fail("Unrecognised chain id when verifying Prague specifics."); + Assert.Fail("Unrecognized chain id when verifying Prague specifics."); return; } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs index 72dce31c2d2..0e60190a575 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs @@ -11,7 +11,7 @@ namespace Nethermind.Trie.Pruning; /// OverlayTrieStore works by reading and writing to the passed in keyValueStore first as if it is an archive node. /// If a node is missing, then it will try to find from the base store. /// On reset the base db provider is expected to clear any diff which causes this overlay trie store to no longer -/// see overlayed keys. +/// see overlaid keys. /// public class OverlayTrieStore(IKeyValueStoreWithBatching keyValueStore, IReadOnlyTrieStore baseStore) : ITrieStore { diff --git a/src/Nethermind/Nethermind.TxPool/ITxPool.cs b/src/Nethermind/Nethermind.TxPool/ITxPool.cs index a8f4507b8d1..844cd776963 100644 --- a/src/Nethermind/Nethermind.TxPool/ITxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/ITxPool.cs @@ -39,7 +39,7 @@ public interface ITxPool void AddPeer(ITxPoolPeer peer); void RemovePeer(PublicKey nodeId); bool ContainsTx(Hash256 hash, TxType txType); - AnnounceResult NoitifyAboutTx(Hash256 txhash, IMessageHandler retryHandler); + AnnounceResult NotifyAboutTx(Hash256 txhash, IMessageHandler retryHandler); AcceptTxResult SubmitTx(Transaction tx, TxHandlingOptions handlingOptions); bool RemoveTransaction(Hash256? hash); Transaction? GetBestTx(); diff --git a/src/Nethermind/Nethermind.TxPool/NullTxPool.cs b/src/Nethermind/Nethermind.TxPool/NullTxPool.cs index 40a6855a4b3..afb1f5b20e7 100644 --- a/src/Nethermind/Nethermind.TxPool/NullTxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/NullTxPool.cs @@ -87,7 +87,7 @@ public bool TryGetBlobAndProofV1(byte[] blobVersionedHash, public UInt256 GetLatestPendingNonce(Address address) => 0; - public AnnounceResult NoitifyAboutTx(Hash256 txhash, IMessageHandler retryHandler) => AnnounceResult.RequestRequired; + public AnnounceResult NotifyAboutTx(Hash256 txhash, IMessageHandler retryHandler) => AnnounceResult.RequestRequired; public event EventHandler NewDiscovered { diff --git a/src/Nethermind/Nethermind.TxPool/RetryCache.cs b/src/Nethermind/Nethermind.TxPool/RetryCache.cs index 24c979ce1f6..56ae7a42aab 100644 --- a/src/Nethermind/Nethermind.TxPool/RetryCache.cs +++ b/src/Nethermind/Nethermind.TxPool/RetryCache.cs @@ -23,7 +23,7 @@ public sealed class RetryCache : IAsyncDisposable private readonly int _expiringQueueLimit; private readonly int _maxRetryRequests; private readonly Task _mainLoopTask; - private static readonly ObjectPool>> _handlerBagsPool = new DefaultObjectPool>>(new ConcurrentBagPolicy>()); + private static readonly ObjectPool>> _handlerBagsPool = new DefaultObjectPool>>(new ConcurrentHashSetPolicy>()); private readonly ConcurrentDictionary>> _retryRequests = new(); private readonly ConcurrentQueue<(TResourceId ResourceId, DateTimeOffset ExpiresAfter)> _expiringQueue = new(); private int _expiringQueueCounter = 0; @@ -194,7 +194,7 @@ public enum AnnounceResult Delayed } -internal class ConcurrentBagPolicy : IPooledObjectPolicy> +internal class ConcurrentHashSetPolicy : IPooledObjectPolicy> { public ConcurrentHashSet Create() => []; diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index b5596680f02..9f8fcf7706e 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -576,7 +576,7 @@ private void TryConvertProofVersion(Transaction tx) } } - public AnnounceResult NoitifyAboutTx(Hash256 hash, IMessageHandler retryHandler) => + public AnnounceResult NotifyAboutTx(Hash256 hash, IMessageHandler retryHandler) => (!AcceptTxWhenNotSynced && _headInfo.IsSyncing) || _hashCache.Get(hash) ? AnnounceResult.Delayed : _retryCache.Announced(hash, retryHandler); diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcModuleTestOverrides.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcModuleTestOverrides.cs index fb2b1b0edad..c311814b1f0 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcModuleTestOverrides.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcModuleTestOverrides.cs @@ -53,7 +53,7 @@ protected override void Load(ContainerBuilder builder) .AddSingleton() // add missing components - .AddSingleton() + .AddSingleton() .AddSingleton() // Environments @@ -85,7 +85,7 @@ protected override void Load(ContainerBuilder builder) }); } - internal class RandomPenalizer(ISpecProvider specProvider) : IPenaltyHandler + internal class RandomPenaltyHandler(ISpecProvider specProvider) : IPenaltyHandler { readonly Dictionary _penaltiesCache = new(); public Address[] Penalize(long number, Hash256 currentHash, Address[] candidates, int count = 2) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs index f4b27d472f4..66ccec3426b 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs @@ -188,9 +188,9 @@ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder, .AddSingleton(ctx => { var spec = ctx.Resolve(); - var logmanager = ctx.Resolve(); + var logManager = ctx.Resolve(); //Set the first signer to be a non master node to avoid accidental block proposals - return new Signer(spec.ChainId, TestItem.PrivateKeyA, logmanager); + return new Signer(spec.ChainId, TestItem.PrivateKeyA, logManager); }) .AddSingleton((_) => BlockProducer) //.AddSingleton((_) => BlockProducerRunner) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestHelper.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestHelper.cs index a6cf48bb438..9b6021e10fa 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestHelper.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestHelper.cs @@ -31,13 +31,13 @@ public static QuorumCertificate CreateQc(BlockRoundInfo roundInfo, ulong gapNumb return new QuorumCertificate(roundInfo, signatures.ToArray(), gapNumber); } - public static Signature[] CreateVoteSignatures(BlockRoundInfo roundInfo, ulong gapnumber, PrivateKey[] keys) + public static Signature[] CreateVoteSignatures(BlockRoundInfo roundInfo, ulong gapNumber, PrivateKey[] keys) { var encoder = new VoteDecoder(); IEnumerable signatures = keys.Select(k => { var stream = new KeccakRlpStream(); - encoder.Encode(stream, new Vote(roundInfo, gapnumber), RlpBehaviors.ForSealing); + encoder.Encode(stream, new Vote(roundInfo, gapNumber), RlpBehaviors.ForSealing); return ecdsa.Sign(k, stream.GetValueHash()); }).ToArray(); return signatures.ToArray(); diff --git a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/HeaderVerificationTests.cs b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/HeaderVerificationTests.cs index f4226215cca..a228172df53 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/HeaderVerificationTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/HeaderVerificationTests.cs @@ -51,8 +51,8 @@ public void Block_With_Invalid_Qc_Fails() var voteForSign = new Vote(proposedBlockInfo, 1); var validSigners = xdcTestBlockchain.MasterNodeCandidates - .Where(pvkey => invalidRoundBlockParent.ValidatorsAddress!.Value.Contains(pvkey.Address)) - .Select(pvkey => new Signer(0, pvkey, xdcTestBlockchain.LogManager)) + .Where(pvKey => invalidRoundBlockParent.ValidatorsAddress!.Value.Contains(pvKey.Address)) + .Select(pvKey => new Signer(0, pvKey, xdcTestBlockchain.LogManager)) .ToList(); List signatures = []; @@ -73,7 +73,7 @@ public void Block_With_Invalid_Qc_Fails() } [Test] - public async Task Block_With_Illigitimate_Signer_Fails() + public async Task Block_With_Illegitimate_Signer_Fails() { var previousSigner = xdcSigner.Key; @@ -255,8 +255,8 @@ public void Block_With_QcSignature_Below_Threshold_Fails() var proposedBlockInfo = new BlockRoundInfo(invalidQcSignatureBlockParent!.Hash!, invalidQcSignatureBlockParent.ExtraConsensusData!.BlockRound, invalidQcSignatureBlockParent.Number); var voteForSign = new Vote(proposedBlockInfo, 1); var validSigners = xdcTestBlockchain.MasterNodeCandidates - .Where(pvkey => invalidQcSignatureBlockParent.ValidatorsAddress!.Value.Contains(pvkey.Address)) - .Select(pvkey => new Signer(0, pvkey, xdcTestBlockchain.LogManager)) + .Where(pvKey => invalidQcSignatureBlockParent.ValidatorsAddress!.Value.Contains(pvKey.Address)) + .Select(pvKey => new Signer(0, pvKey, xdcTestBlockchain.LogManager)) .ToList(); List signatures = []; diff --git a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/MineModuleTests.cs b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/MineModuleTests.cs index 846b0c0c9d1..9c451b00b6b 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/MineModuleTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/MineModuleTests.cs @@ -53,7 +53,7 @@ public async Task TestUpdateMultipleMasterNodes() // mine the gap block that should trigger master node update var gapBlock = await blockchain.AddBlock(); - while (!ISnapshotManager.IsTimeforSnapshot(tree.Head!.Header!.Number, spec)) + while (!ISnapshotManager.IsTimeForSnapshot(tree.Head!.Header!.Number, spec)) { gapBlock = await blockchain.AddBlock(); } @@ -127,7 +127,7 @@ public async Task TestUpdateMasterNodes() Assert.That(snapshot.NextEpochCandidates.Length, Is.EqualTo(30)); var gapBlock = await blockchain.AddBlock(); - while (!ISnapshotManager.IsTimeforSnapshot(tree.Head!.Header!.Number, spec)) + while (!ISnapshotManager.IsTimeForSnapshot(tree.Head!.Header!.Number, spec)) { gapBlock = await blockchain.AddBlock(); } @@ -142,8 +142,6 @@ public async Task TestUpdateMasterNodes() Assert.That(snapshot.BlockNumber, Is.EqualTo(gapBlock.Number)); Assert.That(snapshot.NextEpochCandidates.Length, Is.EqualTo(blockchain.MasterNodeCandidates.Count)); - long tstamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); - var epochSwitchBlock = await blockchain.AddBlock(); while (!blockchain.EpochSwitchManager.IsEpochSwitchAtBlock((XdcBlockHeader)tree.Head!.Header!)) { diff --git a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/ProposedBlockTests.cs b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/ProposedBlockTests.cs index 64e17c02712..fe51092ef36 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/ProposedBlockTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/ProposedBlockTests.cs @@ -32,8 +32,8 @@ public async Task TestShouldSendVoteMsgAndCommitGreatGrandparentBlockAsync() { //If we randomly picked the block proposer we need to remove him with a another voting masternode var extraMaster = switchInfo.Masternodes.First((m) => m != head.Beneficiary && masternodes.Any(x => x.Address != m)); - var extraMasterkey = blockChain.MasterNodeCandidates.First(x => x.Address == extraMaster); - masternodes = [.. masternodes.Where(x => x.Address != head.Beneficiary), extraMasterkey]; + var extraMasterKey = blockChain.MasterNodeCandidates.First(x => x.Address == extraMaster); + masternodes = [.. masternodes.Where(x => x.Address != head.Beneficiary), extraMasterKey]; } BlockRoundInfo votingBlock = new BlockRoundInfo(head.Hash!, blockChain.XdcContext.CurrentRound, head.Number); @@ -106,8 +106,8 @@ public async Task TestProposedBlockMessageHandlerSuccessfullyGenerateVote() { //If we randomly picked the block proposer we need to remove him with a another voting masternode var extraMaster = switchInfo.Masternodes.First((m) => m != head.Beneficiary && masternodes.Any(x => x.Address != m)); - var extraMasterkey = blockChain.MasterNodeCandidates.First(x => x.Address == extraMaster); - masternodes = [.. masternodes.Where(x => x.Address != head.Beneficiary), extraMasterkey]; + var extraMasterKey = blockChain.MasterNodeCandidates.First(x => x.Address == extraMaster); + masternodes = [.. masternodes.Where(x => x.Address != head.Beneficiary), extraMasterKey]; } BlockRoundInfo votingBlock = new BlockRoundInfo(head.Hash!, blockChain.XdcContext.CurrentRound, head.Number); @@ -181,8 +181,8 @@ public async Task TestProposedBlockMessageHandlerNotGenerateVoteIfSignerNotInMNl { //If we randomly picked the block proposer we need to remove him with a another voting masternode var extraMaster = switchInfo.Masternodes.First((m) => m != head.Beneficiary && masternodes.Any(x => x.Address != m)); - var extraMasterkey = blockChain.MasterNodeCandidates.First(x => x.Address == extraMaster); - masternodes = [.. masternodes.Where(x => x.Address != head.Beneficiary), extraMasterkey]; + var extraMasterKey = blockChain.MasterNodeCandidates.First(x => x.Address == extraMaster); + masternodes = [.. masternodes.Where(x => x.Address != head.Beneficiary), extraMasterKey]; } BlockRoundInfo votingBlock = new BlockRoundInfo(head.Hash!, blockChain.XdcContext.CurrentRound, head.Number); diff --git a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/XdcReorgModuleTests.cs b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/XdcReorgModuleTests.cs index b1f4b45b86e..02a8317d50f 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/XdcReorgModuleTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/XdcReorgModuleTests.cs @@ -48,24 +48,24 @@ public async Task BuildAValidForkOnFinalizedBlockAndAssertForkBecomesCanonical() newHeadWaitHandle.SetResult(); }; - XdcBlockHeader forkparent = finalizedBlock; + XdcBlockHeader forkParent = finalizedBlock; for (int i = 0; i < 3; i++) { //Build a fork on finalized block, which should result in fork becoming new head - forkparent = (XdcBlockHeader)(await blockChain.AddBlockFromParent(forkparent)).Header; + forkParent = (XdcBlockHeader)(await blockChain.AddBlockFromParent(forkParent)).Header; } - if (blockChain.BlockTree.Head!.Hash != forkparent.Hash) + if (blockChain.BlockTree.Head!.Hash != forkParent.Hash) { //Wait for new head await Task.WhenAny(newHeadWaitHandle.Task, Task.Delay(5_000)); } - blockChain.BlockTree.Head!.Hash.Should().Be(forkparent.Hash!); + blockChain.BlockTree.Head!.Hash.Should().Be(forkParent.Hash!); //The new fork head should commit it's grandparent as finalized - blockChain.XdcContext.HighestCommitBlock.Hash.Should().Be(blockChain.BlockTree.FindHeader(forkparent.ParentHash!)!.ParentHash!); + blockChain.XdcContext.HighestCommitBlock.Hash.Should().Be(blockChain.BlockTree.FindHeader(forkParent.ParentHash!)!.ParentHash!); //Our lock QC should be parent of the fork head - blockChain.XdcContext.LockQC!.ProposedBlockInfo.Hash.Should().Be(forkparent.ParentHash!); + blockChain.XdcContext.LockQC!.ProposedBlockInfo.Hash.Should().Be(forkParent.ParentHash!); } [TestCase(5)] diff --git a/src/Nethermind/Nethermind.Xdc.Test/SnapshotDecoderTests.cs b/src/Nethermind/Nethermind.Xdc.Test/SnapshotDecoderTests.cs index 873b55a067f..6c4702d670f 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/SnapshotDecoderTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/SnapshotDecoderTests.cs @@ -21,7 +21,7 @@ public class SnapshotDecoderTests ]; [Test, TestCaseSource(nameof(Snapshots))] - public void RoundTrip_valuedecoder(Snapshot original) + public void RoundTrip_ValueDecoder(Snapshot original) { SnapshotDecoder encoder = new(); RlpStream rlpStream = new(encoder.GetLength(original, RlpBehaviors.None)); diff --git a/src/Nethermind/Nethermind.Xdc.Test/XdcSealValidatorTests.cs b/src/Nethermind/Nethermind.Xdc.Test/XdcSealValidatorTests.cs index fd9c0783f99..0cc13b7f80c 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/XdcSealValidatorTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/XdcSealValidatorTests.cs @@ -68,10 +68,10 @@ public static IEnumerable InvalidSignatureCases() yield return new TestCaseData(header, new byte[0]); yield return new TestCaseData(header, new byte[65]); yield return new TestCaseData(header, new byte[66]); - byte[] extralongSignature = new byte[66]; + byte[] extraLongSignature = new byte[66]; var keyASig = new EthereumEcdsa(0).Sign(TestItem.PrivateKeyA, header).BytesWithRecovery; - keyASig.CopyTo(extralongSignature, 0); - yield return new TestCaseData(header, extralongSignature); + keyASig.CopyTo(extraLongSignature, 0); + yield return new TestCaseData(header, extraLongSignature); var keyBSig = new EthereumEcdsa(0).Sign(TestItem.PrivateKeyB, header).BytesWithRecovery; yield return new TestCaseData(header, keyBSig); } diff --git a/src/Nethermind/Nethermind.Xdc.Test/XdcTestExtentions.cs b/src/Nethermind/Nethermind.Xdc.Test/XdcTestExtentions.cs index 63f221747bb..4d13e7fdfa0 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/XdcTestExtentions.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/XdcTestExtentions.cs @@ -5,7 +5,7 @@ namespace Nethermind.Core.Test.Builders; -public static class BuildExtentions +public static class BuildExtensions { public static XdcBlockHeaderBuilder XdcBlockHeader(this Build build) { diff --git a/src/Nethermind/Nethermind.Xdc/EpochSwitchManager.cs b/src/Nethermind/Nethermind.Xdc/EpochSwitchManager.cs index b4eca2644d6..0aa44f928dc 100644 --- a/src/Nethermind/Nethermind.Xdc/EpochSwitchManager.cs +++ b/src/Nethermind/Nethermind.Xdc/EpochSwitchManager.cs @@ -135,17 +135,17 @@ public bool IsEpochSwitchAtRound(ulong currentRound, XdcBlockHeader parent) Address[] penalties = header.PenaltiesAddress.Value.ToArray(); Address[] candidates = snap.NextEpochCandidates; - var stanbyNodes = new Address[0]; + var standbyNodes = new Address[0]; if (masterNodes.Length != candidates.Length) { - stanbyNodes = candidates + standbyNodes = candidates .Except(masterNodes) .Except(penalties) .ToArray(); } - epochSwitchInfo = new EpochSwitchInfo(masterNodes, stanbyNodes, penalties, new BlockRoundInfo(header.Hash, header.ExtraConsensusData?.BlockRound ?? 0, header.Number)); + epochSwitchInfo = new EpochSwitchInfo(masterNodes, standbyNodes, penalties, new BlockRoundInfo(header.Hash, header.ExtraConsensusData?.BlockRound ?? 0, header.Number)); if (header.ExtraConsensusData?.QuorumCert is not null) { diff --git a/src/Nethermind/Nethermind.Xdc/ISnapshotManager.cs b/src/Nethermind/Nethermind.Xdc/ISnapshotManager.cs index f43abe604d7..cd41816d6a4 100644 --- a/src/Nethermind/Nethermind.Xdc/ISnapshotManager.cs +++ b/src/Nethermind/Nethermind.Xdc/ISnapshotManager.cs @@ -10,7 +10,7 @@ namespace Nethermind.Xdc; public interface ISnapshotManager { - static bool IsTimeforSnapshot(long blockNumber, IXdcReleaseSpec spec) + static bool IsTimeForSnapshot(long blockNumber, IXdcReleaseSpec spec) { if (blockNumber == spec.SwitchBlock) return true; diff --git a/src/Nethermind/Nethermind.Xdc/QuorumCertificateManager.cs b/src/Nethermind/Nethermind.Xdc/QuorumCertificateManager.cs index 7f33e7dd5d1..16ce9cdf913 100644 --- a/src/Nethermind/Nethermind.Xdc/QuorumCertificateManager.cs +++ b/src/Nethermind/Nethermind.Xdc/QuorumCertificateManager.cs @@ -100,7 +100,7 @@ private bool CommitBlock(IBlockTree chain, XdcBlockHeader proposedBlockHeader, u if (parentHeader.ExtraConsensusData is null) { - error = $"Block {parentHeader.ToString(BlockHeader.Format.FullHashAndNumber)} does not have required consensus data! Chain migth be corrupt!"; + error = $"Block {parentHeader.ToString(BlockHeader.Format.FullHashAndNumber)} does not have required consensus data! Chain might be corrupt!"; return false; } diff --git a/src/Nethermind/Nethermind.Xdc/SnapshotManager.cs b/src/Nethermind/Nethermind.Xdc/SnapshotManager.cs index 6b406a8fab5..05ff2b96392 100644 --- a/src/Nethermind/Nethermind.Xdc/SnapshotManager.cs +++ b/src/Nethermind/Nethermind.Xdc/SnapshotManager.cs @@ -129,7 +129,7 @@ private void UpdateMasterNodes(XdcBlockHeader header) round = header.ExtraConsensusData.BlockRound; // Could consider dropping the round parameter here, since the consensus parameters used here should not change IXdcReleaseSpec spec = specProvider.GetXdcSpec(header, round); - if (!ISnapshotManager.IsTimeforSnapshot(header.Number, spec)) + if (!ISnapshotManager.IsTimeForSnapshot(header.Number, spec)) return; Address[] candidates; diff --git a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs index 3088ca79c6d..18e41e0fd0d 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs @@ -138,8 +138,8 @@ public BlockReward[] CalculateRewards(Block block) for (long i = start; i < endBlockNumber; i += MergeSignRange) { if (!blockNumberToHash.TryGetValue(i, out var blockHash)) continue; - if (!hashToSigningAddress.TryGetValue(blockHash, out var addrs)) continue; - foreach (Address addr in addrs) + if (!hashToSigningAddress.TryGetValue(blockHash, out var addresses)) continue; + foreach (Address addr in addresses) { if (!masternodes.Contains(addr)) continue; if (!signers.ContainsKey(addr)) signers[addr] = 0; diff --git a/src/Nethermind/cspell.json b/src/Nethermind/cspell.json deleted file mode 100644 index 474d387832b..00000000000 --- a/src/Nethermind/cspell.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "version": "0.2", - "language": "en", - "files": [ - "**/*.{cs,csproj,fs,fsproj,vb,vbproj,props,targets,sln,tt,ttinclude,config,json,yml,yaml,md,txt,ps1,psm1,sh}", - "**/*.{ts,tsx,js,jsx,html,css,scss,xml}", - "**/*.proto" - ], - "ignorePaths": [ - "src/bench_precompiles/**", - "src/tests/**", - "src/Nethermind/artifacts/**", - "src/Nethermind/Chains/**", - "src/Nethermind/TestResults/**", - "**/bin/**", - "**/obj/**", - "**/node_modules/**", - "**/.git/**", - "**/.vs/**" - ], - "ignoreRegExpList": [ - "/0x[0-9a-fA-F]+/g", - "/https?:\\/\\/\\S+/g" - ], - "words": [ - "Autofac", - "Blobpool", - "Blobtransactions", - "Blockhash", - "Chiado", - "Commitset", - "Configurer", - "Demerzel", - "Dont", - "Ethash", - "Forkchoice", - "Hoodi", - "Hashtable", - "Keccak", - "Linea", - "Masternodes", - "Nethermind", - "Nethermind's", - "Parallelizable", - "Posdao", - "Randao", - "Readahead", - "Rlps", - "Rlpx", - "Scopable", - "Spaceneth", - "Stelem", - "Szalay", - "Taiko", - "Timestamper", - "Unresolve", - "blobgasused", - "blobpool", - "blobtransactions", - "blobversionedhashes", - "blockhash", - "chiado", - "commitset", - "configurer", - "dont", - "ethash", - "forkchoice", - "hashcode", - "hashtable", - "hoodi", - "keccaks", - "linea", - "nethermind", - "nodestore", - "posdao", - "ptree", - "randao", - "scopable", - "spaceneth", - "stelem", - "taiko", - "timestamper", - "triestore", - "unreferred", - "unresolve" - ], - "overrides": [ - { - "filename": "**/*.json", - "ignoreRegExpList": [ - "/\\\\u[0-9a-fA-F]{4}/g" - ] - } - ] -} diff --git a/tools/Kute/Nethermind.Tools.Kute/Config.cs b/tools/Kute/Nethermind.Tools.Kute/Config.cs index 2fc32cdc038..7298564cd93 100644 --- a/tools/Kute/Nethermind.Tools.Kute/Config.cs +++ b/tools/Kute/Nethermind.Tools.Kute/Config.cs @@ -89,7 +89,7 @@ public static class Config public static Option UnwrapBatch { get; } = new("--unwrapBatch", "-u") { - Description = "Batch requests will be unwraped to single requests", + Description = "Batch requests will be unwrapped to single requests", }; public static Option> Labels { get; } = new("--labels", "-l") diff --git a/tools/Kute/README.md b/tools/Kute/README.md index 87697ed9a27..19c97151c98 100644 --- a/tools/Kute/README.md +++ b/tools/Kute/README.md @@ -1,6 +1,6 @@ # Kute -Kute - /kjuːt/ - is a benchmarking tool developed at Nethermind to simulate an Ethereum Consensus Layer, expected to be used together with the Nethermind Client. The tool sends JSON-RPC messages to the Client and measures its performance. +Kute - is a benchmarking tool developed at Nethermind to simulate an Ethereum Consensus Layer, expected to be used together with the Nethermind Client. The tool sends JSON-RPC messages to the Client and measures its performance. ## Prerequisites diff --git a/tools/SendBlobs/BlobSender.cs b/tools/SendBlobs/BlobSender.cs index e652fce7cec..f4689e7f4e8 100644 --- a/tools/SendBlobs/BlobSender.cs +++ b/tools/SendBlobs/BlobSender.cs @@ -51,7 +51,7 @@ public BlobSender(string rpcUrl, ILogManager logManager) // 7 = max fee per blob gas = max value // 9 = 1st proof removed // 10 = 1st commitment removed - // 11 = max fee per blob gas = max value / blobgasperblob + 1 + // 11 = max fee per blob gas = max value / blobGasPerBlob + 1 // 14 = 100 blobs // 15 = 1000 blobs public async Task SendRandomBlobs( @@ -96,7 +96,7 @@ public async Task SendRandomBlobs( int signerIndex = -1; - ulong excessBlobs = (ulong)blobTxCounts.Sum(btxc => btxc.blobCount) / 2; + ulong excessBlobs = (ulong)blobTxCounts.Sum(bc => bc.blobCount) / 2; foreach ((int txCount, int blobCount, string @break) txs in blobTxCounts) { diff --git a/tools/SendBlobs/FundsDistributor.cs b/tools/SendBlobs/FundsDistributor.cs index 7a66867066d..d813a5e44f7 100644 --- a/tools/SendBlobs/FundsDistributor.cs +++ b/tools/SendBlobs/FundsDistributor.cs @@ -36,7 +36,7 @@ public FundsDistributor(IJsonRpcClient rpcClient, ulong chainId, string? keyFile /// /// containing all the executed tx hashes. /// - public async Task> DitributeFunds(Signer distributeFrom, uint keysToMake, UInt256 maxFee, UInt256 maxPriorityFee) + public async Task> DistributeFunds(Signer distributeFrom, uint keysToMake, UInt256 maxFee, UInt256 maxPriorityFee) { if (keysToMake == 0) throw new ArgumentException("keysToMake must be greater than zero.", nameof(keysToMake)); diff --git a/tools/SendBlobs/SetupCli.cs b/tools/SendBlobs/SetupCli.cs index af627173441..72220651be3 100644 --- a/tools/SendBlobs/SetupCli.cs +++ b/tools/SendBlobs/SetupCli.cs @@ -209,7 +209,7 @@ public static void SetupDistributeCommand(Command root) FundsDistributor distributor = new( rpcClient, chainId, parseResult.GetValue(keyFileOption), SimpleConsoleLogManager.Instance); - await distributor.DitributeFunds( + await distributor.DistributeFunds( signer, parseResult.GetValue(keyNumberOption), parseResult.GetValue(maxFeeOption), From 9eed4e914365c59e09853e30f6025f7807ccd648 Mon Sep 17 00:00:00 2001 From: GarmashAlex Date: Sat, 10 Jan 2026 13:07:43 +0300 Subject: [PATCH 196/255] fix: remove duplicate transaction processor adapter registration (#10170) --- src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs b/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs index 210416b8651..41b75f80d98 100644 --- a/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs +++ b/src/Nethermind/Nethermind.Init/Modules/MainProcessingContext.cs @@ -45,7 +45,6 @@ public MainProcessingContext( // These are main block processing specific .AddSingleton(worldState) .AddModule(blockValidationModules) - .AddScoped() .AddSingleton(this) .AddModule(mainProcessingModules) From 8553e9dc2290e6a2c8ba4d7e07fc8b5f7d364a21 Mon Sep 17 00:00:00 2001 From: SashaMalysehko Date: Sat, 10 Jan 2026 12:11:17 +0200 Subject: [PATCH 197/255] perf: avoid extra init code allocations in CREATE/EOFCREATE (#10019) * perf: avoid extra init code allocations in CREATE/EOFCREATE * perf: avoid extra init code allocations in CREATE/EOFCREATE --- .../Nethermind.Evm/Instructions/EvmInstructions.Create.cs | 2 +- .../Nethermind.Evm/Instructions/EvmInstructions.Eof.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs index f7056954d04..66f79084b2c 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Create.cs @@ -200,7 +200,7 @@ public static EvmExceptionType InstructionCreate(Vi goto OutOfGas; // 5. Load the init code (EOF subContainer) from the container using the given index. - ReadOnlySpan initContainer = container.ContainerSection.Span[(Range)container.ContainerSectionOffset(initContainerIndex)!.Value]; + ReadOnlyMemory initContainer = container.ContainerSection[(Range)container.ContainerSectionOffset(initContainerIndex)!.Value]; // EIP-3860: Check that the init code size does not exceed the maximum allowed. if (spec.IsEip3860Enabled) { @@ -709,7 +709,7 @@ public static EvmExceptionType InstructionEofCreate(Vi state.IncrementNonce(env.ExecutingAccount); // 11. Calculate the new contract address. - Address contractAddress = ContractAddress.From(env.ExecutingAccount, salt, initContainer); + Address contractAddress = ContractAddress.From(env.ExecutingAccount, salt, initContainer.Span); if (spec.UseHotAndColdStorage) { // Warm up the target address for subsequent storage accesses. @@ -742,7 +742,7 @@ public static EvmExceptionType InstructionEofCreate(Vi state.SubtractFromBalance(env.ExecutingAccount, value, spec); // Create new code info for the init code. - ICodeInfo codeInfo = CodeInfoFactory.CreateCodeInfo(initContainer.ToArray(), spec, ValidationStrategy.ExtractHeader); + ICodeInfo codeInfo = CodeInfoFactory.CreateCodeInfo(initContainer, spec, ValidationStrategy.ExtractHeader); // 8. Prepare the callData from the caller’s memory slice. if (!vm.VmState.Memory.TryLoad(dataOffset, dataSize, out ReadOnlyMemory callData)) From 6cedba4fbbc1fb88dc1c7d4ac6801940aa8c22df Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 11:12:41 +0100 Subject: [PATCH 198/255] Replace empty array initializations with Array.Empty() (#10172) * Initial plan * Replace empty array initializations with Array.Empty() Co-authored-by: MarekM25 <9356351+MarekM25@users.noreply.github.com> * Replace new Address[0] with Array.Empty
() in Xdc production code Co-authored-by: MarekM25 <9356351+MarekM25@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: MarekM25 <9356351+MarekM25@users.noreply.github.com> --- src/Nethermind/Ethereum.Rlp.Test/RlpTests.cs | 4 ++-- src/Nethermind/Ethereum.Trie.Test/StorageTrieTests.cs | 3 ++- src/Nethermind/Ethereum.Trie.Test/TrieTests.cs | 8 ++++---- .../Nethermind.Benchmark/Core/Keccak256Benchmarks.cs | 2 +- .../Nethermind.Benchmark/Core/Keccak512Benchmarks.cs | 2 +- .../Core/LruCacheKeccakBytesBenchmarks.cs | 2 +- .../Nethermind.Merge.Plugin.Test/EngineModuleTests.V4.cs | 2 +- src/Nethermind/Nethermind.Xdc/EpochSwitchManager.cs | 2 +- 8 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Nethermind/Ethereum.Rlp.Test/RlpTests.cs b/src/Nethermind/Ethereum.Rlp.Test/RlpTests.cs index eb03c9b8c4a..29adbae0102 100644 --- a/src/Nethermind/Ethereum.Rlp.Test/RlpTests.cs +++ b/src/Nethermind/Ethereum.Rlp.Test/RlpTests.cs @@ -107,8 +107,8 @@ private static IEnumerable LoadTests(string testFileName) [Test] public void TestEmpty() { - Assert.That(Nethermind.Serialization.Rlp.Rlp.Encode(new byte[0]), Is.EqualTo(Nethermind.Serialization.Rlp.Rlp.OfEmptyByteArray)); - Assert.That(Nethermind.Serialization.Rlp.Rlp.Encode(new Nethermind.Serialization.Rlp.Rlp[0]), Is.EqualTo(Nethermind.Serialization.Rlp.Rlp.OfEmptySequence)); + Assert.That(Nethermind.Serialization.Rlp.Rlp.Encode(Array.Empty()), Is.EqualTo(Nethermind.Serialization.Rlp.Rlp.OfEmptyByteArray)); + Assert.That(Nethermind.Serialization.Rlp.Rlp.Encode(Array.Empty()), Is.EqualTo(Nethermind.Serialization.Rlp.Rlp.OfEmptySequence)); } [Test] diff --git a/src/Nethermind/Ethereum.Trie.Test/StorageTrieTests.cs b/src/Nethermind/Ethereum.Trie.Test/StorageTrieTests.cs index 65a5fc9a126..445fc2575e8 100644 --- a/src/Nethermind/Ethereum.Trie.Test/StorageTrieTests.cs +++ b/src/Nethermind/Ethereum.Trie.Test/StorageTrieTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Core.Crypto; using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; @@ -25,7 +26,7 @@ public void Storage_trie_set_reset_with_empty() StorageTree tree = CreateStorageTrie(); Hash256 rootBefore = tree.RootHash; tree.Set(1, new byte[] { 1 }); - tree.Set(1, new byte[] { }); + tree.Set(1, Array.Empty()); tree.UpdateRootHash(); Hash256 rootAfter = tree.RootHash; Assert.That(rootAfter, Is.EqualTo(rootBefore)); diff --git a/src/Nethermind/Ethereum.Trie.Test/TrieTests.cs b/src/Nethermind/Ethereum.Trie.Test/TrieTests.cs index 637c77717f0..9185ec807b4 100644 --- a/src/Nethermind/Ethereum.Trie.Test/TrieTests.cs +++ b/src/Nethermind/Ethereum.Trie.Test/TrieTests.cs @@ -311,7 +311,7 @@ public void Quick_empty() public void Delete_on_empty() { PatriciaTree patriciaTree = new PatriciaTree(_db, Keccak.EmptyTreeHash, true, NullLogManager.Instance); - patriciaTree.Set(Keccak.Compute("1").Bytes, new byte[0]); + patriciaTree.Set(Keccak.Compute("1").Bytes, Array.Empty()); patriciaTree.Commit(); Assert.That(patriciaTree.RootHash, Is.EqualTo(PatriciaTree.EmptyTreeHash)); } @@ -323,7 +323,7 @@ public void Delete_missing_resolved_on_branch() patriciaTree.Set(Keccak.Compute("1123").Bytes, new byte[] { 1 }); patriciaTree.Set(Keccak.Compute("1124").Bytes, new byte[] { 2 }); Hash256 rootBefore = patriciaTree.RootHash; - patriciaTree.Set(Keccak.Compute("1125").Bytes, new byte[0]); + patriciaTree.Set(Keccak.Compute("1125").Bytes, Array.Empty()); Assert.That(patriciaTree.RootHash, Is.EqualTo(rootBefore)); } @@ -335,7 +335,7 @@ public void Delete_missing_resolved_on_extension() patriciaTree.Set(new Nibble[] { 1, 2, 3, 4, 5 }.ToPackedByteArray(), new byte[] { 2 }); patriciaTree.UpdateRootHash(); Hash256 rootBefore = patriciaTree.RootHash; - patriciaTree.Set(new Nibble[] { 1, 2, 3 }.ToPackedByteArray(), new byte[] { }); + patriciaTree.Set(new Nibble[] { 1, 2, 3 }.ToPackedByteArray(), Array.Empty()); patriciaTree.UpdateRootHash(); Assert.That(patriciaTree.RootHash, Is.EqualTo(rootBefore)); } @@ -348,7 +348,7 @@ public void Delete_missing_resolved_on_leaf() patriciaTree.Set(Keccak.Compute("1234501").Bytes, new byte[] { 2 }); patriciaTree.UpdateRootHash(); Hash256 rootBefore = patriciaTree.RootHash; - patriciaTree.Set(Keccak.Compute("1234502").Bytes, new byte[0]); + patriciaTree.Set(Keccak.Compute("1234502").Bytes, Array.Empty()); patriciaTree.UpdateRootHash(); Assert.That(patriciaTree.RootHash, Is.EqualTo(rootBefore)); } diff --git a/src/Nethermind/Nethermind.Benchmark/Core/Keccak256Benchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Core/Keccak256Benchmarks.cs index 85d737f14a6..7e0c156295b 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/Keccak256Benchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/Keccak256Benchmarks.cs @@ -17,7 +17,7 @@ public class Keccak256Benchmarks private byte[][] _scenarios = { - new byte[]{}, + Array.Empty(), new byte[]{1}, new byte[100000], TestItem.AddressA.Bytes diff --git a/src/Nethermind/Nethermind.Benchmark/Core/Keccak512Benchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Core/Keccak512Benchmarks.cs index fd511255d29..0b4b149501c 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/Keccak512Benchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/Keccak512Benchmarks.cs @@ -17,7 +17,7 @@ public class Keccak512Benchmarks private byte[][] _scenarios = { - new byte[]{}, + Array.Empty(), new byte[]{1}, new byte[100000], TestItem.AddressA.Bytes diff --git a/src/Nethermind/Nethermind.Benchmark/Core/LruCacheKeccakBytesBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Core/LruCacheKeccakBytesBenchmarks.cs index f9e00b8dc29..ab3861cf03f 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/LruCacheKeccakBytesBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/LruCacheKeccakBytesBenchmarks.cs @@ -28,7 +28,7 @@ public void InitKeccaks() public Hash256[] Keys { get; set; } = new Hash256[64]; - public byte[] Value { get; set; } = new byte[0]; + public byte[] Value { get; set; } = Array.Empty(); [Benchmark] public LruCache WithItems() diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V4.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V4.cs index a9e4bf15321..54112b3112a 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V4.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V4.cs @@ -279,7 +279,7 @@ private async Task> ProduceBranchV4(IEngineRpcMo ExecutionPayloadV3? getPayloadResult = await BuildAndGetPayloadOnBranchV4(rpc, chain, parentHeader, parentBlock.Timestamp + 12, random ?? TestItem.KeccakA, Address.Zero); - PayloadStatusV1 payloadStatusResponse = (await rpc.engine_newPayloadV4(getPayloadResult, [], Keccak.Zero, executionRequests: withRequests ? ExecutionRequestsProcessorMock.Requests : new byte[][] { })).Data; + PayloadStatusV1 payloadStatusResponse = (await rpc.engine_newPayloadV4(getPayloadResult, [], Keccak.Zero, executionRequests: withRequests ? ExecutionRequestsProcessorMock.Requests : Array.Empty())).Data; payloadStatusResponse.Status.Should().Be(PayloadStatus.Valid); if (setHead) { diff --git a/src/Nethermind/Nethermind.Xdc/EpochSwitchManager.cs b/src/Nethermind/Nethermind.Xdc/EpochSwitchManager.cs index 0aa44f928dc..a62fd148c25 100644 --- a/src/Nethermind/Nethermind.Xdc/EpochSwitchManager.cs +++ b/src/Nethermind/Nethermind.Xdc/EpochSwitchManager.cs @@ -135,7 +135,7 @@ public bool IsEpochSwitchAtRound(ulong currentRound, XdcBlockHeader parent) Address[] penalties = header.PenaltiesAddress.Value.ToArray(); Address[] candidates = snap.NextEpochCandidates; - var standbyNodes = new Address[0]; + var standbyNodes = Array.Empty
(); if (masterNodes.Length != candidates.Length) { From 19a9a50c2b98bc20e0ee1516843692933ed6af39 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 12 Jan 2026 12:15:52 +0300 Subject: [PATCH 199/255] Fix disposing of a pooled array (#10168) --- .../Discv5/DiscoveryV5App.cs | 93 +++++++++++-------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/src/Nethermind/Nethermind.Network.Discovery/Discv5/DiscoveryV5App.cs b/src/Nethermind/Nethermind.Network.Discovery/Discv5/DiscoveryV5App.cs index 523e03e089c..1d6ade11338 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Discv5/DiscoveryV5App.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Discv5/DiscoveryV5App.cs @@ -208,64 +208,72 @@ public async IAsyncEnumerable DiscoverNodes([EnumeratorCancellation] Cance { Channel discoveredNodesChannel = Channel.CreateBounded(1); - async Task DiscoverAsync(IEnumerable startingNode, ArrayPoolSpan nodeId) + async Task DiscoverAsync(IEnumerable startingNode, ArrayPoolSpan nodeId, bool disposeNodeId = true) { - using ArrayPoolSpan _ = nodeId; - - static int[] GetDistances(byte[] srcNodeId, in ArrayPoolSpan destNodeId) + try { - const int WiderDistanceRange = 3; + static int[] GetDistances(byte[] srcNodeId, in ArrayPoolSpan destNodeId) + { + const int WiderDistanceRange = 3; - int[] distances = new int[WiderDistanceRange]; - distances[0] = TableUtility.Log2Distance(srcNodeId, destNodeId); + int[] distances = new int[WiderDistanceRange]; + distances[0] = TableUtility.Log2Distance(srcNodeId, destNodeId); - for (int n = 1, i = 1; n < WiderDistanceRange; i++) - { - if (distances[0] - i > 0) + for (int n = 1, i = 1; n < WiderDistanceRange; i++) { - distances[n++] = distances[0] - i; + if (distances[0] - i > 0) + { + distances[n++] = distances[0] - i; + } + if (distances[0] + i <= 256) + { + distances[n++] = distances[0] + i; + } } - if (distances[0] + i <= 256) - { - distances[n++] = distances[0] + i; - } - } - return distances; - } + return distances; + } - Queue nodesToCheck = new(startingNode); - HashSet checkedNodes = []; + Queue nodesToCheck = new(startingNode); + HashSet checkedNodes = []; - while (!token.IsCancellationRequested) - { - if (!nodesToCheck.TryDequeue(out IEnr? newEntry)) + while (!token.IsCancellationRequested) { - return; - } + if (!nodesToCheck.TryDequeue(out IEnr? newEntry)) + { + return; + } - if (TryGetNodeFromEnr(newEntry, out Node? node2)) - { - await discoveredNodesChannel.Writer.WriteAsync(node2!, token); + if (TryGetNodeFromEnr(newEntry, out Node? node2)) + { + await discoveredNodesChannel.Writer.WriteAsync(node2!, token); - if (_logger.IsDebug) _logger.Debug($"A node discovered via discv5: {newEntry} = {node2}."); + if (_logger.IsDebug) _logger.Debug($"A node discovered via discv5: {newEntry} = {node2}."); - _discoveryReport?.NodeFound(); - } + _discoveryReport?.NodeFound(); + } - if (!checkedNodes.Add(newEntry)) - { - continue; - } + if (!checkedNodes.Add(newEntry)) + { + continue; + } - foreach (IEnr newEnr in await _discv5Protocol.SendFindNodeAsync(newEntry, GetDistances(newEntry.NodeId, in nodeId)) ?? []) - { - if (!checkedNodes.Contains(newEnr)) + foreach (IEnr newEnr in await _discv5Protocol.SendFindNodeAsync(newEntry, GetDistances(newEntry.NodeId, in nodeId)) ?? []) { - nodesToCheck.Enqueue(newEnr); + if (!checkedNodes.Contains(newEnr)) + { + nodesToCheck.Enqueue(newEnr); + } } } } + finally + { + if (disposeNodeId) + { + nodeId.Dispose(); + } + } } IEnumerable GetStartingNodes() => _discv5Protocol.GetAllNodes; @@ -284,7 +292,7 @@ static int[] GetDistances(byte[] srcNodeId, in ArrayPoolSpan destNodeId) { using ArrayPoolList discoverTasks = new(RandomNodesToLookupCount); - discoverTasks.Add(DiscoverAsync(GetStartingNodes(), selfNodeId)); + discoverTasks.Add(DiscoverAsync(GetStartingNodes(), selfNodeId, false)); for (int i = 0; i < RandomNodesToLookupCount; i++) { @@ -294,6 +302,11 @@ static int[] GetDistances(byte[] srcNodeId, in ArrayPoolSpan destNodeId) } await Task.WhenAll(discoverTasks); + await Task.Delay(TimeSpan.FromSeconds(2), token); + } + catch (OperationCanceledException) + { + if (_logger.IsTrace) _logger.Trace($"Discovery has been stopped."); } catch (Exception ex) { From bc5d20ddc98d832f6493e13f03853763ae2df2f0 Mon Sep 17 00:00:00 2001 From: Alex Pikme <30472093+reject-i@users.noreply.github.com> Date: Mon, 12 Jan 2026 09:24:55 +0000 Subject: [PATCH 200/255] fix(SendBlobs): add missing receiverOption to reclaim command (#10136) --- tools/SendBlobs/SetupCli.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/SendBlobs/SetupCli.cs b/tools/SendBlobs/SetupCli.cs index 72220651be3..7e3731a9ce1 100644 --- a/tools/SendBlobs/SetupCli.cs +++ b/tools/SendBlobs/SetupCli.cs @@ -254,6 +254,7 @@ public static void SetupReclaimCommand(Command root) }; command.Add(rpcUrlOption); + command.Add(receiverOption); command.Add(keyFileOption); command.Add(maxPriorityFeeGasOption); command.Add(maxFeeOption); From 43cdccfe133b89810f4ff48725aa08d6c033b0ae Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Mon, 12 Jan 2026 10:29:50 +0100 Subject: [PATCH 201/255] Auto-update fast sync settings (#10179) Co-authored-by: rubo --- src/Nethermind/Nethermind.Runner/configs/base-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/base-sepolia.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/chiado.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/gnosis.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/joc-testnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sepolia.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-mainnet.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-sepolia.json | 4 ++-- 14 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index 30f2e293146..f6d3814d72a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": 10000000000, - "PivotNumber": 40340000, - "PivotHash": "0x42aa9b1d248ba0173d76a00b4255528f8719ff92f1124c34ec1de7e993de61bb" + "PivotNumber": 40640000, + "PivotHash": "0xd110a315f31ff7cde0073f4203a212636b0aaaa5d2b07dc4534a4f92affefedb" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index e4d89748f40..c5fa0b70cf9 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": 10000000000, - "PivotNumber": 35850000, - "PivotHash": "0xd7006ba1950b68c00dfae913c0de97ac855be355573f15142bf269a77dd378cf" + "PivotNumber": 36150000, + "PivotHash": "0x0b006a487ea3bc9197eb847f9a1baaa8de1b6c5ab3bf12eb775deb15f2da243b" }, "Discovery": { "DiscoveryVersion": "V5" @@ -36,4 +36,4 @@ "Optimism": { "SequencerUrl": "https://sepolia-sequencer.base.org" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.json b/src/Nethermind/Nethermind.Runner/configs/chiado.json index 49705e6ee74..827cfecddd5 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.json +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.json @@ -18,8 +18,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 19530000, - "PivotHash": "0x00ead99cab26fddc9804d697de2bc8e64e6fa85264ef4864a7b35989931ab665", + "PivotNumber": 19610000, + "PivotHash": "0x765715a5c794e1fdb994be6ed5170817f24433e5f0b3ae53d9a432e6062cf5ae", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": 10000000000, "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.json b/src/Nethermind/Nethermind.Runner/configs/gnosis.json index ff43be86cdc..a9c7dfb0dc1 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.json +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.json @@ -14,8 +14,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 43970000, - "PivotHash": "0xdd75a603dd94638a2cd3bc5e8625e2e1b9e4fa976c698d8e011c8ae59db495ab", + "PivotNumber": 44090000, + "PivotHash": "0xe99aa9d41e4911c2d3c1127a87d9913dcabf5eff7bdf999e9633b51edf6c6b80", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000, diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json index c24a040dcb3..1abb88a2039 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 21560000, - "PivotHash": "0xba316a7a54faf7870506dfe4aa12138141dab2115bf9d3767bd13908bb922345", - "PivotTotalDifficulty": "38834019" + "PivotNumber": 21680000, + "PivotHash": "0x0bfe08da1c01ca53815f275e92ff42eb0445d5063074e4dba2e29e2de18cbc07", + "PivotTotalDifficulty": "39012116" }, "Metrics": { "NodeName": "JOC-Mainnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json index 156cb836607..294f5a03239 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 15170000, - "PivotHash": "0x63ef6fad18f2fb68ce4ea143265f585cf61691076f356316ce16cfead69beb2d", - "PivotTotalDifficulty": "25248307" + "PivotNumber": 15290000, + "PivotHash": "0x31b25b887fea4db1ea81d84e2f076612c887d8b4d02a8d1ea3aa9407b5a669fa", + "PivotTotalDifficulty": "25435913" }, "Metrics": { "NodeName": "JOC-Testnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json index 40b55454e6b..0eef8217747 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 27380000, - "PivotHash": "0x5e6870a0a2fc04bc795630ce13a9f3ecb91d33ebd86329d82ab9dfb9fba1e5db", + "PivotNumber": 27670000, + "PivotHash": "0x1977f99dbb3975e26662b1cbf8d4cc5f22980e3760912e6f1fe8b5123c066d91", "PivotTotalDifficulty": "0", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json index 212ab068c23..588816bffcf 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 22880000, - "PivotHash": "0x8b327501ef7474ddc60f360f5d1ac9b635f950265d26d8ea58f1fa0b06aa6da9", + "PivotNumber": 23180000, + "PivotHash": "0x5dbf4d40e1489385c101d10c9d1132a2d50b942c08882d54b80488450b5b4a8f", "PivotTotalDifficulty": "37331807", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index e36b29c1f84..3b207169970 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -10,8 +10,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 24156000, - "PivotHash": "0xda6de49233e78a0aaf669fd880bd36aea98318e1cbccf0aeb3e5db464070ac30", + "PivotNumber": 24206000, + "PivotHash": "0x8b93b9748a198442fbbd6fd9cd67950c938d171f7b0a2495abb3f54f8078daf4", "PivotTotalDifficulty": "58750003716598352816469", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 15537394, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index 941f4c478e6..0b534e2f7d5 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -15,8 +15,8 @@ "FastSyncCatchUpHeightDelta": 10000000000, "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, - "PivotNumber": 145930000, - "PivotHash": "0x49b2334bc8fe69aaa9c1efdf5d32521e8eb55f770d57c22876bc5569cf929a25" + "PivotNumber": 146230000, + "PivotHash": "0xeef27226ffcb4cdfae7e9d87ec52b9dcf6317ef79ad077bbe0eeb7d3ce8850a5" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index deac9811813..ac96069b3c6 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": 10000000000, - "PivotNumber": 37830000, - "PivotHash": "0xf151fb33df6aa6acdf73b8043ba3d57483fe3e4ac48c56d5375535b063f9582f" + "PivotNumber": 38130000, + "PivotHash": "0xd6821e58d2ec675660f8abf3e3abef108ced0ebc63737e0f718925a87acc5ac8" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index b9d6b2620d4..21883b0536b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -17,8 +17,8 @@ "FastSync": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 9973000, - "PivotHash": "0x689761fe14abede25d4a22cec1b0fdc445b273a05f66635e1e2131632fffce77", + "PivotNumber": 10017000, + "PivotHash": "0xf7fb54e189b8b3d83606deecd95b186faa00880002ba1e02c111e446f13809b8", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 1450409, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index c838db016eb..501b93805d9 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": 10000000000, - "PivotNumber": 24060000, - "PivotHash": "0xb20cd0979431e3a226ffab9ecfd5905b9d94093f07d43b234fd788cfab26d56d" + "PivotNumber": 24360000, + "PivotHash": "0x6c135c9b8c463f10a4e52ca08b05c732af6f5b753d26bee65009ab4eabb7b8c6" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index 3b101034729..c0c318f1e87 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": 10000000000, - "PivotNumber": 23460000, - "PivotHash": "0xf633722e8fcceaa519564b79da80de4b7ed98d6ec455dad0cf0173cdc6389a21" + "PivotNumber": 23760000, + "PivotHash": "0x7256f30608e0e27979b11d13e385b98999979881b6e49aec6670c73d377bccef" }, "Discovery": { "DiscoveryVersion": "V5" From 3aa3d01a27ee91b0263a6daa984f301111a10866 Mon Sep 17 00:00:00 2001 From: Andrew Davis <1709934+Savid@users.noreply.github.com> Date: Mon, 12 Jan 2026 19:54:16 +1000 Subject: [PATCH 202/255] fix(sync): use INetworkConfig constructor for SyncPeerPool DI registration (#10158) * fix(sync): use INetworkConfig constructor for SyncPeerPool DI registration SyncPeerPool was ignoring the configured MaxActivePeers value and always using a hardcoded default of 100 peers. Root cause: SyncPeerPool has two constructors: 1. One taking INetworkConfig that reads ActivePeersMaxCount from config 2. One with default parameters (peersMaxCount = 100) The DI registration `.AddSingleton()` allowed Autofac to pick a constructor automatically. Autofac selected the constructor with default parameters, completely bypassing INetworkConfig. This caused SyncPeerPool.PeerMaxCount to always be 100 regardless of the configured Network.MaxActivePeers value. Fix: Use explicit factory registration that specifies INetworkConfig as a dependency, ensuring the correct constructor is called with config values. * refactor: use UseConstructorForDependencyInjection attribute and add test --- .../SynchronizerModuleTests.cs | 19 +++++++++++++++++++ .../Peers/SyncPeerPool.cs | 2 ++ 2 files changed, 21 insertions(+) diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerModuleTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerModuleTests.cs index 3920eb07a27..d635aadccf8 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerModuleTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerModuleTests.cs @@ -8,9 +8,11 @@ using Nethermind.Core; using Nethermind.Core.Test.Builders; using Nethermind.Core.Test.Modules; +using Nethermind.Network.Config; using Nethermind.State; using Nethermind.Synchronization.FastSync; using Nethermind.Synchronization.ParallelSync; +using Nethermind.Synchronization.Peers; using NSubstitute; using NUnit.Framework; @@ -52,4 +54,21 @@ public async Task TestOnTreeSyncFinish_CallVisit() .Received(1) .VerifyTrie(Arg.Any(), Arg.Any()); } + + [Test] + public void SyncPeerPool_should_use_INetworkConfig_MaxActivePeers() + { + NetworkConfig networkConfig = new() { MaxActivePeers = 75 }; + + using IContainer container = new ContainerBuilder() + .AddModule(new TestNethermindModule(networkConfig)) + .AddModule(new SynchronizerModule(new TestSyncConfig())) + .AddSingleton(Substitute.For()) + .AddSingleton(Substitute.For()) + .Build(); + + SyncPeerPool pool = container.Resolve(); + + Assert.That(pool.PeerMaxCount, Is.EqualTo(75)); + } } diff --git a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs index 99adcbd3eeb..4cdc6c68723 100644 --- a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs +++ b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs @@ -15,6 +15,7 @@ using Nethermind.Blockchain.Synchronization; using Nethermind.Consensus.Validators; using Nethermind.Core; +using Nethermind.Core.Container; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Int256; @@ -61,6 +62,7 @@ public class SyncPeerPool : ISyncPeerPool, IPeerDifficultyRefreshPool private readonly TimeSpan _timeBeforeWakingShallowSleepingPeerUp = TimeSpan.FromMilliseconds(DefaultUpgradeIntervalInMs); private Timer? _upgradeTimer; + [UseConstructorForDependencyInjection] public SyncPeerPool(IBlockTree blockTree, INodeStatsManager nodeStatsManager, IBetterPeerStrategy betterPeerStrategy, From 8a53cb148e1a8be4fb0998c539fdb6657b0f3500 Mon Sep 17 00:00:00 2001 From: Maxim Evtush <154841002+maximevtush@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:46:53 +0200 Subject: [PATCH 203/255] refactor(tools): eliminate redundant First() calls in HiveConsensusWorkflowGenerator (#10182) Update Program.cs Co-authored-by: Lukasz Rozmej --- tools/HiveConsensusWorkflowGenerator/Program.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/HiveConsensusWorkflowGenerator/Program.cs b/tools/HiveConsensusWorkflowGenerator/Program.cs index 1a13e2c1c26..5ed026fc728 100644 --- a/tools/HiveConsensusWorkflowGenerator/Program.cs +++ b/tools/HiveConsensusWorkflowGenerator/Program.cs @@ -27,11 +27,12 @@ static void Main(string[] args) if (groupedTestNames.Count == MaxJobsCount) { - testsList = new List(groupedTestNames.First().Value); - size = groupedTestNames.First().Key; + var smallestGroup = groupedTestNames.First(); + testsList = new List(smallestGroup.Value); + size = smallestGroup.Key; testsList.Add(test.Key); size += test.Value; - groupedTestNames.Remove(groupedTestNames.First().Key); + groupedTestNames.Remove(smallestGroup.Key); } else { From 2f1ab2d9e951d2382d63c94894b5cc825cf0dcea Mon Sep 17 00:00:00 2001 From: iPLAY888 <133153661+letmehateu@users.noreply.github.com> Date: Mon, 12 Jan 2026 13:47:00 +0300 Subject: [PATCH 204/255] docs: fix dead link (#10181) Update ForkchoiceUpdatedV1Result.cs Co-authored-by: Lukasz Rozmej --- .../Nethermind.Merge.Plugin/Data/ForkchoiceUpdatedV1Result.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/ForkchoiceUpdatedV1Result.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/ForkchoiceUpdatedV1Result.cs index 70fac33c3fb..9a00701af1a 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/ForkchoiceUpdatedV1Result.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/ForkchoiceUpdatedV1Result.cs @@ -11,7 +11,7 @@ namespace Nethermind.Merge.Plugin.Data /// /// Result of engine_forkChoiceUpdate call. /// - /// + /// /// public class ForkchoiceUpdatedV1Result { From c651d6cfc743bbe0548f0f454bd73911a72f5c04 Mon Sep 17 00:00:00 2001 From: strmfos <155266597+strmfos@users.noreply.github.com> Date: Mon, 12 Jan 2026 11:49:54 +0100 Subject: [PATCH 205/255] Remove redundant ToArray calls in eth_accounts (#10185) Co-authored-by: Lukasz Rozmej --- src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index 6b70f928c7d..af3617fe38a 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -143,9 +143,7 @@ public ResultWrapper> eth_accounts() { try { - Address[] result = _wallet.GetAccounts(); - Address[] data = result.ToArray(); - return ResultWrapper>.Success(data.ToArray()); + return ResultWrapper>.Success(_wallet.GetAccounts()); } catch (Exception) { From e04dfbf9d4916864046f57eed1493722a2aa4121 Mon Sep 17 00:00:00 2001 From: Artiom Tretjakovas <44021713+ArtiomTr@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:40:40 +0200 Subject: [PATCH 206/255] Override default CLI option alias (#10148) Co-authored-by: Ruben Buniatyan --- .../Nethermind.Config/ConfigItemAttribute.cs | 22 +++++++------- src/Nethermind/Nethermind.Runner/Program.cs | 29 ++++++++++--------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/Nethermind/Nethermind.Config/ConfigItemAttribute.cs b/src/Nethermind/Nethermind.Config/ConfigItemAttribute.cs index e37ece79cad..21038431e3c 100644 --- a/src/Nethermind/Nethermind.Config/ConfigItemAttribute.cs +++ b/src/Nethermind/Nethermind.Config/ConfigItemAttribute.cs @@ -3,20 +3,22 @@ using System; -namespace Nethermind.Config +namespace Nethermind.Config; + +[AttributeUsage(AttributeTargets.Property)] +public class ConfigItemAttribute : Attribute { - public class ConfigItemAttribute : Attribute - { - public string Description { get; set; } + public string Description { get; set; } + + public string DefaultValue { get; set; } - public string DefaultValue { get; set; } + public bool HiddenFromDocs { get; set; } - public bool HiddenFromDocs { get; set; } + public bool DisabledForCli { get; set; } - public bool DisabledForCli { get; set; } + public string EnvironmentVariable { get; set; } - public string EnvironmentVariable { get; set; } + public bool IsPortOption { get; set; } - public bool IsPortOption { get; set; } - } + public string CliOptionAlias { get; set; } } diff --git a/src/Nethermind/Nethermind.Runner/Program.cs b/src/Nethermind/Nethermind.Runner/Program.cs index 54fce7573e1..f6c063b77f7 100644 --- a/src/Nethermind/Nethermind.Runner/Program.cs +++ b/src/Nethermind/Nethermind.Runner/Program.cs @@ -213,10 +213,13 @@ async Task RunAsync(ParseResult parseResult, PluginLoader pluginLoader, Can void AddConfigurationOptions(Command command) { - static Option CreateOption(string name, Type configType) => - new Option( - $"--{ConfigExtensions.GetCategoryName(configType)}.{name}", - $"--{ConfigExtensions.GetCategoryName(configType)}-{name}".ToLowerInvariant()); + static Option CreateOption(Type configType, string name, string? alias) + { + var category = ConfigExtensions.GetCategoryName(configType); + alias = string.IsNullOrWhiteSpace(alias) ? name : alias; + + return new Option($"--{category}.{name}", $"--{category}-{alias}".ToLowerInvariant()); + } IEnumerable configTypes = TypeDiscovery .FindNethermindBasedTypes(typeof(IConfig)) @@ -238,19 +241,19 @@ static Option CreateOption(string name, Type configType) => foreach (PropertyInfo prop in configType.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(p => p.Name)) { - ConfigItemAttribute? configItemAttribute = prop.GetCustomAttribute(); + ConfigItemAttribute? configItemAttr = prop.GetCustomAttribute(); - if (configItemAttribute?.DisabledForCli != true) + if (configItemAttr?.DisabledForCli != true) { Option option = prop.PropertyType == typeof(bool) - ? CreateOption(prop.Name, configType) - : CreateOption(prop.Name, configType); + ? CreateOption(configType, prop.Name, configItemAttr?.CliOptionAlias) + : CreateOption(configType, prop.Name, configItemAttr?.CliOptionAlias); - string? description = configItemAttribute?.Description; + string? description = configItemAttr?.Description; - if (!string.IsNullOrEmpty(configItemAttribute?.DefaultValue)) + if (!string.IsNullOrEmpty(configItemAttr?.DefaultValue)) { - string defaultValue = $"Defaults to `{configItemAttribute.DefaultValue}`."; + string defaultValue = $"Defaults to `{configItemAttr.DefaultValue}`."; description = string.IsNullOrEmpty(description) ? defaultValue @@ -259,12 +262,12 @@ static Option CreateOption(string name, Type configType) => option.Description = description; option.HelpName = "value"; - option.Hidden = categoryHidden || configItemAttribute?.HiddenFromDocs == true; + option.Hidden = categoryHidden || configItemAttr?.HiddenFromDocs == true; command.Add(option); } - if (configItemAttribute?.IsPortOption == true) + if (configItemAttr?.IsPortOption == true) ConfigExtensions.AddPortOptionName(configType, prop.Name); } } From da034e3fe6eafeaf609dbe03ac0955dd2f101354 Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Mon, 12 Jan 2026 18:01:12 +0100 Subject: [PATCH 207/255] Add AGENTS.md (#10177) --- .github/copilot-instructions.md | 251 ------------------------------- .gitignore | 7 +- AGENTS.md | 112 ++++++++++++++ CLAUDE.md | 256 +------------------------------- GEMINI.md | 1 + 5 files changed, 118 insertions(+), 509 deletions(-) delete mode 100644 .github/copilot-instructions.md create mode 100644 AGENTS.md create mode 100644 GEMINI.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index e1724408447..00000000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,251 +0,0 @@ -# Copilot Instructions for Nethermind - -## Repository Overview - -Nethermind is an industry-leading Ethereum execution client built on .NET, designed for high-performance syncing and tip-of-chain processing. This enterprise-grade blockchain client features a modular architecture with plugin system support, serving multiple networks including Ethereum, Gnosis, Optimism, Base, Taiko, World Chain, Linea, and Energy Web. - -**Repository Characteristics:** -- **Size:** Large-scale enterprise codebase with 100+ C# projects -- **Language:** C# with .NET 9.0 target framework -- **Architecture:** Modular design with plugin-based extensibility -- **Type:** High-performance blockchain execution client -- **License:** LGPL-3.0-only - -## General - -- Make only high confidence suggestions when reviewing code changes. -- Always use the latest version C#, currently C# 13 features. -- Never change global.json unless explicitly asked to. -- Never change package.json or package-lock.json files unless explicitly asked to. -- Never change NuGet.config files unless explicitly asked to. -- Always trim trailing whitespace, and do not have whitespace on otherwise empty lines. - -**Any code you commit SHOULD compile, and new and existing tests related to the change SHOULD pass.** - -You MUST make your best effort to ensure your changes satisfy those criteria before committing. If for any reason you were unable to build or test the changes, you MUST report that. You MUST NOT claim success unless all builds and tests pass as described above. - -You MUST follow all code-formatting and naming conventions defined in [`.editorconfig`](/.editorconfig). - -In addition to the rules enforced by `.editorconfig`, you SHOULD: - -- Prefer file-scoped namespace declarations and single-line using directives; however do not change the type of namespace format in an existing file unless specifically asked. -- Ensure that the final return statement of a method is on its own line. -- Use pattern matching and switch expressions wherever possible. -- Use `nameof` instead of string literals when referring to member names. -- Always use `is null` or `is not null` instead of `== null` or `!= null`. -- Trust the C# null annotations and don't add null checks when the type system says a value cannot be null. -- Prefer `?.` if applicable (e.g. `scope?.Dispose()`). -- Use `ObjectDisposedException.ThrowIf` where applicable. -- When adding new unit tests, strongly prefer to add them to existing test code files rather than creating new code files. -- If you add new code files, ensure they are listed in the csproj file (if other files in that folder are listed there) so they build. -- When running tests, if possible use filters and check test run counts, or look at test logs, to ensure they actually ran. -- Do not finish work with any tests commented out or disabled that were not previously commented out or disabled. -- When writing tests, do not emit "Act", "Arrange" or "Assert" comments. -- Copy existing style in nearby files for test method names and capitalization. -- Provide code comments when helpful to explain why something is being done; however do not comment what is obvious and just a repeation of the code line. -- Ensure that XML doc comments are created for any public APIs. -- Do NOT use #regions. -- Perfer low allocation and higher performance code. - ---- - -## Build Requirements and Setup - -### Prerequisites - -**CRITICAL:** Always install .NET SDK 9.0.x before building. The project requires specific .NET version compatibility. - -```bash -# Install .NET 9.0 (if not available via package manager) -curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 9.0 -export PATH="$HOME/.dotnet:$PATH" - -# Verify installation -dotnet --version # Should show 9.0.x -``` - -### Build Instructions - -**Complete build sequence (always follow this order):** - -```bash -# 1. Navigate to main source directory -cd src/Nethermind - -# 2. Build main solution (takes ~4 minutes) -dotnet build Nethermind.slnx -c Release - -# 3. Build Ethereum Foundation tests (if needed) -dotnet build EthereumTests.slnx -c Release - -# 4. Build benchmarks (if needed) -dotnet build Benchmarks.slnx -c Release -``` - -### Testing - -**Run tests in this order to ensure dependencies are built:** - -```bash -# Core functionality tests (fast, ~15 seconds) -dotnet test Nethermind.Core.Test/Nethermind.Core.Test.csproj - -# Full Nethermind test suite -dotnet test Nethermind.slnx -c Release - -# Ethereum Foundation tests (comprehensive, takes longer) -dotnet test EthereumTests.slnx -c Release -``` - -### Code Formatting and Validation - -**ALWAYS run before creating PRs:** - -```bash -# Check code formatting (required by CI) -dotnet format whitespace src/Nethermind/ --folder --verify-no-changes - -# Fix formatting issues -dotnet format whitespace src/Nethermind/ --folder -``` - -### Running the Application - -```bash -# From repository root -cd src/Nethermind/Nethermind.Runner - -# Run with mainnet configuration -dotnet run -c release -- -c mainnet --data-dir path/to/data/dir - -# Debug mode -dotnet run -c debug -- -c mainnet -``` - -## Project Architecture and Layout - -### Solution Structure - -The codebase is organized into three main solutions: - -- **`src/Nethermind/Nethermind.slnx`** - Main application and libraries -- **`src/Nethermind/EthereumTests.slnx`** - Ethereum Foundation test suite -- **`src/Nethermind/Benchmarks.slnx`** - Performance benchmarking tools - -### Key Directories - -``` -src/Nethermind/ -├── Nethermind.Runner/ # Main executable entry point -├── Nethermind.Core/ # Core types and utilities -├── Nethermind.Blockchain/ # Block processing logic -├── Nethermind.Consensus.* # Consensus mechanisms (Ethash, AuRa, Clique) -├── Nethermind.Synchronization/ # Node synchronization -├── Nethermind.Network*/ # P2P networking stack -├── Nethermind.JsonRpc/ # JSON-RPC API layer -├── Nethermind.State/ # State management -├── Nethermind.TxPool/ # Transaction pool -├── Nethermind.Evm/ # Ethereum Virtual Machine -└── *Test/ # Test projects (suffix pattern) -``` - -### Configuration Files - -- **`global.json`** - .NET SDK version requirement (9.0.x) -- **`Directory.Build.props`** - MSBuild properties and compilation settings -- **`.editorconfig`** - Code style rules (enforced in CI) -- **`nuget.config`** - NuGet package source configuration -- **`src/Nethermind/Directory.Build.props`** - Project-specific build properties - -### Critical Build Dependencies - -1. **TreatWarningsAsErrors:** Project configured to treat warnings as errors -2. **InvariantGlobalization:** Enabled for consistent behavior across locales -3. **UseArtifactsOutput:** Build outputs go to `artifacts/` directory -4. **Git submodules:** May be required for some test suites (`git clone --recursive`) - -## Continuous Integration Validation - -The project uses GitHub Actions with these key workflows: - -### Pre-commit Checks -```bash -# Replicate CI formatting check locally -dotnet format whitespace src/Nethermind/ --folder --verify-no-changes - -# Replicate CI build checks -dotnet build src/Nethermind/Nethermind.slnx -c Release -dotnet build src/Nethermind/Nethermind.slnx -c Debug -``` - -### Test Validation -```bash -# Core test matrix (replicates CI) -dotnet test Nethermind.Core.Test/Nethermind.Core.Test.csproj -dotnet test EthereumTests.slnx -c Release # Comprehensive test suite -``` - -## Common Development Workflows - -### Making Code Changes - -1. **Always run formatting first:** `dotnet format whitespace src/Nethermind/ --folder` -2. **Build incrementally:** Start with specific project if working on single component -3. **Test locally:** Run relevant test project before full suite -4. **Validate CI requirements:** Run formatting check before committing - -### Performance Considerations - -- **Full build time:** ~4 minutes for Release configuration -- **Test execution:** Core tests ~15 seconds, full suite several minutes -- **Memory usage:** Large solution requires adequate system memory -- **Parallel builds:** MSBuild automatically parallelizes where possible - -### File Headers - -All source files must include this header: -```csharp -// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only -``` - -## Troubleshooting Common Issues - -### .NET SDK Version Mismatch -``` -Error: A compatible .NET SDK was not found. Requested SDK version: 9.0.2 -``` -**Solution:** Install .NET 9.0.x SDK as shown in prerequisites section. - -### Build Timeout in CI -**Cause:** Full builds take 4+ minutes -**Solution:** Use `timeout: 600` for build commands in automation - -### Memory Issues During Build -**Cause:** Large solution with many projects -**Solution:** Ensure adequate system memory (8GB+ recommended) - -### Code Formatting Failures -``` -Error: Fix whitespace formatting by running: dotnet format whitespace -``` -**Solution:** Run `dotnet format whitespace src/Nethermind/ --folder` before committing - -## Docker Development - -```bash -# Build Docker image directly from repository -docker build https://github.com/nethermindeth/nethermind.git -t nethermind - -# Run containerized -docker run -d nethermind -c mainnet -``` - -## Trust These Instructions - -These instructions are validated against the current codebase. Only search for additional information if: -- Instructions are incomplete for your specific task -- You encounter errors not covered in troubleshooting -- Working with components not mentioned in the architecture section - -When in doubt, start with the build sequence and test a small component first before attempting larger changes. \ No newline at end of file diff --git a/.gitignore b/.gitignore index e1f4fb7b03b..0742ca13e6e 100644 --- a/.gitignore +++ b/.gitignore @@ -435,9 +435,10 @@ FodyWeavers.xsd ## macOS .DS_Store +# AI +.claude/ +.gemini/ + ## Nethermind keystore/ /.githooks - -# AI -**/.claude/** diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..b3bb411a5cb --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,112 @@ +# AGENTS instructions + +This guide helps to get started with the Nethermind Ethereum execution client repository. It covers the project structure, how to build and test the code, and follow the PR workflow. + +## Repo structure + +- [src/Nethermind](./src/Nethermind/): The Nethermind codebase +- [tools](./tools/): Various servicing tools for testing, monitoring, etc. +- [scripts](./scripts/): The build scripts and stuff used by GitHub Actions workflows +- See [README.md](./README.md) for more info + +## Coding guidelines and style + +- Do follow the [CONTRIBUTING.md](./CONTRIBUTING.md) guidelines +- Do follow the [.editorconfig](./.editorconfig) rules +- Do prefer low-allocation code patterns +- Prefer the latest C# syntax and conventions +- Prefer file-scoped namespaces (for existing files, follow their style) +- Prefer pattern matching and switch expressions over the traditional control flow +- Use the `nameof` operator instead of string literals for member references +- Use `is null` and `is not null` instead of `== null` and `!= null` +- Use `?.` null-conditional operator where applicable +- Use the `ArgumentNullException.ThrowIfNull` method for null checks and other similar methods +- Use the `ObjectDisposedException.ThrowIf` method for disposal checks +- Use documentation comments for all public APIs with proper structure +- Consider performance implications in high-throughput paths +- Trust null annotations—don't add redundant null checks +- Add tests to existing test files rather than creating new ones +- Code comments must explain _why_, not _what_ +- Do not use the `#region` and `#endregion` pragmas +- Do not alter anything in the [src/bench_precompiles](./src/bench_precompiles/) and [src/tests](./src/tests/) directories + +## Project structure + +The codebase in [src/Nethermind](./src/Nethermind/) is organized into three independent solutions: + +- [Nethermind.slnx](./src/Nethermind/Nethermind.slnx): The Nethermind client codebase and tests +- [EthereumTests.slnx](./src/Nethermind/EthereumTests.slnx): The Ethereum Foundation test suite +- [Benchmarks.slnx](./src/Nethermind/Benchmarks.slnx): Performance benchmarking + +### Architecture + +- **Entry point and initialization** + - [Nethermind.Runner](./src/Nethermind/Nethermind.Runner/): The app entry point and startup orchestration + - [Nethermind.Init](./src/Nethermind/Nethermind.Init/): Initialization logic, memory management, metrics +- **General API** + - [Nethermind.Api](./src/Nethermind/Nethermind.Api/): Core API interfaces and plugin API + - [Nethermind.Config](./src/Nethermind/Nethermind.Config/): Configuration handling + - [Nethermind.Logging](./src/Nethermind/Nethermind.Logging/): Logging +- **Consensus algorithms** + - [Nethermind.Consensus.AuRa](./src/Nethermind/Nethermind.Consensus.AuRa/): Authority round (Aura) + - [Nethermind.Consensus.Clique](./src/Nethermind/Nethermind.Consensus.Clique/): Proof of Authority (PoA) + - [Nethermind.Consensus.Ethash](./src/Nethermind/Nethermind.Consensus.Ethash/): Proof of Work (PoW) + - [Nethermind.Merge.Plugin](./src/Nethermind/Nethermind.Merge.Plugin/): Proof of Stake (PoS) +- **Core blockchain** + - [Nethermind.Blockchain](./src/Nethermind/Nethermind.Blockchain/): Block processing, chain management, validators + - [Nethermind.Core](./src/Nethermind/Nethermind.Core/): Foundational types + - [Nethermind.Crypto](./src/Nethermind/Nethermind.Crypto/): Core cryptographic algorithms + - [Nethermind.Evm](./src/Nethermind/Nethermind.Evm/): EVM implementation + - [Nethermind.Evm.Precompiles](./src/Nethermind/Nethermind.Evm.Precompiles/): EVM precompiled contracts + - [Nethermind.Specs](./src/Nethermind/Nethermind.Specs/): Network specifications and hard fork rules +- **State and storage:** + - [Nethermind.Db](./src/Nethermind/Nethermind.Db/): Database abstraction layer + - [Nethermind.Db.Rocks](./src/Nethermind/Nethermind.Db.Rocks/): RocksDB implementation (primary storage backend) + - [Nethermind.State](./src/Nethermind/Nethermind.State/): World state management, accounts, contract storage + - [Nethermind.Trie](./src/Nethermind/Nethermind.Trie/): Merkle Patricia trie implementation +- **Networking:** + - [Nethermind.Network](./src/Nethermind/Nethermind.Network/): devp2p protocol implementation + - [Nethermind.Network.Discovery](./src/Nethermind/Nethermind.Network.Discovery/): Peer discovery + - [Nethermind.Network.Dns](./src/Nethermind/Nethermind.Network.Dns/): DNS-based node discovery + - [Nethermind.Network.Enr](./src/Nethermind/Nethermind.Network.Enr/): Ethereum Node Records (ENR) handling + - [Nethermind.Synchronization](./src/Nethermind/Nethermind.Synchronization/): Block synchronization strategies (fast sync, snap sync) + - [Nethermind.UPnP.Plugin](./src/Nethermind/Nethermind.UPnP.Plugin/): UPnP support +- **Transaction management:** + - [Nethermind.TxPool](./src/Nethermind/Nethermind.TxPool/): Transaction pool (mempool) management, validation, sorting +- **RPC and external interface:** + - [Nethermind.Facade](./src/Nethermind/Nethermind.Facade/): High-level API facades for external interaction + - [Nethermind.JsonRpc](./src/Nethermind/Nethermind.JsonRpc/): JSON-RPC server + - [Nethermind.Sockets](./src/Nethermind/Nethermind.Sockets/): WebSocket server +- **Monitoring** + - [Nethermind.HealthChecks](./src/Nethermind/Nethermind.HealthChecks/): Health checks + - [Nethermind.Monitoring](./src/Nethermind/Nethermind.Monitoring/): Monitoring API + - [Nethermind.Seq](./src/Nethermind/Nethermind.Seq/): Seq integration +- **Serialization:** + - [Nethermind.Serialization.Json](./src/Nethermind/Nethermind.Serialization.Json/): JSON serialization + - [Nethermind.Serialization.Rlp](./src/Nethermind/Nethermind.Serialization.Rlp/): RLP serialization + - [Nethermind.Serialization.Ssz](./src/Nethermind/Nethermind.Serialization.Ssz/): SSZ serialization +- **Third-party integration:** + - [Nethermind.Flashbots](./src/Nethermind/Nethermind.Flashbots/): Flashbots integration + - [Nethermind.Optimism](./src/Nethermind/Nethermind.Optimism/): Optimism network (OP Stack) support + - [Nethermind.Taiko](./src/Nethermind/Nethermind.Taiko/): Taiko network support +- **Tests** + - Test suites reside in Nethermind.\*.Test directories + +## Pull request guidelines + +Before creating a pull request: + +- Ensure the code compiles +- Add tests covering your changes and ensure they pass: + ```bash + dotnet test --project path/to/.csproj -c release -- --filter FullyQualifiedName~TestName + ``` +- Ensure the code is well-formatted: + ```bash + dotnet format whitespace src/Nethermind/ --folder + ``` +- Use [pull_request_template.md](.github/pull_request_template.md) + +## Prerequisites + +See [global.json](./global.json) for the required .NET SDK version. diff --git a/CLAUDE.md b/CLAUDE.md index 954ccb13926..285e0f5b36b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,255 +1 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Repository Overview - -Nethermind is an industry-leading Ethereum execution client built on .NET 9.0, designed for high-performance syncing and tip-of-chain processing. It features a modular architecture with a plugin system, supporting multiple networks including Ethereum, Gnosis, Optimism, Base, Taiko, World Chain, Linea, and Energy Web. - -**Key Characteristics:** -- Large-scale C# codebase with 100+ projects -- Target framework: .NET 9.0 (C# 13) -- License: LGPL-3.0-only -- Modular plugin-based architecture - -## Essential Build Commands - -### Prerequisites -- .NET SDK 9.0.2 or later (required by `global.json`) -- Git with submodules: `git clone --recursive https://github.com/nethermindeth/nethermind.git` - -### Build Commands -All build commands run from `src/Nethermind/`: - -```bash -# Navigate to source directory -cd src/Nethermind - -# Build main solution (~4 minutes) -dotnet build Nethermind.slnx -c Release - -# Build for debugging -dotnet build Nethermind.slnx -c Debug - -# Build Ethereum Foundation tests (when needed) -dotnet build EthereumTests.slnx -c Release - -# Build benchmarks (when needed) -dotnet build Benchmarks.slnx -c Release -``` - -### Testing Commands - -```bash -# From src/Nethermind/ directory - -# Run single test project (fast, ~15 seconds) -dotnet test Nethermind.Core.Test/Nethermind.Core.Test.csproj - -# Run all Nethermind tests -dotnet test Nethermind.slnx -c Release - -# Run Ethereum Foundation test suite -dotnet test EthereumTests.slnx -c Release - -# Run specific test class or method -dotnet test .csproj --filter "FullyQualifiedName~ClassName" -``` - -### Code Formatting - -**CRITICAL: Always run before committing. CI enforces this.** - -```bash -# Check formatting (what CI runs) -dotnet format whitespace src/Nethermind/ --folder --verify-no-changes - -# Fix formatting issues -dotnet format whitespace src/Nethermind/ --folder -``` - -### Running the Application - -```bash -# From repository root -cd src/Nethermind/Nethermind.Runner - -# Run mainnet -dotnet run -c release -- -c mainnet --data-dir path/to/data/dir - -# Debug mode -dotnet run -c debug -- -c mainnet -``` - -## Architecture Overview - -### Three Solution Structure - -The codebase is organized into three independent solutions located in `src/Nethermind/`: - -1. **Nethermind.slnx** - Main execution client with all core functionality -2. **EthereumTests.slnx** - Ethereum Foundation test suite compliance -3. **Benchmarks.slnx** - Performance benchmarking tools - -### Core Architecture Layers - -**Entry Point and Initialization:** -- `Nethermind.Runner/` - Application entry point, startup orchestration -- `Nethermind.Init/` - Initialization logic, memory management, metrics - -**API and Extension System:** -- `Nethermind.Api/` - Core API interfaces (`INethermindApi`, `IApiWithNetwork`, `IApiWithStores`) -- `Nethermind.Api/Extensions/` - Plugin system interfaces (`INethermindPlugin`, `IConsensusPlugin`) -- Plugins implement lifecycle hooks: `InitTxTypesAndRlpDecoders()`, `Init()`, `InitNetworkProtocol()`, `InitRpcModules()` - -**Consensus Layer:** -- `Nethermind.Consensus.*/` - Pluggable consensus mechanisms: - - `Nethermind.Consensus.Ethash/` - Proof of Work - - `Nethermind.Consensus.AuRa/` - Authority Round (Gnosis) - - `Nethermind.Consensus.Clique/` - Proof of Authority -- `Nethermind.Merge.Plugin/` - Proof of Stake (post-merge Ethereum) - -**Blockchain Core:** -- `Nethermind.Core/` - Fundamental types (`Block`, `BlockHeader`, `Transaction`, `TransactionReceipt`) -- `Nethermind.Blockchain/` - Block processing, chain management, validators -- `Nethermind.Evm/` - Ethereum Virtual Machine implementation -- `Nethermind.Evm.Precompiles/` - Precompiled contracts -- `Nethermind.Specs/` - Network specifications and hard fork rules - -**State and Storage:** -- `Nethermind.State/` - World state management, accounts, contract storage -- `Nethermind.Trie/` - Merkle Patricia Trie implementation -- `Nethermind.Db/` - Database abstraction layer -- `Nethermind.Db.Rocks/` - RocksDB implementation (primary storage backend) - -**Networking:** -- `Nethermind.Network/` - P2P protocol implementation (DevP2P) -- `Nethermind.Network.Discovery/` - Peer discovery -- `Nethermind.Network.Dns/` - DNS-based node discovery -- `Nethermind.Network.Enr/` - Ethereum Node Records -- `Nethermind.Synchronization/` - Block synchronization strategies (fast sync, snap sync, beam sync) - -**Transaction Management:** -- `Nethermind.TxPool/` - Transaction pool management, validation, sorting -- Custom transaction types registered via `INethermindApi.RegisterTxType()` - -**RPC and External Interface:** -- `Nethermind.JsonRpc/` - JSON-RPC API server -- `Nethermind.Facade/` - High-level API facades for external interaction - -**Serialization:** -- `Nethermind.Serialization.Rlp/` - RLP (Recursive Length Prefix) encoding -- `Nethermind.Serialization.Ssz/` - SSZ (Simple Serialize) for consensus layer -- `Nethermind.Serialization.Json/` - JSON serialization - -**Network-Specific Implementations:** -- `Nethermind.Taiko/` - Taiko L2 support -- `Nethermind.Xdc/` - XDC Network support -- `Nethermind.Flashbots/` - MEV-Boost integration - -### Plugin System Architecture - -Plugins extend Nethermind functionality through the `INethermindPlugin` interface: - -```csharp -public interface INethermindPlugin -{ - string Name { get; } - void InitTxTypesAndRlpDecoders(INethermindApi api); - Task Init(INethermindApi nethermindApi); - Task InitNetworkProtocol(); - Task InitRpcModules(); - bool MustInitialize => false; - bool Enabled { get; } -} -``` - -Consensus plugins implement `IConsensusPlugin` which extends `IBlockProducerFactory` and `IBlockProducerRunnerFactory`. - -Examples: `Nethermind.Merge.Plugin`, `Nethermind.ExternalSigner.Plugin`, `Nethermind.UPnP.Plugin` - -### Configuration System - -Configuration uses strongly-typed interfaces inheriting from `IConfig`: -- Each module has `IConfig` interface and `Config` implementation -- Examples: `ITxPoolConfig`, `IDbConfig`, `IInitConfig` -- Access via `INethermindApi.Config()` where `T : IConfig` - -## Code Style and Conventions - -**Critical Requirements:** -- All code MUST follow `.editorconfig` rules (enforced by CI) -- Use C# 13 features (latest language version) -- All files require SPDX header: - ```csharp - // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited - // SPDX-License-Identifier: LGPL-3.0-only - ``` - -**Strongly Preferred Patterns:** -- Use file-scoped namespaces (but match existing file style if present) -- Pattern matching and switch expressions over traditional control flow -- `nameof()` instead of string literals for member references -- `is null` / `is not null` instead of `== null` / `!= null` -- `?.` null-conditional operator where applicable -- Trust null annotations - don't add redundant null checks -- `ObjectDisposedException.ThrowIf` for disposal checks -- Add tests to existing test files rather than creating new ones -- XML doc comments for all public APIs with proper structure: - - Use `` tag for brief description (one sentence preferred) - - Use `` tag for each parameter with concise description - - Use `` tag to describe the return value - - Use `` tag (optional) for additional implementation details, behavior notes, or important context when needed -- Code comments explain "why", not "what" - -**Prohibited Patterns:** -- Do NOT use `#region` -- Do NOT use "Act", "Arrange", "Assert" comments in tests -- Do NOT leave tests commented out or disabled unless previously disabled -- Do NOT change `global.json`, `package.json`, `NuGet.config` unless explicitly requested - -**Performance Focus:** -- Prefer low-allocation code patterns -- Consider performance implications in high-throughput paths - -## Build Configuration - -Key settings from `Directory.Build.props`: -- `TreatWarningsAsErrors`: true (warnings block builds) -- `InvariantGlobalization`: true (consistent cross-locale behavior) -- `UseArtifactsOutput`: true (outputs to `artifacts/` directory) -- `TargetFramework`: net9.0 -- `LangVersion`: 13.0 - -## Testing Requirements - -**Before committing code:** -1. Your changes MUST compile -2. New and existing related tests MUST pass -3. Formatting check MUST pass: `dotnet format whitespace src/Nethermind/ --folder --verify-no-changes` -4. Report if unable to verify build/test success - -**When writing tests:** -- Use filters and verify test counts to ensure tests actually ran -- Copy style from nearby test files for naming and capitalization -- Ensure new code files are listed in `.csproj` if other files in the folder are listed - -## Common File Locations - -- Solution files: `src/Nethermind/*.slnx` -- Main entry point: `src/Nethermind/Nethermind.Runner/Program.cs` -- Core types: `src/Nethermind/Nethermind.Core/` -- API definitions: `src/Nethermind/Nethermind.Api/` -- Plugin interfaces: `src/Nethermind/Nethermind.Api/Extensions/` -- Global build config: `Directory.Build.props`, `global.json` -- Editor config: `.editorconfig` - -## Branch Naming Convention - -Use `kebab-case` or `snake_case`, all lowercase. Pattern: `[project/]type/[issue-]description` - -Examples: -- `feature/1234-issue-title` -- `shanghai/feature/1234-issue-title` -- `fix/1234-bug-description` -- `shanghai/refactor/title` +@./AGENTS.md diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 00000000000..285e0f5b36b --- /dev/null +++ b/GEMINI.md @@ -0,0 +1 @@ +@./AGENTS.md From 9c955833f9c8ae6d7e18b602083b5c9e74ab5dfa Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Tue, 13 Jan 2026 18:02:08 +0800 Subject: [PATCH 208/255] Fix cannot prune storage root (#10203) * Fix cannot prune storage root * Fix whitespace formatting in TreeStoreTests.cs (#10204) * Initial plan * Fix whitespace formatting in TreeStoreTests.cs Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --- .../Pruning/TreeStoreTests.cs | 49 +++++++++++++++++++ .../Pruning/TrieStoreDirtyNodesCache.cs | 2 +- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs b/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs index fd920defda1..a5b93e6758c 100644 --- a/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/Pruning/TreeStoreTests.cs @@ -1222,6 +1222,55 @@ void WriteRandomData(int seed) fullTrieStore.CachedNodesCount.Should().Be(36); } + [Test] + public void Can_Prune_StorageTreeRoot() + { + if (_scheme == INodeStorage.KeyScheme.Hash) Assert.Ignore("Not applicable for hash"); + + MemDb memDb = new(); + TestPruningStrategy testPruningStrategy = new TestPruningStrategy( + shouldPrune: false, + deleteObsoleteKeys: true + ); + + TrieStore fullTrieStore = CreateTrieStore( + kvStore: memDb, + pruningStrategy: testPruningStrategy, + persistenceStrategy: No.Persistence, + pruningConfig: new PruningConfig() + { + PruningBoundary = 4, + PrunePersistedNodePortion = 1.0, + DirtyNodeShardBit = 4, + MaxBufferedCommitCount = 0, + TrackPastKeys = true + }); + + StateTree ptree = new StateTree(fullTrieStore.GetTrieStore(null), LimboLogs.Instance); + + void WriteRandomData(int seed) + { + Hash256 address = Keccak.Compute(seed.ToBigEndianByteArray()); + StorageTree storageTree = new StorageTree(fullTrieStore.GetTrieStore(address), LimboLogs.Instance); + storageTree.Set(Keccak.Compute((seed * 2).ToBigEndianByteArray()).Bytes, Keccak.Compute(seed.ToBigEndianByteArray()).BytesToArray()); + storageTree.Commit(); + + ptree.Set(address, new Account(0, 0, storageTree.RootHash, Keccak.OfAnEmptyString)); + ptree.Commit(); + } + + for (int i = 0; i < 16; i++) + { + using (fullTrieStore.BeginBlockCommit(i)) + { + WriteRandomData(i); + } + fullTrieStore.PersistAndPruneDirtyCache(); + fullTrieStore.PrunePersistedNodes(); + } + fullTrieStore.CachedNodesCount.Should().Be(19); + } + [TestCase(27, 1000, 31, 7)] [TestCase(27, 1000, 2, 2)] public void Will_HaveConsistentState_AfterPrune(int possibleSeed, int totalBlock, int snapshotInterval, int prunePersistedInterval) diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs index 34268a8db49..94590de60f2 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs @@ -502,7 +502,7 @@ public override string ToString() public bool IsRoot() { - return Path.Length == 0; + return Address is null && Path.Length == 0; } } From 8cf94bb4ea38b0576cdf4726bfd53c9234418e08 Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Wed, 14 Jan 2026 00:16:47 +0100 Subject: [PATCH 209/255] Support CLI alias overrides in docs (#10197) --- cspell.json | 1 + tools/DocGen/ConfigGenerator.cs | 13 ++++++++----- tools/DocGen/DBSizeGenerator.cs | 1 - tools/DocGen/MetricsGenerator.cs | 1 - 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cspell.json b/cspell.json index 053b4563bcd..160440cf2f4 100644 --- a/cspell.json +++ b/cspell.json @@ -45,6 +45,7 @@ "aspnetcore", "assertoor", "autofac", + "autogen", "auxdata", "badreq", "barebone", diff --git a/tools/DocGen/ConfigGenerator.cs b/tools/DocGen/ConfigGenerator.cs index 4ef93e62645..414b3d4c2ba 100644 --- a/tools/DocGen/ConfigGenerator.cs +++ b/tools/DocGen/ConfigGenerator.cs @@ -96,12 +96,15 @@ private static void WriteMarkdown(StreamWriter file, Type configType) foreach (var prop in props) { - var itemAttr = prop.GetCustomAttribute(); + var configAttr = prop.GetCustomAttribute(); - if (itemAttr?.HiddenFromDocs ?? true) + if (configAttr?.HiddenFromDocs ?? true) continue; - var description = itemAttr.Description.Replace("\n", "\n ").TrimEnd(' '); + var description = configAttr.Description.Replace("\n", "\n ").TrimEnd(' '); + var cliAlias = string.IsNullOrWhiteSpace(configAttr.CliOptionAlias) + ? $"{moduleName}-{prop.Name}" + : configAttr.CliOptionAlias; (string value, string cliValue) = GetValue(prop); file.Write($$""" @@ -110,7 +113,7 @@ private static void WriteMarkdown(StreamWriter file, Type configType) ``` - --{{moduleName.ToLowerInvariant()}}-{{prop.Name.ToLowerInvariant()}} {{cliValue}} + --{{cliAlias.ToLowerInvariant()}} {{cliValue}} --{{moduleName}}.{{prop.Name}} {{cliValue}} ``` @@ -135,7 +138,7 @@ private static void WriteMarkdown(StreamWriter file, Type configType) var startsFromNewLine = WriteAllowedValues(file, prop.PropertyType) || description.EndsWith('\n'); - WriteDefaultValue(file, itemAttr, startsFromNewLine); + WriteDefaultValue(file, configAttr, startsFromNewLine); file.WriteLine(); file.WriteLine(); diff --git a/tools/DocGen/DBSizeGenerator.cs b/tools/DocGen/DBSizeGenerator.cs index db8c77ecc54..6987321701e 100644 --- a/tools/DocGen/DBSizeGenerator.cs +++ b/tools/DocGen/DBSizeGenerator.cs @@ -97,7 +97,6 @@ private static void GenerateFile(string docsPath, string dbSizeSourcePath, IList writeStream.Close(); File.Move(tempFileName, fileName, true); - File.Delete(tempFileName); AnsiConsole.MarkupLine($"[green]Updated[/] {fileName}"); } diff --git a/tools/DocGen/MetricsGenerator.cs b/tools/DocGen/MetricsGenerator.cs index 697b0381772..72b19253585 100644 --- a/tools/DocGen/MetricsGenerator.cs +++ b/tools/DocGen/MetricsGenerator.cs @@ -70,7 +70,6 @@ internal static void Generate(string path) writeStream.Close(); File.Move(tempFileName, fileName, true); - File.Delete(tempFileName); AnsiConsole.MarkupLine($"[green]Updated[/] {fileName}"); } From 1d5fe28b7aa07e03135d0c3c3c6dbd3d3e2630ed Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Tue, 13 Jan 2026 18:30:06 -0500 Subject: [PATCH 210/255] Fast-path ConcurrentDict AddOrUpdate (#10220) * Fast-path ConcurrentDict AddOrUpdate * Also debug --- src/Nethermind/Nethermind.Logging/ILogger.cs | 6 ++++-- .../Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Logging/ILogger.cs b/src/Nethermind/Nethermind.Logging/ILogger.cs index 6791b0a00af..e226478b2cf 100644 --- a/src/Nethermind/Nethermind.Logging/ILogger.cs +++ b/src/Nethermind/Nethermind.Logging/ILogger.cs @@ -12,9 +12,9 @@ namespace Nethermind.Logging; /// the struct rather than being an interface call each time. /// #if DEBUG -public struct ILogger +public struct ILogger : IEquatable #else -public readonly struct ILogger +public readonly struct ILogger : IEquatable #endif { private readonly InterfaceLogger _logger; @@ -56,6 +56,8 @@ public readonly void Debug(string text) _logger.Debug(text); } + public bool Equals(ILogger other) => _logger == other._logger; + [MethodImpl(MethodImplOptions.NoInlining)] public readonly void Error(string text, Exception ex = null) { diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs index 94590de60f2..356f94abde0 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStoreDirtyNodesCache.cs @@ -119,10 +119,12 @@ public bool IsNodeCached(in Key key) return _byKeyObjectCache.ContainsKey(key); } - public readonly struct NodeRecord(TrieNode node, long lastCommit) + public readonly struct NodeRecord(TrieNode node, long lastCommit) : IEquatable { public readonly TrieNode Node = node; public readonly long LastCommit = lastCommit; + + public bool Equals(NodeRecord other) => other.Node == Node && other.LastCommit == LastCommit; } public IEnumerable> AllNodes From 8a4a2d76013a374b3dfe381f964ae521970488f9 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Tue, 13 Jan 2026 18:50:00 -0500 Subject: [PATCH 211/255] Reuse same nibble keys for short paths (#10214) * Reuse same nibble keys for short paths * Address review comments: remove unused parameter, add XML docs, add unit tests for GetPathArray (#10215) * Initial plan * Address review comments: remove unused parameter, add XML docs, add unit tests Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> * formatting * Other places * formatting * More optimal * Add tests for PrependNibble and ConcatNibbles methods (#10216) * Initial plan * Add comprehensive tests for PrependNibble and ConcatNibbles methods Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> * Fix misleading comments in ConcatNibbles tests Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> * Add validation checks to ConcatNibbles for invalid nibble values (#10217) * Initial plan * Add validation checks to ConcatNibbles for robustness Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> * Update src/Nethermind/Nethermind.Trie/HexPrefix.cs Co-authored-by: Ruben Buniatyan --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: benaadams <1142958+benaadams@users.noreply.github.com> Co-authored-by: Ruben Buniatyan --- .../Nethermind.Trie.Test/HexPrefixTests.cs | 375 ++++++++++++++++++ src/Nethermind/Nethermind.Trie/HexPrefix.cs | 318 ++++++++++++--- .../Nethermind.Trie/PatriciaTree.BulkSet.cs | 3 +- .../Nethermind.Trie/PatriciaTree.cs | 18 +- .../Nethermind.Trie/TrieNodeFactory.cs | 38 +- 5 files changed, 673 insertions(+), 79 deletions(-) diff --git a/src/Nethermind/Nethermind.Trie.Test/HexPrefixTests.cs b/src/Nethermind/Nethermind.Trie.Test/HexPrefixTests.cs index 522e9776507..bf35cbb1232 100644 --- a/src/Nethermind/Nethermind.Trie.Test/HexPrefixTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/HexPrefixTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Linq; using NUnit.Framework; @@ -95,4 +96,378 @@ public void Nibbles_to_bytes_correct_output() byte[] result = Nibbles.ToBytes(nibbles); Assert.That(bytes, Is.EqualTo(result).AsCollection); } + + [Test] + public void GetPathArray_returns_cached_array_for_single_nibble() + { + // Test all valid single nibble values (0-15) + for (byte i = 0; i < 16; i++) + { + byte[] path1 = HexPrefix.GetArray(new byte[] { i }); + byte[] path2 = HexPrefix.GetArray(new byte[] { i }); + + // Should return the same cached instance + Assert.That(ReferenceEquals(path1, path2), Is.True, $"Single nibble {i} should return cached array"); + Assert.That(path1.Length, Is.EqualTo(1)); + Assert.That(path1[0], Is.EqualTo(i)); + } + } + + [Test] + public void GetPathArray_returns_cached_array_for_double_nibble() + { + // Test a sample of double nibble values + for (byte i = 0; i < 16; i++) + { + for (byte j = 0; j < 16; j++) + { + byte[] path1 = HexPrefix.GetArray(new byte[] { i, j }); + byte[] path2 = HexPrefix.GetArray(new byte[] { i, j }); + + // Should return the same cached instance + Assert.That(ReferenceEquals(path1, path2), Is.True, $"Double nibble [{i},{j}] should return cached array"); + Assert.That(path1.Length, Is.EqualTo(2)); + Assert.That(path1[0], Is.EqualTo(i)); + Assert.That(path1[1], Is.EqualTo(j)); + } + } + } + + [Test] + public void GetPathArray_returns_cached_array_for_triple_nibble() + { + // Test a sample of triple nibble values + for (byte i = 0; i < 4; i++) + { + for (byte j = 0; j < 4; j++) + { + for (byte k = 0; k < 4; k++) + { + byte[] path1 = HexPrefix.GetArray(new byte[] { i, j, k }); + byte[] path2 = HexPrefix.GetArray(new byte[] { i, j, k }); + + // Should return the same cached instance + Assert.That(ReferenceEquals(path1, path2), Is.True, $"Triple nibble [{i},{j},{k}] should return cached array"); + Assert.That(path1.Length, Is.EqualTo(3)); + Assert.That(path1[0], Is.EqualTo(i)); + Assert.That(path1[1], Is.EqualTo(j)); + Assert.That(path1[2], Is.EqualTo(k)); + } + } + } + } + + [Test] + public void GetPathArray_allocates_new_array_for_invalid_nibble_values() + { + // Test single nibble with value >= 16 + byte[] path1 = HexPrefix.GetArray(new byte[] { 16 }); + byte[] path2 = HexPrefix.GetArray(new byte[] { 16 }); + Assert.That(ReferenceEquals(path1, path2), Is.False, "Should allocate new array for nibble value >= 16"); + Assert.That(path1[0], Is.EqualTo(16)); + + // Test double nibble with value >= 16 + byte[] path3 = HexPrefix.GetArray(new byte[] { 5, 16 }); + byte[] path4 = HexPrefix.GetArray(new byte[] { 5, 16 }); + Assert.That(ReferenceEquals(path3, path4), Is.False, "Should allocate new array for nibble value >= 16"); + Assert.That(path3[0], Is.EqualTo(5)); + Assert.That(path3[1], Is.EqualTo(16)); + + // Test triple nibble with value >= 16 + byte[] path5 = HexPrefix.GetArray(new byte[] { 3, 7, 20 }); + byte[] path6 = HexPrefix.GetArray(new byte[] { 3, 7, 20 }); + Assert.That(ReferenceEquals(path5, path6), Is.False, "Should allocate new array for nibble value >= 16"); + Assert.That(path5[0], Is.EqualTo(3)); + Assert.That(path5[1], Is.EqualTo(7)); + Assert.That(path5[2], Is.EqualTo(20)); + } + + [Test] + public void GetPathArray_allocates_new_array_for_longer_paths() + { + // Test paths longer than 3 nibbles + byte[] path1 = HexPrefix.GetArray(new byte[] { 1, 2, 3, 4 }); + byte[] path2 = HexPrefix.GetArray(new byte[] { 1, 2, 3, 4 }); + + Assert.That(ReferenceEquals(path1, path2), Is.False, "Should allocate new array for paths longer than 3"); + Assert.That(path1.Length, Is.EqualTo(4)); + Assert.That(path1, Is.EqualTo(new byte[] { 1, 2, 3, 4 }).AsCollection); + } + + [Test] + public void GetPathArray_returns_empty_array_for_empty_path() + { + byte[] path = HexPrefix.GetArray(ReadOnlySpan.Empty); + Assert.That(path.Length, Is.EqualTo(0)); + } + + [Test] + public void PrependNibble_returns_cached_array_for_single_nibble_result() + { + // Prepending to empty array should return cached single nibble + for (byte i = 0; i < 16; i++) + { + byte[] result1 = HexPrefix.PrependNibble(i, []); + byte[] result2 = HexPrefix.PrependNibble(i, []); + + Assert.That(ReferenceEquals(result1, result2), Is.True, $"PrependNibble({i}, []) should return cached array"); + Assert.That(result1.Length, Is.EqualTo(1)); + Assert.That(result1[0], Is.EqualTo(i)); + } + } + + [Test] + public void PrependNibble_returns_cached_array_for_double_nibble_result() + { + // Prepending to single nibble array should return cached double nibble + for (byte i = 0; i < 16; i++) + { + for (byte j = 0; j < 16; j++) + { + byte[] result1 = HexPrefix.PrependNibble(i, new byte[] { j }); + byte[] result2 = HexPrefix.PrependNibble(i, new byte[] { j }); + + Assert.That(ReferenceEquals(result1, result2), Is.True, $"PrependNibble({i}, [{j}]) should return cached array"); + Assert.That(result1.Length, Is.EqualTo(2)); + Assert.That(result1[0], Is.EqualTo(i)); + Assert.That(result1[1], Is.EqualTo(j)); + } + } + } + + [Test] + public void PrependNibble_returns_cached_array_for_triple_nibble_result() + { + // Prepending to double nibble array should return cached triple nibble + for (byte i = 0; i < 4; i++) + { + for (byte j = 0; j < 4; j++) + { + for (byte k = 0; k < 4; k++) + { + byte[] result1 = HexPrefix.PrependNibble(i, new byte[] { j, k }); + byte[] result2 = HexPrefix.PrependNibble(i, new byte[] { j, k }); + + Assert.That(ReferenceEquals(result1, result2), Is.True, $"PrependNibble({i}, [{j},{k}]) should return cached array"); + Assert.That(result1.Length, Is.EqualTo(3)); + Assert.That(result1[0], Is.EqualTo(i)); + Assert.That(result1[1], Is.EqualTo(j)); + Assert.That(result1[2], Is.EqualTo(k)); + } + } + } + } + + [Test] + public void PrependNibble_allocates_new_array_for_invalid_nibble_values() + { + // Test with nibble value >= 16 + byte[] result1 = HexPrefix.PrependNibble(16, []); + byte[] result2 = HexPrefix.PrependNibble(16, []); + Assert.That(ReferenceEquals(result1, result2), Is.False, "Should allocate new array for nibble value >= 16"); + Assert.That(result1.Length, Is.EqualTo(1)); + Assert.That(result1[0], Is.EqualTo(16)); + } + + [Test] + public void PrependNibble_allocates_new_array_for_longer_results() + { + // Prepending to array of length 3+ should allocate new array + byte[] result1 = HexPrefix.PrependNibble(1, new byte[] { 2, 3, 4 }); + byte[] result2 = HexPrefix.PrependNibble(1, new byte[] { 2, 3, 4 }); + + Assert.That(ReferenceEquals(result1, result2), Is.False, "Should allocate new array for length > 3"); + Assert.That(result1.Length, Is.EqualTo(4)); + Assert.That(result1, Is.EqualTo(new byte[] { 1, 2, 3, 4 }).AsCollection); + } + + [Test] + public void ConcatNibbles_returns_empty_array_for_empty_inputs() + { + byte[] result = HexPrefix.ConcatNibbles([], []); + Assert.That(result.Length, Is.EqualTo(0)); + } + + [Test] + public void ConcatNibbles_returns_cached_array_for_single_nibble_result() + { + // Test [1] + [] = [1] + for (byte i = 0; i < 16; i++) + { + byte[] result1 = HexPrefix.ConcatNibbles(new byte[] { i }, []); + byte[] result2 = HexPrefix.ConcatNibbles(new byte[] { i }, []); + Assert.That(ReferenceEquals(result1, result2), Is.True, $"ConcatNibbles([{i}], []) should return cached array"); + Assert.That(result1.Length, Is.EqualTo(1)); + Assert.That(result1[0], Is.EqualTo(i)); + + // Test [] + [1] = [1] + byte[] result3 = HexPrefix.ConcatNibbles([], new byte[] { i }); + byte[] result4 = HexPrefix.ConcatNibbles([], new byte[] { i }); + Assert.That(ReferenceEquals(result3, result4), Is.True, $"ConcatNibbles([], [{i}]) should return cached array"); + Assert.That(result3.Length, Is.EqualTo(1)); + Assert.That(result3[0], Is.EqualTo(i)); + } + } + + [Test] + public void ConcatNibbles_returns_cached_array_for_double_nibble_result() + { + // Test various combinations that result in length 2 + for (byte i = 0; i < 16; i++) + { + for (byte j = 0; j < 16; j++) + { + // Test [i,j] + [] = [i,j] + byte[] result1 = HexPrefix.ConcatNibbles(new byte[] { i, j }, []); + byte[] result2 = HexPrefix.ConcatNibbles(new byte[] { i, j }, []); + Assert.That(ReferenceEquals(result1, result2), Is.True, $"ConcatNibbles([{i},{j}], []) should return cached array"); + Assert.That(result1.Length, Is.EqualTo(2)); + Assert.That(result1[0], Is.EqualTo(i)); + Assert.That(result1[1], Is.EqualTo(j)); + + // Test [i] + [j] = [i,j] + byte[] result3 = HexPrefix.ConcatNibbles(new byte[] { i }, new byte[] { j }); + byte[] result4 = HexPrefix.ConcatNibbles(new byte[] { i }, new byte[] { j }); + Assert.That(ReferenceEquals(result3, result4), Is.True, $"ConcatNibbles([{i}], [{j}]) should return cached array"); + Assert.That(result3.Length, Is.EqualTo(2)); + Assert.That(result3[0], Is.EqualTo(i)); + Assert.That(result3[1], Is.EqualTo(j)); + + // Test [] + [i,j] = [i,j] + byte[] result5 = HexPrefix.ConcatNibbles([], new byte[] { i, j }); + byte[] result6 = HexPrefix.ConcatNibbles([], new byte[] { i, j }); + Assert.That(ReferenceEquals(result5, result6), Is.True, $"ConcatNibbles([], [{i},{j}]) should return cached array"); + Assert.That(result5.Length, Is.EqualTo(2)); + Assert.That(result5[0], Is.EqualTo(i)); + Assert.That(result5[1], Is.EqualTo(j)); + } + } + } + + [Test] + public void ConcatNibbles_returns_cached_array_for_triple_nibble_result() + { + // Test various combinations that result in length 3 + for (byte i = 0; i < 4; i++) + { + for (byte j = 0; j < 4; j++) + { + for (byte k = 0; k < 4; k++) + { + // Test [i,j,k] + [] = [i,j,k] + byte[] result1 = HexPrefix.ConcatNibbles(new byte[] { i, j, k }, []); + byte[] result2 = HexPrefix.ConcatNibbles(new byte[] { i, j, k }, []); + Assert.That(ReferenceEquals(result1, result2), Is.True, $"ConcatNibbles([{i},{j},{k}], []) should return cached array"); + Assert.That(result1.Length, Is.EqualTo(3)); + Assert.That(result1[0], Is.EqualTo(i)); + Assert.That(result1[1], Is.EqualTo(j)); + Assert.That(result1[2], Is.EqualTo(k)); + + // Test [i] + [j,k] = [i,j,k] + byte[] result3 = HexPrefix.ConcatNibbles(new byte[] { i }, new byte[] { j, k }); + byte[] result4 = HexPrefix.ConcatNibbles(new byte[] { i }, new byte[] { j, k }); + Assert.That(ReferenceEquals(result3, result4), Is.True, $"ConcatNibbles([{i}], [{j},{k}]) should return cached array"); + Assert.That(result3.Length, Is.EqualTo(3)); + Assert.That(result3[0], Is.EqualTo(i)); + Assert.That(result3[1], Is.EqualTo(j)); + Assert.That(result3[2], Is.EqualTo(k)); + + // Test [i,j] + [k] = [i,j,k] + byte[] result5 = HexPrefix.ConcatNibbles(new byte[] { i, j }, new byte[] { k }); + byte[] result6 = HexPrefix.ConcatNibbles(new byte[] { i, j }, new byte[] { k }); + Assert.That(ReferenceEquals(result5, result6), Is.True, $"ConcatNibbles([{i},{j}], [{k}]) should return cached array"); + Assert.That(result5.Length, Is.EqualTo(3)); + Assert.That(result5[0], Is.EqualTo(i)); + Assert.That(result5[1], Is.EqualTo(j)); + Assert.That(result5[2], Is.EqualTo(k)); + + // Test [] + [i,j,k] = [i,j,k] + byte[] result7 = HexPrefix.ConcatNibbles([], new byte[] { i, j, k }); + byte[] result8 = HexPrefix.ConcatNibbles([], new byte[] { i, j, k }); + Assert.That(ReferenceEquals(result7, result8), Is.True, $"ConcatNibbles([], [{i},{j},{k}]) should return cached array"); + Assert.That(result7.Length, Is.EqualTo(3)); + Assert.That(result7[0], Is.EqualTo(i)); + Assert.That(result7[1], Is.EqualTo(j)); + Assert.That(result7[2], Is.EqualTo(k)); + } + } + } + } + + [Test] + public void ConcatNibbles_allocates_new_array_for_longer_results() + { + // Test combinations that result in length > 3 + byte[] result1 = HexPrefix.ConcatNibbles(new byte[] { 1, 2 }, new byte[] { 3, 4 }); + byte[] result2 = HexPrefix.ConcatNibbles(new byte[] { 1, 2 }, new byte[] { 3, 4 }); + + Assert.That(ReferenceEquals(result1, result2), Is.False, "Should allocate new array for length > 3"); + Assert.That(result1.Length, Is.EqualTo(4)); + Assert.That(result1, Is.EqualTo(new byte[] { 1, 2, 3, 4 }).AsCollection); + + // Test longer arrays + byte[] result3 = HexPrefix.ConcatNibbles(new byte[] { 1, 2, 3 }, new byte[] { 4, 5 }); + byte[] result4 = HexPrefix.ConcatNibbles(new byte[] { 1, 2, 3 }, new byte[] { 4, 5 }); + + Assert.That(ReferenceEquals(result3, result4), Is.False, "Should allocate new array for length > 3"); + Assert.That(result3.Length, Is.EqualTo(5)); + Assert.That(result3, Is.EqualTo(new byte[] { 1, 2, 3, 4, 5 }).AsCollection); + } + + [Test] + public void ConcatNibbles_preserves_values_correctly() + { + // Test that values are preserved in the correct order + byte[] result = HexPrefix.ConcatNibbles(new byte[] { 15, 14, 13 }, new byte[] { 12, 11, 10 }); + Assert.That(result, Is.EqualTo(new byte[] { 15, 14, 13, 12, 11, 10 }).AsCollection); + } + + [Test] + public void ConcatNibbles_allocates_new_array_for_invalid_nibble_values() + { + // Test single nibble with value >= 16 + byte[] result1 = HexPrefix.ConcatNibbles(new byte[] { 16 }, []); + byte[] result2 = HexPrefix.ConcatNibbles(new byte[] { 16 }, []); + Assert.That(ReferenceEquals(result1, result2), Is.False, "Should allocate new array for nibble value >= 16"); + Assert.That(result1.Length, Is.EqualTo(1)); + Assert.That(result1[0], Is.EqualTo(16)); + + byte[] result3 = HexPrefix.ConcatNibbles([], new byte[] { 16 }); + byte[] result4 = HexPrefix.ConcatNibbles([], new byte[] { 16 }); + Assert.That(ReferenceEquals(result3, result4), Is.False, "Should allocate new array for nibble value >= 16"); + Assert.That(result3.Length, Is.EqualTo(1)); + Assert.That(result3[0], Is.EqualTo(16)); + + // Test double nibble with value >= 16 + byte[] result5 = HexPrefix.ConcatNibbles(new byte[] { 5 }, new byte[] { 16 }); + byte[] result6 = HexPrefix.ConcatNibbles(new byte[] { 5 }, new byte[] { 16 }); + Assert.That(ReferenceEquals(result5, result6), Is.False, "Should allocate new array for nibble value >= 16"); + Assert.That(result5.Length, Is.EqualTo(2)); + Assert.That(result5[0], Is.EqualTo(5)); + Assert.That(result5[1], Is.EqualTo(16)); + + byte[] result7 = HexPrefix.ConcatNibbles(new byte[] { 16, 5 }, []); + byte[] result8 = HexPrefix.ConcatNibbles(new byte[] { 16, 5 }, []); + Assert.That(ReferenceEquals(result7, result8), Is.False, "Should allocate new array for nibble value >= 16"); + Assert.That(result7.Length, Is.EqualTo(2)); + Assert.That(result7[0], Is.EqualTo(16)); + Assert.That(result7[1], Is.EqualTo(5)); + + // Test triple nibble with value >= 16 + byte[] result9 = HexPrefix.ConcatNibbles(new byte[] { 3, 7 }, new byte[] { 20 }); + byte[] result10 = HexPrefix.ConcatNibbles(new byte[] { 3, 7 }, new byte[] { 20 }); + Assert.That(ReferenceEquals(result9, result10), Is.False, "Should allocate new array for nibble value >= 16"); + Assert.That(result9.Length, Is.EqualTo(3)); + Assert.That(result9[0], Is.EqualTo(3)); + Assert.That(result9[1], Is.EqualTo(7)); + Assert.That(result9[2], Is.EqualTo(20)); + + byte[] result11 = HexPrefix.ConcatNibbles(new byte[] { 3 }, new byte[] { 16, 7 }); + byte[] result12 = HexPrefix.ConcatNibbles(new byte[] { 3 }, new byte[] { 16, 7 }); + Assert.That(ReferenceEquals(result11, result12), Is.False, "Should allocate new array for nibble value >= 16"); + Assert.That(result11.Length, Is.EqualTo(3)); + Assert.That(result11[0], Is.EqualTo(3)); + Assert.That(result11[1], Is.EqualTo(16)); + Assert.That(result11[2], Is.EqualTo(7)); + } } diff --git a/src/Nethermind/Nethermind.Trie/HexPrefix.cs b/src/Nethermind/Nethermind.Trie/HexPrefix.cs index 739db8afa83..e7babfa09bc 100644 --- a/src/Nethermind/Nethermind.Trie/HexPrefix.cs +++ b/src/Nethermind/Nethermind.Trie/HexPrefix.cs @@ -6,81 +6,299 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -namespace Nethermind.Trie +namespace Nethermind.Trie; + +public static class HexPrefix { - public static class HexPrefix + private static readonly byte[][] SingleNibblePaths = CreateSingleNibblePaths(); + private static readonly byte[][] DoubleNibblePaths = CreateDoubleNibblePaths(); + private static readonly byte[][] TripleNibblePaths = CreateTripleNibblePaths(); + + public static int ByteLength(byte[] path) => path.Length / 2 + 1; + + public static void CopyToSpan(byte[] path, bool isLeaf, Span output) { - public static int ByteLength(byte[] path) => path.Length / 2 + 1; + ArgumentOutOfRangeException.ThrowIfNotEqual(ByteLength(path), output.Length, nameof(output)); - public static void CopyToSpan(byte[] path, bool isLeaf, Span output) + output[0] = (byte)(isLeaf ? 0x20 : 0x00); + if (path.Length % 2 != 0) { - if (output.Length != ByteLength(path)) throw new ArgumentOutOfRangeException(nameof(output)); + output[0] += (byte)(0x10 + path[0]); + } - output[0] = (byte)(isLeaf ? 0x20 : 0x00); - if (path.Length % 2 != 0) - { - output[0] += (byte)(0x10 + path[0]); - } + for (int i = 0; i < path.Length - 1; i += 2) + { + output[i / 2 + 1] = + path.Length % 2 == 0 + ? (byte)(16 * path[i] + path[i + 1]) + : (byte)(16 * path[i + 1] + path[i + 2]); + } + } - for (int i = 0; i < path.Length - 1; i += 2) - { - output[i / 2 + 1] = - path.Length % 2 == 0 - ? (byte)(16 * path[i] + path[i + 1]) - : (byte)(16 * path[i + 1] + path[i + 2]); - } + public static byte[] ToBytes(byte[] path, bool isLeaf) + { + byte[] output = new byte[path.Length / 2 + 1]; + + CopyToSpan(path, isLeaf, output); + + return output; + } + + public static (byte[] key, bool isLeaf) FromBytes(ReadOnlySpan bytes) + { + bool isEven = (bytes[0] & 16) == 0; + bool isLeaf = bytes[0] >= 32; + int nibblesCount = bytes.Length * 2 - (isEven ? 2 : 1); + // Return cached arrays for small paths + switch (nibblesCount) + { + case 0: + return ([], isLeaf); + case 1: + // !isEven, bytes.Length == 1 + return (Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(SingleNibblePaths), bytes[0] & 0xF), isLeaf); + case 2: + // isEven, bytes.Length == 2 - byte value IS the index + return (Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(DoubleNibblePaths), bytes[1]), isLeaf); + case 3: + // !isEven, bytes.Length == 2 + return (Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(TripleNibblePaths), ((bytes[0] & 0xF) << 8) | bytes[1]), isLeaf); } - public static byte[] ToBytes(byte[] path, bool isLeaf) + // Longer paths - allocate + byte[] path = new byte[nibblesCount]; + Span span = new(path); + if (!isEven) + { + span[0] = (byte)(bytes[0] & 0xF); + span = span[1..]; + } + bytes = bytes[1..]; + Span nibbles = MemoryMarshal.CreateSpan( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + span.Length / 2); + Debug.Assert(nibbles.Length == bytes.Length); + ref byte byteRef = ref MemoryMarshal.GetReference(bytes); + ref ushort lookup16 = ref MemoryMarshal.GetArrayDataReference(Lookup16); + for (int i = 0; i < nibbles.Length; i++) { - byte[] output = new byte[path.Length / 2 + 1]; + nibbles[i] = Unsafe.Add(ref lookup16, Unsafe.Add(ref byteRef, i)); + } + return (path, isLeaf); + } - CopyToSpan(path, isLeaf, output); + private static readonly ushort[] Lookup16 = CreateLookup16(); - return output; + private static ushort[] CreateLookup16() + { + ushort[] result = new ushort[256]; + for (int i = 0; i < 256; i++) + { + result[i] = (ushort)(((i & 0xF) << 8) | ((i & 240) >> 4)); } - public static (byte[] key, bool isLeaf) FromBytes(ReadOnlySpan bytes) + return result; + } + + /// + /// Returns a byte array for the specified nibble path, using cached arrays for short paths (1-3 nibbles) with valid nibble values (0-15) to reduce allocations. + /// + /// The nibble path to convert to a byte array. + /// + /// A byte array representing the nibble path. For paths of length 1-3 with nibble values 0-15, returns a shared cached array that must not be modified. + /// For longer paths or paths with nibble values >= 16, allocates and returns a new array. + /// + /// + /// This optimization takes advantage of the fact that short nibble paths are common and their possible combinations are limited. + /// The returned cached arrays are shared and must not be modified by callers. + /// + public static byte[] GetArray(ReadOnlySpan path) + { + if (path.Length == 0) + { + return []; + } + if (path.Length == 1) + { + uint value = path[0]; + if (value < 16) + { + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(SingleNibblePaths), (int)value); + } + } + else if (path.Length == 2) + { + uint v1 = path[1]; + uint v0 = path[0]; + if ((v0 | v1) < 16) + { + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(DoubleNibblePaths), (int)((v0 << 4) | v1)); + } + } + else if (path.Length == 3) { - bool isEven = (bytes[0] & 16) == 0; - int nibblesCount = bytes.Length * 2 - (isEven ? 2 : 1); - byte[] path = new byte[nibblesCount]; - Span span = new(path); - if (!isEven) + uint v2 = path[2]; + uint v1 = path[1]; + uint v0 = path[0]; + if ((v0 | v1 | v2) < 16) { - span[0] = (byte)(bytes[0] & 0xF); - span = span[1..]; + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(TripleNibblePaths), (int)((v0 << 8) | (v1 << 4) | v2)); } - bool isLeaf = bytes[0] >= 32; - bytes = bytes[1..]; + } + return path.ToArray(); + } - Span nibbles = MemoryMarshal.CreateSpan( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - span.Length / 2); + /// + /// Prepends a nibble to an existing nibble array, returning a cached array for small results. + /// + /// The nibble value (0-15) to prepend. + /// The existing nibble array to prepend to. + /// + /// A cached array if the result length is 3 or fewer nibbles; otherwise a newly allocated array. + /// + public static byte[] PrependNibble(byte prefix, byte[] array) + { + switch (array.Length) + { + case 0: + if (prefix < 16) + { + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(SingleNibblePaths), prefix); + } + break; + case 1: + { + uint v1 = array[0]; + if ((prefix | v1) < 16) + { + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(DoubleNibblePaths), (prefix << 4) | (int)v1); + } + break; + } + case 2: + { + uint v2 = array[1]; + uint v1 = array[0]; + if ((prefix | v1 | v2) < 16) + { + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(TripleNibblePaths), (prefix << 8) | (int)((v1 << 4) | v2)); + } + break; + } + } - Debug.Assert(nibbles.Length == bytes.Length); + // Fallback - allocate and concat + byte[] result = new byte[array.Length + 1]; + result[0] = prefix; + array.CopyTo(result, 1); + return result; + } - ref byte byteRef = ref MemoryMarshal.GetReference(bytes); - ref ushort lookup16 = ref MemoryMarshal.GetArrayDataReference(Lookup16); - for (int i = 0; i < nibbles.Length; i++) - { - nibbles[i] = Unsafe.Add(ref lookup16, Unsafe.Add(ref byteRef, i)); - } + /// + /// Concatenates two nibble arrays, returning a cached array for small results. + /// + /// The first nibble array. + /// The second nibble array to append. + /// + /// A cached array if the combined length is 3 or fewer nibbles; otherwise a newly allocated array. + /// + public static byte[] ConcatNibbles(byte[] first, byte[] second) + { + switch (first.Length + second.Length) + { + case 0: + return []; + case 1: + { + byte nibble = first.Length == 1 ? first[0] : second[0]; + if (nibble < 16) + { + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(SingleNibblePaths), nibble); + } + break; + } + case 2: + { + (uint v1, uint v2) = first.Length switch + { + 0 => (second[0], second[1]), + 1 => (first[0], second[0]), + _ => (first[0], first[1]) + }; + if ((v1 | v2) < 16) + { + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(DoubleNibblePaths), (int)((v1 << 4) | v2)); + } + break; + } + case 3: + { + (uint v1, uint v2, uint v3) = first.Length switch + { + 0 => (second[0], second[1], second[2]), + 1 => (first[0], second[0], second[1]), + 2 => (first[0], first[1], second[0]), + _ => (first[0], first[1], first[2]) + }; + if ((v1 | v2 | v3) < 16) + { + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(TripleNibblePaths), (int)((v1 << 8) | (v2 << 4) | v3)); + } + break; + } + } - return (path, isLeaf); + // Fallback - allocate and concat + byte[] result = new byte[first.Length + second.Length]; + first.CopyTo(result, 0); + second.CopyTo(result, first.Length); + return result; + } + + /// + /// Returns a cached single-nibble array for a byte value if it's a valid nibble (0-15); + /// otherwise allocates a new single-element array. + /// + /// The byte value. + /// + /// A cached single-element array if the value is 0-15; otherwise a newly allocated array. + /// + public static byte[] SingleNibble(byte value) + { + if (value < 16) + { + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(SingleNibblePaths), value); } + return [value]; + } - private static readonly ushort[] Lookup16 = CreateLookup16("x2"); + private static byte[][] CreateSingleNibblePaths() + { + var paths = new byte[16][]; + for (int i = 0; i < 16; i++) + { + paths[i] = [(byte)i]; + } + return paths; + } - private static ushort[] CreateLookup16(string format) + private static byte[][] CreateDoubleNibblePaths() + { + var paths = new byte[256][]; + for (int i = 0; i < 256; i++) { - ushort[] result = new ushort[256]; - for (int i = 0; i < 256; i++) - { - result[i] = (ushort)(((i & 0xF) << 8) | ((i & 240) >> 4)); - } + paths[i] = [(byte)(i >> 4), (byte)(i & 0xF)]; + } + return paths; + } - return result; + private static byte[][] CreateTripleNibblePaths() + { + var paths = new byte[4096][]; + for (int i = 0; i < 4096; i++) + { + paths[i] = [(byte)(i >> 8), (byte)((i >> 4) & 0xF), (byte)(i & 0xF)]; } + return paths; } } diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs index 482e9aaa784..d1b528ce4a5 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs @@ -273,8 +273,7 @@ private struct Context private TrieNode? MakeFakeBranch(ref TreePath currentPath, TrieNode? existingNode) { - byte[] shortenedKey = new byte[existingNode.Key.Length - 1]; - Array.Copy(existingNode.Key, 1, shortenedKey, 0, existingNode.Key.Length - 1); + ReadOnlySpan shortenedKey = existingNode.Key.AsSpan(1, existingNode.Key.Length - 1); int branchIdx = existingNode.Key[0]; diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs index 65e57990dd1..94c08386e9e 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs @@ -8,6 +8,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Nethermind.Core; @@ -538,7 +539,7 @@ public void Set(ReadOnlySpan rawKey, Rlp? value) { if (node is null) { - node = value.IsNullOrEmpty ? null : TrieNodeFactory.CreateLeaf(remainingKey.ToArray(), value); + node = value.IsNullOrEmpty ? null : TrieNodeFactory.CreateLeaf(remainingKey, value); // End traverse break; @@ -623,17 +624,17 @@ public void Set(ReadOnlySpan rawKey, Rlp? value) else { // Note: could be a leaf at the end of the tree which now have zero length key - theBranch[currentNodeNib] = node.CloneWithChangedKey(node.Key.Slice(commonPrefixLength + 1)); + theBranch[currentNodeNib] = node.CloneWithChangedKey(HexPrefix.GetArray(node.Key.AsSpan(commonPrefixLength + 1))); } // This is the new branch theBranch[remainingKey[commonPrefixLength]] = - TrieNodeFactory.CreateLeaf(remainingKey[(commonPrefixLength + 1)..].ToArray(), value); + TrieNodeFactory.CreateLeaf(remainingKey[(commonPrefixLength + 1)..], value); // Extension in front of the branch node = commonPrefixLength == 0 ? theBranch : - TrieNodeFactory.CreateExtension(remainingKey[..commonPrefixLength].ToArray(), theBranch); + TrieNodeFactory.CreateExtension(remainingKey[..commonPrefixLength], theBranch); break; } @@ -674,7 +675,7 @@ public void Set(ReadOnlySpan rawKey, Rlp? value) if (child.IsExtension || child.IsLeaf) { // Merge current node with child - node = child.CloneWithChangedKey(Bytes.Concat(node.Key, child.Key)); + node = child.CloneWithChangedKey(HexPrefix.ConcatNibbles(node.Key, child.Key)); } else { @@ -767,7 +768,7 @@ internal bool ShouldUpdateChild(TrieNode? parent, TrieNode? oldChild, TrieNode? if (onlyChildNode.IsBranch) { - byte[] extensionKey = [(byte)onlyChildIdx]; + byte[] extensionKey = HexPrefix.SingleNibble((byte)onlyChildIdx); if (originalNode is not null && originalNode.IsExtension && Bytes.AreEqual(extensionKey, originalNode.Key)) { TrieNode? originalChild = originalNode.GetChildWithChildPath(TrieStore, ref path, 0); @@ -777,13 +778,12 @@ internal bool ShouldUpdateChild(TrieNode? parent, TrieNode? oldChild, TrieNode? } } - return TrieNodeFactory.CreateExtension([(byte)onlyChildIdx], onlyChildNode); + return TrieNodeFactory.CreateExtension(extensionKey, onlyChildNode); } // 35% // Replace the only child with something with extra key. - byte[] newKey = Bytes.Concat((byte)onlyChildIdx, onlyChildNode.Key); - + byte[] newKey = HexPrefix.PrependNibble((byte)onlyChildIdx, onlyChildNode.Key); if (originalNode is not null) // Only bulkset provide original node { if (originalNode.IsExtension && onlyChildNode.IsExtension) diff --git a/src/Nethermind/Nethermind.Trie/TrieNodeFactory.cs b/src/Nethermind/Nethermind.Trie/TrieNodeFactory.cs index 0469b0b439c..7b44107d633 100644 --- a/src/Nethermind/Nethermind.Trie/TrieNodeFactory.cs +++ b/src/Nethermind/Nethermind.Trie/TrieNodeFactory.cs @@ -1,30 +1,32 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Core.Buffers; -namespace Nethermind.Trie +namespace Nethermind.Trie; + +public static class TrieNodeFactory { - public static class TrieNodeFactory + public static TrieNode CreateBranch() { - public static TrieNode CreateBranch() - { - return new(new BranchData()); - } + return new(new BranchData()); + } - public static TrieNode CreateLeaf(byte[] path, SpanSource value) - { - return new(new LeafData(path, value)); - } + public static TrieNode CreateLeaf(ReadOnlySpan path, SpanSource value) + { + byte[] pathArray = HexPrefix.GetArray(path); + return new(new LeafData(pathArray, value)); + } - public static TrieNode CreateExtension(byte[] path) - { - return new(new ExtensionData(path)); - } + public static TrieNode CreateExtension(ReadOnlySpan path, TrieNode child) + { + byte[] pathArray = HexPrefix.GetArray(path); + return new(new ExtensionData(pathArray, child)); + } - public static TrieNode CreateExtension(byte[] path, TrieNode child) - { - return new(new ExtensionData(path, child)); - } + public static TrieNode CreateExtension(byte[] pathArray, TrieNode child) + { + return new(new ExtensionData(pathArray, child)); } } From 65df7a4420071543640afaeefedadc6c9094674f Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:10:21 +0100 Subject: [PATCH 212/255] Update Dockerfiles (#10222) Co-authored-by: rubo --- Dockerfile | 4 ++-- Dockerfile.chiseled | 4 ++-- scripts/build/Dockerfile | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index d7c9b37d270..8ecddbd5413 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited # SPDX-License-Identifier: LGPL-3.0-only -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0.101-noble@sha256:d1823fecac3689a2eb959e02ee3bfe1c2142392808240039097ad70644566190 AS build +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0.102-noble@sha256:25d14b400b75fa4e89d5bd4487a92a604a4e409ab65becb91821e7dc4ac7f81f AS build ARG BUILD_CONFIG=release ARG CI=true @@ -25,7 +25,7 @@ RUN arch=$([ "$TARGETARCH" = "amd64" ] && echo "x64" || echo "$TARGETARCH") && \ # A temporary symlink to support the old executable name RUN ln -sr /publish/nethermind /publish/Nethermind.Runner -FROM mcr.microsoft.com/dotnet/aspnet:10.0.1-noble@sha256:eaa79205c3ade4792a7f7bf310a3aac51fe0e1d91c44e40f70b7c6423d475fe0 +FROM mcr.microsoft.com/dotnet/aspnet:10.0.2-noble@sha256:1aacc8154bc3071349907dae26849df301188be1a2e1f4560b903fb6275e481a WORKDIR /nethermind diff --git a/Dockerfile.chiseled b/Dockerfile.chiseled index b8f8c568e14..bf96919ae53 100644 --- a/Dockerfile.chiseled +++ b/Dockerfile.chiseled @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited # SPDX-License-Identifier: LGPL-3.0-only -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0.101-noble@sha256:d1823fecac3689a2eb959e02ee3bfe1c2142392808240039097ad70644566190 AS build +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0.102-noble@sha256:25d14b400b75fa4e89d5bd4487a92a604a4e409ab65becb91821e7dc4ac7f81f AS build ARG BUILD_CONFIG=release ARG CI=true @@ -28,7 +28,7 @@ RUN cd /publish && \ mkdir logs && \ mkdir nethermind_db -FROM mcr.microsoft.com/dotnet/aspnet:10.0.1-noble-chiseled@sha256:ba111738d21b4898f433fd8724ba1ed2e450adcb295c58f31d4137751922c83c +FROM mcr.microsoft.com/dotnet/aspnet:10.0.2-noble-chiseled@sha256:cc6a8adc9402e9c2c84423ee1a4c58a3098511ed5399804df0659eeafb0ae0cb WORKDIR /nethermind diff --git a/scripts/build/Dockerfile b/scripts/build/Dockerfile index 67a11fcd07d..bb2f165f611 100644 --- a/scripts/build/Dockerfile +++ b/scripts/build/Dockerfile @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited # SPDX-License-Identifier: LGPL-3.0-only -FROM mcr.microsoft.com/dotnet/sdk:10.0.101-noble@sha256:d1823fecac3689a2eb959e02ee3bfe1c2142392808240039097ad70644566190 +FROM mcr.microsoft.com/dotnet/sdk:10.0.102-noble@sha256:25d14b400b75fa4e89d5bd4487a92a604a4e409ab65becb91821e7dc4ac7f81f ARG COMMIT_HASH ARG SOURCE_DATE_EPOCH From f87221dfd9666e5a3470c5de32c675634dd04f7e Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Wed, 14 Jan 2026 04:36:25 -0500 Subject: [PATCH 213/255] Change async capturing closures to regular async methods (#10221) * Change async capturing closures to regular async methods * Formatting * Spelling --- .../Nethermind.Trie/PatriciaTree.cs | 24 ++++++----- .../Nethermind.Trie/Pruning/TrieStore.cs | 42 ++++++++++--------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs index 94c08386e9e..5119615e484 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs @@ -189,16 +189,6 @@ private TrieNode Commit(ICommitter committer, ref TreePath path, TrieNode node, } else { - Task CreateTaskForPath(TreePath childPath, TrieNode childNode, int idx) => Task.Run(() => - { - TrieNode newChild = Commit(committer, ref childPath, childNode!, maxLevelForConcurrentCommit); - if (!ReferenceEquals(childNode, newChild)) - { - node[idx] = newChild; - } - committer.ReturnConcurrencyQuota(); - }); - ArrayPoolList? childTasks = null; path.AppendMut(0); @@ -211,7 +201,7 @@ Task CreateTaskForPath(TreePath childPath, TrieNode childNode, int idx) => Task. { childTasks ??= new ArrayPoolList(15); // path is copied here - childTasks.Add(CreateTaskForPath(path, childNode, i)); + childTasks.Add(CreateTaskForPath(committer, node, maxLevelForConcurrentCommit, path, childNode, i)); } else { @@ -307,6 +297,18 @@ void TraceSkipInlineNode(TrieNode node) } } + private async Task CreateTaskForPath(ICommitter committer, TrieNode node, int maxLevelForConcurrentCommit, TreePath childPath, TrieNode childNode, int idx) + { + // Background task + await Task.Yield(); + TrieNode newChild = Commit(committer, ref childPath, childNode!, maxLevelForConcurrentCommit); + if (!ReferenceEquals(childNode, newChild)) + { + node[idx] = newChild; + } + committer.ReturnConcurrencyQuota(); + } + public void UpdateRootHash(bool canBeParallel = true) { TreePath path = TreePath.Empty; diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index 03b01088941..dfa1a361e16 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -909,25 +909,7 @@ private void PruneCache(bool prunePersisted = false, bool doNotRemoveNodes = fal { int closureIndex = index; TrieStoreDirtyNodesCache dirtyNode = _dirtyNodes[closureIndex]; - _dirtyNodesTasks[closureIndex] = Task.Run(() => - { - ConcurrentDictionary? persistedHashes = null; - if (_persistedHashes.Length > 0) - { - persistedHashes = _persistedHashes[closureIndex]; - } - - INodeStorage nodeStorage = _nodeStorage; - if (doNotRemoveNodes) nodeStorage = null; - - dirtyNode - .PruneCache( - prunePersisted: prunePersisted, - forceRemovePersistedNodes: forceRemovePersistedNodes, - persistedHashes: persistedHashes, - nodeStorage: nodeStorage); - persistedHashes?.NoResizeClear(); - }); + _dirtyNodesTasks[closureIndex] = CreatePruneDirtyNodeTask(prunePersisted, doNotRemoveNodes, forceRemovePersistedNodes, closureIndex, dirtyNode); } Task.WaitAll(_dirtyNodesTasks); @@ -937,6 +919,28 @@ private void PruneCache(bool prunePersisted = false, bool doNotRemoveNodes = fal if (_logger.IsDebug) _logger.Debug($"Finished pruning nodes in {(long)Stopwatch.GetElapsedTime(start).TotalMilliseconds}ms {DirtyMemoryUsedByDirtyCache / 1.MB()} MB, last persisted block: {LastPersistedBlockNumber} current: {LatestCommittedBlockNumber}."); } + private async Task CreatePruneDirtyNodeTask(bool prunePersisted, bool doNotRemoveNodes, bool forceRemovePersistedNodes, int closureIndex, TrieStoreDirtyNodesCache dirtyNode) + { + // Background task + await Task.Yield(); + ConcurrentDictionary? persistedHashes = null; + if (_persistedHashes.Length > 0) + { + persistedHashes = _persistedHashes[closureIndex]; + } + + INodeStorage nodeStorage = _nodeStorage; + if (doNotRemoveNodes) nodeStorage = null; + + dirtyNode + .PruneCache( + prunePersisted: prunePersisted, + forceRemovePersistedNodes: forceRemovePersistedNodes, + persistedHashes: persistedHashes, + nodeStorage: nodeStorage); + persistedHashes?.NoResizeClear(); + } + /// /// Only prune persisted nodes. This method attempt to pick only some shard for pruning. /// From af1f4e6c65d57110adc4265b6fc86ac15a61d429 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Wed, 14 Jan 2026 04:46:08 -0500 Subject: [PATCH 214/255] Reduce closure allocations in RetryCache (#10223) * Reduce closure allocations in RetryCache * Feedback --- .../Nethermind.TxPool/RetryCache.cs | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/Nethermind/Nethermind.TxPool/RetryCache.cs b/src/Nethermind/Nethermind.TxPool/RetryCache.cs index 56ae7a42aab..4bd9b40626c 100644 --- a/src/Nethermind/Nethermind.TxPool/RetryCache.cs +++ b/src/Nethermind/Nethermind.TxPool/RetryCache.cs @@ -29,6 +29,7 @@ public sealed class RetryCache : IAsyncDisposable private int _expiringQueueCounter = 0; private readonly ClockKeyCache _requestingResources; private readonly ILogger _logger; + private readonly Func>, IMessageHandler, ConcurrentHashSet>> _announceUpdate; internal int ResourcesInRetryQueue => _expiringQueueCounter; @@ -42,6 +43,8 @@ public RetryCache(ILogManager logManager, int timeoutMs = 2500, int requestingCa _requestingResources = new(requestingCacheSize); _expiringQueueLimit = expiringQueueLimit; _maxRetryRequests = maxRetryRequests; + // Closure capture + _announceUpdate = AnnounceUpdate; _mainLoopTask = Task.Run(async () => { @@ -102,7 +105,7 @@ public RetryCache(ILogManager logManager, int timeoutMs = 2500, int requestingCa }, token); } - public AnnounceResult Announced(in TResourceId resourceId, IMessageHandler retryHandler) + public AnnounceResult Announced(in TResourceId resourceId, IMessageHandler handler) { if (_token.IsCancellationRequested) { @@ -119,35 +122,41 @@ public AnnounceResult Announced(in TResourceId resourceId, IMessageHandler + _retryRequests.AddOrUpdate(resourceId, (resourceId, retryHandler) => { - if (_logger.IsTrace) _logger.Trace($"Announced {resourceId} by {retryHandler}: NEW"); + return AnnounceAdd(resourceId, retryHandler, out result); + }, _announceUpdate, handler); - _expiringQueue.Enqueue((resourceId, DateTimeOffset.UtcNow.AddMilliseconds(_timeoutMs))); - Interlocked.Increment(ref _expiringQueueCounter); + return result; + } - result = AnnounceResult.RequestRequired; + if (_logger.IsTrace) _logger.Trace($"Announced {resourceId} by {handler}, but a retry is in progress already, immediately firing"); - return _handlerBagsPool.Get(); - }, (resourceId, requests) => - { - if (_logger.IsTrace) _logger.Trace($"Announced {resourceId} by {retryHandler}: UPDATE"); + return AnnounceResult.RequestRequired; + } - if (requests.Count < _maxRetryRequests) - { - requests.Add(retryHandler); - } + private ConcurrentHashSet> AnnounceAdd(TResourceId resourceId, IMessageHandler retryHandler, out AnnounceResult result) + { + if (_logger.IsTrace) _logger.Trace($"Announced {resourceId} by {retryHandler}: NEW"); - return requests; - }); + _expiringQueue.Enqueue((resourceId, DateTimeOffset.UtcNow.AddMilliseconds(_timeoutMs))); + Interlocked.Increment(ref _expiringQueueCounter); - return result; - } + result = AnnounceResult.RequestRequired; - if (_logger.IsTrace) _logger.Trace($"Announced {resourceId} by {retryHandler}, but a retry is in progress already, immediately firing"); + return _handlerBagsPool.Get(); + } - return AnnounceResult.RequestRequired; + private ConcurrentHashSet> AnnounceUpdate(TResourceId resourceId, ConcurrentHashSet> requests, IMessageHandler retryHandler) + { + if (_logger.IsTrace) _logger.Trace($"Announced {resourceId} by {retryHandler}: UPDATE"); + + if (requests.Count < _maxRetryRequests) + { + requests.Add(retryHandler); + } + + return requests; } public void Received(in TResourceId resourceId) From babe72c3fb7605d1c2e5ca82fafaded820c89bce Mon Sep 17 00:00:00 2001 From: Forostovec Date: Wed, 14 Jan 2026 15:13:27 +0200 Subject: [PATCH 215/255] perf: Avoid unnecessary base fee calculations (#10213) --- .../Transactions/BaseFeeTxFilter.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/BaseFeeTxFilter.cs b/src/Nethermind/Nethermind.Consensus/Transactions/BaseFeeTxFilter.cs index 8e1ba000575..614ca9b63a3 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/BaseFeeTxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/BaseFeeTxFilter.cs @@ -13,11 +13,15 @@ public class BaseFeeTxFilter : ITxFilter { public AcceptTxResult IsAllowed(Transaction tx, BlockHeader parentHeader, IReleaseSpec spec) { - UInt256 baseFee = BaseFeeCalculator.Calculate(parentHeader, spec); bool isEip1559Enabled = spec.IsEip1559Enabled; - bool skipCheck = tx.IsServiceTransaction || !isEip1559Enabled; - bool allowed = skipCheck || tx.MaxFeePerGas >= baseFee; + if (!isEip1559Enabled || tx.IsServiceTransaction) + { + return AcceptTxResult.Accepted; + } + + UInt256 baseFee = BaseFeeCalculator.Calculate(parentHeader, spec); + bool allowed = tx.MaxFeePerGas >= baseFee; return allowed ? AcceptTxResult.Accepted : AcceptTxResult.FeeTooLow.WithMessage( From 41b055b73693625e4fbf198874351294fff3b5cb Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 14:20:41 +0100 Subject: [PATCH 216/255] Update OP Superchain chains (#10178) Co-authored-by: emlautarom1 Co-authored-by: Lukasz Rozmej --- src/Nethermind/Nethermind.Runner/configs/arena-z-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/arena-z-sepolia.json | 4 ++-- .../Nethermind.Runner/configs/automata-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/base-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/base-sepolia.json | 2 +- src/Nethermind/Nethermind.Runner/configs/bob-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/boba-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/boba-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/camp-sepolia.json | 4 ++-- .../Nethermind.Runner/configs/celo-sep-sepolia.json | 2 +- src/Nethermind/Nethermind.Runner/configs/cyber-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/cyber-sepolia.json | 2 +- .../Nethermind.Runner/configs/ethernity-mainnet.json | 2 +- .../Nethermind.Runner/configs/ethernity-sepolia.json | 2 +- src/Nethermind/Nethermind.Runner/configs/fraxtal-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/funki-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/funki-sepolia.json | 2 +- .../Nethermind.Runner/configs/hashkeychain-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/ink-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/ink-sepolia.json | 2 +- src/Nethermind/Nethermind.Runner/configs/lisk-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/lisk-sepolia.json | 2 +- src/Nethermind/Nethermind.Runner/configs/lyra-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/metal-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/metal-sepolia.json | 2 +- src/Nethermind/Nethermind.Runner/configs/mint-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/mode-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/mode-sepolia.json | 2 +- src/Nethermind/Nethermind.Runner/configs/op-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/op-sepolia.json | 2 +- src/Nethermind/Nethermind.Runner/configs/orderly-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/ozean-sepolia.json | 2 +- src/Nethermind/Nethermind.Runner/configs/pivotal-sepolia.json | 2 +- .../Nethermind.Runner/configs/polynomial-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/race-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/race-sepolia.json | 2 +- .../Nethermind.Runner/configs/redstone-mainnet.json | 2 +- .../Nethermind.Runner/configs/settlus-mainnet-mainnet.json | 2 +- .../Nethermind.Runner/configs/settlus-sepolia-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/shape-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/shape-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/soneium-mainnet.json | 2 +- .../Nethermind.Runner/configs/soneium-minato-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sseed-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/swan-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/swell-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/tbn-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/tbn-sepolia.json | 2 +- .../Nethermind.Runner/configs/unichain-mainnet.json | 2 +- .../Nethermind.Runner/configs/unichain-sepolia.json | 2 +- .../Nethermind.Runner/configs/worldchain-mainnet.json | 2 +- .../Nethermind.Runner/configs/worldchain-sepolia.json | 2 +- .../Nethermind.Runner/configs/xterio-eth-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/zora-mainnet.json | 2 +- src/Nethermind/Nethermind.Runner/configs/zora-sepolia.json | 2 +- 55 files changed, 67 insertions(+), 67 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/arena-z-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/arena-z-mainnet.json index a8c3e9a1a32..bab58793cb5 100644 --- a/src/Nethermind/Nethermind.Runner/configs/arena-z-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/arena-z-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://rpc.arena-z.gg" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/arena-z-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/arena-z-sepolia.json index 44960241092..e5f4106176c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/arena-z-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/arena-z-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://testnet-rpc.arena-z.gg" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/automata-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/automata-mainnet.json index 58e2b9de89b..c30c764476e 100644 --- a/src/Nethermind/Nethermind.Runner/configs/automata-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/automata-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://automata-mainnet.alt.technology/" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index f6d3814d72a..5a66cd8000d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000, + "FastSyncCatchUpHeightDelta": "10000000000", "PivotNumber": 40640000, "PivotHash": "0xd110a315f31ff7cde0073f4203a212636b0aaaa5d2b07dc4534a4f92affefedb" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index c5fa0b70cf9..093765e4036 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000, + "FastSyncCatchUpHeightDelta": "10000000000", "PivotNumber": 36150000, "PivotHash": "0x0b006a487ea3bc9197eb847f9a1baaa8de1b6c5ab3bf12eb775deb15f2da243b" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/bob-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/bob-mainnet.json index de9ab8e3207..d79f8353c61 100644 --- a/src/Nethermind/Nethermind.Runner/configs/bob-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/bob-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/boba-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/boba-mainnet.json index 04edc8fadbe..3343389f324 100644 --- a/src/Nethermind/Nethermind.Runner/configs/boba-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/boba-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://mainnet.boba.network" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/boba-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/boba-sepolia.json index 7c959010a94..c488fa4552f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/boba-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/boba-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://sepolia.boba.network" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/camp-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/camp-sepolia.json index 3a77232fae2..2bcfaa686a5 100644 --- a/src/Nethermind/Nethermind.Runner/configs/camp-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/camp-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://rpc.camp-network-testnet.gelato.digital" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json index 412aa76db8d..6452392575c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/celo-sep-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/cyber-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/cyber-mainnet.json index 0cbf9321894..bd2a0fb4c36 100644 --- a/src/Nethermind/Nethermind.Runner/configs/cyber-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/cyber-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/cyber-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/cyber-sepolia.json index 1d2025dbfc6..2873df985ed 100644 --- a/src/Nethermind/Nethermind.Runner/configs/cyber-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/cyber-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/ethernity-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/ethernity-mainnet.json index 6098c3a4592..a0da27de9c7 100644 --- a/src/Nethermind/Nethermind.Runner/configs/ethernity-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/ethernity-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/ethernity-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/ethernity-sepolia.json index d59c3c57b0f..0fcb8d3694c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/ethernity-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/ethernity-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/fraxtal-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/fraxtal-mainnet.json index 91c9b400916..3d0f5f85f91 100644 --- a/src/Nethermind/Nethermind.Runner/configs/fraxtal-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/fraxtal-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/funki-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/funki-mainnet.json index a065f1ef7f1..03f3a9f72cf 100644 --- a/src/Nethermind/Nethermind.Runner/configs/funki-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/funki-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/funki-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/funki-sepolia.json index 9c5f4864d3a..43684359e3c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/funki-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/funki-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/hashkeychain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/hashkeychain-mainnet.json index 0c33c128bfa..2e2ec620d81 100644 --- a/src/Nethermind/Nethermind.Runner/configs/hashkeychain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/hashkeychain-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/ink-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/ink-mainnet.json index d6651db31ec..b60ad9afb77 100644 --- a/src/Nethermind/Nethermind.Runner/configs/ink-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/ink-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/ink-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/ink-sepolia.json index 736d7db6b9e..03e7b161e4c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/ink-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/ink-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/lisk-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/lisk-mainnet.json index 062eb61cf07..328cff8f05a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/lisk-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/lisk-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/lisk-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/lisk-sepolia.json index c074053666b..d21a5722f34 100644 --- a/src/Nethermind/Nethermind.Runner/configs/lisk-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/lisk-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/lyra-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/lyra-mainnet.json index 1a8af9d222d..f78b7f1ad24 100644 --- a/src/Nethermind/Nethermind.Runner/configs/lyra-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/lyra-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://rpc.lyra.finance" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/metal-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/metal-mainnet.json index 6a2ee18ce7c..7c217972a0f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/metal-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/metal-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/metal-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/metal-sepolia.json index 9eb0d621ab1..f1c84bb655f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/metal-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/metal-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/mint-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mint-mainnet.json index 3ea8b656f21..21d524f4daf 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mint-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mint-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/mode-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mode-mainnet.json index c08a2fe4380..838b1b051c4 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mode-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mode-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/mode-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/mode-sepolia.json index d6a2340b72c..08474c9cc0f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mode-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/mode-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index 0b534e2f7d5..911d8a1c472 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000, + "FastSyncCatchUpHeightDelta": "10000000000", "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, "PivotNumber": 146230000, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index ac96069b3c6..f934cee8c4e 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000, + "FastSyncCatchUpHeightDelta": "10000000000", "PivotNumber": 38130000, "PivotHash": "0xd6821e58d2ec675660f8abf3e3abef108ced0ebc63737e0f718925a87acc5ac8" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/orderly-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/orderly-mainnet.json index 3aac45e5d24..52c3b27c3ca 100644 --- a/src/Nethermind/Nethermind.Runner/configs/orderly-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/orderly-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/ozean-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/ozean-sepolia.json index a0dad90d46a..a38c80ae97e 100644 --- a/src/Nethermind/Nethermind.Runner/configs/ozean-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/ozean-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/pivotal-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/pivotal-sepolia.json index a06fdc39b8c..8dda3a43954 100644 --- a/src/Nethermind/Nethermind.Runner/configs/pivotal-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/pivotal-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/polynomial-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/polynomial-mainnet.json index 5e80eecda0d..3d90623e18f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/polynomial-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/polynomial-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/race-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/race-mainnet.json index 68ed6cd4cf0..7daa781170f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/race-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/race-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/race-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/race-sepolia.json index 8fd9fb4acee..26f827d313c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/race-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/race-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/redstone-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/redstone-mainnet.json index 98d54970e0e..c567b0e6127 100644 --- a/src/Nethermind/Nethermind.Runner/configs/redstone-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/redstone-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/settlus-mainnet-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/settlus-mainnet-mainnet.json index 1b870437826..1e8a3d93b86 100644 --- a/src/Nethermind/Nethermind.Runner/configs/settlus-mainnet-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/settlus-mainnet-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/settlus-sepolia-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/settlus-sepolia-sepolia.json index 15c0149a964..e56a98d2720 100644 --- a/src/Nethermind/Nethermind.Runner/configs/settlus-sepolia-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/settlus-sepolia-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://settlus-sep-testnet-sequencer.g.alchemy.com/" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/shape-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/shape-mainnet.json index da9ccc1845c..a6b15850740 100644 --- a/src/Nethermind/Nethermind.Runner/configs/shape-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/shape-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://shape-mainnet-sequencer.g.alchemy.com" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/shape-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/shape-sepolia.json index faa5eb85959..8cded2c56e9 100644 --- a/src/Nethermind/Nethermind.Runner/configs/shape-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/shape-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://shape-sepolia-sequencer.g.alchemy.com" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/soneium-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/soneium-mainnet.json index 3d246d647bc..ae9a769fb31 100644 --- a/src/Nethermind/Nethermind.Runner/configs/soneium-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/soneium-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/soneium-minato-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/soneium-minato-sepolia.json index 92e05621ad1..5768e1879a6 100644 --- a/src/Nethermind/Nethermind.Runner/configs/soneium-minato-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/soneium-minato-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://rpc.minato.soneium.org" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/sseed-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/sseed-mainnet.json index 1000203289d..128a3cdb0c3 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sseed-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/sseed-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" @@ -34,4 +34,4 @@ "Optimism": { "SequencerUrl": "https://mainnet.superseed.xyz" } -} +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/swan-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/swan-mainnet.json index f5c31feaf49..43553239008 100644 --- a/src/Nethermind/Nethermind.Runner/configs/swan-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/swan-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/swell-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/swell-mainnet.json index 0e11106aae7..86b70258293 100644 --- a/src/Nethermind/Nethermind.Runner/configs/swell-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/swell-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/tbn-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/tbn-mainnet.json index 25f3a8f8930..c7c28891363 100644 --- a/src/Nethermind/Nethermind.Runner/configs/tbn-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/tbn-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/tbn-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/tbn-sepolia.json index 1d294e96314..22462abfc6f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/tbn-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/tbn-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/unichain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/unichain-mainnet.json index db237391970..9239c6afe4f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/unichain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/unichain-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/unichain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/unichain-sepolia.json index 83a206258c8..8f751367852 100644 --- a/src/Nethermind/Nethermind.Runner/configs/unichain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/unichain-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index 501b93805d9..85d2a54732a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000, + "FastSyncCatchUpHeightDelta": "10000000000", "PivotNumber": 24360000, "PivotHash": "0x6c135c9b8c463f10a4e52ca08b05c732af6f5b753d26bee65009ab4eabb7b8c6" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index c0c318f1e87..cfdf41675a0 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000, + "FastSyncCatchUpHeightDelta": "10000000000", "PivotNumber": 23760000, "PivotHash": "0x7256f30608e0e27979b11d13e385b98999979881b6e49aec6670c73d377bccef" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/xterio-eth-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/xterio-eth-mainnet.json index 593b4b1f909..7e2e6907cfb 100644 --- a/src/Nethermind/Nethermind.Runner/configs/xterio-eth-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/xterio-eth-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/zora-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/zora-mainnet.json index bb02d09fcf5..0fc8a6d876c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/zora-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/zora-mainnet.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/zora-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/zora-sepolia.json index 00c020b35de..31eb7c42128 100644 --- a/src/Nethermind/Nethermind.Runner/configs/zora-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/zora-sepolia.json @@ -12,7 +12,7 @@ "Sync": { "FastSync": true, "SnapSync": true, - "FastSyncCatchUpHeightDelta": 10000000000 + "FastSyncCatchUpHeightDelta": "10000000000" }, "Discovery": { "DiscoveryVersion": "V5" From 768923dae4bf28a2f2909d45c0b0d1fded99b2a1 Mon Sep 17 00:00:00 2001 From: "fuder.eth" Date: Wed, 14 Jan 2026 15:24:56 +0200 Subject: [PATCH 217/255] Remove redundant static metadata from `CachedPrecompile` wrapper (#10225) Update CachedCodeInfoRepository.cs Co-authored-by: Lukasz Rozmej --- .../Nethermind.Blockchain/CachedCodeInfoRepository.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/CachedCodeInfoRepository.cs b/src/Nethermind/Nethermind.Blockchain/CachedCodeInfoRepository.cs index 9da126d68fa..59b11b6e67c 100644 --- a/src/Nethermind/Nethermind.Blockchain/CachedCodeInfoRepository.cs +++ b/src/Nethermind/Nethermind.Blockchain/CachedCodeInfoRepository.cs @@ -68,10 +68,6 @@ private class CachedPrecompile( IPrecompile precompile, ConcurrentDictionary> cache) : IPrecompile { - public static Address Address => Address.Zero; - - public static string Name => ""; - public long BaseGasCost(IReleaseSpec releaseSpec) => precompile.BaseGasCost(releaseSpec); public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec) => precompile.DataGasCost(inputData, releaseSpec); From 893d7dc371b09fc35e607ab26d7c43920036e358 Mon Sep 17 00:00:00 2001 From: Maxim Evtush <154841002+maximevtush@users.noreply.github.com> Date: Wed, 14 Jan 2026 15:27:32 +0200 Subject: [PATCH 218/255] refactor: extract duplicate chain ID retrieval logic in SendBlobs CLI (#10150) Update SetupCli.cs --- tools/SendBlobs/SetupCli.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/SendBlobs/SetupCli.cs b/tools/SendBlobs/SetupCli.cs index 7e3731a9ce1..99b00d5e260 100644 --- a/tools/SendBlobs/SetupCli.cs +++ b/tools/SendBlobs/SetupCli.cs @@ -201,8 +201,7 @@ public static void SetupDistributeCommand(Command root) parseResult.GetValue(rpcUrlOption)!, SimpleConsoleLogManager.Instance.GetClassLogger()); - string? chainIdString = await rpcClient.Post("eth_chainId") ?? "1"; - ulong chainId = HexConvert.ToUInt64(chainIdString); + ulong chainId = await GetChainIdAsync(rpcClient); Signer signer = new(chainId, new PrivateKey(parseResult.GetValue(privateKeyOption)!), SimpleConsoleLogManager.Instance); @@ -264,8 +263,7 @@ public static void SetupReclaimCommand(Command root) parseResult.GetValue(rpcUrlOption)!, SimpleConsoleLogManager.Instance.GetClassLogger()); - string? chainIdString = await rpcClient.Post("eth_chainId") ?? "1"; - ulong chainId = HexConvert.ToUInt64(chainIdString); + ulong chainId = await GetChainIdAsync(rpcClient); FundsDistributor distributor = new(rpcClient, chainId, parseResult.GetValue(keyFileOption), SimpleConsoleLogManager.Instance); await distributor.ReclaimFunds( @@ -276,6 +274,12 @@ await distributor.ReclaimFunds( root.Add(command); } + private static async Task GetChainIdAsync(IJsonRpcClient rpcClient) + { + string? chainIdString = await rpcClient.Post("eth_chainId") ?? "1"; + return HexConvert.ToUInt64(chainIdString); + } + public static IJsonRpcClient InitRpcClient(string rpcUrl, ILogger logger) => new BasicJsonRpcClient( new Uri(rpcUrl), From e9b1b381a608867e755388ef134ecdcb821c03b2 Mon Sep 17 00:00:00 2001 From: MoNyAvA Date: Wed, 14 Jan 2026 14:43:02 +0100 Subject: [PATCH 219/255] perf: avoid eager client id formatting in ZeroNettyP2PHandler (#10189) * perf: avoid eager client id formatting in ZeroNettyP2PHandler * Update src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroNettyP2PHandler.cs Co-authored-by: Lukasz Rozmej * add GetClientId and remove duplication * Apply suggestions from code review * Apply suggestion from @LukaszRozmej --------- Co-authored-by: Lukasz Rozmej --- .../P2P/ProtocolHandlers/ZeroNettyP2PHandler.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroNettyP2PHandler.cs b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroNettyP2PHandler.cs index 436b97980b0..df1e7650381 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroNettyP2PHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroNettyP2PHandler.cs @@ -106,14 +106,13 @@ protected override void ChannelRead0(IChannelHandlerContext ctx, ZeroPacket inpu public override void ExceptionCaught(IChannelHandlerContext context, Exception exception) { //In case of SocketException we log it as debug to avoid noise - string clientId = _session?.Node?.ToString(Node.Format.Console) ?? $"unknown {_session?.RemoteHost}"; if (exception is SocketException) { - if (_logger.IsTrace) _logger.Trace($"Error in communication with {clientId} (SocketException): {exception}"); + if (_logger.IsTrace) _logger.Trace($"Error in communication with {GetClientId(_session)} (SocketException): {exception}"); } else { - if (_logger.IsDebug) _logger.Debug($"Error in communication with {clientId}: {exception}"); + if (_logger.IsDebug) _logger.Debug($"Error in communication with {GetClientId(_session)}: {exception}"); } if (exception is IInternalNethermindException) @@ -122,8 +121,7 @@ public override void ExceptionCaught(IChannelHandlerContext context, Exception e } else if (_session?.Node?.IsStatic != true) { - _session.InitiateDisconnect(DisconnectReason.Exception, - $"Error in communication with {clientId} ({exception.GetType().Name}): {exception.Message}"); + _session.InitiateDisconnect(DisconnectReason.Exception, $"Error in communication with {GetClientId(_session)} ({exception.GetType().Name}): {exception.Message}"); } else { @@ -131,6 +129,9 @@ public override void ExceptionCaught(IChannelHandlerContext context, Exception e } } + private static string GetClientId(ISession? session) => + session?.Node?.ToString(Node.Format.Console) ?? $"unknown {session?.RemoteHost}"; + public void EnableSnappy() { SnappyEnabled = true; From 2a985c8dad9161b962185c010695984323d92d00 Mon Sep 17 00:00:00 2001 From: VolodymyrBg Date: Wed, 14 Jan 2026 15:43:23 +0200 Subject: [PATCH 220/255] fix: align storage tracing flag for ReportStorageChange (#10201) Co-authored-by: Lukasz Rozmej --- src/Nethermind/Nethermind.Evm/Tracing/CancellationTxTracer.cs | 2 +- src/Nethermind/Nethermind.Evm/Tracing/CompositeTxTracer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/Tracing/CancellationTxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/CancellationTxTracer.cs index 7a2db1770ee..206f7729156 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/CancellationTxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/CancellationTxTracer.cs @@ -310,7 +310,7 @@ public void ReportMemoryChange(UInt256 offset, byte data) public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) { token.ThrowIfCancellationRequested(); - if (innerTracer.IsTracingInstructions) + if (innerTracer.IsTracingStorage) { innerTracer.ReportStorageChange(key, value); } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/CompositeTxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/CompositeTxTracer.cs index 0a1d8100b02..d341d6c6c4a 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/CompositeTxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/CompositeTxTracer.cs @@ -313,7 +313,7 @@ public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan for (int index = 0; index < _txTracers.Count; index++) { ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + if (innerTracer.IsTracingStorage) { innerTracer.ReportStorageChange(key, value); } From 107a251ec77a572f2f512ca8eae324c104e43460 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Wed, 14 Jan 2026 19:16:59 +0530 Subject: [PATCH 221/255] fix(test-runner): Use maxPriorityFeePerGas for EIP-1559 state test parsing (#10205) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For EIP-1559+ transactions, GasPrice is aliased to MaxPriorityFeePerGas in go-ethereum. When parsing state tests, use maxPriorityFeePerGas from JSON when available, falling back to maxFeePerGas if not specified. This aligns Nethermind's state test parsing behavior with go-ethereum. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Co-authored-by: Alexey Osipov Co-authored-by: Lukasz Rozmej --- src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs index 36b05b9fb0e..4c7c5d6317e 100644 --- a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs +++ b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs @@ -155,7 +155,12 @@ public static Transaction Convert(PostStateJson postStateJson, TransactionJson t transaction.AccessList = null; if (transactionJson.MaxFeePerGas is not null) + { transaction.Type = TxType.EIP1559; + // For EIP-1559+ transactions, GasPrice is aliased to MaxPriorityFeePerGas. + // Use maxPriorityFeePerGas from JSON, falling back to maxFeePerGas per go-ethereum behavior. + transaction.GasPrice = transactionJson.MaxPriorityFeePerGas ?? transactionJson.MaxFeePerGas.Value; + } if (transaction.BlobVersionedHashes?.Length > 0) transaction.Type = TxType.Blob; From 66589860c98b178c6a0b3e99a01beda38dbb50be Mon Sep 17 00:00:00 2001 From: radik878 Date: Wed, 14 Jan 2026 15:47:35 +0200 Subject: [PATCH 222/255] fix: gRPC client reconnect to shutdown previous channel (#10156) * fix: gRPC client reconnect to shutdown previous channel * Update src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs --------- Co-authored-by: Lukasz Rozmej --- src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs b/src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs index 5ba7a4b1bc5..2c6fc5e8510 100644 --- a/src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs +++ b/src/Nethermind/Nethermind.Grpc/Clients/GrpcClient.cs @@ -135,7 +135,7 @@ await stream.ResponseStream.MoveNext(cancellationToken)) private async Task TryReconnectAsync() { - _connected = false; + await StopAsync(); _retry++; if (_logger.IsWarn) _logger.Warn($"Retrying ({_retry}) gRPC connection to: '{_address}' in {_reconnectionInterval} ms."); await Task.Delay(_reconnectionInterval); From d712d3b479d40eb905dee4362d24a0513e5f3512 Mon Sep 17 00:00:00 2001 From: 0xFloki Date: Wed, 14 Jan 2026 14:50:27 +0100 Subject: [PATCH 223/255] perf: eliminate redundant allocations in SendData byte normalization (#10154) Update BlobSender.cs --- tools/SendBlobs/BlobSender.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/SendBlobs/BlobSender.cs b/tools/SendBlobs/BlobSender.cs index f4689e7f4e8..71ec7dad2de 100644 --- a/tools/SendBlobs/BlobSender.cs +++ b/tools/SendBlobs/BlobSender.cs @@ -204,9 +204,18 @@ public async Task SendData( bool waitForInclusion, IReleaseSpec spec) { - data = data - .Select((s, i) => i % 32 != 0 ? [s] : (s < 0x73 ? new byte[] { s } : [(byte)(32), s])) - .SelectMany(b => b).ToArray(); + int capacity = data.Length + data.Length / 32; // at most one extra byte per 32-byte chunk + List normalized = new(capacity); + for (int i = 0; i < data.Length; i++) + { + byte value = data[i]; + if (i % 32 == 0 && value >= 0x73) + { + normalized.Add(32); + } + normalized.Add(value); + } + data = normalized.ToArray(); if (waitForInclusion) { From e18ccbfb0cc6fabf7204ee2ba084fbc2f6494ea6 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Wed, 14 Jan 2026 15:50:51 +0200 Subject: [PATCH 224/255] refactor: split ClHealthTrackerTests into separate test methods (#10171) * Update ClHealthTrackerTests.cs * Update ClHealthTrackerTests.cs --------- Co-authored-by: Lukasz Rozmej --- .../ClHealthTrackerTests.cs | 87 +++++++++++++++---- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/src/Nethermind/Nethermind.HealthChecks.Test/ClHealthTrackerTests.cs b/src/Nethermind/Nethermind.HealthChecks.Test/ClHealthTrackerTests.cs index a7169e7e4e8..06b086dff91 100644 --- a/src/Nethermind/Nethermind.HealthChecks.Test/ClHealthTrackerTests.cs +++ b/src/Nethermind/Nethermind.HealthChecks.Test/ClHealthTrackerTests.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Threading.Tasks; using FluentAssertions; using Nethermind.Core; using Nethermind.Logging; @@ -12,44 +11,96 @@ namespace Nethermind.HealthChecks.Test; public class ClHealthTrackerTests { - [Test] - public async Task ClHealthRequestsTracker_multiple_requests() + private const int MaxIntervalSeconds = 300; + + private static ClHealthRequestsTracker CreateHealthTracker(ManualTimestamper timestamper) { - ManualTimestamper timestamper = new(DateTime.Parse("18:23:00")); - await using ClHealthRequestsTracker healthTracker = new( + return new ClHealthRequestsTracker( timestamper, new HealthChecksConfig() { - MaxIntervalClRequestTime = 300 + MaxIntervalClRequestTime = MaxIntervalSeconds }, LimboLogs.Instance); + } + + [Test] + public void CheckClAlive_Initially_ReturnsTrue() + { + ManualTimestamper timestamper = new(DateTime.Parse("18:23:00")); + ClHealthRequestsTracker healthTracker = CreateHealthTracker(timestamper); healthTracker.CheckClAlive().Should().BeTrue(); + } - timestamper.Add(TimeSpan.FromSeconds(299)); - healthTracker.CheckClAlive().Should().BeTrue(); // Not enough time from start + [Test] + public void CheckClAlive_AfterMaxInterval_ReturnsFalse() + { + ManualTimestamper timestamper = new(DateTime.Parse("18:23:00")); + ClHealthRequestsTracker healthTracker = CreateHealthTracker(timestamper); - timestamper.Add(TimeSpan.FromSeconds(2)); - healthTracker.CheckClAlive().Should().BeFalse(); // More than 300 since start + timestamper.Add(TimeSpan.FromSeconds(MaxIntervalSeconds + 1)); + healthTracker.CheckClAlive().Should().BeFalse(); + } + + [Test] + public void CheckClAlive_BeforeMaxInterval_ReturnsTrue() + { + ManualTimestamper timestamper = new(DateTime.Parse("18:23:00")); + ClHealthRequestsTracker healthTracker = CreateHealthTracker(timestamper); + + timestamper.Add(TimeSpan.FromSeconds(MaxIntervalSeconds - 1)); + healthTracker.CheckClAlive().Should().BeTrue(); + } + + [Test] + public void CheckClAlive_AfterForkchoiceUpdated_ResetsTimer() + { + ManualTimestamper timestamper = new(DateTime.Parse("18:23:00")); + ClHealthRequestsTracker healthTracker = CreateHealthTracker(timestamper); + + timestamper.Add(TimeSpan.FromSeconds(MaxIntervalSeconds + 1)); + healthTracker.CheckClAlive().Should().BeFalse(); healthTracker.OnForkchoiceUpdatedCalled(); - healthTracker.CheckClAlive().Should().BeTrue(); // Fcu + healthTracker.CheckClAlive().Should().BeTrue(); + } + + [Test] + public void CheckClAlive_AfterNewPayload_ResetsTimer() + { + ManualTimestamper timestamper = new(DateTime.Parse("18:23:00")); + ClHealthRequestsTracker healthTracker = CreateHealthTracker(timestamper); + + timestamper.Add(TimeSpan.FromSeconds(MaxIntervalSeconds + 1)); + healthTracker.CheckClAlive().Should().BeFalse(); healthTracker.OnNewPayloadCalled(); - healthTracker.CheckClAlive().Should().BeTrue(); // Fcu + Np + healthTracker.CheckClAlive().Should().BeTrue(); + } - timestamper.Add(TimeSpan.FromSeconds(301)); - healthTracker.CheckClAlive().Should().BeFalse(); // Big gap since fcu + Np + [Test] + public void CheckClAlive_WithBothRequests_WorksCorrectly() + { + ManualTimestamper timestamper = new(DateTime.Parse("18:23:00")); + ClHealthRequestsTracker healthTracker = CreateHealthTracker(timestamper); healthTracker.OnForkchoiceUpdatedCalled(); healthTracker.CheckClAlive().Should().BeTrue(); - timestamper.Add(TimeSpan.FromSeconds(301)); - healthTracker.CheckClAlive().Should().BeFalse(); // Big gap - healthTracker.OnNewPayloadCalled(); healthTracker.CheckClAlive().Should().BeTrue(); - timestamper.Add(TimeSpan.FromSeconds(299)); + timestamper.Add(TimeSpan.FromSeconds(MaxIntervalSeconds + 1)); + healthTracker.CheckClAlive().Should().BeFalse(); + } + + [Test] + public void CheckClAlive_AtBoundaryConditions_WorksCorrectly() + { + ManualTimestamper timestamper = new(DateTime.Parse("18:23:00")); + ClHealthRequestsTracker healthTracker = CreateHealthTracker(timestamper); + + timestamper.Add(TimeSpan.FromSeconds(MaxIntervalSeconds - 1)); healthTracker.OnForkchoiceUpdatedCalled(); healthTracker.CheckClAlive().Should().BeTrue(); From b4a3b21eb3b183ab89cb82159f86a5c4ef9a7e93 Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Wed, 14 Jan 2026 14:56:47 +0100 Subject: [PATCH 225/255] Optimize `PathUtils` (#10219) --- .../Nethermind.Logging/PathUtils.cs | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/src/Nethermind/Nethermind.Logging/PathUtils.cs b/src/Nethermind/Nethermind.Logging/PathUtils.cs index 564d531032a..4e325456370 100644 --- a/src/Nethermind/Nethermind.Logging/PathUtils.cs +++ b/src/Nethermind/Nethermind.Logging/PathUtils.cs @@ -2,31 +2,14 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Diagnostics; using System.IO; using System.Linq; -using System.Reflection; namespace Nethermind.Logging; public static class PathUtils { - public static string ExecutingDirectory { get; } - - static PathUtils() - { - Process process = Process.GetCurrentProcess(); - if (process.ProcessName.StartsWith("dotnet", StringComparison.OrdinalIgnoreCase) - || process.ProcessName.Equals("ReSharperTestRunner", StringComparison.OrdinalIgnoreCase)) - { - ExecutingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - } - else - { - ExecutingDirectory = Path.GetDirectoryName(process.MainModule.FileName); - //Console.WriteLine($"Resolved executing directory as {ExecutingDirectory}."); - } - } + public static string ExecutingDirectory { get; } = Path.GetDirectoryName(Environment.ProcessPath); public static string GetApplicationResourcePath(this string resourcePath, string overridePrefixPath = null) { @@ -50,13 +33,13 @@ public static string GetApplicationResourcePath(this string resourcePath, string : Path.Combine(ExecutingDirectory, overridePrefixPath, resourcePath); } - static readonly string[] RelativePrefixes = new[] + static readonly string[] RelativePrefixes = [.. new[] { - "." + Path.DirectorySeparatorChar, - "." + Path.AltDirectorySeparatorChar, - ".." + Path.DirectorySeparatorChar, - ".." + Path.AltDirectorySeparatorChar, - }.Distinct().ToArray(); + $".{Path.DirectorySeparatorChar}", + $".{Path.AltDirectorySeparatorChar}", + $"..{Path.DirectorySeparatorChar}", + $"..{Path.AltDirectorySeparatorChar}", + }.Distinct()]; public static bool IsExplicitlyRelative(string resourcePath) => RelativePrefixes.Any(resourcePath.StartsWith); } From bb28606bfc65adf60fc3d9e1cb78b7d891f91141 Mon Sep 17 00:00:00 2001 From: FT <140458077+zeevick10@users.noreply.github.com> Date: Wed, 14 Jan 2026 15:24:30 +0100 Subject: [PATCH 226/255] Use `ConcurrentDictionary.GetOrAdd` in `Session` to avoid manual get-or-add logic (#10229) Update Session.cs --- src/Nethermind/Nethermind.Network/P2P/Session.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Nethermind/Nethermind.Network/P2P/Session.cs b/src/Nethermind/Nethermind.Network/P2P/Session.cs index a9d07402c3f..7faaee20745 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Session.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Session.cs @@ -553,15 +553,10 @@ public void AddProtocolHandler(IProtocolHandler handler) private AdaptiveCodeResolver GetOrCreateResolver() { string key = string.Join(":", _protocols.Select(static p => p.Value.Name).OrderBy(static x => x)); - if (!_resolvers.TryGetValue(key, out AdaptiveCodeResolver value)) - { - value = _resolvers.AddOrUpdate( - key, - addValueFactory: (k) => new AdaptiveCodeResolver(_protocols), - updateValueFactory: (k, v) => v); - } - - return value; + return _resolvers.GetOrAdd( + key, + static (_, protocols) => new AdaptiveCodeResolver(protocols), + _protocols); } public override string ToString() From 0d3c48e043ac0f45431866cd860bf8b92a9ecb75 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Wed, 14 Jan 2026 09:24:59 -0500 Subject: [PATCH 227/255] Allow some delays to be configurable (#10227) * Allow some delays to be configurable * Always async * Formatting * Update src/Nethermind/Nethermind.Merge.Plugin/IMergeConfig.cs Co-authored-by: Ruben Buniatyan * Update src/Nethermind/Nethermind.Db/IPruningConfig.cs Co-authored-by: Ruben Buniatyan --------- Co-authored-by: Ruben Buniatyan --- src/Nethermind/Nethermind.Db/IPruningConfig.cs | 3 +++ src/Nethermind/Nethermind.Db/PruningConfig.cs | 1 + .../Nethermind.Merge.Plugin/GC/GCKeeper.cs | 13 ++++++++++++- .../Nethermind.Merge.Plugin/GC/IGCStrategy.cs | 1 + .../Nethermind.Merge.Plugin/GC/NoGCStrategy.cs | 1 + .../GC/NoSyncGcRegionStrategy.cs | 3 +++ .../Nethermind.Merge.Plugin/IMergeConfig.cs | 3 +++ .../Nethermind.Merge.Plugin/MergeConfig.cs | 1 + src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs | 13 ++++++++++++- 9 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Db/IPruningConfig.cs b/src/Nethermind/Nethermind.Db/IPruningConfig.cs index 476042605a3..9503a26a15d 100644 --- a/src/Nethermind/Nethermind.Db/IPruningConfig.cs +++ b/src/Nethermind/Nethermind.Db/IPruningConfig.cs @@ -103,4 +103,7 @@ The max number of parallel tasks that can be used by full pruning. [ConfigItem(Description = "[TECHNICAL] Simulate long finalization by not moving finalized block pointer until after this depth.", DefaultValue = "0", HiddenFromDocs = true)] int SimulateLongFinalizationDepth { get; set; } + + [ConfigItem(Description = "If in-memory pruning is scheduled, the duration between `newPayload` and the GC trigger. If too short, it may clash with fork choice; if too long, it may overlap with GC.", DefaultValue = "75", HiddenFromDocs = true)] + int PruneDelayMilliseconds { get; set; } } diff --git a/src/Nethermind/Nethermind.Db/PruningConfig.cs b/src/Nethermind/Nethermind.Db/PruningConfig.cs index 76a0296cb5f..593e2289b92 100644 --- a/src/Nethermind/Nethermind.Db/PruningConfig.cs +++ b/src/Nethermind/Nethermind.Db/PruningConfig.cs @@ -64,5 +64,6 @@ public int DirtyNodeShardBit public long MinUnpersistedBlockCount { get; set; } = 8; // About slightly more than 1 minute public int MaxBufferedCommitCount { get; set; } = 128; public int SimulateLongFinalizationDepth { get; set; } = 0; + public int PruneDelayMilliseconds { get; set; } = 75; } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs index 6dbd20f8cff..fc9276f0fad 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs @@ -17,6 +17,7 @@ public class GCKeeper private static ulong _forcedGcCount = 0; private readonly Lock _lock = new(); private readonly IGCStrategy _gcStrategy; + private readonly int _postBlockDelayMs; private readonly ILogger _logger; private static readonly long _defaultSize = 512.MB(); private Task _gcScheduleTask = Task.CompletedTask; @@ -25,6 +26,7 @@ public class GCKeeper public GCKeeper(IGCStrategy gcStrategy, ILogManager logManager) { _gcStrategy = gcStrategy; + _postBlockDelayMs = gcStrategy.PostBlockDelayMs; _logger = logManager.GetClassLogger(); _tryStartNoGCRegionFunc = TryStartNoGCRegion; } @@ -155,7 +157,16 @@ private async Task ScheduleGCInternal() // This should give time to finalize response in Engine API // Normally we should get block every 12s (5s on some chains) // Lets say we process block in 2s, then delay 125ms, then invoke GC - await Task.Delay(125); + int postBlockDelayMs = _postBlockDelayMs; + if (postBlockDelayMs <= 0) + { + // Always async + await Task.Yield(); + } + else + { + await Task.Delay(postBlockDelayMs); + } if (GCSettings.LatencyMode != GCLatencyMode.NoGCRegion) { diff --git a/src/Nethermind/Nethermind.Merge.Plugin/GC/IGCStrategy.cs b/src/Nethermind/Nethermind.Merge.Plugin/GC/IGCStrategy.cs index 42d8012f590..d71d267db7f 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/GC/IGCStrategy.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/GC/IGCStrategy.cs @@ -8,6 +8,7 @@ namespace Nethermind.Merge.Plugin.GC; public interface IGCStrategy { int CollectionsPerDecommit { get; } + int PostBlockDelayMs { get; } bool CanStartNoGCRegion(); (GcLevel Generation, GcCompaction Compacting) GetForcedGCParams(); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/GC/NoGCStrategy.cs b/src/Nethermind/Nethermind.Merge.Plugin/GC/NoGCStrategy.cs index 3a92c3e366c..043b09109d8 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/GC/NoGCStrategy.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/GC/NoGCStrategy.cs @@ -7,6 +7,7 @@ public class NoGCStrategy : IGCStrategy { public static readonly NoGCStrategy Instance = new(); public int CollectionsPerDecommit => -1; + public int PostBlockDelayMs => 0; public bool CanStartNoGCRegion() => false; public (GcLevel Generation, GcCompaction Compacting) GetForcedGCParams() => (GcLevel.NoGC, GcCompaction.No); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/GC/NoSyncGcRegionStrategy.cs b/src/Nethermind/Nethermind.Merge.Plugin/GC/NoSyncGcRegionStrategy.cs index fcc3ea994b0..3aee165f6e6 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/GC/NoSyncGcRegionStrategy.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/GC/NoSyncGcRegionStrategy.cs @@ -20,9 +20,12 @@ public NoSyncGcRegionStrategy(ISyncModeSelector syncModeSelector, IMergeConfig m GcLevel gcLevel = (GcLevel)Math.Min((int)GcLevel.Gen2, (int)mergeConfig.SweepMemory); GcCompaction gcCompaction = (GcCompaction)Math.Min((int)GcCompaction.Full, (int)mergeConfig.CompactMemory); _gcParams = (gcLevel, gcCompaction); + PostBlockDelayMs = mergeConfig.PostBlockGcDelayMs ?? (int)((mergeConfig.SecondsPerSlot * 1000) / 8); } public int CollectionsPerDecommit { get; } + public int PostBlockDelayMs { get; } + public bool CanStartNoGCRegion() => _canStartNoGCRegion && _syncModeSelector.Current == SyncMode.WaitingForBlock; public (GcLevel, GcCompaction) GetForcedGCParams() => _gcParams; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/IMergeConfig.cs b/src/Nethermind/Nethermind.Merge.Plugin/IMergeConfig.cs index c737e54c232..d2b5ce16536 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/IMergeConfig.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/IMergeConfig.cs @@ -72,4 +72,7 @@ The number of requests to the garbage collector (GC) to release the process memo [ConfigItem(Description = "[TECHNICAL] Simulate block production for every possible slot. Just for stress-testing purposes.", DefaultValue = "false", HiddenFromDocs = true)] bool SimulateBlockProduction { get; set; } + + [ConfigItem(Description = "Delay, in milliseconds, between `newPayload` and GC trigger. If not set, defaults to 1/8th of `Blocks.SecondsPerSlot`.", DefaultValue = null, HiddenFromDocs = true)] + int? PostBlockGcDelayMs { get; set; } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergeConfig.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergeConfig.cs index 220a25c9705..f5a82770d3d 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergeConfig.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergeConfig.cs @@ -35,5 +35,6 @@ public class MergeConfig : IMergeConfig public int NewPayloadCacheSize { get; set; } = 50; public bool SimulateBlockProduction { get; set; } = false; + public int? PostBlockGcDelayMs { get; set; } = null; } } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index dfa1a361e16..df908804acb 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -32,6 +32,7 @@ public sealed class TrieStore : ITrieStore, IPruningTrieStore private readonly int _maxDepth; private readonly double _prunePersistedNodePortion; private readonly long _prunePersistedNodeMinimumTarget; + private readonly int _pruneDelayMs; private int _isFirst; @@ -91,6 +92,7 @@ public TrieStore( _maxBufferedCommitCount = pruningConfig.MaxBufferedCommitCount; _pastKeyTrackingEnabled = pruningConfig.TrackPastKeys && nodeStorage.RequirePath; + _pruneDelayMs = pruningConfig.PruneDelayMilliseconds; _deleteOldNodes = _pruningStrategy.DeleteObsoleteKeys && _pastKeyTrackingEnabled; _shardBit = pruningConfig.DirtyNodeShardBit; _shardedDirtyNodeCount = 1 << _shardBit; @@ -585,7 +587,16 @@ private async Task TrySyncPrune() // 2. Allow kick off (block processing) some time to finish before starting to prune (prune in block gap) // 3. If we are n+1 Task passing the .IsCompleted check but not going to be first to pass lock, // remain uncompleted for a time to prevent other tasks seeing .IsCompleted and also trying to queue. - await Task.Delay(10); + int pruneDelayMs = _pruneDelayMs; + if (pruneDelayMs <= 0) + { + // Always async + await Task.Yield(); + } + else + { + await Task.Delay(pruneDelayMs); + } if (!_pruningLock.TryEnter()) { From 538d53fd504564b4afe68898cb3301779e337ebb Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Wed, 14 Jan 2026 17:50:24 -0500 Subject: [PATCH 228/255] Schedule largest storage changes first (#10236) * Schedule largest storage changes first * Feedback --- .../Nethermind.State/PersistentStorageProvider.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs index 1f6c4af48de..1891b69b12e 100644 --- a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs +++ b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs @@ -275,6 +275,10 @@ void UpdateRootHashesMultiThread() { // We can recalculate the roots in parallel as they are all independent tries using ArrayPoolList<(AddressAsKey Key, PerContractState ContractState, IWorldStateScopeProvider.IStorageWriteBatch WriteBatch)> storages = _storages + // Only consider contracts that actually have pending changes + .Where(kv => _toUpdateRoots.TryGetValue(kv.Key, out bool hasChanges) && hasChanges) + // Schedule larger changes first to help balance the work + .OrderByDescending(kv => kv.Value.EstimatedChanges) .Select((kv) => ( kv.Key, kv.Value, @@ -290,12 +294,6 @@ void UpdateRootHashesMultiThread() static (i, state) => { ref var kvp = ref state.storages.GetRef(i); - if (!state.toUpdateRoots.TryGetValue(kvp.Key, out bool hasChanges) || !hasChanges) - { - // Wasn't updated don't recalculate - return state; - } - (int writes, int skipped) = kvp.ContractState.ProcessStorageChanges(kvp.WriteBatch); if (writes == 0) { From 4d58a87c6f3f56075bb68d54b80767e159ffa7e9 Mon Sep 17 00:00:00 2001 From: Snezhkko Date: Thu, 15 Jan 2026 02:59:00 +0200 Subject: [PATCH 229/255] fix: SyncDispatcher leak by disposing CountdownEvent (#10240) --- .../Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs index a62c8a3f699..9770595b696 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs @@ -334,6 +334,7 @@ public async ValueTask DisposeAsync() { if (Logger.IsWarn) Logger.Warn($"Timeout on waiting for active tasks for feed {Feed.GetType().Name} {_activeTasks.CurrentCount}"); } + _activeTasks.Dispose(); _cancellationTokenSource.Dispose(); _concurrentProcessingSemaphore.Dispose(); } From aebf0ec5cdec89112668ee0e9771e5f13f1db737 Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Thu, 15 Jan 2026 08:57:03 +0100 Subject: [PATCH 230/255] Move default implementations out of IReleaseSpec (#10237) * Move default implementations out of IReleaseSpec * fix some test * Update src/Nethermind/Nethermind.Core/Specs/IReleaseSpecExtensions.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix more tests * Cleanup ISpecProvider.GetSpec * fix test * less whitespace --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Spec/ChainHeadSpecProvider.cs | 2 +- .../FixedBlockChainHeadSpecProvider.cs | 2 +- .../Nethermind.Core/Specs/AuRaSpecProvider.cs | 6 +- .../Nethermind.Core/Specs/IReleaseSpec.cs | 104 +----------------- .../Specs/IReleaseSpecExtensions.cs | 70 ++++++++++++ .../Nethermind.Core/Specs/ISpecProvider.cs | 3 +- .../Specs/ReleaseSpecDecorator.cs | 70 +++--------- .../Specs/SpecProviderDecorator.cs | 2 +- .../CodeInfoRepositoryTests.cs | 79 ++++++------- .../Nethermind.Evm.Test/Eip152Tests.cs | 1 + .../Nethermind.Evm.Test/Eip2537Tests.cs | 1 + .../Modules/Eth/EthRpcModuleTests.cs | 2 +- .../ChainSpecBasedSpecProviderTests.cs | 8 +- .../Nethermind.Specs.Test.csproj | 1 + .../OverridableReleaseSpec.cs | 3 +- .../OverridableSpecProvider.cs | 2 +- .../ChainSpecStyle/SpecProviderBase.cs | 2 +- .../Nethermind.Specs/ChiadoSpecProvider.cs | 2 +- .../Nethermind.Specs/FrontierSpecProvider.cs | 2 +- .../Nethermind.Specs/GnosisSpecProvider.cs | 2 +- .../Nethermind.Specs/HoodiSpecProvider.cs | 2 +- .../Nethermind.Specs/MainnetSpecProvider.cs | 2 +- .../Nethermind.Specs/MordenSpecProvider.cs | 2 +- .../Nethermind.Specs/OlympicSpecProvider.cs | 2 +- .../Nethermind.Specs/ReleaseSpec.cs | 1 + .../Nethermind.Specs/SepoliaSpecProvider.cs | 2 +- .../SingleReleaseSpecProvider.cs | 2 +- .../Nethermind.Specs/TestSpecProvider.cs | 2 +- .../TxBroadcasterTests.cs | 9 +- 29 files changed, 151 insertions(+), 237 deletions(-) create mode 100644 src/Nethermind/Nethermind.Core/Specs/IReleaseSpecExtensions.cs diff --git a/src/Nethermind/Nethermind.Blockchain/Spec/ChainHeadSpecProvider.cs b/src/Nethermind/Nethermind.Blockchain/Spec/ChainHeadSpecProvider.cs index b9ddc9f9ae6..7530d72461b 100644 --- a/src/Nethermind/Nethermind.Blockchain/Spec/ChainHeadSpecProvider.cs +++ b/src/Nethermind/Nethermind.Blockchain/Spec/ChainHeadSpecProvider.cs @@ -31,7 +31,7 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public IReleaseSpec GenesisSpec => _specProvider.GenesisSpec; - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => _specProvider.GetSpec(forkActivation); + public IReleaseSpec GetSpec(ForkActivation forkActivation) => _specProvider.GetSpec(forkActivation); public long? DaoBlockNumber => _specProvider.DaoBlockNumber; diff --git a/src/Nethermind/Nethermind.Core.Test/FixedBlockChainHeadSpecProvider.cs b/src/Nethermind/Nethermind.Core.Test/FixedBlockChainHeadSpecProvider.cs index 30b0ca5f7e6..49b43aaf566 100644 --- a/src/Nethermind/Nethermind.Core.Test/FixedBlockChainHeadSpecProvider.cs +++ b/src/Nethermind/Nethermind.Core.Test/FixedBlockChainHeadSpecProvider.cs @@ -23,7 +23,7 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public IReleaseSpec GenesisSpec => specProvider.GenesisSpec; - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => specProvider.GetSpec(forkActivation); + public IReleaseSpec GetSpec(ForkActivation forkActivation) => specProvider.GetSpec(forkActivation); public long? DaoBlockNumber => specProvider.DaoBlockNumber; diff --git a/src/Nethermind/Nethermind.Core/Specs/AuRaSpecProvider.cs b/src/Nethermind/Nethermind.Core/Specs/AuRaSpecProvider.cs index f5d78c4c02a..da4c55202fe 100644 --- a/src/Nethermind/Nethermind.Core/Specs/AuRaSpecProvider.cs +++ b/src/Nethermind/Nethermind.Core/Specs/AuRaSpecProvider.cs @@ -6,10 +6,8 @@ namespace Nethermind.Core.Specs; public class AuRaSpecProvider(ISpecProvider baseSpecProvider) : SpecProviderDecorator(baseSpecProvider) { - public override IReleaseSpec GetSpecInternal(ForkActivation forkActivation) - { - return new AuRaReleaseSpecDecorator(base.GetSpecInternal(forkActivation)); - } + public override IReleaseSpec GetSpec(ForkActivation forkActivation) => + new AuRaReleaseSpecDecorator(base.GetSpec(forkActivation)); } public class AuRaReleaseSpecDecorator(IReleaseSpec spec) : ReleaseSpecDecorator(spec) diff --git a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs index 4894b670596..fdaea1e7339 100644 --- a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs @@ -15,8 +15,6 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec public string Name { get; } long MaximumExtraDataSize { get; } long MaxCodeSize { get; } - //EIP-3860: Limit and meter initcode - long MaxInitCodeSize => 2 * MaxCodeSize; long MinGasLimit { get; } long MinHistoryRetentionEpochs { get; } long GasLimitBoundDivisor { get; } @@ -202,10 +200,8 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec /// /// Should EIP158 be ignored for this account. /// - /// THis is needed for SystemUser account compatibility with Parity. - /// - /// - bool IsEip158IgnoredAccount(Address address) => false; + /// This is needed for SystemUser account compatibility with Parity. + bool IsEip158IgnoredAccount(Address address); /// /// BaseFee opcode @@ -276,14 +272,12 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec /// EIP-6110: Supply validator deposits on chain /// bool IsEip6110Enabled { get; } - bool DepositsEnabled => IsEip6110Enabled; Address DepositContractAddress { get; } /// /// Execution layer triggerable exits /// bool IsEip7002Enabled { get; } - bool WithdrawalRequestsEnabled => IsEip7002Enabled; Address Eip7002ContractAddress { get; } @@ -291,7 +285,6 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec /// EIP-7251: triggered consolidations /// bool IsEip7251Enabled { get; } - bool ConsolidationRequestsEnabled => IsEip7251Enabled; Address Eip7251ContractAddress { get; } @@ -310,7 +303,7 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec /// EIP-2935 ring buffer size for historical block hash storage. /// Defaults to 8,191 blocks for Ethereum mainnet. /// - long Eip2935RingBufferSize => Eip2935Constants.RingBufferSize; + public long Eip2935RingBufferSize { get; } /// /// SELFDESTRUCT only in same transaction @@ -385,7 +378,7 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec /// Should transactions be validated against chainId. /// /// Backward compatibility for early Kovan blocks. - bool ValidateChainId => true; + public bool ValidateChainId { get; } /// /// EIP-7780: Add blob schedule to EL config files @@ -399,84 +392,6 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec public ulong Eip4844TransitionTimestamp { get; } - // STATE related - public bool ClearEmptyAccountWhenTouched => IsEip158Enabled; - - // VM - public bool LimitCodeSize => IsEip170Enabled; - - public bool UseHotAndColdStorage => IsEip2929Enabled; - - public bool UseTxAccessLists => IsEip2930Enabled; - - public bool AddCoinbaseToTxAccessList => IsEip3651Enabled; - - public bool ModExpEnabled => IsEip198Enabled; - - public bool BN254Enabled => IsEip196Enabled && IsEip197Enabled; - - public bool BlakeEnabled => IsEip152Enabled; - - public bool Bls381Enabled => IsEip2537Enabled; - - public bool ChargeForTopLevelCreate => IsEip2Enabled; - - public bool FailOnOutOfGasCodeDeposit => IsEip2Enabled; - - public bool UseShanghaiDDosProtection => IsEip150Enabled; - - public bool UseExpDDosProtection => IsEip160Enabled; - - public bool UseLargeStateDDosProtection => IsEip1884Enabled; - - public bool ReturnDataOpcodesEnabled => IsEip211Enabled; - - public bool ChainIdOpcodeEnabled => IsEip1344Enabled; - - public bool Create2OpcodeEnabled => IsEip1014Enabled; - - public bool DelegateCallEnabled => IsEip7Enabled; - - public bool StaticCallEnabled => IsEip214Enabled; - - public bool ShiftOpcodesEnabled => IsEip145Enabled; - - public bool RevertOpcodeEnabled => IsEip140Enabled; - - public bool ExtCodeHashOpcodeEnabled => IsEip1052Enabled; - - public bool SelfBalanceOpcodeEnabled => IsEip1884Enabled; - - public bool UseConstantinopleNetGasMetering => IsEip1283Enabled; - - public bool UseIstanbulNetGasMetering => IsEip2200Enabled; - - public bool UseNetGasMetering => UseConstantinopleNetGasMetering | UseIstanbulNetGasMetering; - - public bool UseNetGasMeteringWithAStipendFix => UseIstanbulNetGasMetering; - - public bool Use63Over64Rule => UseShanghaiDDosProtection; - - public bool BaseFeeEnabled => IsEip3198Enabled; - - // EVM Related - public bool IncludePush0Instruction => IsEip3855Enabled; - - public bool TransientStorageEnabled => IsEip1153Enabled; - - public bool WithdrawalsEnabled => IsEip4895Enabled; - public bool SelfdestructOnlyOnSameTransaction => IsEip6780Enabled; - - public bool IsBeaconBlockRootAvailable => IsEip4788Enabled; - public bool IsBlockHashInStateAvailable => IsEip7709Enabled; - public bool MCopyIncluded => IsEip5656Enabled; - - public bool BlobBaseFeeEnabled => IsEip4844Enabled; - - bool IsAuthorizationListEnabled => IsEip7702Enabled; - - public bool RequestsEnabled => ConsolidationRequestsEnabled || WithdrawalRequestsEnabled || DepositsEnabled; - public bool IsEip7594Enabled { get; } /// @@ -506,28 +421,17 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec /// public Array? EvmInstructionsTraced { get; set; } - /// - /// Determines whether the specified address is a precompiled contract for this release specification. - /// - /// The address to check for precompile status. - /// True if the address is a precompiled contract; otherwise, false. - bool IsPrecompile(Address address) => Precompiles.Contains(address); - /// /// Gets a cached set of all precompiled contract addresses for this release specification. /// Chain-specific implementations can override this to include their own precompiled contracts. /// FrozenSet Precompiles { get; } - public ProofVersion BlobProofVersion => IsEip7594Enabled ? ProofVersion.V1 : ProofVersion.V0; - /// /// EIP-7939 - CLZ - Count leading zeros instruction /// public bool IsEip7939Enabled { get; } - public bool CLZEnabled => IsEip7939Enabled; - /// /// EIP-7907: Meter Contract Code Size And Increase Limit /// diff --git a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpecExtensions.cs b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpecExtensions.cs new file mode 100644 index 00000000000..ba4d778cac7 --- /dev/null +++ b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpecExtensions.cs @@ -0,0 +1,70 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +namespace Nethermind.Core.Specs; + +/// +/// Extension members for providing computed properties +/// and helper methods based on EIP enablement flags. +/// +public static class IReleaseSpecExtensions +{ + extension(IReleaseSpec spec) + { + //EIP-3860: Limit and meter initcode + public long MaxInitCodeSize => 2 * spec.MaxCodeSize; + public bool DepositsEnabled => spec.IsEip6110Enabled; + public bool WithdrawalRequestsEnabled => spec.IsEip7002Enabled; + public bool ConsolidationRequestsEnabled => spec.IsEip7251Enabled; + // STATE related + public bool ClearEmptyAccountWhenTouched => spec.IsEip158Enabled; + // VM + public bool LimitCodeSize => spec.IsEip170Enabled; + public bool UseHotAndColdStorage => spec.IsEip2929Enabled; + public bool UseTxAccessLists => spec.IsEip2930Enabled; + public bool AddCoinbaseToTxAccessList => spec.IsEip3651Enabled; + public bool ModExpEnabled => spec.IsEip198Enabled; + public bool BN254Enabled => spec.IsEip196Enabled && spec.IsEip197Enabled; + public bool BlakeEnabled => spec.IsEip152Enabled; + public bool Bls381Enabled => spec.IsEip2537Enabled; + public bool ChargeForTopLevelCreate => spec.IsEip2Enabled; + public bool FailOnOutOfGasCodeDeposit => spec.IsEip2Enabled; + public bool UseShanghaiDDosProtection => spec.IsEip150Enabled; + public bool UseExpDDosProtection => spec.IsEip160Enabled; + public bool UseLargeStateDDosProtection => spec.IsEip1884Enabled; + public bool ReturnDataOpcodesEnabled => spec.IsEip211Enabled; + public bool ChainIdOpcodeEnabled => spec.IsEip1344Enabled; + public bool Create2OpcodeEnabled => spec.IsEip1014Enabled; + public bool DelegateCallEnabled => spec.IsEip7Enabled; + public bool StaticCallEnabled => spec.IsEip214Enabled; + public bool ShiftOpcodesEnabled => spec.IsEip145Enabled; + public bool RevertOpcodeEnabled => spec.IsEip140Enabled; + public bool ExtCodeHashOpcodeEnabled => spec.IsEip1052Enabled; + public bool SelfBalanceOpcodeEnabled => spec.IsEip1884Enabled; + public bool UseConstantinopleNetGasMetering => spec.IsEip1283Enabled; + public bool UseIstanbulNetGasMetering => spec.IsEip2200Enabled; + public bool UseNetGasMetering => spec.UseConstantinopleNetGasMetering || spec.UseIstanbulNetGasMetering; + public bool UseNetGasMeteringWithAStipendFix => spec.UseIstanbulNetGasMetering; + public bool Use63Over64Rule => spec.UseShanghaiDDosProtection; + public bool BaseFeeEnabled => spec.IsEip3198Enabled; + // EVM Related + public bool IncludePush0Instruction => spec.IsEip3855Enabled; + public bool TransientStorageEnabled => spec.IsEip1153Enabled; + public bool WithdrawalsEnabled => spec.IsEip4895Enabled; + public bool SelfdestructOnlyOnSameTransaction => spec.IsEip6780Enabled; + public bool IsBeaconBlockRootAvailable => spec.IsEip4788Enabled; + public bool IsBlockHashInStateAvailable => spec.IsEip7709Enabled; + public bool MCopyIncluded => spec.IsEip5656Enabled; + public bool BlobBaseFeeEnabled => spec.IsEip4844Enabled; + public bool IsAuthorizationListEnabled => spec.IsEip7702Enabled; + public bool RequestsEnabled => spec.ConsolidationRequestsEnabled || spec.WithdrawalRequestsEnabled || spec.DepositsEnabled; + /// + /// Determines whether the specified address is a precompiled contract for this release specification. + /// + /// The address to check for precompile status. + /// True if the address is a precompiled contract; otherwise, false. + public bool IsPrecompile(Address address) => spec.Precompiles.Contains(address); + public ProofVersion BlobProofVersion => spec.IsEip7594Enabled ? ProofVersion.V1 : ProofVersion.V0; + public bool CLZEnabled => spec.IsEip7939Enabled; + } +} diff --git a/src/Nethermind/Nethermind.Core/Specs/ISpecProvider.cs b/src/Nethermind/Nethermind.Core/Specs/ISpecProvider.cs index 7abe0168014..76cb758023d 100644 --- a/src/Nethermind/Nethermind.Core/Specs/ISpecProvider.cs +++ b/src/Nethermind/Nethermind.Core/Specs/ISpecProvider.cs @@ -79,12 +79,11 @@ public interface ISpecProvider /// /// /// A spec that is valid at the given chain height - protected internal IReleaseSpec GetSpecInternal(ForkActivation forkActivation); + IReleaseSpec GetSpec(ForkActivation forkActivation); } public static class SpecProviderExtensions { - public static IReleaseSpec GetSpec(this ISpecProvider specProvider, ForkActivation forkActivation) => specProvider.GetSpecInternal(forkActivation); public static IReleaseSpec GetSpec(this ISpecProvider specProvider, long blockNumber, ulong? timestamp) => specProvider.GetSpec(new ForkActivation(blockNumber, timestamp)); public static IReleaseSpec GetSpec(this ISpecProvider specProvider, BlockHeader blockHeader) => specProvider.GetSpec(new ForkActivation(blockHeader.Number, blockHeader.Timestamp)); diff --git a/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs b/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs index 063200b9f34..81200ab400b 100644 --- a/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs +++ b/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs @@ -70,23 +70,25 @@ public class ReleaseSpecDecorator(IReleaseSpec spec) : IReleaseSpec public virtual bool IsEip4895Enabled => spec.IsEip4895Enabled; public virtual bool IsEip4844Enabled => spec.IsEip4844Enabled; public virtual bool IsEip4788Enabled => spec.IsEip4788Enabled; + public virtual bool ValidateChainId => spec.ValidateChainId; public virtual ulong TargetBlobCount => spec.TargetBlobCount; public virtual ulong MaxBlobCount => spec.MaxBlobCount; public virtual ulong MaxBlobsPerTx { get; init; } = spec.MaxBlobsPerTx; public virtual UInt256 BlobBaseFeeUpdateFraction => spec.BlobBaseFeeUpdateFraction; public virtual Address? Eip4788ContractAddress => spec.Eip4788ContractAddress; - public bool IsEip6110Enabled => spec.IsEip6110Enabled; - public Address DepositContractAddress => spec.DepositContractAddress; - public bool IsEip7002Enabled => spec.IsEip7002Enabled; - public Address Eip7002ContractAddress => spec.Eip7002ContractAddress; - public bool IsEip7251Enabled => spec.IsEip7251Enabled; - public Address Eip7251ContractAddress => spec.Eip7251ContractAddress; + public virtual bool IsEip6110Enabled => spec.IsEip6110Enabled; + public virtual Address DepositContractAddress => spec.DepositContractAddress; + public virtual bool IsEip7002Enabled => spec.IsEip7002Enabled; + public virtual Address Eip7002ContractAddress => spec.Eip7002ContractAddress; + public virtual bool IsEip7251Enabled => spec.IsEip7251Enabled; + public virtual Address Eip7251ContractAddress => spec.Eip7251ContractAddress; public virtual bool IsEip2935Enabled => spec.IsEip2935Enabled; public virtual bool IsEip7709Enabled => spec.IsEip7709Enabled; public virtual Address Eip2935ContractAddress => spec.Eip2935ContractAddress; + public virtual long Eip2935RingBufferSize => spec.Eip2935RingBufferSize; public virtual bool IsEip6780Enabled => spec.IsEip6780Enabled; - public bool IsEip7702Enabled => spec.IsEip7702Enabled; - public bool IsEip7823Enabled => spec.IsEip7823Enabled; + public virtual bool IsEip7702Enabled => spec.IsEip7702Enabled; + public virtual bool IsEip7823Enabled => spec.IsEip7823Enabled; public virtual bool IsEip7934Enabled => spec.IsEip7934Enabled; public virtual int Eip7934MaxRlpBlockSize => spec.Eip7934MaxRlpBlockSize; public virtual bool IsEip7951Enabled => spec.IsEip7951Enabled; @@ -103,57 +105,15 @@ public class ReleaseSpecDecorator(IReleaseSpec spec) : IReleaseSpec public virtual ulong Eip4844TransitionTimestamp => spec.Eip4844TransitionTimestamp; public virtual bool IsEofEnabled => spec.IsEofEnabled; public virtual bool IsEip158IgnoredAccount(Address address) => spec.IsEip158IgnoredAccount(address); - public bool IsEip4844FeeCollectorEnabled => spec.IsEip4844FeeCollectorEnabled; - public bool IsEip7594Enabled => spec.IsEip7594Enabled; - - public virtual long MaxInitCodeSize => spec.MaxInitCodeSize; - public virtual bool ValidateChainId => spec.ValidateChainId; - public virtual bool ClearEmptyAccountWhenTouched => spec.ClearEmptyAccountWhenTouched; - // VM - public virtual bool LimitCodeSize => spec.LimitCodeSize; - public virtual bool UseHotAndColdStorage => spec.UseHotAndColdStorage; - public virtual bool UseTxAccessLists => spec.UseTxAccessLists; - public virtual bool AddCoinbaseToTxAccessList => spec.AddCoinbaseToTxAccessList; - public virtual bool ModExpEnabled => spec.ModExpEnabled; - public virtual bool BN254Enabled => spec.BN254Enabled; - public virtual bool BlakeEnabled => spec.BlakeEnabled; - public virtual bool Bls381Enabled => spec.Bls381Enabled; - public virtual bool ChargeForTopLevelCreate => spec.ChargeForTopLevelCreate; - public virtual bool FailOnOutOfGasCodeDeposit => spec.FailOnOutOfGasCodeDeposit; - public virtual bool UseShanghaiDDosProtection => spec.UseShanghaiDDosProtection; - public virtual bool UseExpDDosProtection => spec.UseExpDDosProtection; - public virtual bool UseLargeStateDDosProtection => spec.UseLargeStateDDosProtection; - public virtual bool ReturnDataOpcodesEnabled => spec.ReturnDataOpcodesEnabled; - public virtual bool ChainIdOpcodeEnabled => spec.ChainIdOpcodeEnabled; - public virtual bool Create2OpcodeEnabled => spec.Create2OpcodeEnabled; - public virtual bool DelegateCallEnabled => spec.DelegateCallEnabled; - public virtual bool StaticCallEnabled => spec.StaticCallEnabled; - public virtual bool ShiftOpcodesEnabled => spec.ShiftOpcodesEnabled; - public virtual bool RevertOpcodeEnabled => spec.RevertOpcodeEnabled; - public virtual bool ExtCodeHashOpcodeEnabled => spec.ExtCodeHashOpcodeEnabled; - public virtual bool SelfBalanceOpcodeEnabled => spec.SelfBalanceOpcodeEnabled; - public virtual bool UseConstantinopleNetGasMetering => spec.UseConstantinopleNetGasMetering; - public virtual bool UseIstanbulNetGasMetering => spec.UseIstanbulNetGasMetering; - public virtual bool UseNetGasMetering => spec.UseNetGasMetering; - public virtual bool UseNetGasMeteringWithAStipendFix => spec.UseNetGasMeteringWithAStipendFix; - public virtual bool Use63Over64Rule => spec.Use63Over64Rule; - public virtual bool BaseFeeEnabled => spec.BaseFeeEnabled; - // EVM Related - public virtual bool IncludePush0Instruction => spec.IncludePush0Instruction; - public virtual bool TransientStorageEnabled => spec.TransientStorageEnabled; - public virtual bool WithdrawalsEnabled => spec.WithdrawalsEnabled; - public virtual bool SelfdestructOnlyOnSameTransaction => spec.SelfdestructOnlyOnSameTransaction; - public virtual bool IsBeaconBlockRootAvailable => spec.IsBeaconBlockRootAvailable; - public virtual bool IsBlockHashInStateAvailable => spec.IsBlockHashInStateAvailable; - public virtual bool MCopyIncluded => spec.MCopyIncluded; - public virtual bool BlobBaseFeeEnabled => spec.BlobBaseFeeEnabled; + public virtual bool IsEip4844FeeCollectorEnabled => spec.IsEip4844FeeCollectorEnabled; + public virtual bool IsEip7594Enabled => spec.IsEip7594Enabled; public virtual Address? FeeCollector => spec.FeeCollector; public virtual UInt256? Eip1559BaseFeeMinValue => spec.Eip1559BaseFeeMinValue; public virtual bool ValidateReceipts => spec.ValidateReceipts; Array? IReleaseSpec.EvmInstructionsNoTrace { get => spec.EvmInstructionsNoTrace; set => spec.EvmInstructionsNoTrace = value; } Array? IReleaseSpec.EvmInstructionsTraced { get => spec.EvmInstructionsTraced; set => spec.EvmInstructionsTraced = value; } FrozenSet IReleaseSpec.Precompiles => spec.Precompiles; - public bool IsEip7939Enabled => spec.IsEip7939Enabled; - public bool IsEip7907Enabled => spec.IsEip7907Enabled; - public bool IsRip7728Enabled => spec.IsRip7728Enabled; + public virtual bool IsEip7939Enabled => spec.IsEip7939Enabled; + public virtual bool IsEip7907Enabled => spec.IsEip7907Enabled; + public virtual bool IsRip7728Enabled => spec.IsRip7728Enabled; } diff --git a/src/Nethermind/Nethermind.Core/Specs/SpecProviderDecorator.cs b/src/Nethermind/Nethermind.Core/Specs/SpecProviderDecorator.cs index b7856c4f7f2..da475887053 100644 --- a/src/Nethermind/Nethermind.Core/Specs/SpecProviderDecorator.cs +++ b/src/Nethermind/Nethermind.Core/Specs/SpecProviderDecorator.cs @@ -27,5 +27,5 @@ public class SpecProviderDecorator(ISpecProvider baseSpecProvider) : ISpecProvid public ForkActivation[] TransitionActivations => baseSpecProvider.TransitionActivations; - public virtual IReleaseSpec GetSpecInternal(ForkActivation forkActivation) => baseSpecProvider.GetSpecInternal(forkActivation); + public virtual IReleaseSpec GetSpec(ForkActivation forkActivation) => baseSpecProvider.GetSpec(forkActivation); } diff --git a/src/Nethermind/Nethermind.Evm.Test/CodeInfoRepositoryTests.cs b/src/Nethermind/Nethermind.Evm.Test/CodeInfoRepositoryTests.cs index a297fe3945b..9865e344167 100644 --- a/src/Nethermind/Nethermind.Evm.Test/CodeInfoRepositoryTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/CodeInfoRepositoryTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Frozen; using Nethermind.Core.Crypto; using Nethermind.Core; using NSubstitute; @@ -14,13 +15,20 @@ using Nethermind.Evm.CodeAnalysis; using Nethermind.Core.Extensions; using Nethermind.Core.Test; -using Nethermind.State; namespace Nethermind.Evm.Test; [TestFixture, Parallelizable] public class CodeInfoRepositoryTests { + private static readonly IReleaseSpec _releaseSpec; + + static CodeInfoRepositoryTests() + { + _releaseSpec = Substitute.For(); + _releaseSpec.Precompiles.Returns(FrozenSet.Empty); + } + public static IEnumerable NotDelegationCodeCases() { byte[] rndAddress = new byte[20]; @@ -28,45 +36,31 @@ public static IEnumerable NotDelegationCodeCases() //Change first byte of the delegation header byte[] code = [.. Eip7702Constants.DelegationHeader, .. rndAddress]; code[0] = TestContext.CurrentContext.Random.NextByte(0xee); - yield return new object[] - { - code - }; + yield return [code]; //Change second byte of the delegation header code = [.. Eip7702Constants.DelegationHeader, .. rndAddress]; code[1] = TestContext.CurrentContext.Random.NextByte(0x2, 0xff); - yield return new object[] - { - code - }; + yield return [code]; //Change third byte of the delegation header code = [.. Eip7702Constants.DelegationHeader, .. rndAddress]; code[2] = TestContext.CurrentContext.Random.NextByte(0x1, 0xff); - yield return new object[] - { - code - }; + yield return [code]; code = [.. Eip7702Constants.DelegationHeader, .. new byte[21]]; - yield return new object[] - { - code - }; + yield return [code]; code = [.. Eip7702Constants.DelegationHeader, .. new byte[19]]; - yield return new object[] - { - code - }; + yield return [code]; } + [TestCaseSource(nameof(NotDelegationCodeCases))] public void TryGetDelegation_CodeIsNotDelegation_ReturnsFalse(byte[] code) { IWorldState stateProvider = TestWorldStateFactory.CreateForTest(); using var _scope = stateProvider.BeginScope(IWorldState.PreGenesis); stateProvider.CreateAccount(TestItem.AddressA, 0); - stateProvider.InsertCode(TestItem.AddressA, code, Substitute.For()); + stateProvider.InsertCode(TestItem.AddressA, code, _releaseSpec); EthereumCodeInfoRepository sut = new(stateProvider); - sut.TryGetDelegation(TestItem.AddressA, Substitute.For(), out _).Should().Be(false); + sut.TryGetDelegation(TestItem.AddressA, _releaseSpec, out _).Should().Be(false); } @@ -74,27 +68,22 @@ public static IEnumerable DelegationCodeCases() { byte[] address = new byte[20]; byte[] code = [.. Eip7702Constants.DelegationHeader, .. address]; - yield return new object[] - { - code - }; + yield return [code]; TestContext.CurrentContext.Random.NextBytes(address); code = [.. Eip7702Constants.DelegationHeader, .. address]; - yield return new object[] - { - code - }; + yield return [code]; } + [TestCaseSource(nameof(DelegationCodeCases))] public void TryGetDelegation_CodeTryGetDelegation_ReturnsTrue(byte[] code) { IWorldState stateProvider = TestWorldStateFactory.CreateForTest(); using var _scope = stateProvider.BeginScope(IWorldState.PreGenesis); stateProvider.CreateAccount(TestItem.AddressA, 0); - stateProvider.InsertCode(TestItem.AddressA, code, Substitute.For()); + stateProvider.InsertCode(TestItem.AddressA, code, _releaseSpec); EthereumCodeInfoRepository sut = new(stateProvider); - sut.TryGetDelegation(TestItem.AddressA, Substitute.For(), out _).Should().Be(true); + sut.TryGetDelegation(TestItem.AddressA, _releaseSpec, out _).Should().Be(true); } [TestCaseSource(nameof(DelegationCodeCases))] @@ -103,11 +92,11 @@ public void TryGetDelegation_CodeTryGetDelegation_CorrectDelegationAddressIsSet( IWorldState stateProvider = TestWorldStateFactory.CreateForTest(); using var _ = stateProvider.BeginScope(IWorldState.PreGenesis); stateProvider.CreateAccount(TestItem.AddressA, 0); - stateProvider.InsertCode(TestItem.AddressA, code, Substitute.For()); + stateProvider.InsertCode(TestItem.AddressA, code, _releaseSpec); EthereumCodeInfoRepository sut = new(stateProvider); Address result; - sut.TryGetDelegation(TestItem.AddressA, Substitute.For(), out result); + sut.TryGetDelegation(TestItem.AddressA, _releaseSpec, out result); result.Should().Be(new Address(code.Slice(3, Address.Size))); } @@ -118,15 +107,15 @@ public void GetExecutableCodeHash_CodeTryGetDelegation_ReturnsHashOfDelegated(by IWorldState stateProvider = TestWorldStateFactory.CreateForTest(); using var _ = stateProvider.BeginScope(IWorldState.PreGenesis); stateProvider.CreateAccount(TestItem.AddressA, 0); - stateProvider.InsertCode(TestItem.AddressA, code, Substitute.For()); + stateProvider.InsertCode(TestItem.AddressA, code, _releaseSpec); Address delegationAddress = new Address(code.Slice(3, Address.Size)); byte[] delegationCode = new byte[32]; stateProvider.CreateAccount(delegationAddress, 0); - stateProvider.InsertCode(delegationAddress, delegationCode, Substitute.For()); + stateProvider.InsertCode(delegationAddress, delegationCode, _releaseSpec); EthereumCodeInfoRepository sut = new(stateProvider); - sut.GetExecutableCodeHash(TestItem.AddressA, Substitute.For()).Should().Be(Keccak.Compute(code).ValueHash256); + sut.GetExecutableCodeHash(TestItem.AddressA, _releaseSpec).Should().Be(Keccak.Compute(code).ValueHash256); } [TestCaseSource(nameof(NotDelegationCodeCases))] @@ -135,11 +124,11 @@ public void GetExecutableCodeHash_CodeIsNotDelegation_ReturnsCodeHashOfAddress(b IWorldState stateProvider = TestWorldStateFactory.CreateForTest(); using var _ = stateProvider.BeginScope(IWorldState.PreGenesis); stateProvider.CreateAccount(TestItem.AddressA, 0); - stateProvider.InsertCode(TestItem.AddressA, code, Substitute.For()); + stateProvider.InsertCode(TestItem.AddressA, code, _releaseSpec); EthereumCodeInfoRepository sut = new(stateProvider); - sut.GetExecutableCodeHash(TestItem.AddressA, Substitute.For()).Should().Be(Keccak.Compute(code).ValueHash256); + sut.GetExecutableCodeHash(TestItem.AddressA, _releaseSpec).Should().Be(Keccak.Compute(code).ValueHash256); } [TestCaseSource(nameof(DelegationCodeCases))] @@ -148,14 +137,14 @@ public void GetCachedCodeInfo_CodeTryGetDelegation_ReturnsCodeOfDelegation(byte[ IWorldState stateProvider = TestWorldStateFactory.CreateForTest(); using var _ = stateProvider.BeginScope(IWorldState.PreGenesis); stateProvider.CreateAccount(TestItem.AddressA, 0); - stateProvider.InsertCode(TestItem.AddressA, code, Substitute.For()); + stateProvider.InsertCode(TestItem.AddressA, code, _releaseSpec); Address delegationAddress = new Address(code.Slice(3, Address.Size)); stateProvider.CreateAccount(delegationAddress, 0); byte[] delegationCode = new byte[32]; - stateProvider.InsertCode(delegationAddress, delegationCode, Substitute.For()); + stateProvider.InsertCode(delegationAddress, delegationCode, _releaseSpec); EthereumCodeInfoRepository sut = new(stateProvider); - ICodeInfo result = sut.GetCachedCodeInfo(TestItem.AddressA, Substitute.For()); + ICodeInfo result = sut.GetCachedCodeInfo(TestItem.AddressA, _releaseSpec); result.CodeSpan.ToArray().Should().BeEquivalentTo(delegationCode); } @@ -165,10 +154,10 @@ public void GetCachedCodeInfo_CodeIsNotDelegation_ReturnsCodeOfAddress(byte[] co IWorldState stateProvider = TestWorldStateFactory.CreateForTest(); using var _ = stateProvider.BeginScope(IWorldState.PreGenesis); stateProvider.CreateAccount(TestItem.AddressA, 0); - stateProvider.InsertCode(TestItem.AddressA, code, Substitute.For()); + stateProvider.InsertCode(TestItem.AddressA, code, _releaseSpec); EthereumCodeInfoRepository sut = new(stateProvider); - sut.GetCachedCodeInfo(TestItem.AddressA, Substitute.For()).Should().BeEquivalentTo(new CodeInfo(code)); + sut.GetCachedCodeInfo(TestItem.AddressA, _releaseSpec).Should().BeEquivalentTo(new CodeInfo(code)); } } diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip152Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip152Tests.cs index 2431e6ae167..dae7f1845b3 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip152Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip152Tests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core; +using Nethermind.Core.Specs; using Nethermind.Specs; using Nethermind.Evm.Precompiles; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip2537Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip2537Tests.cs index b91632f29ab..5dfcd9f1e69 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip2537Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip2537Tests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core.Specs; using NUnit.Framework; using Nethermind.Evm.Precompiles.Bls; using Nethermind.Evm.Precompiles; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index 8d75e4d3819..023b6188d30 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -215,7 +215,7 @@ public async Task Eth_get_uncle_by_block_hash_and_index(bool eip1559, string exp if (eip1559) { specProvider = Substitute.For(); - ReleaseSpec releaseSpec = new() { IsEip1559Enabled = true, Eip1559TransitionBlock = 1 }; + ReleaseSpec releaseSpec = new() { IsEip1559Enabled = true, Eip1559TransitionBlock = 0 }; specProvider.GetSpec(Arg.Any()).Returns(releaseSpec); } diff --git a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs index a8de14b0ec5..f43d064c646 100644 --- a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs @@ -56,8 +56,7 @@ public void Timestamp_activation_equal_to_genesis_timestamp_loads_correctly(long var logManager = Substitute.For(); logManager.GetClassLogger().Returns(logger); ChainSpecBasedSpecProvider provider = new(chainSpec); - ReleaseSpec expectedSpec = ((ReleaseSpec)MainnetSpecProvider - .Instance.GetSpec((MainnetSpecProvider.GrayGlacierBlockNumber, null))).Clone(); + ReleaseSpec expectedSpec = ((ReleaseSpec)MainnetSpecProvider.Instance.GetSpec((MainnetSpecProvider.GrayGlacierBlockNumber, null))).Clone(); expectedSpec.Name = "Genesis_with_non_zero_timestamp"; expectedSpec.IsEip3651Enabled = true; expectedSpec.IsEip3198Enabled = false; @@ -661,12 +660,9 @@ private static void CompareSpecs(IReleaseSpec expectedSpec, IReleaseSpec actualS // handle gnosis specific exceptions .Where(p => !isGnosis || p.Name != nameof(IReleaseSpec.MaxCodeSize)) - .Where(p => !isGnosis || p.Name != nameof(IReleaseSpec.MaxInitCodeSize)) .Where(p => !isGnosis || p.Name != nameof(IReleaseSpec.MaximumUncleCount)) .Where(p => !isGnosis || p.Name != nameof(IReleaseSpec.IsEip170Enabled)) - .Where(p => !isGnosis || p.Name != nameof(IReleaseSpec.IsEip1283Enabled)) - .Where(p => !isGnosis || p.Name != nameof(IReleaseSpec.LimitCodeSize)) - .Where(p => !isGnosis || p.Name != nameof(IReleaseSpec.UseConstantinopleNetGasMetering))) + .Where(p => !isGnosis || p.Name != nameof(IReleaseSpec.IsEip1283Enabled))) { Assert.That(propertyInfo.GetValue(actualSpec), Is.EqualTo(propertyInfo.GetValue(expectedSpec)), activation + "." + propertyInfo.Name); diff --git a/src/Nethermind/Nethermind.Specs.Test/Nethermind.Specs.Test.csproj b/src/Nethermind/Nethermind.Specs.Test/Nethermind.Specs.Test.csproj index 79f401ccb4e..d6fc33aed5d 100644 --- a/src/Nethermind/Nethermind.Specs.Test/Nethermind.Specs.Test.csproj +++ b/src/Nethermind/Nethermind.Specs.Test/Nethermind.Specs.Test.csproj @@ -12,6 +12,7 @@ + diff --git a/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs b/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs index 5dd0d445065..bd6810c0564 100644 --- a/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs @@ -128,7 +128,7 @@ public UInt256 BlockReward public bool IsEip7934Enabled => spec.IsEip7934Enabled; public int Eip7934MaxRlpBlockSize => spec.Eip7934MaxRlpBlockSize; - + public bool ValidateChainId => spec.ValidateChainId; public bool IsEip3607Enabled { get; set; } = spec.IsEip3607Enabled; public bool IsEip158IgnoredAccount(Address address) => spec.IsEip158IgnoredAccount(address); @@ -172,6 +172,7 @@ public ulong Eip4844TransitionTimestamp public bool IsEip4895Enabled => spec.IsEip4895Enabled; public ulong WithdrawalTimestamp => spec.WithdrawalTimestamp; public bool IsEip5656Enabled => spec.IsEip5656Enabled; + public long Eip2935RingBufferSize => spec.Eip2935RingBufferSize; public bool IsEip6780Enabled => spec.IsEip6780Enabled; public bool IsEip4788Enabled => spec.IsEip4788Enabled; public bool IsEip4844FeeCollectorEnabled => spec.IsEip4844FeeCollectorEnabled; diff --git a/src/Nethermind/Nethermind.Specs.Test/OverridableSpecProvider.cs b/src/Nethermind/Nethermind.Specs.Test/OverridableSpecProvider.cs index 4a5699e4c18..14abbe55843 100644 --- a/src/Nethermind/Nethermind.Specs.Test/OverridableSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs.Test/OverridableSpecProvider.cs @@ -37,7 +37,7 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public IReleaseSpec GenesisSpec => _overrideAction(SpecProvider.GenesisSpec, new ForkActivation(0)); - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => _overrideAction(SpecProvider.GetSpec(forkActivation), forkActivation); + public IReleaseSpec GetSpec(ForkActivation forkActivation) => _overrideAction(SpecProvider.GetSpec(forkActivation), forkActivation); public long? DaoBlockNumber => SpecProvider.DaoBlockNumber; public ulong? BeaconChainGenesisTimestamp => SpecProvider.BeaconChainGenesisTimestamp; diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/SpecProviderBase.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/SpecProviderBase.cs index 8d826557df9..4a3ef4b16b1 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/SpecProviderBase.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/SpecProviderBase.cs @@ -43,7 +43,7 @@ protected void LoadTransitions((ForkActivation Activation, IReleaseSpec Spec)[] public IReleaseSpec GenesisSpec { get; private set; } - public IReleaseSpec GetSpecInternal(ForkActivation activation) + public IReleaseSpec GetSpec(ForkActivation activation) { static int CompareTransitionOnActivation(ForkActivation activation, (ForkActivation Activation, IReleaseSpec Spec) transition) => activation.CompareTo(transition.Activation); diff --git a/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs b/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs index 75e2be5ae74..2d7bc1291f8 100644 --- a/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs @@ -21,7 +21,7 @@ public class ChiadoSpecProvider : ISpecProvider private ChiadoSpecProvider() { } - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => forkActivation.BlockNumber switch + public IReleaseSpec GetSpec(ForkActivation forkActivation) => forkActivation.BlockNumber switch { _ => forkActivation.Timestamp switch { diff --git a/src/Nethermind/Nethermind.Specs/FrontierSpecProvider.cs b/src/Nethermind/Nethermind.Specs/FrontierSpecProvider.cs index 975b10dab09..f172aba8b0e 100644 --- a/src/Nethermind/Nethermind.Specs/FrontierSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/FrontierSpecProvider.cs @@ -25,7 +25,7 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public UInt256? TerminalTotalDifficulty { get; private set; } public IReleaseSpec GenesisSpec => Frontier.Instance; - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => Frontier.Instance; + public IReleaseSpec GetSpec(ForkActivation forkActivation) => Frontier.Instance; public long? DaoBlockNumber { get; } = null; public ulong? BeaconChainGenesisTimestamp => null; diff --git a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs index 7e7ebb248c5..821df7a8d0f 100644 --- a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs @@ -25,7 +25,7 @@ public class GnosisSpecProvider : ISpecProvider private GnosisSpecProvider() { } - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) + public IReleaseSpec GetSpec(ForkActivation forkActivation) { return forkActivation.BlockNumber switch { diff --git a/src/Nethermind/Nethermind.Specs/HoodiSpecProvider.cs b/src/Nethermind/Nethermind.Specs/HoodiSpecProvider.cs index e9e328fe113..bb02ff2e72f 100644 --- a/src/Nethermind/Nethermind.Specs/HoodiSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/HoodiSpecProvider.cs @@ -26,7 +26,7 @@ public class HoodiSpecProvider : ISpecProvider private HoodiSpecProvider() { } - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) + public IReleaseSpec GetSpec(ForkActivation forkActivation) { return forkActivation.Timestamp switch { diff --git a/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs b/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs index 9e9f7b91332..948e8ebd869 100644 --- a/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs @@ -31,7 +31,7 @@ public class MainnetSpecProvider : ISpecProvider public const ulong BPO1BlockTimestamp = 0x69383057; public const ulong BPO2BlockTimestamp = 0x695db057; - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => + public IReleaseSpec GetSpec(ForkActivation forkActivation) => forkActivation switch { { BlockNumber: < HomesteadBlockNumber } => Frontier.Instance, diff --git a/src/Nethermind/Nethermind.Specs/MordenSpecProvider.cs b/src/Nethermind/Nethermind.Specs/MordenSpecProvider.cs index a75fe3fe8d1..aa572aad154 100644 --- a/src/Nethermind/Nethermind.Specs/MordenSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/MordenSpecProvider.cs @@ -25,7 +25,7 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public UInt256? TerminalTotalDifficulty { get; private set; } public IReleaseSpec GenesisSpec => Frontier.Instance; - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => + public IReleaseSpec GetSpec(ForkActivation forkActivation) => forkActivation.BlockNumber switch { < 494000 => Frontier.Instance, diff --git a/src/Nethermind/Nethermind.Specs/OlympicSpecProvider.cs b/src/Nethermind/Nethermind.Specs/OlympicSpecProvider.cs index 89a6c258ead..b3556fa01aa 100644 --- a/src/Nethermind/Nethermind.Specs/OlympicSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/OlympicSpecProvider.cs @@ -24,7 +24,7 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public UInt256? TerminalTotalDifficulty { get; private set; } public IReleaseSpec GenesisSpec => Olympic.Instance; - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => Olympic.Instance; + public IReleaseSpec GetSpec(ForkActivation forkActivation) => Olympic.Instance; public long? DaoBlockNumber => 0L; public ulong? BeaconChainGenesisTimestamp => null; diff --git a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs index e0b3ae60a95..2d4f0d50d58 100644 --- a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs @@ -66,6 +66,7 @@ public bool IsEip1559Enabled set => _isEip1559Enabled = value; } + public bool IsEip158IgnoredAccount(Address address) => false; public bool IsEip3198Enabled { get; set; } public bool IsEip3529Enabled { get; set; } public bool IsEip3607Enabled { get; set; } diff --git a/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs b/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs index 3eb52bde3e0..c84e0fe7c79 100644 --- a/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs @@ -26,7 +26,7 @@ public class SepoliaSpecProvider : ISpecProvider private SepoliaSpecProvider() { } - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => + public IReleaseSpec GetSpec(ForkActivation forkActivation) => forkActivation switch { { Timestamp: null } or { Timestamp: < ShanghaiTimestamp } => London.Instance, diff --git a/src/Nethermind/Nethermind.Specs/SingleReleaseSpecProvider.cs b/src/Nethermind/Nethermind.Specs/SingleReleaseSpecProvider.cs index ded0e575e20..75fb5a087fd 100644 --- a/src/Nethermind/Nethermind.Specs/SingleReleaseSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/SingleReleaseSpecProvider.cs @@ -42,7 +42,7 @@ public SingleReleaseSpecProvider(IReleaseSpec releaseSpec, ulong networkId, ulon public IReleaseSpec GenesisSpec => _releaseSpec; - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => _releaseSpec; + public IReleaseSpec GetSpec(ForkActivation forkActivation) => _releaseSpec; public long? DaoBlockNumber { get; } public ulong? BeaconChainGenesisTimestamp { get; } diff --git a/src/Nethermind/Nethermind.Specs/TestSpecProvider.cs b/src/Nethermind/Nethermind.Specs/TestSpecProvider.cs index 054be202f35..2e8e199c913 100644 --- a/src/Nethermind/Nethermind.Specs/TestSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/TestSpecProvider.cs @@ -30,7 +30,7 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public IReleaseSpec GenesisSpec { get; set; } - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => forkActivation.BlockNumber == 0 || forkActivation.BlockNumber < ForkOnBlockNumber ? GenesisSpec : NextForkSpec; + public IReleaseSpec GetSpec(ForkActivation forkActivation) => forkActivation.BlockNumber == 0 || forkActivation.BlockNumber < ForkOnBlockNumber ? GenesisSpec : NextForkSpec; public IReleaseSpec NextForkSpec { get; set; } public long? ForkOnBlockNumber { get; set; } diff --git a/src/Nethermind/Nethermind.TxPool.Test/TxBroadcasterTests.cs b/src/Nethermind/Nethermind.TxPool.Test/TxBroadcasterTests.cs index 3c575ea5f35..8104846f17b 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/TxBroadcasterTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/TxBroadcasterTests.cs @@ -739,7 +739,7 @@ public void can_correctly_broadcast_light_transactions_without_wrappers([Values] IChainHeadInfoProvider mockChainHeadInfoProvider = Substitute.For(); mockChainHeadInfoProvider.CurrentProofVersion.Returns(proofVersion); IReleaseSpec spec = Substitute.For(); - spec.BlobProofVersion.Returns(versionMatches ? proofVersion : GetInvalidVersion(proofVersion)); + spec.IsEip7594Enabled.Returns(versionMatches ? proofVersion == ProofVersion.V1 : proofVersion == ProofVersion.V0); SpecDrivenTxGossipPolicy gossipPolicy = new(mockChainHeadInfoProvider); @@ -755,13 +755,6 @@ public void can_correctly_broadcast_light_transactions_without_wrappers([Values] // Assert result.Should().Be(versionMatches, "LightTransaction from blob transaction should be gossiped when proof version matches."); - - // Gets (version + 1) % (version + 1) - so next version round robin - ProofVersion GetInvalidVersion(ProofVersion version) - { - byte mod = (byte)(FastEnum.GetMaxValue() + 1); - return (ProofVersion)((byte)(version + 1) % mod); - } } private (IList expectedTxs, IList expectedHashes) GetTxsAndHashesExpectedToBroadcast(Transaction[] transactions, int expectedCountTotal) From 16a4e12ff5e06a3c36049a4c899abf55d12538e7 Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Thu, 15 Jan 2026 09:31:16 +0100 Subject: [PATCH 231/255] Fix `PathUtils` for JetBrains Rider (#10238) * Apply a workaround for JetBrains Rider * Don't use `System.Diagnostics` * Fix formatting --- src/Nethermind/Nethermind.Logging/PathUtils.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Logging/PathUtils.cs b/src/Nethermind/Nethermind.Logging/PathUtils.cs index 4e325456370..e6ec6ac69dd 100644 --- a/src/Nethermind/Nethermind.Logging/PathUtils.cs +++ b/src/Nethermind/Nethermind.Logging/PathUtils.cs @@ -9,7 +9,19 @@ namespace Nethermind.Logging; public static class PathUtils { - public static string ExecutingDirectory { get; } = Path.GetDirectoryName(Environment.ProcessPath); + static PathUtils() + { + string processName = Path.GetFileNameWithoutExtension(Environment.ProcessPath); + + ExecutingDirectory = processName.Equals("dotnet", StringComparison.OrdinalIgnoreCase) + || processName.Equals("ReSharperTestRunner", StringComparison.OrdinalIgnoreCase) + // A workaround for tests in JetBrains Rider ignoring MTP: + // https://youtrack.jetbrains.com/projects/RIDER/issues/RIDER-131530 + ? AppContext.BaseDirectory + : Path.GetDirectoryName(Environment.ProcessPath); + } + + public static string ExecutingDirectory { get; } public static string GetApplicationResourcePath(this string resourcePath, string overridePrefixPath = null) { From 2a930940b4bf27b064447149962dd5ea7eb9e5b0 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Thu, 15 Jan 2026 04:48:44 -0500 Subject: [PATCH 232/255] Optimize storage key handling (#10241) * Optimize storage key handling Replaces byte[] with ValueHash256 for storage key lookup and computation in StorageTree for improved type safety and performance. Updates related method signatures and usages to use ValueHash256. Adds [SkipLocalsInit] attribute to several performance-critical methods in trie and pruning code. * Feedback --- .../Nethermind.State/StorageTree.cs | 86 ++++++++++--------- .../TrieStoreScopeProvider.cs | 2 +- .../Nethermind.Trie/NibbleExtensions.cs | 3 +- .../Nethermind.Trie/PatriciaTree.BulkSet.cs | 4 +- .../Nethermind.Trie/PatriciaTree.cs | 1 + .../Nethermind.Trie/Pruning/TreePath.cs | 1 + 6 files changed, 55 insertions(+), 42 deletions(-) diff --git a/src/Nethermind/Nethermind.State/StorageTree.cs b/src/Nethermind/Nethermind.State/StorageTree.cs index 088fa41fa35..a756a8a5b95 100644 --- a/src/Nethermind/Nethermind.State/StorageTree.cs +++ b/src/Nethermind/Nethermind.State/StorageTree.cs @@ -2,12 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Frozen; -using System.Collections.Generic; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using Nethermind.Core; -using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Evm.State; @@ -16,27 +12,30 @@ using Nethermind.Serialization.Rlp; using Nethermind.Trie; using Nethermind.Trie.Pruning; +using System.Runtime.InteropServices; namespace Nethermind.State { public class StorageTree : PatriciaTree, IWorldStateScopeProvider.IStorageTree { - private const int LookupSize = 1024; - private static readonly FrozenDictionary Lookup = CreateLookup(); + private static readonly ValueHash256[] Lookup = CreateLookup(); public static readonly byte[] ZeroBytes = [0]; - private static FrozenDictionary CreateLookup() + private static ValueHash256[] CreateLookup() { + const int LookupSize = 1024; + Span buffer = stackalloc byte[32]; - Dictionary lookup = new Dictionary(LookupSize); - for (int i = 0; i < LookupSize; i++) + ValueHash256[] lookup = new ValueHash256[LookupSize]; + + for (int i = 0; i < lookup.Length; i++) { - UInt256 index = (UInt256)i; + UInt256 index = new UInt256((uint)i); index.ToBigEndian(buffer); - lookup[index] = Keccak.Compute(buffer).BytesToArray(); + lookup[i] = ValueKeccak.Compute(buffer); } - return lookup.ToFrozenDictionary(); + return lookup; } public StorageTree(IScopedTrieStore? trieStore, ILogManager? logManager) @@ -52,27 +51,30 @@ public StorageTree(IScopedTrieStore? trieStore, Hash256 rootHash, ILogManager? l [SkipLocalsInit] [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void ComputeKey(in UInt256 index, Span key) + private static void ComputeKey(in UInt256 index, out ValueHash256 key) { - index.ToBigEndian(key); - - // We can't direct ComputeTo the key as its also the input, so need a separate variable - KeccakCache.ComputeTo(key, out ValueHash256 keyHash); - // Which we can then directly assign to fast update the key - Unsafe.As(ref MemoryMarshal.GetReference(key)) = keyHash; + // Cannot use key as both in and out to KeccakCache.ComputeTo, + // so create another 32-byte buffer + Unsafe.SkipInit(out ValueHash256 buffer); + index.ToBigEndian(buffer.BytesAsSpan); + KeccakCache.ComputeTo(buffer.Bytes, out key); } - public static void ComputeKeyWithLookup(in UInt256 index, Span key) + [SkipLocalsInit] + public static void ComputeKeyWithLookup(in UInt256 index, ref ValueHash256 key) { - if (index < LookupSize) + ValueHash256[] lookup = Lookup; + ulong u0 = index.u0; + if (index.IsUint64 && u0 < (uint)lookup.Length) { - Lookup[index].CopyTo(key); + key = Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(lookup), (nuint)u0); + return; } - ComputeKey(index, key); + ComputeKey(index, out key); } - public static BulkSetEntry CreateBulkSetEntry(ValueHash256 key, byte[]? value) + public static BulkSetEntry CreateBulkSetEntry(in ValueHash256 key, byte[]? value) { byte[] encodedValue; if (value.IsZero()) @@ -92,15 +94,19 @@ public static BulkSetEntry CreateBulkSetEntry(ValueHash256 key, byte[]? value) } } - return new BulkSetEntry(key, encodedValue); + return new BulkSetEntry(in key, encodedValue); } [SkipLocalsInit] public byte[] Get(in UInt256 index, Hash256? storageRoot = null) { - if (index < LookupSize) + ValueHash256[] lookup = Lookup; + ulong u0 = index.u0; + if (index.IsUint64 && u0 < (uint)lookup.Length) { - return GetArray(Lookup[index], storageRoot); + return GetArray( + in Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(lookup), (nuint)u0), + storageRoot); } return GetWithKeyGenerate(in index, storageRoot); @@ -108,14 +114,14 @@ public byte[] Get(in UInt256 index, Hash256? storageRoot = null) [SkipLocalsInit] byte[] GetWithKeyGenerate(in UInt256 index, Hash256 storageRoot) { - Span key = stackalloc byte[32]; - ComputeKey(index, key); - return GetArray(key, storageRoot); + ComputeKey(index, out ValueHash256 key); + return GetArray(in key, storageRoot); } } - public byte[] GetArray(ReadOnlySpan rawKey, Hash256? rootHash = null) + public byte[] GetArray(in ValueHash256 key, Hash256? rootHash = null) { + ReadOnlySpan rawKey = key.Bytes; ReadOnlySpan value = Get(rawKey, rootHash); if (value.IsEmpty) @@ -150,15 +156,17 @@ public void HintGet(in UInt256 index, byte[]? value) public byte[] Get(in ValueHash256 hash) { - return GetArray(hash.Bytes, null); + return GetArray(in hash, null); } [SkipLocalsInit] public void Set(in UInt256 index, byte[] value) { - if (index < LookupSize) + ValueHash256[] lookup = Lookup; + ulong u0 = index.u0; + if (index.IsUint64 && u0 < (uint)lookup.Length) { - SetInternal(Lookup[index], value); + SetInternal(in Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(lookup), (nuint)u0), value); } else { @@ -168,19 +176,19 @@ public void Set(in UInt256 index, byte[] value) [SkipLocalsInit] void SetWithKeyGenerate(in UInt256 index, byte[] value) { - Span key = stackalloc byte[32]; - ComputeKey(index, key); - SetInternal(key, value); + ComputeKey(index, out ValueHash256 key); + SetInternal(in key, value); } } public void Set(in ValueHash256 key, byte[] value, bool rlpEncode = true) { - SetInternal(key.Bytes, value, rlpEncode); + SetInternal(in key, value, rlpEncode); } - private void SetInternal(ReadOnlySpan rawKey, byte[] value, bool rlpEncode = true) + private void SetInternal(in ValueHash256 hash, byte[] value, bool rlpEncode = true) { + ReadOnlySpan rawKey = hash.Bytes; if (value.IsZero()) { Set(rawKey, []); diff --git a/src/Nethermind/Nethermind.State/TrieStoreScopeProvider.cs b/src/Nethermind/Nethermind.State/TrieStoreScopeProvider.cs index 6f0a26a2b21..30ee38f58a7 100644 --- a/src/Nethermind/Nethermind.State/TrieStoreScopeProvider.cs +++ b/src/Nethermind/Nethermind.State/TrieStoreScopeProvider.cs @@ -249,7 +249,7 @@ public void Set(in UInt256 index, byte[] value) } else { - StorageTree.ComputeKeyWithLookup(index, _keyBuff.BytesAsSpan); + StorageTree.ComputeKeyWithLookup(index, ref _keyBuff); _bulkWrite.Add(StorageTree.CreateBulkSetEntry(_keyBuff, value)); } } diff --git a/src/Nethermind/Nethermind.Trie/NibbleExtensions.cs b/src/Nethermind/Nethermind.Trie/NibbleExtensions.cs index f56c055057f..97d6ecefdcb 100644 --- a/src/Nethermind/Nethermind.Trie/NibbleExtensions.cs +++ b/src/Nethermind/Nethermind.Trie/NibbleExtensions.cs @@ -35,7 +35,7 @@ public static byte[] BytesToNibbleBytes(ReadOnlySpan bytes) return output; } - public unsafe static void BytesToNibbleBytes(ReadOnlySpan bytes, Span nibbles) + public static void BytesToNibbleBytes(ReadOnlySpan bytes, Span nibbles) { // Ensure the length of the nibbles span is exactly twice the length of the bytes span. if (nibbles.Length != 2 * bytes.Length) @@ -196,6 +196,7 @@ public static byte[] ToBytes(ReadOnlySpan nibbles) return bytes; } + [SkipLocalsInit] public static byte[] CompactToHexEncode(byte[] compactPath) { if (compactPath.Length == 0) diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs index d1b528ce4a5..07938e21839 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.BulkSet.cs @@ -27,7 +27,7 @@ public enum Flags DoNotParallelize = 2 } - public readonly struct BulkSetEntry(ValueHash256 path, byte[] value) : IComparable + public readonly struct BulkSetEntry(in ValueHash256 path, byte[] value) : IComparable { public readonly ValueHash256 Path = path; public readonly byte[] Value = value; @@ -261,6 +261,7 @@ private struct Context return node; } + [SkipLocalsInit] private TrieNode? BulkSetOne(Stack traverseStack, in BulkSetEntry entry, ref TreePath path, TrieNode? node) { Span nibble = stackalloc byte[64]; @@ -450,6 +451,7 @@ internal static int HexarySearchAlreadySortedSmall(Span entries, i return usedMask; } + [SkipLocalsInit] internal static int HexarySearchAlreadySortedLarge( Span entries, int pathIndex, diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs index 5119615e484..e903cd28fa0 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs @@ -388,6 +388,7 @@ public virtual ReadOnlySpan Get(ReadOnlySpan rawKey, Hash256? rootHa } } + [SkipLocalsInit] [DebuggerStepThrough] public byte[]? GetNodeByKey(Span rawKey, Hash256? rootHash = null) { diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TreePath.cs b/src/Nethermind/Nethermind.Trie/Pruning/TreePath.cs index 9714b92ddbc..5ab32a9a613 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TreePath.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TreePath.cs @@ -231,6 +231,7 @@ public void TruncateOne() Length--; } + [SkipLocalsInit] public readonly byte[] ToNibble() { bool odd = Length % 2 == 1; From b29460cd9b85c23351822ac9d07e7b6a4684dee7 Mon Sep 17 00:00:00 2001 From: sashass1315 Date: Thu, 15 Jan 2026 13:23:27 +0200 Subject: [PATCH 233/255] fix: avoid mutating levels in header/body existence checks (#10157) --- src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs index a3fdae24ed3..7425bb3b789 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs @@ -110,7 +110,7 @@ private bool HeaderExists(long blockNumber, bool findBeacon = false) foreach (BlockInfo blockInfo in level.BlockInfos) { - BlockHeader? header = FindHeader(blockInfo.BlockHash, BlockTreeLookupOptions.None); + BlockHeader? header = FindHeader(blockInfo.BlockHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded | BlockTreeLookupOptions.DoNotCreateLevelIfMissing); if (header is not null) { if (findBeacon && blockInfo.IsBeaconHeader) @@ -138,7 +138,7 @@ private bool BodyExists(long blockNumber, bool findBeacon = false) foreach (BlockInfo blockInfo in level.BlockInfos) { - Block? block = FindBlock(blockInfo.BlockHash, BlockTreeLookupOptions.None); + Block? block = FindBlock(blockInfo.BlockHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded | BlockTreeLookupOptions.DoNotCreateLevelIfMissing); if (block is not null) { if (findBeacon && blockInfo.IsBeaconBody) From 233500e0bf704650a6465d24a5f3e9beaed30b0a Mon Sep 17 00:00:00 2001 From: Fallengirl <155266340+Fallengirl@users.noreply.github.com> Date: Thu, 15 Jan 2026 13:03:45 +0100 Subject: [PATCH 234/255] fix: Add missing fields to Transaction.CopyTo and PoolPolicy.Return (#9890) Co-authored-by: Lukasz Rozmej --- src/Nethermind/Nethermind.Core/Transaction.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Nethermind/Nethermind.Core/Transaction.cs b/src/Nethermind/Nethermind.Core/Transaction.cs index e33c976cbc0..c672eb29a2a 100644 --- a/src/Nethermind/Nethermind.Core/Transaction.cs +++ b/src/Nethermind/Nethermind.Core/Transaction.cs @@ -287,11 +287,16 @@ public bool Return(Transaction obj) obj.Hash = default; obj.ChainId = default; obj.Type = default; + obj.IsAnchorTx = default; + obj.SourceHash = default; + obj.Mint = default; + obj.IsOPSystemTransaction = default; obj.Nonce = default; obj.GasPrice = default; obj.GasBottleneck = default; obj.DecodedMaxFeePerGas = default; obj.GasLimit = default; + obj._spentGas = default; obj.To = default; obj.Value = default; obj.Data = default; @@ -315,6 +320,7 @@ public void CopyTo(Transaction tx) { tx.ChainId = ChainId; tx.Type = Type; + tx.IsAnchorTx = IsAnchorTx; tx.SourceHash = SourceHash; tx.Mint = Mint; tx.IsOPSystemTransaction = IsOPSystemTransaction; From e459e3f97e68467b3e310458c4b8e5888f3a1029 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Thu, 15 Jan 2026 16:15:05 +0300 Subject: [PATCH 235/255] Consider genesis in processing and finalization (#10235) --- src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs | 2 +- .../Nethermind.Blockchain/ReorgDepthFinalizedStateProvider.cs | 4 +++- .../Nethermind.Consensus/Processing/BranchProcessor.cs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs b/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs index 374f738ab79..8e509fd0d81 100644 --- a/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs @@ -44,7 +44,7 @@ public abstract class BlockchainTestBase private static readonly ILogger _logger; private static readonly ILogManager _logManager = new TestLogManager(LogLevel.Warn); private static DifficultyCalculatorWrapper DifficultyCalculator { get; } - private const int _genesisProcessingTimeoutMs = 5000; + private const int _genesisProcessingTimeoutMs = 30000; static BlockchainTestBase() { diff --git a/src/Nethermind/Nethermind.Blockchain/ReorgDepthFinalizedStateProvider.cs b/src/Nethermind/Nethermind.Blockchain/ReorgDepthFinalizedStateProvider.cs index abe22d32a00..fda29ae0910 100644 --- a/src/Nethermind/Nethermind.Blockchain/ReorgDepthFinalizedStateProvider.cs +++ b/src/Nethermind/Nethermind.Blockchain/ReorgDepthFinalizedStateProvider.cs @@ -4,12 +4,14 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Trie.Pruning; +using System; namespace Nethermind.Blockchain; public class ReorgDepthFinalizedStateProvider(IBlockTree blockTree) : IFinalizedStateProvider { - public long FinalizedBlockNumber => blockTree.BestKnownNumber - Reorganization.MaxDepth; + public long FinalizedBlockNumber => Math.Max(0, blockTree.BestKnownNumber - Reorganization.MaxDepth); + public Hash256? GetFinalizedStateRootAt(long blockNumber) { if (FinalizedBlockNumber < blockNumber) return null; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs index ce070783a71..719adc62367 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BranchProcessor.cs @@ -70,7 +70,8 @@ public Block[] Process(BlockHeader? baseBlock, IReadOnlyList suggestedBlo } else { - worldStateCloser = stateProvider.BeginScope(baseBlock); + BlockHeader? scopeBaseBlock = baseBlock ?? (suggestedBlock.IsGenesis ? suggestedBlock.Header : null); + worldStateCloser = stateProvider.BeginScope(scopeBaseBlock); } CancellationTokenSource? backgroundCancellation = new(); From 61947f45d780a9e7b9ca63fbdf213d769f20873c Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Fri, 16 Jan 2026 00:00:46 +0800 Subject: [PATCH 236/255] Refactor/Allow metrics before block processing (#10076) * Invert metric dependencies * Use timer loop * Rename metrics updater * Comment * Reduce change * Reduce change * Unit tests * Some cleanup * Fix dependencies * Add missing file header * Update src/Nethermind/Nethermind.Init/Modules/MonitoringModule.cs Co-authored-by: Lukasz Rozmej * Update src/Nethermind/Nethermind.Init/Steps/EthereumStepsManager.cs Co-authored-by: Lukasz Rozmej * Split the monitoring module out * Use BlockEventArgs * Whitespace * Address PR review comments: fix comment and remove unused method (#10084) * Initial plan * Address PR review comments: update comment and remove StopAsync Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> * Move db monitoring outside * Fix build * [WIP] Refactor to allow metrics before block processing (#10186) * Initial plan * Fix filename format issue: remove trailing space from IMonitoringService.cs Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> * Does this fix format? --------- Co-authored-by: Ruben Buniatyan Co-authored-by: Lukasz Rozmej Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --- .../Processing/BlockchainProcessor.cs | 3 + .../Processing/IBlockProcessingQueue.cs | 1 + .../Db/TestMemDbProvider.cs | 7 +- .../ContainerBuilderExtensions.cs | 9 + .../Nethermind.Db.Test/DbTrackerTests.cs | 126 +++++++++++++- src/Nethermind/Nethermind.Db/DbTracker.cs | 48 ------ src/Nethermind/Nethermind.Db/MemDb.cs | 2 +- .../Nethermind.Init/Modules/DbModule.cs | 5 - .../Modules/DbMonitoringModule.cs | 132 ++++++++++++++ .../Modules/MonitoringModule.cs | 119 +++++++++++++ .../Modules/NethermindModule.cs | 6 +- .../Nethermind.Init/Modules/RpcModules.cs | 2 - .../Steps/EthereumStepsManager.cs | 5 +- .../Nethermind.Init/Steps/StartMonitoring.cs | 163 +----------------- .../Config/IMetricsConfig.cs | 6 + .../Config/MetricsConfig.cs | 2 + ...oringService .cs => IMonitoringService.cs} | 1 - .../Metrics/IMetricsController.cs | 5 +- .../Metrics/MetricsController.cs | 28 ++- .../MonitoringService.cs | 42 +++-- .../NoopMonitoringService.cs | 22 +++ 21 files changed, 476 insertions(+), 258 deletions(-) delete mode 100644 src/Nethermind/Nethermind.Db/DbTracker.cs create mode 100644 src/Nethermind/Nethermind.Init/Modules/DbMonitoringModule.cs create mode 100644 src/Nethermind/Nethermind.Init/Modules/MonitoringModule.cs rename src/Nethermind/Nethermind.Monitoring/{IMonitoringService .cs => IMonitoringService.cs} (92%) create mode 100644 src/Nethermind/Nethermind.Monitoring/NoopMonitoringService.cs diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs index 0469e62fc9f..816517ff416 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs @@ -143,6 +143,8 @@ public async ValueTask Enqueue(Block block, ProcessingOptions processingOptions) if (!_recoveryComplete) { Interlocked.Increment(ref _queueCount); + BlockAdded?.Invoke(this, new BlockEventArgs(block)); + _lastProcessedBlock = DateTime.UtcNow; try { @@ -424,6 +426,7 @@ private void FireProcessingQueueEmpty() public event EventHandler? ProcessingQueueEmpty; public event EventHandler? BlockRemoved; + public event EventHandler? BlockAdded; public bool IsEmpty => Volatile.Read(ref _queueCount) == 0; public int Count => Volatile.Read(ref _queueCount); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessingQueue.cs b/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessingQueue.cs index 7ca72e70d41..3312d286e23 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessingQueue.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessingQueue.cs @@ -26,6 +26,7 @@ public interface IBlockProcessingQueue /// event EventHandler ProcessingQueueEmpty; + event EventHandler BlockAdded; event EventHandler BlockRemoved; /// diff --git a/src/Nethermind/Nethermind.Core.Test/Db/TestMemDbProvider.cs b/src/Nethermind/Nethermind.Core.Test/Db/TestMemDbProvider.cs index b13c69f5aff..c0fa78e4d9b 100644 --- a/src/Nethermind/Nethermind.Core.Test/Db/TestMemDbProvider.cs +++ b/src/Nethermind/Nethermind.Core.Test/Db/TestMemDbProvider.cs @@ -10,6 +10,7 @@ using Nethermind.Blockchain.Synchronization; using Nethermind.Db; using Nethermind.Init.Modules; +using Nethermind.Monitoring; namespace Nethermind.Core.Test.Db { @@ -23,7 +24,11 @@ public static Task InitAsync() public static IDbProvider Init() { return new ContainerBuilder() - .AddModule(new DbModule(new InitConfig() { DiagnosticMode = DiagnosticMode.MemDb }, new ReceiptConfig(), new SyncConfig())) + .AddModule(new DbModule( + new InitConfig() { DiagnosticMode = DiagnosticMode.MemDb }, + new ReceiptConfig(), + new SyncConfig() + )) .AddSingleton() .Build() .Resolve(); diff --git a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs index 3cad05bac4b..224300328fa 100644 --- a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs +++ b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs @@ -374,6 +374,15 @@ public static ContainerBuilder Intercept(this ContainerBuilder builder, Actio }); } + public static ContainerBuilder Intercept(this ContainerBuilder builder, Action interceptor) where T : class + { + return builder.AddDecorator((ctx, service) => + { + interceptor(service, ctx); + return service; + }); + } + /// /// A convenient way of creating a service whose members can be configured independent of other instances of the same /// type (assuming the type is of lifetime scope). This is useful for same type with multiple configuration diff --git a/src/Nethermind/Nethermind.Db.Test/DbTrackerTests.cs b/src/Nethermind/Nethermind.Db.Test/DbTrackerTests.cs index 27a1344fc3f..67d041f9c6b 100644 --- a/src/Nethermind/Nethermind.Db.Test/DbTrackerTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/DbTrackerTests.cs @@ -1,9 +1,23 @@ +// SPDX-FileCopyrightText: 2026 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Linq; using Autofac; using FluentAssertions; +using Nethermind.Api; +using Nethermind.Blockchain.Receipts; +using Nethermind.Blockchain.Synchronization; +using Nethermind.Consensus.Processing; using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test; +using Nethermind.Core.Test.Builders; +using Nethermind.Init.Modules; +using Nethermind.Logging; +using Nethermind.Monitoring; +using Nethermind.Monitoring.Config; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Db.Test; @@ -14,14 +28,17 @@ public class DbTrackerTests public void TestTrackOnlyCreatedDb() { using IContainer container = new ContainerBuilder() - .AddSingleton() - .AddDecorator() + .AddSingleton() + .AddSingleton(new MetricsConfig()) + .AddSingleton(LimboLogs.Instance) + .AddSingleton(NoopMonitoringService.Instance) + .AddDecorator() .AddSingleton() .Build(); IDbFactory dbFactory = container.Resolve(); - DbTracker tracker = container.Resolve(); + DbMonitoringModule.DbTracker tracker = container.Resolve(); tracker.GetAllDbMeta().Count().Should().Be(0); dbFactory.CreateDb(new DbSettings("TestDb", "TestDb")); @@ -30,4 +47,107 @@ public void TestTrackOnlyCreatedDb() var firstEntry = tracker.GetAllDbMeta().First(); firstEntry.Key.Should().Be("TestDb"); } + + [Parallelizable(ParallelScope.None)] + [TestCase(true)] + [TestCase(false)] + public void TestUpdateDbMetric(bool isProcessing) + { + IBlockProcessingQueue queue = Substitute.For(); + (IContainer container, Action updateAction, FakeDb fakeDb) = ConfigureMetricUpdater((builder) => builder.AddSingleton(queue)); + using var _ = container; + + // Reset + Metrics.DbReads["TestDb"] = 0; + + if (isProcessing) + { + container.Resolve(); // Only setup is something requested the block processing queue. + queue.IsEmpty.Returns(false); + queue.BlockAdded += Raise.EventWith(new BlockEventArgs(Build.A.Block.TestObject)); + } + + updateAction!(); + + // Assert + Assert.That(Metrics.DbReads["TestDb"], isProcessing ? Is.EqualTo(0) : Is.EqualTo(10)); + } + + [Parallelizable(ParallelScope.None)] + [Test] + public void DoesNotUpdateIfIntervalHasNotPassed() + { + (IContainer container, Action updateAction, FakeDb fakeDb) = ConfigureMetricUpdater(); + using var _ = container; + + container.Resolve().CreateDb(new DbSettings("TestDb", "TestDb")); + + // Reset + Metrics.DbReads["TestDb"] = 0; + + updateAction!(); + Assert.That(Metrics.DbReads["TestDb"], Is.EqualTo(10)); + + fakeDb.SetMetric(new IDbMeta.DbMetric() + { + TotalReads = 11 + }); + + updateAction!(); + Assert.That(Metrics.DbReads["TestDb"], Is.EqualTo(10)); + } + + private (IContainer, Action, FakeDb) ConfigureMetricUpdater(Action? configurer = null) + { + IDbFactory fakeDbFactory = Substitute.For(); + + IMonitoringService monitoringService = Substitute.For(); + ContainerBuilder builder = new ContainerBuilder() + .AddModule(new DbModule(new InitConfig(), new ReceiptConfig(), new SyncConfig())) + .AddModule(new DbMonitoringModule()) + .AddSingleton(new MetricsConfig()) + .AddSingleton(LimboLogs.Instance) + .AddSingleton(monitoringService) + .AddDecorator() + .AddSingleton(fakeDbFactory); + + configurer?.Invoke(builder); + + IContainer container = builder + .Build(); + + IDbMeta.DbMetric metric = new IDbMeta.DbMetric() + { + TotalReads = 10 + }; + FakeDb fakeDb = new FakeDb(metric); + fakeDbFactory.CreateDb(Arg.Any()).Returns(fakeDb); + + Action updateAction = null; + monitoringService + .When((m) => m.AddMetricsUpdateAction(Arg.Any())) + .Do((c) => + { + updateAction = (Action)c[0]; + }); + + container.Resolve().CreateDb(new DbSettings("TestDb", "TestDb")); + + return (container, updateAction, fakeDb); + } + + private class FakeDb(IDbMeta.DbMetric metric) : TestMemDb, IDbMeta + { + private IDbMeta.DbMetric _metric = metric; + + public override IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) + { + return _metric; + } + + internal void SetMetric(IDbMeta.DbMetric metric) + { + _metric = metric; + } + } } diff --git a/src/Nethermind/Nethermind.Db/DbTracker.cs b/src/Nethermind/Nethermind.Db/DbTracker.cs deleted file mode 100644 index 95829f161be..00000000000 --- a/src/Nethermind/Nethermind.Db/DbTracker.cs +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using NonBlocking; - -namespace Nethermind.Db; - -public class DbTracker -{ - private readonly ConcurrentDictionary _createdDbs = new ConcurrentDictionary(); - - public void AddDb(string name, IDbMeta dbMeta) - { - _createdDbs.TryAdd(name, dbMeta); - } - - public IEnumerable> GetAllDbMeta() - { - return _createdDbs; - } - - public class DbFactoryInterceptor(DbTracker tracker, IDbFactory baseFactory) : IDbFactory - { - public IDb CreateDb(DbSettings dbSettings) - { - IDb db = baseFactory.CreateDb(dbSettings); - if (db is IDbMeta dbMeta) - { - tracker.AddDb(dbSettings.DbName, dbMeta); - } - return db; - } - - public IColumnsDb CreateColumnsDb(DbSettings dbSettings) where T : struct, Enum - { - IColumnsDb db = baseFactory.CreateColumnsDb(dbSettings); - if (db is IDbMeta dbMeta) - { - tracker.AddDb(dbSettings.DbName, dbMeta); - } - return db; - } - - public string GetFullDbPath(DbSettings dbSettings) => baseFactory.GetFullDbPath(dbSettings); - } -} diff --git a/src/Nethermind/Nethermind.Db/MemDb.cs b/src/Nethermind/Nethermind.Db/MemDb.cs index e4fd0566073..72e2087e355 100644 --- a/src/Nethermind/Nethermind.Db/MemDb.cs +++ b/src/Nethermind/Nethermind.Db/MemDb.cs @@ -151,7 +151,7 @@ public virtual void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags _spanDb[key] = value; } - public IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) => new() { Size = Count }; + public virtual IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) => new() { Size = Count }; private IEnumerable> OrderedDb => _db.OrderBy(kvp => kvp.Key, Bytes.Comparer); } diff --git a/src/Nethermind/Nethermind.Init/Modules/DbModule.cs b/src/Nethermind/Nethermind.Init/Modules/DbModule.cs index 8e308a7479b..cd990ccdfe0 100644 --- a/src/Nethermind/Nethermind.Init/Modules/DbModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/DbModule.cs @@ -57,11 +57,6 @@ protected override void Load(ContainerBuilder builder) return sortedKeyValue; }) - // Monitoring use these to track active db. We intercept db factory to keep them lazy. Does not - // track db that is not created by db factory though... - .AddSingleton() - .AddDecorator() - .AddDatabase(DbNames.State) .AddDatabase(DbNames.Code) .AddDatabase(DbNames.Metadata) diff --git a/src/Nethermind/Nethermind.Init/Modules/DbMonitoringModule.cs b/src/Nethermind/Nethermind.Init/Modules/DbMonitoringModule.cs new file mode 100644 index 00000000000..e4bb8c6d874 --- /dev/null +++ b/src/Nethermind/Nethermind.Init/Modules/DbMonitoringModule.cs @@ -0,0 +1,132 @@ +// SPDX-FileCopyrightText: 2026 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using Autofac; +using Nethermind.Consensus.Processing; +using Nethermind.Core; +using Nethermind.Db; +using Nethermind.Logging; +using Nethermind.Monitoring; +using Nethermind.Monitoring.Config; + +namespace Nethermind.Init.Modules; + +public class DbMonitoringModule : Module +{ + protected override void Load(ContainerBuilder builder) + { + base.Load(builder); + + // Intercept created db to publish metric. + // Dont use constructor injection to get all db because that would resolve all db + // making them not lazy. + builder + .AddSingleton() + .AddDecorator() + + // Intercept block processing by checking the queue and pausing the metrics when that happen. + // Dont use constructor injection because this would prevent the metric from being updated before + // the block processing chain is constructed, eg: VerifyTrie or import jobs. + .Intercept((processingQueue, ctx) => + { + if (!ctx.Resolve().PauseDbMetricDuringBlockProcessing) return; + + // Do not update db metrics while processing a block + DbTracker updater = ctx.Resolve(); + processingQueue.BlockAdded += (sender, args) => updater.Paused = !processingQueue.IsEmpty; + processingQueue.BlockRemoved += (sender, args) => updater.Paused = !processingQueue.IsEmpty; + }) + ; + } + + public class DbTracker + { + private readonly ConcurrentDictionary _createdDbs = new ConcurrentDictionary(); + private readonly int _intervalSec; + private long _lastDbMetricsUpdate = 0; + + private ILogger _logger; + + public DbTracker(IMonitoringService monitoringService, IMetricsConfig metricsConfig, ILogManager logManager) + { + _intervalSec = metricsConfig.DbMetricIntervalSeconds; + _logger = logManager.GetClassLogger(); + + if (metricsConfig.EnableDbSizeMetrics) + { + monitoringService.AddMetricsUpdateAction(UpdateDbMetrics); + } + } + + public void AddDb(string name, IDbMeta dbMeta) + { + _createdDbs.TryAdd(name, dbMeta); + } + + public IEnumerable> GetAllDbMeta() + { + return _createdDbs; + } + + public bool Paused { get; set; } = false; + + private void UpdateDbMetrics() + { + try + { + if (Paused) return; + + if (Environment.TickCount64 - _lastDbMetricsUpdate < _intervalSec * 1000) + { + // Update based on configured interval + return; + } + + foreach (KeyValuePair kv in GetAllDbMeta()) + { + // Note: At the moment, the metric for a columns db is combined across column. + IDbMeta.DbMetric dbMetric = kv.Value.GatherMetric(includeSharedCache: kv.Key == DbNames.State); // Only include shared cache if state db + Db.Metrics.DbSize[kv.Key] = dbMetric.Size; + Db.Metrics.DbBlockCacheSize[kv.Key] = dbMetric.CacheSize; + Db.Metrics.DbMemtableSize[kv.Key] = dbMetric.MemtableSize; + Db.Metrics.DbIndexFilterSize[kv.Key] = dbMetric.IndexSize; + Db.Metrics.DbReads[kv.Key] = dbMetric.TotalReads; + Db.Metrics.DbWrites[kv.Key] = dbMetric.TotalWrites; + } + _lastDbMetricsUpdate = Environment.TickCount64; + } + catch (Exception e) + { + if (_logger.IsError) _logger.Error("Error during updating db metrics", e); + } + } + + public class DbFactoryInterceptor(DbTracker tracker, IDbFactory baseFactory) : IDbFactory + { + public IDb CreateDb(DbSettings dbSettings) + { + IDb db = baseFactory.CreateDb(dbSettings); + if (db is IDbMeta dbMeta) + { + tracker.AddDb(dbSettings.DbName, dbMeta); + } + return db; + } + + public IColumnsDb CreateColumnsDb(DbSettings dbSettings) where T : struct, Enum + { + IColumnsDb db = baseFactory.CreateColumnsDb(dbSettings); + if (db is IDbMeta dbMeta) + { + tracker.AddDb(dbSettings.DbName, dbMeta); + } + return db; + } + + public string GetFullDbPath(DbSettings dbSettings) => baseFactory.GetFullDbPath(dbSettings); + } + } +} diff --git a/src/Nethermind/Nethermind.Init/Modules/MonitoringModule.cs b/src/Nethermind/Nethermind.Init/Modules/MonitoringModule.cs new file mode 100644 index 00000000000..814ab35de12 --- /dev/null +++ b/src/Nethermind/Nethermind.Init/Modules/MonitoringModule.cs @@ -0,0 +1,119 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Generic; +using System.Linq; +using Autofac; +using DotNetty.Buffers; +using Nethermind.Blockchain.Synchronization; +using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.Db; +using Nethermind.Facade.Eth; +using Nethermind.Logging; +using Nethermind.Monitoring; +using Nethermind.Monitoring.Config; +using Nethermind.Monitoring.Metrics; +using Nethermind.Serialization.Rlp; + +namespace Nethermind.Init.Modules; + +public class MonitoringModule(IMetricsConfig metricsConfig) : Module +{ + protected override void Load(ContainerBuilder builder) + { + if (metricsConfig.Enabled || metricsConfig.CountersEnabled) + { + builder + .AddSingleton() + .AddSingleton( + PrepareProductInfoMetrics) + + .AddSingleton() + .Intercept(ConfigureDefaultMetrics) + + .Intercept((syncInfo, ctx) => + { + ctx.Resolve().AddMetricsUpdateAction(() => + { + Synchronization.Metrics.SyncTime = (long?)syncInfo.UpdateAndGetSyncTime().TotalSeconds ?? 0; + }); + }) + + ; + } + else + { + builder.AddSingleton(); + } + } + + private IMetricsController PrepareProductInfoMetrics(IMetricsConfig metricsConfig, ISyncConfig syncConfig, IPruningConfig pruningConfig, ISpecProvider specProvider) + { + // Need to be set here, or we cant start before blocktree, which is the one that set this normally. + ProductInfo.Network = $"{(specProvider.ChainId == specProvider.NetworkId ? BlockchainIds.GetBlockchainName(specProvider.NetworkId) : specProvider.ChainId)}"; + + ProductInfo.Instance = metricsConfig.NodeName; + + ProductInfo.SyncType = syncConfig.FastSync + ? syncConfig.SnapSync ? "Snap" : "Fast" + : "Full"; + + + ProductInfo.PruningMode = pruningConfig.Mode.ToString(); + Metrics.Version = VersionToMetrics.ConvertToNumber(ProductInfo.Version); + + IMetricsController controller = new MetricsController(metricsConfig); + + IEnumerable metrics = TypeDiscovery.FindNethermindBasedTypes(nameof(Metrics)); + foreach (Type metric in metrics) + { + controller.RegisterMetrics(metric); + } + + return controller; + } + + private void ConfigureDefaultMetrics(IMonitoringService monitoringService, IComponentContext ctx) + { + // Note: Do not add dependencies outside of monitoring module. + AllocatorMetricsUpdater allocatorMetricsUpdater = ctx.Resolve(); + monitoringService.AddMetricsUpdateAction(() => allocatorMetricsUpdater.UpdateAllocatorMetrics()); + } + + private class AllocatorMetricsUpdater(ILogManager logManager) + { + ILogger _logger = logManager.GetClassLogger(); + + public void UpdateAllocatorMetrics() + { + try + { + SetAllocatorMetrics(NethermindBuffers.RlpxAllocator, "rlpx"); + SetAllocatorMetrics(NethermindBuffers.DiscoveryAllocator, "discovery"); + SetAllocatorMetrics(NethermindBuffers.Default, "default"); + SetAllocatorMetrics(PooledByteBufferAllocator.Default, "netty_default"); + } + catch (Exception e) + { + if (_logger.IsError) _logger.Error("Error during allocator metrics", e); + } + } + + private static void SetAllocatorMetrics(IByteBufferAllocator allocator, string name) + { + if (allocator is PooledByteBufferAllocator byteBufferAllocator) + { + PooledByteBufferAllocatorMetric metric = byteBufferAllocator.Metric; + Serialization.Rlp.Metrics.AllocatorArenaCount[name] = metric.DirectArenas().Count; + Serialization.Rlp.Metrics.AllocatorChunkSize[name] = metric.ChunkSize; + Serialization.Rlp.Metrics.AllocatorUsedHeapMemory[name] = metric.UsedHeapMemory; + Serialization.Rlp.Metrics.AllocatorUsedDirectMemory[name] = metric.UsedDirectMemory; + Serialization.Rlp.Metrics.AllocatorActiveAllocations[name] = metric.HeapArenas().Sum((it) => it.NumActiveAllocations); + Serialization.Rlp.Metrics.AllocatorActiveAllocationBytes[name] = metric.HeapArenas().Sum((it) => it.NumActiveBytes); + Serialization.Rlp.Metrics.AllocatorAllocations[name] = metric.HeapArenas().Sum((it) => it.NumAllocations); + } + } + } +} diff --git a/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs b/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs index 9ff2ea05f82..41df70db238 100644 --- a/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs @@ -6,7 +6,6 @@ using Nethermind.Abi; using Nethermind.Api; using Nethermind.Blockchain; -using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Spec; using Nethermind.Blockchain.Synchronization; @@ -16,11 +15,10 @@ using Nethermind.Core.Specs; using Nethermind.Core.Timers; using Nethermind.Crypto; -using Nethermind.Db; using Nethermind.Era1; -using Nethermind.History; using Nethermind.JsonRpc; using Nethermind.Logging; +using Nethermind.Monitoring.Config; using Nethermind.Network.Config; using Nethermind.Runner.Ethereum.Modules; using Nethermind.Specs.ChainSpecStyle; @@ -48,6 +46,7 @@ protected override void Load(ContainerBuilder builder) configProvider.GetConfig(), configProvider.GetConfig() )) + .AddModule(new DbMonitoringModule()) .AddModule(new WorldStateModule(configProvider.GetConfig())) .AddModule(new PrewarmerModule(configProvider.GetConfig())) .AddModule(new BuiltInStepsModule()) @@ -56,6 +55,7 @@ protected override void Load(ContainerBuilder builder) .AddSource(new ConfigRegistrationSource()) .AddModule(new BlockProcessingModule(configProvider.GetConfig(), configProvider.GetConfig())) .AddModule(new BlockTreeModule(configProvider.GetConfig())) + .AddModule(new MonitoringModule(configProvider.GetConfig())) .AddSingleton() .AddKeyedSingleton(IProtectedPrivateKey.NodeKey, (ctx) => ctx.Resolve().NodeKey!) diff --git a/src/Nethermind/Nethermind.Init/Modules/RpcModules.cs b/src/Nethermind/Nethermind.Init/Modules/RpcModules.cs index 8f0ee78e45f..c9ff690ad82 100644 --- a/src/Nethermind/Nethermind.Init/Modules/RpcModules.cs +++ b/src/Nethermind/Nethermind.Init/Modules/RpcModules.cs @@ -8,7 +8,6 @@ using Nethermind.Blockchain.Filters; using Nethermind.Blockchain.Receipts; using Nethermind.Config; -using Nethermind.Consensus.Processing; using Nethermind.Consensus.Tracing; using Nethermind.Core; using Nethermind.Core.Timers; @@ -31,7 +30,6 @@ using Nethermind.JsonRpc.Modules.Trace; using Nethermind.JsonRpc.Modules.TxPool; using Nethermind.JsonRpc.Modules.Web3; -using Nethermind.Logging; using Nethermind.Network; using Nethermind.Network.Config; using Nethermind.Sockets; diff --git a/src/Nethermind/Nethermind.Init/Steps/EthereumStepsManager.cs b/src/Nethermind/Nethermind.Init/Steps/EthereumStepsManager.cs index a96786ba094..2a12b622109 100644 --- a/src/Nethermind/Nethermind.Init/Steps/EthereumStepsManager.cs +++ b/src/Nethermind/Nethermind.Init/Steps/EthereumStepsManager.cs @@ -254,10 +254,7 @@ private string BuildStepDependencyTree(Dictionary stepInfoMap List deps = deduplicatedDependency[node]; sb.Append(dependentsMap[node].Count == 0 ? "● " : "○ "); sb.Append(node); - if (deps.Count != 0) - { - sb.AppendLine($" (depends on {string.Join(", ", deps)})"); - } + sb.AppendLine(deps.Count != 0 ? $" (depends on {string.Join(", ", deps)})" : ""); } return sb.ToString(); diff --git a/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs b/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs index 9f4026090f6..a3ac17f3ea7 100644 --- a/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs +++ b/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs @@ -1,38 +1,20 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; -using System.Collections.Generic; -using System.Linq; using System.Threading; using System.Threading.Tasks; -using DotNetty.Buffers; using Nethermind.Api.Steps; -using Nethermind.Blockchain; -using Nethermind.Blockchain.Synchronization; -using Nethermind.Core; -using Nethermind.Core.ServiceStopper; -using Nethermind.Db; -using Nethermind.Facade.Eth; using Nethermind.Logging; using Nethermind.Monitoring; using Nethermind.Monitoring.Config; -using Nethermind.Monitoring.Metrics; -using Nethermind.Serialization.Rlp; -using Type = System.Type; namespace Nethermind.Init.Steps; -[RunnerStepDependencies(typeof(InitializeBlockchain))] +[RunnerStepDependencies()] public class StartMonitoring( - IEthSyncingInfo ethSyncingInfo, - DbTracker dbTracker, - IPruningConfig pruningConfig, - ISyncConfig syncConfig, - IServiceStopper serviceStopper, + IMonitoringService monitoringService, ILogManager logManager, - IMetricsConfig metricsConfig, - ChainHeadInfoProvider chainHeadInfoProvider + IMetricsConfig metricsConfig ) : IStep { private readonly ILogger _logger = logManager.GetClassLogger(); @@ -45,32 +27,13 @@ public async Task Execute(CancellationToken cancellationToken) logManager.SetGlobalVariable("nodeName", metricsConfig.NodeName); } - MetricsController? controller = null; - if (metricsConfig.Enabled || metricsConfig.CountersEnabled) - { - PrepareProductInfoMetrics(); - controller = new(metricsConfig); - - IEnumerable metrics = TypeDiscovery.FindNethermindBasedTypes(nameof(Metrics)); - foreach (Type metric in metrics) - { - controller.RegisterMetrics(metric); - } - } - if (metricsConfig.Enabled) { - MonitoringService monitoringService = new(controller, metricsConfig, logManager); - - SetupMetrics(monitoringService); - await monitoringService.StartAsync().ContinueWith(x => { if (x.IsFaulted && _logger.IsError) _logger.Error("Error during starting a monitoring.", x.Exception); }, cancellationToken); - - serviceStopper.AddStoppable(monitoringService); } else { @@ -86,125 +49,5 @@ await monitoringService.StartAsync().ContinueWith(x => } } - private void SetupMetrics(MonitoringService monitoringService) - { - if (metricsConfig.EnableDbSizeMetrics) - { - monitoringService.AddMetricsUpdateAction(() => Task.Run(() => UpdateDbMetrics())); - } - - if (metricsConfig.EnableDetailedMetric) - { - monitoringService.AddMetricsUpdateAction(() => Task.Run(() => UpdateAllocatorMetrics())); - } - - monitoringService.AddMetricsUpdateAction(() => - { - Synchronization.Metrics.SyncTime = (long?)ethSyncingInfo?.UpdateAndGetSyncTime().TotalSeconds ?? 0; - }); - } - - private bool _isUpdatingDbMetrics = false; - private long _lastDbMetricsUpdate = 0; - private void UpdateDbMetrics() - { - if (!Interlocked.Exchange(ref _isUpdatingDbMetrics, true)) - { - try - { - if (Environment.TickCount64 - _lastDbMetricsUpdate < 60_000) - { - // Update max every minute - return; - } - if (chainHeadInfoProvider.IsProcessingBlock) - { - // Do not update db metrics while processing a block - return; - } - - foreach (KeyValuePair kv in dbTracker.GetAllDbMeta()) - { - // Note: At the moment, the metric for a columns db is combined across column. - IDbMeta.DbMetric dbMetric = kv.Value.GatherMetric(includeSharedCache: kv.Key == DbNames.State); // Only include shared cache if state db - Db.Metrics.DbSize[kv.Key] = dbMetric.Size; - Db.Metrics.DbBlockCacheSize[kv.Key] = dbMetric.CacheSize; - Db.Metrics.DbMemtableSize[kv.Key] = dbMetric.MemtableSize; - Db.Metrics.DbIndexFilterSize[kv.Key] = dbMetric.IndexSize; - Db.Metrics.DbReads[kv.Key] = dbMetric.TotalReads; - Db.Metrics.DbWrites[kv.Key] = dbMetric.TotalWrites; - } - _lastDbMetricsUpdate = Environment.TickCount64; - } - catch (Exception e) - { - if (_logger.IsError) _logger.Error("Error during updating db metrics", e); - } - finally - { - Volatile.Write(ref _isUpdatingDbMetrics, false); - } - } - } - - private bool _isUpdatingAllocatorMetrics = false; - private void UpdateAllocatorMetrics() - { - if (!Interlocked.Exchange(ref _isUpdatingAllocatorMetrics, true)) - { - try - { - SetAllocatorMetrics(NethermindBuffers.RlpxAllocator, "rlpx"); - SetAllocatorMetrics(NethermindBuffers.DiscoveryAllocator, "discovery"); - SetAllocatorMetrics(NethermindBuffers.Default, "default"); - SetAllocatorMetrics(PooledByteBufferAllocator.Default, "netty_default"); - } - catch (Exception e) - { - if (_logger.IsError) _logger.Error("Error during allocator metrics", e); - } - finally - { - Volatile.Write(ref _isUpdatingAllocatorMetrics, false); - } - } - } - - private static void SetAllocatorMetrics(IByteBufferAllocator allocator, string name) - { - if (allocator is PooledByteBufferAllocator byteBufferAllocator) - { - PooledByteBufferAllocatorMetric metric = byteBufferAllocator.Metric; - Serialization.Rlp.Metrics.AllocatorArenaCount[name] = metric.DirectArenas().Count; - Serialization.Rlp.Metrics.AllocatorChunkSize[name] = metric.ChunkSize; - Serialization.Rlp.Metrics.AllocatorUsedHeapMemory[name] = metric.UsedHeapMemory; - Serialization.Rlp.Metrics.AllocatorUsedDirectMemory[name] = metric.UsedDirectMemory; - Serialization.Rlp.Metrics.AllocatorActiveAllocations[name] = metric.HeapArenas().Sum((it) => it.NumActiveAllocations); - Serialization.Rlp.Metrics.AllocatorActiveAllocationBytes[name] = metric.HeapArenas().Sum((it) => it.NumActiveBytes); - Serialization.Rlp.Metrics.AllocatorAllocations[name] = metric.HeapArenas().Sum((it) => it.NumAllocations); - } - } - - private void PrepareProductInfoMetrics() - { - ProductInfo.Instance = metricsConfig.NodeName; - - if (syncConfig.SnapSync) - { - ProductInfo.SyncType = "Snap"; - } - else if (syncConfig.FastSync) - { - ProductInfo.SyncType = "Fast"; - } - else - { - ProductInfo.SyncType = "Full"; - } - - ProductInfo.PruningMode = pruningConfig.Mode.ToString(); - Metrics.Version = VersionToMetrics.ConvertToNumber(ProductInfo.Version); - } - public bool MustInitialize => false; } diff --git a/src/Nethermind/Nethermind.Monitoring/Config/IMetricsConfig.cs b/src/Nethermind/Nethermind.Monitoring/Config/IMetricsConfig.cs index 83ac5bcd7e5..0eb30fade85 100644 --- a/src/Nethermind/Nethermind.Monitoring/Config/IMetricsConfig.cs +++ b/src/Nethermind/Nethermind.Monitoring/Config/IMetricsConfig.cs @@ -26,6 +26,12 @@ public interface IMetricsConfig : IConfig [ConfigItem(DefaultValue = "5", Description = "The frequency of pushing metrics to Prometheus, in seconds.")] int IntervalSeconds { get; } + [ConfigItem(DefaultValue = "60", Description = "The frequency of updating db metrics, in seconds.")] + int DbMetricIntervalSeconds { get; } + + [ConfigItem(DefaultValue = "true", Description = "Pause db metric collection during block processing to prevent overhead.")] + bool PauseDbMetricDuringBlockProcessing { get; } + [ConfigItem(Description = "The name to display on the Grafana dashboard.", DefaultValue = "Nethermind")] string NodeName { get; } diff --git a/src/Nethermind/Nethermind.Monitoring/Config/MetricsConfig.cs b/src/Nethermind/Nethermind.Monitoring/Config/MetricsConfig.cs index 77e194cc7f8..c9dc00e6f7d 100644 --- a/src/Nethermind/Nethermind.Monitoring/Config/MetricsConfig.cs +++ b/src/Nethermind/Nethermind.Monitoring/Config/MetricsConfig.cs @@ -11,6 +11,8 @@ public class MetricsConfig : IMetricsConfig public bool CountersEnabled { get; set; } = false; public string PushGatewayUrl { get; set; } = null; public int IntervalSeconds { get; set; } = 5; + public int DbMetricIntervalSeconds { get; set; } = 60; + public bool PauseDbMetricDuringBlockProcessing { get; set; } = true; public string NodeName { get; set; } = "Nethermind"; public bool EnableDbSizeMetrics { get; set; } = true; public string MonitoringGroup { get; set; } = "nethermind"; diff --git a/src/Nethermind/Nethermind.Monitoring/IMonitoringService .cs b/src/Nethermind/Nethermind.Monitoring/IMonitoringService.cs similarity index 92% rename from src/Nethermind/Nethermind.Monitoring/IMonitoringService .cs rename to src/Nethermind/Nethermind.Monitoring/IMonitoringService.cs index f8d13fc417f..d023c62503a 100644 --- a/src/Nethermind/Nethermind.Monitoring/IMonitoringService .cs +++ b/src/Nethermind/Nethermind.Monitoring/IMonitoringService.cs @@ -9,7 +9,6 @@ namespace Nethermind.Monitoring public interface IMonitoringService { Task StartAsync(); - Task StopAsync(); void AddMetricsUpdateAction(Action callback); } } diff --git a/src/Nethermind/Nethermind.Monitoring/Metrics/IMetricsController.cs b/src/Nethermind/Nethermind.Monitoring/Metrics/IMetricsController.cs index a5ed5783c91..e9a2ab9ee21 100644 --- a/src/Nethermind/Nethermind.Monitoring/Metrics/IMetricsController.cs +++ b/src/Nethermind/Nethermind.Monitoring/Metrics/IMetricsController.cs @@ -2,14 +2,15 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Threading; +using System.Threading.Tasks; namespace Nethermind.Monitoring.Metrics { public interface IMetricsController { void RegisterMetrics(Type type); - void StartUpdating(); - void StopUpdating(); + Task RunTimer(CancellationToken cancellationToken); void AddMetricsUpdateAction(Action callback); } } diff --git a/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs b/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs index a0a0b6a0cba..c28e777eca0 100644 --- a/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs +++ b/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs @@ -14,6 +14,7 @@ using System.Runtime.Serialization; using System.Text.RegularExpressions; using System.Threading; +using System.Threading.Tasks; using Nethermind.Core; using Nethermind.Core.Attributes; using Nethermind.Core.Collections; @@ -29,7 +30,6 @@ namespace Nethermind.Monitoring.Metrics public partial class MetricsController : IMetricsController { private readonly int _intervalMilliseconds; - private Timer _timer = null!; private static bool _staticLabelsInitialized; private readonly Dictionary _metricUpdaters = new(); @@ -326,29 +326,23 @@ public MetricsController(IMetricsConfig metricsConfig) _enableDetailedMetric = metricsConfig.EnableDetailedMetric; } - public void StartUpdating() => _timer = new Timer(UpdateAllMetrics, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(_intervalMilliseconds)); - - public void StopUpdating() => _timer?.Change(Timeout.Infinite, 0); - - private void UpdateAllMetrics(object? state) => UpdateAllMetrics(); - - private bool _isUpdating = false; - public void UpdateAllMetrics() + public async Task RunTimer(CancellationToken cancellationToken) { - if (!Interlocked.Exchange(ref _isUpdating, true)) + using var standardTimer = new PeriodicTimer(TimeSpan.FromMilliseconds(_intervalMilliseconds)); + + try { - try + while (await standardTimer.WaitForNextTickAsync(cancellationToken)) { - UpdateAllMetricsInner(); - } - finally - { - Volatile.Write(ref _isUpdating, false); + UpdateAllMetrics(); } } + catch (OperationCanceledException) + { + } } - private void UpdateAllMetricsInner() + public void UpdateAllMetrics() { foreach (Action callback in _callbacks) { diff --git a/src/Nethermind/Nethermind.Monitoring/MonitoringService.cs b/src/Nethermind/Nethermind.Monitoring/MonitoringService.cs index a4d23fa75f0..eac30b0f2fe 100644 --- a/src/Nethermind/Nethermind.Monitoring/MonitoringService.cs +++ b/src/Nethermind/Nethermind.Monitoring/MonitoringService.cs @@ -8,12 +8,12 @@ using Nethermind.Monitoring.Metrics; using Nethermind.Monitoring.Config; using System.Net.Sockets; -using Nethermind.Core.ServiceStopper; +using System.Threading; using Prometheus; namespace Nethermind.Monitoring; -public class MonitoringService : IMonitoringService, IStoppableService +public class MonitoringService : IMonitoringService, IAsyncDisposable { private readonly IMetricsController _metricsController; private readonly ILogger _logger; @@ -24,9 +24,18 @@ public class MonitoringService : IMonitoringService, IStoppableService private readonly string _nodeName; private readonly string _pushGatewayUrl; private readonly int _intervalSeconds; + private readonly CancellationTokenSource _timerCancellationSource; - public MonitoringService(IMetricsController metricsController, IMetricsConfig metricsConfig, ILogManager logManager) + private Task _monitoringTimerTask = Task.CompletedTask; + private int _isDisposed = 0; + + public MonitoringService( + IMetricsController metricsController, + IMetricsConfig metricsConfig, + ILogManager logManager + ) { + _timerCancellationSource = new CancellationTokenSource(); _metricsController = metricsController ?? throw new ArgumentNullException(nameof(metricsController)); string exposeHost = metricsConfig.ExposeHost; @@ -82,7 +91,17 @@ public Task StartAsync() new NethermindKestrelMetricServer(_exposeHost, _exposePort.Value).Start(); } - _metricsController.StartUpdating(); + _monitoringTimerTask = Task.Run(async () => + { + try + { + await _metricsController.RunTimer(_timerCancellationSource.Token); + } + catch (Exception ex) + { + if (_logger.IsError) _logger.Error($"Monitoring timer failed: {ex}"); + } + }); if (_logger.IsInfo) _logger.Info($"Started monitoring for the group: {_options.Group}, instance: {_options.Instance}"); return Task.CompletedTask; @@ -93,13 +112,6 @@ public void AddMetricsUpdateAction(Action callback) _metricsController.AddMetricsUpdateAction(callback); } - public Task StopAsync() - { - _metricsController.StopUpdating(); - - return Task.CompletedTask; - } - public string Description => "Monitoring service"; private Options GetOptions(IMetricsConfig config) @@ -118,4 +130,12 @@ private class Options(string job, string group, string instance) public string Instance { get; } = instance; public string Group { get; } = group; } + + public async ValueTask DisposeAsync() + { + if (Interlocked.CompareExchange(ref _isDisposed, 1, 0) != 0) return; + await _timerCancellationSource.CancelAsync(); + await _monitoringTimerTask; + _timerCancellationSource.Dispose(); + } } diff --git a/src/Nethermind/Nethermind.Monitoring/NoopMonitoringService.cs b/src/Nethermind/Nethermind.Monitoring/NoopMonitoringService.cs new file mode 100644 index 00000000000..9f7fc17d71c --- /dev/null +++ b/src/Nethermind/Nethermind.Monitoring/NoopMonitoringService.cs @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Threading.Tasks; +using Autofac; + +namespace Nethermind.Monitoring; + +public class NoopMonitoringService : IMonitoringService +{ + public static IMonitoringService Instance = new NoopMonitoringService(); + + public Task StartAsync() + { + return Task.CompletedTask; + } + + public void AddMetricsUpdateAction(Action callback) + { + } +} From fe8172c3e09e78d5ebb2e6eb762c76651c7cc3cc Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Fri, 16 Jan 2026 00:01:26 +0800 Subject: [PATCH 237/255] Fix maybe combine logic fetch child with wrong path. (#10145) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix maybe combine logicc missed a fetch node * Fix typo in test class name: StrictRawScopedTrieStoce → StrictRawScopedTrieStore (#10146) * Initial plan * Fix typo in class name: StrictRawScopedTrieStoce -> StrictRawScopedTrieStore Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --- .../PatriciaTreeBulkSetterTests.cs | 56 +++++++++++++++++-- .../Nethermind.Trie/PatriciaTree.cs | 19 +++++-- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/src/Nethermind/Nethermind.State.Test/PatriciaTreeBulkSetterTests.cs b/src/Nethermind/Nethermind.State.Test/PatriciaTreeBulkSetterTests.cs index 54e6827808c..e11940237cb 100644 --- a/src/Nethermind/Nethermind.State.Test/PatriciaTreeBulkSetterTests.cs +++ b/src/Nethermind/Nethermind.State.Test/PatriciaTreeBulkSetterTests.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Linq; using FluentAssertions; +using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Core.Test; @@ -90,6 +91,12 @@ public static IEnumerable NewBranchesGen() (new Hash256("cccccccc00000000000000000000000000000000000000000000000000000000"), MakeRandomValue(rng)), (new Hash256("cccc000000000000000000000000000000000000000000000000000000000000"), MakeRandomValue(rng)), }).SetName("deep value"); + + yield return new TestCaseData(new List<(Hash256 key, byte[] value)>() + { + (new Hash256("3333333333333333333333333333333333333333333333333333333333333333"), MakeRandomValue(rng)), + (new Hash256("3333333332222222222222222222222222222222222222222222222222222222"), MakeRandomValue(rng)), + }).SetName("matching long extension"); } public static IEnumerable PreExistingDataGen() @@ -109,6 +116,13 @@ public static IEnumerable PreExistingDataGen() (new Hash256("3322222222222222222222222222222222222222222222222222222222222222"), MakeRandomValue(rng)), }).SetName("one extension"); + yield return new TestCaseData(new List<(Hash256 key, byte[] value)>() + { + (new Hash256("3333333332222222222222222222222222222222222222222222222222222222"), MakeRandomValue(rng)), + (new Hash256("3333333333333333333333333333333333333333333333333333333333333333"), MakeRandomValue(rng)), + (new Hash256("3333333344444444444444444444444444444444444444444444444444444444"), MakeRandomValue(rng)), + }).SetName("long extension with branch child"); + yield return new TestCaseData(GenRandomOfLength(1000)).SetName("random 1000"); } @@ -122,6 +136,10 @@ public static IEnumerable BulkSetTestGen() { yield return new TestCaseData(existingData.Arguments[0], testCaseData.Arguments[0]).SetName(existingData.TestName + " and " + testCaseData.TestName); } + + List<(Hash256 key, byte[] value)> originalSet = (List<(Hash256 key, byte[] value)>)existingData.Arguments[0]; + List<(Hash256 key, byte[] value)> removal = originalSet.Select((kv) => (kv.key, (byte[])null)).ToList(); + yield return new TestCaseData(existingData.Arguments[0], removal).SetName(existingData.TestName + " and remove self completely "); } yield return new TestCaseData( @@ -255,7 +273,7 @@ public void BulkSet(List<(Hash256 key, byte[] value)> existingItems, List<(Hash2 long newWriteCount = 0; { TestMemDb db = new TestMemDb(); - IScopedTrieStore trieStore = new RawScopedTrieStore(db); + IScopedTrieStore trieStore = new StrictRawScopedTrieStore(new RawScopedTrieStore(db)); PatriciaTree pTree = new PatriciaTree(trieStore, LimboLogs.Instance); pTree.RootHash = Keccak.EmptyTreeHash; @@ -306,7 +324,7 @@ public void BulkSetRootHashUpdated(List<(Hash256 key, byte[] value)> existingIte (Hash256 root, TimeSpan baselineTime, long baselineWriteCount, string originalDump) = CalculateBaseline(existingItems, items, recordDump); TestMemDb db = new TestMemDb(); - IScopedTrieStore trieStore = new RawScopedTrieStore(db); + IScopedTrieStore trieStore = new StrictRawScopedTrieStore(new RawScopedTrieStore(db)); PatriciaTree pTree = new PatriciaTree(trieStore, LimboLogs.Instance); pTree.RootHash = Keccak.EmptyTreeHash; @@ -338,7 +356,7 @@ public void BulkSetPreSorted(List<(Hash256 key, byte[] value)> existingItems, Li long preSortedWriteCount; { TestMemDb db = new TestMemDb(); - IScopedTrieStore trieStore = new RawScopedTrieStore(db); + IScopedTrieStore trieStore = new StrictRawScopedTrieStore(new RawScopedTrieStore(db)); PatriciaTree pTree = new PatriciaTree(trieStore, LimboLogs.Instance); pTree.RootHash = Keccak.EmptyTreeHash; @@ -396,7 +414,7 @@ public void BulkSetOneByOne(List<(Hash256 key, byte[] value)> existingItems, Lis { // Just the bulk set one stack TestMemDb db = new TestMemDb(); - IScopedTrieStore trieStore = new RawScopedTrieStore(db); + IScopedTrieStore trieStore = new StrictRawScopedTrieStore(new RawScopedTrieStore(db)); PatriciaTree pTree = new PatriciaTree(trieStore, LimboLogs.Instance); pTree.RootHash = Keccak.EmptyTreeHash; @@ -448,7 +466,7 @@ private static (Hash256, TimeSpan, long, string originalDump) CalculateBaseline( long baselineWriteCount = 0; { TestMemDb db = new TestMemDb(); - IScopedTrieStore trieStore = new RawScopedTrieStore(db); + IScopedTrieStore trieStore = new StrictRawScopedTrieStore(new RawScopedTrieStore(db)); PatriciaTree pTree = new PatriciaTree(trieStore, LimboLogs.Instance); pTree.RootHash = Keccak.EmptyTreeHash; @@ -484,7 +502,7 @@ private static (Hash256, TimeSpan, long, string originalDump) CalculateBaseline( [Test] public void BulkSet_ShouldThrowOnNonUniqueEntries() { - IScopedTrieStore trieStore = new RawScopedTrieStore(new TestMemDb()); + IScopedTrieStore trieStore = new StrictRawScopedTrieStore(new RawScopedTrieStore(new TestMemDb())); PatriciaTree pTree = new PatriciaTree(trieStore, LimboLogs.Instance); pTree.RootHash = Keccak.EmptyTreeHash; @@ -715,4 +733,30 @@ public void HexarySearch(int nibIndex, List paths, List baseTrieStore.LoadRlp(in path, hash, flags); + + public byte[] TryLoadRlp(in TreePath path, Hash256 hash, ReadFlags flags = ReadFlags.None) => baseTrieStore.TryLoadRlp(in path, hash, flags); + + public ITrieNodeResolver GetStorageTrieNodeResolver(Hash256 address) => baseTrieStore.GetStorageTrieNodeResolver(address); + + public INodeStorage.KeyScheme Scheme => baseTrieStore.Scheme; + + public ICommitter BeginCommit(TrieNode root, WriteFlags writeFlags = WriteFlags.None) => baseTrieStore.BeginCommit(root, writeFlags); + + public bool IsPersisted(in TreePath path, in ValueHash256 keccak) => baseTrieStore.IsPersisted(in path, in keccak); + } } diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs index e903cd28fa0..98cbfb2fb76 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs @@ -142,13 +142,19 @@ public void Commit(bool skipRoot = false, WriteFlags writeFlags = WriteFlags.Non _writeBeforeCommit = 0; - using ICommitter committer = TrieStore.BeginCommit(RootRef, writeFlags); - if (RootRef is not null && RootRef.IsDirty) + TrieNode? newRoot = RootRef; + using (ICommitter committer = TrieStore.BeginCommit(RootRef, writeFlags)) { - TreePath path = TreePath.Empty; - RootRef = Commit(committer, ref path, RootRef, skipSelf: skipRoot, maxLevelForConcurrentCommit: maxLevelForConcurrentCommit); + if (RootRef is not null && RootRef.IsDirty) + { + TreePath path = TreePath.Empty; + newRoot = Commit(committer, ref path, RootRef, skipSelf: skipRoot, maxLevelForConcurrentCommit: maxLevelForConcurrentCommit); + } } + // Need to be after committer dispose so that it can find it in trie store properly + RootRef = newRoot; + // Sometimes RootRef is set to null, so we still need to reset roothash to empty tree hash. SetRootHash(RootRef?.Keccak, true); } @@ -774,7 +780,9 @@ internal bool ShouldUpdateChild(TrieNode? parent, TrieNode? oldChild, TrieNode? byte[] extensionKey = HexPrefix.SingleNibble((byte)onlyChildIdx); if (originalNode is not null && originalNode.IsExtension && Bytes.AreEqual(extensionKey, originalNode.Key)) { + path.AppendMut(onlyChildIdx); TrieNode? originalChild = originalNode.GetChildWithChildPath(TrieStore, ref path, 0); + path.TruncateOne(); if (!ShouldUpdateChild(originalNode, originalChild, onlyChildNode)) { return originalNode; @@ -793,8 +801,11 @@ internal bool ShouldUpdateChild(TrieNode? parent, TrieNode? oldChild, TrieNode? { if (Bytes.AreEqual(newKey, originalNode.Key)) { + int originalLength = path.Length; + path.AppendMut(newKey); TrieNode? originalChild = originalNode.GetChildWithChildPath(TrieStore, ref path, 0); TrieNode? newChild = onlyChildNode.GetChildWithChildPath(TrieStore, ref path, 0); + path.TruncateMut(originalLength); if (!ShouldUpdateChild(originalNode, originalChild, newChild)) { return originalNode; From 95f2d696e82e902a33765d8c9e8b0d3f7d3810c1 Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Fri, 16 Jan 2026 00:02:05 +0800 Subject: [PATCH 238/255] Feature/RocksDb Snapshot (#10080) * Snapshot support * Move logic to db reader * Ensure get is used * Add comment on verify checksum * Format * Address PR #10080 review comments: fix memory leaks, improve documentation, add safety checks (#10083) * Initial plan * Address review comments: fix docs, memory leaks, and add safety checks Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> * Remove unused _readOptions field from RocksdbSortedView Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> * Use discard pattern for unused readOptions parameter Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> * Remove unnecessary readOptions parameter from RocksdbSortedView Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> * Make nullable --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --- .../Nethermind.Core/IKeyValueStore.cs | 72 ++++++- .../Nethermind.Db.Rocks/ColumnDb.cs | 57 ++++-- .../Nethermind.Db.Rocks/DbOnTheRocks.cs | 177 ++++++++++++------ .../Nethermind.Db.Rocks/RocksDbReader.cs | 123 ++++++++++++ .../Nethermind.Db.Rocks/RocksdbSortedView.cs | 15 +- .../Nethermind.Db.Test/DbOnTheRocksTests.cs | 126 +++++++++++-- 6 files changed, 481 insertions(+), 89 deletions(-) create mode 100644 src/Nethermind/Nethermind.Db.Rocks/RocksDbReader.cs diff --git a/src/Nethermind/Nethermind.Core/IKeyValueStore.cs b/src/Nethermind/Nethermind.Core/IKeyValueStore.cs index 52a6b97b317..d80cfc3d40a 100644 --- a/src/Nethermind/Nethermind.Core/IKeyValueStore.cs +++ b/src/Nethermind/Nethermind.Core/IKeyValueStore.cs @@ -28,6 +28,32 @@ public interface IReadOnlyKeyValueStore /// Can return null or empty Span on missing key Span GetSpan(scoped ReadOnlySpan key, ReadFlags flags = ReadFlags.None) => Get(key, flags); + /// + /// Get, C-style. Write the output to span and return the length of written data. + /// Cannot differentiate if the data is missing or does not exist. Throws if is not large enough. + /// + /// Key whose associated value should be read. + /// Destination buffer to receive the value bytes; must be large enough to hold the data. + /// Read behavior flags that control how the value is retrieved. + /// The number of bytes written into . + int Get(scoped ReadOnlySpan key, Span output, ReadFlags flags = ReadFlags.None) + { + Span span = GetSpan(key, flags); + try + { + if (span.IsNull()) + { + return 0; + } + span.CopyTo(output); + return span.Length; + } + finally + { + DangerousReleaseMemory(span); + } + } + bool KeyExists(ReadOnlySpan key) { Span span = GetSpan(key); @@ -74,12 +100,54 @@ public interface IMergeableKeyValueStore : IWriteOnlyKeyValueStore void Merge(ReadOnlySpan key, ReadOnlySpan value, WriteFlags flags = WriteFlags.None); } - public interface ISortedKeyValueStore : IKeyValueStore + public interface ISortedKeyValueStore : IReadOnlyKeyValueStore { byte[]? FirstKey { get; } byte[]? LastKey { get; } - ISortedView GetViewBetween(ReadOnlySpan firstKey, ReadOnlySpan lastKey); + ISortedView GetViewBetween(ReadOnlySpan firstKeyInclusive, ReadOnlySpan lastKeyExclusive); + } + + /// + /// Provides the capability to create read-only snapshots of a key-value store. + /// + /// + /// Implementations expose a that represents a consistent, + /// point-in-time view of the underlying store. The snapshot is not affected by subsequent writes + /// to the parent store, but it reflects the state as it existed when + /// was called. + /// + public interface IKeyValueStoreWithSnapshot + { + /// + /// Creates a new read-only snapshot of the current state of the key-value store. + /// + /// + /// An that can be used to perform read operations + /// against a stable view of the data. + /// + /// + /// The returned snapshot must be disposed when no longer needed in order to release any + /// resources that may be held by the underlying storage engine (for example, pinned + /// iterators or file handles). The snapshot is guaranteed to be consistent with the + /// state of the store at the time of creation, regardless of concurrent modifications + /// performed afterwards. + /// + IKeyValueStoreSnapshot CreateSnapshot(); + } + + /// + /// Represents a read-only, point-in-time view of the data in an . + /// + /// + /// A snapshot exposes the API and is isolated from + /// subsequent mutations to the parent store. Implementations are expected to provide a + /// consistent view of the data as it existed when the snapshot was created. Callers must + /// dispose the snapshot via when finished with it to + /// free any underlying resources. + /// + public interface IKeyValueStoreSnapshot : IReadOnlyKeyValueStore, IDisposable + { } /// diff --git a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs index 91879eeea77..3a049de3b6d 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs @@ -10,13 +10,14 @@ namespace Nethermind.Db.Rocks; -public class ColumnDb : IDb, ISortedKeyValueStore, IMergeableKeyValueStore +public class ColumnDb : IDb, ISortedKeyValueStore, IMergeableKeyValueStore, IKeyValueStoreWithSnapshot { private readonly RocksDb _rocksDb; internal readonly DbOnTheRocks _mainDb; internal readonly ColumnFamilyHandle _columnFamily; private readonly DbOnTheRocks.IteratorManager _iteratorManager; + private readonly RocksDbReader _reader; public ColumnDb(RocksDb rocksDb, DbOnTheRocks mainDb, string name) { @@ -27,6 +28,11 @@ public ColumnDb(RocksDb rocksDb, DbOnTheRocks mainDb, string name) Name = name; _iteratorManager = new DbOnTheRocks.IteratorManager(_rocksDb, _columnFamily, _mainDb._readAheadReadOptions); + _reader = new RocksDbReader(mainDb, () => + { + // TODO: Verify checksum not set here. + return new ReadOptions(); + }, _iteratorManager, _columnFamily); } public void Dispose() @@ -36,14 +42,29 @@ public void Dispose() public string Name { get; } - public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) + byte[]? IReadOnlyKeyValueStore.Get(ReadOnlySpan key, ReadFlags flags) + { + return _reader.Get(key, flags); + } + + Span IReadOnlyKeyValueStore.GetSpan(scoped ReadOnlySpan key, ReadFlags flags) { - return _mainDb.GetWithColumnFamily(key, _columnFamily, _iteratorManager, flags); + return _reader.GetSpan(key, flags); } - public Span GetSpan(scoped ReadOnlySpan key, ReadFlags flags = ReadFlags.None) + int IReadOnlyKeyValueStore.Get(scoped ReadOnlySpan key, Span output, ReadFlags flags) { - return _mainDb.GetSpanWithColumnFamily(key, _columnFamily, flags); + return _reader.Get(key, output, flags); + } + + bool IReadOnlyKeyValueStore.KeyExists(ReadOnlySpan key) + { + return _reader.KeyExists(key); + } + + void IReadOnlyKeyValueStore.DangerousReleaseMemory(in ReadOnlySpan key) + { + _reader.DangerousReleaseMemory(key); } public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) @@ -143,11 +164,6 @@ public void Remove(ReadOnlySpan key) Set(key, null); } - public bool KeyExists(ReadOnlySpan key) - { - return _mainDb.KeyExistsWithColumn(key, _columnFamily); - } - public void Flush(bool onlyWal) { _mainDb.FlushWithColumnFamily(_columnFamily); @@ -167,11 +183,6 @@ public void Compact() // Maybe it should be column specific metric? public IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) => _mainDb.GatherMetric(includeSharedCache); - public void DangerousReleaseMemory(in ReadOnlySpan span) - { - _mainDb.DangerousReleaseMemory(span); - } - public byte[]? FirstKey { get @@ -198,4 +209,20 @@ public ISortedView GetViewBetween(ReadOnlySpan firstKey, ReadOnlySpan + { + ReadOptions readOptions = new(); + readOptions.SetSnapshot(snapshot); + return readOptions; + }, + _columnFamily, + snapshot); + } } diff --git a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs index d1d326ef1ac..4b97f49c69f 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs @@ -29,7 +29,7 @@ namespace Nethermind.Db.Rocks; -public partial class DbOnTheRocks : IDb, ITunableDb, IReadOnlyNativeKeyValueStore, ISortedKeyValueStore, IMergeableKeyValueStore +public partial class DbOnTheRocks : IDb, ITunableDb, IReadOnlyNativeKeyValueStore, ISortedKeyValueStore, IMergeableKeyValueStore, IKeyValueStoreWithSnapshot { protected ILogger _logger; @@ -92,6 +92,7 @@ public partial class DbOnTheRocks : IDb, ITunableDb, IReadOnlyNativeKeyValueStor private readonly IteratorManager _iteratorManager; private ulong _writeBufferSize; private int _maxWriteBufferNumber; + private readonly RocksDbReader _reader; public DbOnTheRocks( string basePath, @@ -113,6 +114,13 @@ public DbOnTheRocks( _perTableDbConfig = rocksDbConfigFactory.GetForDatabase(Name, null); _db = Init(basePath, dbSettings.DbPath, dbConfig, logManager, columnFamilies, dbSettings.DeleteOnStart, sharedCache); _iteratorManager = new IteratorManager(_db, null, _readAheadReadOptions); + + _reader = new RocksDbReader(this, () => + { + ReadOptions readOptions = new ReadOptions(); + readOptions.SetVerifyChecksums(_perTableDbConfig.VerifyChecksum ?? true); + return readOptions; + }, _iteratorManager, null); } protected virtual RocksDb DoOpen(string path, (DbOptions Options, ColumnFamilies? Families) db) @@ -250,15 +258,15 @@ private void WarmupFile(string basePath, RocksDb db) long totalSize = 0; fileMetadataEntries = fileMetadataEntries.TakeWhile(metadata => - { - availableMemory -= (long)metadata.metadata.FileSize; - bool take = availableMemory > 0; - if (take) { - totalSize += (long)metadata.metadata.FileSize; - } - return take; - }) + availableMemory -= (long)metadata.metadata.FileSize; + bool take = availableMemory > 0; + if (take) + { + totalSize += (long)metadata.metadata.FileSize; + } + return take; + }) // We reverse them again so that lower level goes last so that it is the freshest. // Not all of the available memory is actually available so we are probably over reading things. .Reverse() @@ -635,44 +643,32 @@ private static WriteOptions CreateWriteOptions(IRocksDbConfig dbConfig) return options; } - public byte[]? this[ReadOnlySpan key] + byte[]? IReadOnlyKeyValueStore.Get(ReadOnlySpan key, ReadFlags flags) { - get => Get(key, ReadFlags.None); - set => Set(key, value, WriteFlags.None); + return _reader.Get(key, flags); } - public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) + Span IReadOnlyKeyValueStore.GetSpan(scoped ReadOnlySpan key, ReadFlags flags) { - return GetWithColumnFamily(key, null, _iteratorManager, flags); + return _reader.GetSpan(key, flags); } - internal byte[]? GetWithColumnFamily(ReadOnlySpan key, ColumnFamilyHandle? cf, IteratorManager iteratorManager, ReadFlags flags = ReadFlags.None) + int IReadOnlyKeyValueStore.Get(scoped ReadOnlySpan key, Span output, ReadFlags flags) { - ObjectDisposedException.ThrowIf(_isDisposing, this); - - UpdateReadMetrics(); + return _reader.Get(key, output, flags); + } - try - { - if (_readAheadReadOptions is not null && (flags & ReadFlags.HintReadAhead) != 0) - { - byte[]? result = GetWithIterator(key, cf, iteratorManager, flags, out bool success); - if (success) - { - return result; - } - } + bool IReadOnlyKeyValueStore.KeyExists(ReadOnlySpan key) + { + return _reader.KeyExists(key); + } - return Get(key, cf, flags); - } - catch (RocksDbSharpException e) - { - CreateMarkerIfCorrupt(e); - throw; - } + void IReadOnlyKeyValueStore.DangerousReleaseMemory(in ReadOnlySpan span) + { + _reader.DangerousReleaseMemory(span); } - private unsafe byte[]? GetWithIterator(ReadOnlySpan key, ColumnFamilyHandle? cf, IteratorManager iteratorManager, ReadFlags flags, out bool success) + internal unsafe byte[]? GetWithIterator(ReadOnlySpan key, ColumnFamilyHandle? cf, IteratorManager iteratorManager, ReadFlags flags, out bool success) { success = true; @@ -694,21 +690,21 @@ public byte[]? this[ReadOnlySpan key] return null; } - private unsafe byte[]? Get(ReadOnlySpan key, ColumnFamilyHandle? cf, ReadFlags flags) + internal unsafe byte[]? Get(ReadOnlySpan key, ColumnFamilyHandle? cf, ReadOptions readOptions) { // TODO: update when merged upstream: https://github.com/curiosity-ai/rocksdb-sharp/pull/61 // return _db.Get(key, cf, (flags & ReadFlags.HintCacheMiss) != 0 ? _hintCacheMissOptions : _defaultReadOptions); nint db = _db.Handle; - nint read_options = ((flags & ReadFlags.HintCacheMiss) != 0 ? _hintCacheMissOptions : _defaultReadOptions).Handle; + nint read_options = readOptions.Handle; UIntPtr skLength = (UIntPtr)key.Length; IntPtr handle; IntPtr errPtr; fixed (byte* ptr = &MemoryMarshal.GetReference(key)) { handle = cf is null - ? Native.Instance.rocksdb_get_pinned(db, read_options, ptr, skLength, out errPtr) - : Native.Instance.rocksdb_get_pinned_cf(db, read_options, cf.Handle, ptr, skLength, out errPtr); + ? Native.Instance.rocksdb_get_pinned(db, read_options, ptr, skLength, out errPtr) + : Native.Instance.rocksdb_get_pinned_cf(db, read_options, cf.Handle, ptr, skLength, out errPtr); } if (errPtr != IntPtr.Zero) ThrowRocksDbException(errPtr); @@ -871,12 +867,7 @@ internal void SetWithColumnFamily(ReadOnlySpan key, ColumnFamilyHandle? cf } } - public Span GetSpan(scoped ReadOnlySpan key, ReadFlags flags) - { - return GetSpanWithColumnFamily(key, null, flags); - } - - internal Span GetSpanWithColumnFamily(scoped ReadOnlySpan key, ColumnFamilyHandle? cf, ReadFlags flags) + internal Span GetSpanWithColumnFamily(scoped ReadOnlySpan key, ColumnFamilyHandle? cf, ReadOptions readOptions) { ObjectDisposedException.ThrowIf(_isDisposing, this); @@ -884,7 +875,7 @@ internal Span GetSpanWithColumnFamily(scoped ReadOnlySpan key, Colum try { - Span span = _db.GetSpan(key, cf, (flags & ReadFlags.HintCacheMiss) != 0 ? _hintCacheMissOptions : _defaultReadOptions); + Span span = _db.GetSpan(key, cf, readOptions); if (!span.IsNullOrEmpty()) { @@ -900,6 +891,58 @@ internal Span GetSpanWithColumnFamily(scoped ReadOnlySpan key, Colum } } + internal unsafe int GetCStyleWithColumnFamily(scoped ReadOnlySpan key, Span output, ColumnFamilyHandle? cf, ReadOptions readOptions) + { + ObjectDisposedException.ThrowIf(_isDisposing, this); + + UpdateReadMetrics(); + + nint db = _db.Handle; + nint read_options = readOptions.Handle; + UIntPtr skLength = (UIntPtr)key.Length; + IntPtr errPtr; + IntPtr slice; + fixed (byte* ptr = &MemoryMarshal.GetReference(key)) + { + slice = cf is null + ? Native.Instance.rocksdb_get_pinned(db, read_options, ptr, skLength, out errPtr) + : Native.Instance.rocksdb_get_pinned_cf(db, read_options, cf.Handle, ptr, skLength, out errPtr); + } + + if (errPtr != IntPtr.Zero) ThrowRocksDbException(errPtr); + if (slice == IntPtr.Zero) return 0; + + IntPtr valuePtr = Native.Instance.rocksdb_pinnableslice_value(slice, out UIntPtr valueLength); + if (valuePtr == IntPtr.Zero) + { + Native.Instance.rocksdb_pinnableslice_destroy(slice); + return 0; + } + + int length = (int)valueLength; + if (output.Length < length) + { + Native.Instance.rocksdb_pinnableslice_destroy(slice); + ThrowNotEnoughMemory(length, output.Length); + } + + new ReadOnlySpan((void*)valuePtr, length).CopyTo(output); + Native.Instance.rocksdb_pinnableslice_destroy(slice); + return length; + + [DoesNotReturn, StackTraceHidden] + static unsafe void ThrowRocksDbException(nint errPtr) + { + throw new RocksDbException(errPtr); + } + + [DoesNotReturn, StackTraceHidden] + static unsafe void ThrowNotEnoughMemory(int length, int bufferLength) + { + throw new ArgumentException($"Output buffer not large enough. Output size: {length}, Buffer size: {bufferLength}"); + } + } + public void PutSpan(ReadOnlySpan key, ReadOnlySpan value, WriteFlags writeFlags) { SetWithColumnFamily(key, null, value, writeFlags); @@ -1193,11 +1236,6 @@ internal IEnumerable GetAllKeysCore(Iterator iterator) } } - public bool KeyExists(ReadOnlySpan key) - { - return KeyExistsWithColumn(key, null); - } - protected internal bool KeyExistsWithColumn(ReadOnlySpan key, ColumnFamilyHandle? cf) { ObjectDisposedException.ThrowIf(_isDisposing, this); @@ -1752,7 +1790,7 @@ private static IDictionary GetBlobFilesOptions() /// /// This class handles a periodic timer which periodically dispose all iterator. /// - internal class IteratorManager : IDisposable + public class IteratorManager : IDisposable { private readonly ManagedIterators _readaheadIterators = new(); private readonly ManagedIterators _readaheadIterators2 = new(); @@ -1927,18 +1965,45 @@ internal ISortedView GetViewBetween(ReadOnlySpan firstKey, ReadOnlySpan(iterateLowerBound.ToPointer(), firstKey.Length)); Native.Instance.rocksdb_readoptions_set_iterate_lower_bound(readOptions.Handle, iterateLowerBound, (UIntPtr)firstKey.Length); - IntPtr iterateUpperBound = Marshal.AllocHGlobal(lastKey.Length); + iterateUpperBound = Marshal.AllocHGlobal(lastKey.Length); lastKey.CopyTo(new Span(iterateUpperBound.ToPointer(), lastKey.Length)); Native.Instance.rocksdb_readoptions_set_iterate_upper_bound(readOptions.Handle, iterateUpperBound, (UIntPtr)lastKey.Length); } Iterator iterator = CreateIterator(readOptions, cf); - return new RocksdbSortedView(iterator); + return new RocksdbSortedView(iterator, iterateLowerBound, iterateUpperBound); + } + + public IKeyValueStoreSnapshot CreateSnapshot() + { + Snapshot snapshot = _db.CreateSnapshot(); + return new RocksDbSnapshot(this, () => + { + ReadOptions readOptions = new ReadOptions(); + readOptions.SetSnapshot(snapshot); + return readOptions; + }, null, snapshot); + } + + public class RocksDbSnapshot( + DbOnTheRocks mainDb, + Func readOptionsFactory, + ColumnFamilyHandle? columnFamily, + Snapshot snapshot + ) : RocksDbReader(mainDb, readOptionsFactory, null, columnFamily), IKeyValueStoreSnapshot + { + public void Dispose() + { + snapshot.Dispose(); + } } } diff --git a/src/Nethermind/Nethermind.Db.Rocks/RocksDbReader.cs b/src/Nethermind/Nethermind.Db.Rocks/RocksDbReader.cs new file mode 100644 index 00000000000..0b5957e2273 --- /dev/null +++ b/src/Nethermind/Nethermind.Db.Rocks/RocksDbReader.cs @@ -0,0 +1,123 @@ +// SPDX-FileCopyrightText: 2026 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Runtime.InteropServices; +using Nethermind.Core; +using Nethermind.Core.Extensions; +using RocksDbSharp; + +namespace Nethermind.Db.Rocks; + +/// +/// Used by `DbOnTheRocks`, `ColumnDb` and `RocksDbSnapshot` to ensure all the methods of +/// `ISortedKeyValueStore` are implemented for the three classes. The three classes are expected +/// to create their relevant read options and create this class then call this class instead of +/// implementing `ISortedKeyValueStore` implementation themselves. +/// This tends to call `DbOnTheRocks` back though. +/// +public class RocksDbReader : ISortedKeyValueStore +{ + private readonly DbOnTheRocks _mainDb; + private readonly Func _readOptionsFactory; + private readonly DbOnTheRocks.IteratorManager? _iteratorManager; + private readonly ColumnFamilyHandle? _columnFamily; + + readonly ReadOptions _options; + readonly ReadOptions _hintCacheMissOptions; + + public RocksDbReader(DbOnTheRocks mainDb, + Func readOptionsFactory, + DbOnTheRocks.IteratorManager? iteratorManager = null, + ColumnFamilyHandle? columnFamily = null) + { + _mainDb = mainDb; + _readOptionsFactory = readOptionsFactory; + _iteratorManager = iteratorManager; + _columnFamily = columnFamily; + + _options = readOptionsFactory(); + _hintCacheMissOptions = readOptionsFactory(); + _hintCacheMissOptions.SetFillCache(false); + } + + public byte[]? Get(scoped ReadOnlySpan key, ReadFlags flags = ReadFlags.None) + { + if ((flags & ReadFlags.HintReadAhead) != 0 && _iteratorManager is not null) + { + byte[]? result = _mainDb.GetWithIterator(key, _columnFamily, _iteratorManager, flags, out bool success); + if (success) + { + return result; + } + } + + ReadOptions readOptions = ((flags & ReadFlags.HintCacheMiss) != 0 ? _hintCacheMissOptions : _options); + return _mainDb.Get(key, _columnFamily, readOptions); + } + + public int Get(scoped ReadOnlySpan key, Span output, ReadFlags flags = ReadFlags.None) + { + ReadOptions readOptions = ((flags & ReadFlags.HintCacheMiss) != 0 ? _hintCacheMissOptions : _options); + return _mainDb.GetCStyleWithColumnFamily(key, output, _columnFamily, readOptions); + } + + public Span GetSpan(scoped ReadOnlySpan key, ReadFlags flags = ReadFlags.None) + { + ReadOptions readOptions = ((flags & ReadFlags.HintCacheMiss) != 0 ? _hintCacheMissOptions : _options); + return _mainDb.GetSpanWithColumnFamily(key, _columnFamily, readOptions); + } + + public void DangerousReleaseMemory(in ReadOnlySpan span) + { + _mainDb.DangerousReleaseMemory(span); + } + + public bool KeyExists(ReadOnlySpan key) + { + return _mainDb.KeyExistsWithColumn(key, _columnFamily); + } + + + public byte[]? FirstKey + { + get + { + using Iterator iterator = _mainDb.CreateIterator(_options, _columnFamily); + iterator.SeekToFirst(); + return iterator.Valid() ? iterator.GetKeySpan().ToArray() : null; + } + } + + public byte[]? LastKey + { + get + { + using Iterator iterator = _mainDb.CreateIterator(_options, _columnFamily); + iterator.SeekToLast(); + return iterator.Valid() ? iterator.GetKeySpan().ToArray() : null; + } + } + + public ISortedView GetViewBetween(ReadOnlySpan firstKey, ReadOnlySpan lastKey) + { + ReadOptions readOptions = _readOptionsFactory(); + + IntPtr iterateLowerBound = IntPtr.Zero; + IntPtr iterateUpperBound = IntPtr.Zero; + + unsafe + { + iterateLowerBound = Marshal.AllocHGlobal(firstKey.Length); + firstKey.CopyTo(new Span(iterateLowerBound.ToPointer(), firstKey.Length)); + Native.Instance.rocksdb_readoptions_set_iterate_lower_bound(readOptions.Handle, iterateLowerBound, (UIntPtr)firstKey.Length); + + iterateUpperBound = Marshal.AllocHGlobal(lastKey.Length); + lastKey.CopyTo(new Span(iterateUpperBound.ToPointer(), lastKey.Length)); + Native.Instance.rocksdb_readoptions_set_iterate_upper_bound(readOptions.Handle, iterateUpperBound, (UIntPtr)lastKey.Length); + } + + Iterator iterator = _mainDb.CreateIterator(readOptions, _columnFamily); + return new RocksdbSortedView(iterator, iterateLowerBound, iterateUpperBound); + } +} diff --git a/src/Nethermind/Nethermind.Db.Rocks/RocksdbSortedView.cs b/src/Nethermind/Nethermind.Db.Rocks/RocksdbSortedView.cs index a64fe85d5b4..02e9a027681 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/RocksdbSortedView.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/RocksdbSortedView.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Runtime.InteropServices; using Nethermind.Core; using RocksDbSharp; @@ -10,16 +11,28 @@ namespace Nethermind.Db.Rocks; internal class RocksdbSortedView : ISortedView { private readonly Iterator _iterator; + private readonly IntPtr _lowerBound; + private readonly IntPtr _upperBound; private bool _started = false; - public RocksdbSortedView(Iterator iterator) + public RocksdbSortedView(Iterator iterator, IntPtr lowerBound = default, IntPtr upperBound = default) { _iterator = iterator; + _lowerBound = lowerBound; + _upperBound = upperBound; } public void Dispose() { _iterator.Dispose(); + if (_lowerBound != IntPtr.Zero) + { + Marshal.FreeHGlobal(_lowerBound); + } + if (_upperBound != IntPtr.Zero) + { + Marshal.FreeHGlobal(_upperBound); + } } public bool StartBefore(ReadOnlySpan value) diff --git a/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs b/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs index 304cb44ce9f..31954292981 100644 --- a/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs @@ -124,9 +124,10 @@ public void CanOpenWithFileWarmer() config.EnableFileWarmer = true; { using DbOnTheRocks db = new("testFileWarmer", GetRocksDbSettings("testFileWarmer", "FileWarmerTest"), config, _rocksdbConfigFactory, LimboLogs.Instance); + IKeyValueStore asKv = db; for (int i = 0; i < 1000; i++) { - db[i.ToBigEndianByteArray()] = i.ToBigEndianByteArray(); + asKv[i.ToBigEndianByteArray()] = i.ToBigEndianByteArray(); } } @@ -289,11 +290,32 @@ public void TearDown() [Test] public void Smoke_test() { - _db[new byte[] { 1, 2, 3 }] = new byte[] { 4, 5, 6 }; - Assert.That(_db[new byte[] { 1, 2, 3 }], Is.EqualTo(new byte[] { 4, 5, 6 })); + _db[[1, 2, 3]] = [4, 5, 6]; + AssertCanGetViaAllMethod(_db, [1, 2, 3], [4, 5, 6]); + + _db.Set([2, 3, 4], [5, 6, 7], WriteFlags.LowPriority); + AssertCanGetViaAllMethod(_db, [2, 3, 4], [5, 6, 7]); + } + + [Test] + public void Snapshot_test() + { + IKeyValueStoreWithSnapshot withSnapshot = (IKeyValueStoreWithSnapshot)_db; + + byte[] key = new byte[] { 1, 2, 3 }; + + _db[key] = new byte[] { 4, 5, 6 }; + AssertCanGetViaAllMethod(_db, key, new byte[] { 4, 5, 6 }); + + using IKeyValueStoreSnapshot snapshot = withSnapshot.CreateSnapshot(); + AssertCanGetViaAllMethod(snapshot, key, new byte[] { 4, 5, 6 }); + + _db.Set(key, new byte[] { 5, 6, 7 }); + AssertCanGetViaAllMethod(_db, key, new byte[] { 5, 6, 7 }); - _db.Set(new byte[] { 2, 3, 4 }, new byte[] { 5, 6, 7 }, WriteFlags.LowPriority); - Assert.That(_db[new byte[] { 2, 3, 4 }], Is.EqualTo(new byte[] { 5, 6, 7 })); + AssertCanGetViaAllMethod(snapshot, key, new byte[] { 4, 5, 6 }); + + Assert.That(_db.KeyExists(new byte[] { 99, 99, 99 }), Is.False); } [Test] @@ -310,7 +332,7 @@ public void Smoke_test_large_writes_with_nowal() for (int i = 0; i < 1000; i++) { - _db[i.ToBigEndianByteArray()].Should().BeEquivalentTo(i.ToBigEndianByteArray()); + AssertCanGetViaAllMethod(_db, i.ToBigEndianByteArray(), i.ToBigEndianByteArray()); } } @@ -401,20 +423,33 @@ public void IteratorWorks() } i--; - sortedKeyValue.FirstKey.Should().BeEquivalentTo(new byte[] { 0, 0, 0 }); - sortedKeyValue.LastKey.Should().BeEquivalentTo(new byte[] { i, i, i }); - using var view = sortedKeyValue.GetViewBetween([0], [9]); + void CheckView(ISortedKeyValueStore sortedKeyValueStore) + { + sortedKeyValue.FirstKey.Should().BeEquivalentTo(new byte[] { 0, 0, 0 }); + sortedKeyValue.LastKey.Should().BeEquivalentTo(new byte[] { (byte)(entryCount - 1), (byte)(entryCount - 1), (byte)(entryCount - 1) }); + using var view = sortedKeyValueStore.GetViewBetween([0], [9]); + + i = 0; + while (view.MoveNext()) + { + view.CurrentKey.ToArray().Should().BeEquivalentTo([i, i, i]); + view.CurrentValue.ToArray().Should().BeEquivalentTo([i, i, i]); + i++; + } - i = 0; - while (view.MoveNext()) + i.Should().Be((byte)entryCount); + } + + CheckView(sortedKeyValue); + + using var snapshot = ((IKeyValueStoreWithSnapshot)_db).CreateSnapshot(); + for (i = 0; i < entryCount; i++) { - view.CurrentKey.ToArray().Should().BeEquivalentTo([i, i, i]); - view.CurrentValue.ToArray().Should().BeEquivalentTo([i, i, i]); - i++; + _db[[i, i, i]] = [(byte)(i + 1), (byte)(i + 1), (byte)(i + 1)]; } - i.Should().Be((byte)entryCount); + CheckView((ISortedKeyValueStore)snapshot); } [Test] @@ -434,6 +469,67 @@ public void Can_GetMetric_AfterDispose() _db.Dispose(); _db.GatherMetric().Size.Should().Be(0); } + + private void AssertCanGetViaAllMethod(IReadOnlyKeyValueStore kv, ReadOnlySpan key, ReadOnlySpan value) + { + Assert.That(kv[key], Is.EqualTo(value.ToArray())); + Assert.That(kv.KeyExists(key), Is.True); + + ReadFlags[] flags = [ReadFlags.None, ReadFlags.HintReadAhead, ReadFlags.HintCacheMiss]; + Span outBuffer = stackalloc byte[value.Length]; + foreach (ReadFlags flag in flags) + { + Assert.That(kv.Get(key, flags: flag), Is.EqualTo(value.ToArray())); + + Span buffer = kv.GetSpan(key, flag); + Assert.That(buffer.ToArray(), Is.EqualTo(value.ToArray())); + kv.DangerousReleaseMemory(buffer); + + int length = kv.Get(key, outBuffer); + Assert.That(outBuffer[..length].ToArray(), Is.EqualTo(value.ToArray())); + } + + using ISortedView iterator = ((ISortedKeyValueStore)kv).GetViewBetween(key, CreateNextKey(key)); + if (iterator.MoveNext()) + { + Assert.That(iterator.CurrentKey.ToArray(), Is.EqualTo(key.ToArray())); + Assert.That(iterator.CurrentValue.ToArray(), Is.EqualTo(value.ToArray())); + } + + Assert.That(iterator.MoveNext(), Is.False); + + // Ai generated + byte[] CreateNextKey(ReadOnlySpan key) + { + // 1. Create a copy of the key to modify + byte[] nextKey = key.ToArray(); + + // 2. Iterate backwards (from the last byte to the first) + for (int i = nextKey.Length - 1; i >= 0; i--) + { + // If the byte is NOT 0xFF (255), we can just increment it and we are done. + if (nextKey[i] < 0xFF) + { + nextKey[i]++; + return nextKey; + } + + // If the byte IS 0xFF, it rolls over to 0x00, and we "carry" the 1 to the next byte loop. + nextKey[i] = 0x00; + } + + // 3. Handle Overflow (Edge Case: All bytes were 0xFF) + // If we are here, the key was something like [FF, FF, FF]. + // The loop turned it into [00, 00, 00]. + // The "Next" lexicographical key is mathematically [01, 00, 00, 00]. + + // Resize array to fit the new leading '1' + var overflowKey = new byte[nextKey.Length + 1]; + overflowKey[0] = 1; + // The rest are already 0 from default initialization, so we return. + return overflowKey; + } + } } class CorruptedDbOnTheRocks : DbOnTheRocks From 5fc6f79b7bb65ac311981a760bcc4506f2032d8a Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Fri, 16 Jan 2026 03:55:01 -0500 Subject: [PATCH 239/255] Bump default pruning cache by 512MB for larger mainnet blocks (#10247) Bump default pruning cache by 512MB --- src/Nethermind/Nethermind.Db/IPruningConfig.cs | 4 ++-- src/Nethermind/Nethermind.Db/PruningConfig.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Nethermind/Nethermind.Db/IPruningConfig.cs b/src/Nethermind/Nethermind.Db/IPruningConfig.cs index 9503a26a15d..efd534d6952 100644 --- a/src/Nethermind/Nethermind.Db/IPruningConfig.cs +++ b/src/Nethermind/Nethermind.Db/IPruningConfig.cs @@ -16,10 +16,10 @@ public interface IPruningConfig : IConfig [ConfigItem(Description = "The pruning mode.", DefaultValue = "Hybrid")] PruningMode Mode { get; set; } - [ConfigItem(Description = "The in-memory cache size, in MB. Bigger size tend to improve performance.", DefaultValue = "1280")] + [ConfigItem(Description = "The in-memory cache size, in MB. Bigger size tend to improve performance.", DefaultValue = "1792")] long CacheMb { get; set; } - [ConfigItem(Description = "The in-memory cache size for dirty nodes, in MB. Increasing this reduces pruning interval but cause increased pruning time.", DefaultValue = "1024")] + [ConfigItem(Description = "The in-memory cache size for dirty nodes, in MB. Increasing this reduces pruning interval but cause increased pruning time.", DefaultValue = "1536")] long DirtyCacheMb { get; set; } [ConfigItem( diff --git a/src/Nethermind/Nethermind.Db/PruningConfig.cs b/src/Nethermind/Nethermind.Db/PruningConfig.cs index 593e2289b92..d02de3caa1c 100644 --- a/src/Nethermind/Nethermind.Db/PruningConfig.cs +++ b/src/Nethermind/Nethermind.Db/PruningConfig.cs @@ -26,8 +26,8 @@ public bool Enabled } public PruningMode Mode { get; set; } = PruningMode.Hybrid; - public long CacheMb { get; set; } = 1280; - public long DirtyCacheMb { get; set; } = 1024; + public long CacheMb { get; set; } = 1792; + public long DirtyCacheMb { get; set; } = 1536; public long PersistenceInterval { get; set; } = 1; public long FullPruningThresholdMb { get; set; } = 256000; public FullPruningTrigger FullPruningTrigger { get; set; } = FullPruningTrigger.Manual; From f60efb5c055fe5724bd5a1c55199f6a94290c86c Mon Sep 17 00:00:00 2001 From: Diptanshu Kakwani Date: Fri, 16 Jan 2026 15:24:59 +0530 Subject: [PATCH 240/255] Fix: Change Taiko RPC Response to PascalCase (#10244) change case --- src/Nethermind/Nethermind.Taiko/Rpc/PreBuiltTxList.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/PreBuiltTxList.cs b/src/Nethermind/Nethermind.Taiko/Rpc/PreBuiltTxList.cs index dd1ce740099..5d4a2dfdf5e 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/PreBuiltTxList.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/PreBuiltTxList.cs @@ -9,11 +9,14 @@ namespace Nethermind.Taiko.Rpc; public sealed class PreBuiltTxList(TransactionForRpc[] transactions, ulong estimatedGasUsed, ulong bytesLength) { + [JsonPropertyName("TxList")] public TransactionForRpc[] TxList { get; } = transactions; + [JsonPropertyName("EstimatedGasUsed")] [JsonConverter(typeof(ULongRawJsonConverter))] public ulong EstimatedGasUsed { get; } = estimatedGasUsed; + [JsonPropertyName("BytesLength")] [JsonConverter(typeof(ULongRawJsonConverter))] public ulong BytesLength { get; } = bytesLength; } From d2ad2056811cd5e75ded93ace4b7d19c33506a48 Mon Sep 17 00:00:00 2001 From: alex017 Date: Fri, 16 Jan 2026 16:10:55 +0100 Subject: [PATCH 241/255] perf(clique): eliminate redundant cache lookup in GetBlockSealer (#10252) Update SnapshotManager.cs --- src/Nethermind/Nethermind.Consensus.Clique/SnapshotManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Consensus.Clique/SnapshotManager.cs b/src/Nethermind/Nethermind.Consensus.Clique/SnapshotManager.cs index e782eac5931..9a63d1949f9 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/SnapshotManager.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/SnapshotManager.cs @@ -53,7 +53,8 @@ public Address GetBlockSealer(BlockHeader header) { if (header.Author is not null) return header.Author; if (header.Number == 0) return Address.Zero; - if (_signatures.Get(header.Hash) is not null) return _signatures.Get(header.Hash); + Address? cached = _signatures.Get(header.Hash); + if (cached is not null) return cached; int extraSeal = 65; From f429b8cbe6e9edfa2ec458493bde71cf420ac834 Mon Sep 17 00:00:00 2001 From: Ben {chmark} Adams Date: Sat, 17 Jan 2026 00:09:02 -0500 Subject: [PATCH 242/255] Skip GC when pruning (#10230) * Skip GC when pruning * fix * feedback --- .../GC/GCScheduler.cs | 11 ++++++++++- src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs | 2 +- src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) rename src/Nethermind/{Nethermind.Consensus => Nethermind.Core}/GC/GCScheduler.cs (96%) diff --git a/src/Nethermind/Nethermind.Consensus/GC/GCScheduler.cs b/src/Nethermind/Nethermind.Core/GC/GCScheduler.cs similarity index 96% rename from src/Nethermind/Nethermind.Consensus/GC/GCScheduler.cs rename to src/Nethermind/Nethermind.Core/GC/GCScheduler.cs index ddb2d5caee4..8465cc5765a 100644 --- a/src/Nethermind/Nethermind.Consensus/GC/GCScheduler.cs +++ b/src/Nethermind/Nethermind.Core/GC/GCScheduler.cs @@ -9,7 +9,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Memory; -namespace Nethermind.Consensus; +namespace Nethermind.Core; public sealed class GCScheduler { @@ -33,6 +33,8 @@ public sealed class GCScheduler private bool _fireGC = false; private long _countToGC = 0L; + private bool _skipNextGC = false; + // Singleton instance of GCScheduler public static GCScheduler Instance { get; } = new GCScheduler(); @@ -134,6 +136,11 @@ public static void MarkGCResumed() /// private void PerformFullGC() { + if (Interlocked.Exchange(ref _skipNextGC, false)) + { + return; + } + // Decide if the next GC should compact the large object heap bool compacting = _isNextGcBlocking && _isNextGcCompacting; @@ -189,4 +196,6 @@ public bool GCCollect(int generation, GCCollectionMode mode, bool blocking, bool return true; } + + public void SkipNextGC() => Volatile.Write(ref _skipNextGC, true); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs index fc9276f0fad..6062bbb67ba 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs @@ -6,7 +6,7 @@ using System.Threading; using System.Threading.Tasks; using FastEnumUtility; -using Nethermind.Consensus; +using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index df908804acb..66c57f32656 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -604,6 +604,8 @@ private async Task TrySyncPrune() return; } + // Skip triggering GC while pruning so they don't fight each other causing pruning to take longer + GCScheduler.Instance.SkipNextGC(); try { SyncPruneNonLocked(); From 47a7de60c75517ccbf85ac37aa9b8d78e51f6f80 Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 11:24:50 +0100 Subject: [PATCH 243/255] Auto-update fast sync settings (#10260) Co-authored-by: rubo --- src/Nethermind/Nethermind.Runner/configs/base-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/base-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/chiado.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/gnosis.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/joc-testnet.json | 6 +++--- src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-mainnet.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/op-sepolia.json | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sepolia.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-mainnet.json | 4 ++-- .../Nethermind.Runner/configs/worldchain-sepolia.json | 4 ++-- 14 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index 5a66cd8000d..346fc1ec959 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 40640000, - "PivotHash": "0xd110a315f31ff7cde0073f4203a212636b0aaaa5d2b07dc4534a4f92affefedb" + "PivotNumber": 40940000, + "PivotHash": "0x778ef345ff357d99252bd3db6a7f51c8d3b131b07f3edc1569d035c13e71df65" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index 093765e4036..2f76ab467e7 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 36150000, - "PivotHash": "0x0b006a487ea3bc9197eb847f9a1baaa8de1b6c5ab3bf12eb775deb15f2da243b" + "PivotNumber": 36450000, + "PivotHash": "0x856c031d90a52d7a3244710a436f68bb2b517e4cf44bcb4a34324c5324db7c14" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.json b/src/Nethermind/Nethermind.Runner/configs/chiado.json index 827cfecddd5..53b11f6bd47 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.json +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.json @@ -18,8 +18,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 19610000, - "PivotHash": "0x765715a5c794e1fdb994be6ed5170817f24433e5f0b3ae53d9a432e6062cf5ae", + "PivotNumber": 19700000, + "PivotHash": "0xfab06a40c27488d573945f6c492955f1aa6e4fcb8fc30c2e8df8a58072fe00f4", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": 10000000000, "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.json b/src/Nethermind/Nethermind.Runner/configs/gnosis.json index a9c7dfb0dc1..d6d8d79a24d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.json +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.json @@ -14,8 +14,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 44090000, - "PivotHash": "0xe99aa9d41e4911c2d3c1127a87d9913dcabf5eff7bdf999e9633b51edf6c6b80", + "PivotNumber": 44210000, + "PivotHash": "0x2f75566e7b27504a0587119e3fdeb148a6b8c03fcd97bec0f803baea595d718b", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000, diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json index 1abb88a2039..055812824e6 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 21680000, - "PivotHash": "0x0bfe08da1c01ca53815f275e92ff42eb0445d5063074e4dba2e29e2de18cbc07", - "PivotTotalDifficulty": "39012116" + "PivotNumber": 21800000, + "PivotHash": "0xb1696386d4c8a573ad9eca043ced6590cce1ff422929fd5b0b5d8f1861cf10a2", + "PivotTotalDifficulty": "39190823" }, "Metrics": { "NodeName": "JOC-Mainnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json index 294f5a03239..23aba507fa0 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 15290000, - "PivotHash": "0x31b25b887fea4db1ea81d84e2f076612c887d8b4d02a8d1ea3aa9407b5a669fa", - "PivotTotalDifficulty": "25435913" + "PivotNumber": 15410000, + "PivotHash": "0xacb1fa4763fcb53b8bee2e259008df4872cf507c8977874b74ad9f88d826630b", + "PivotTotalDifficulty": "25623910" }, "Metrics": { "NodeName": "JOC-Testnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json index 0eef8217747..f380e362ae1 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 27670000, - "PivotHash": "0x1977f99dbb3975e26662b1cbf8d4cc5f22980e3760912e6f1fe8b5123c066d91", + "PivotNumber": 27970000, + "PivotHash": "0xc2ffe62fe8f65c8f4fef9591d3674695368e3df6d361d81157bd3f1dd6a2e2b2", "PivotTotalDifficulty": "0", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json index 588816bffcf..5932fce1cfa 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json @@ -17,8 +17,8 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 23180000, - "PivotHash": "0x5dbf4d40e1489385c101d10c9d1132a2d50b942c08882d54b80488450b5b4a8f", + "PivotNumber": 23480000, + "PivotHash": "0x84228950a8e7b465dfd3985a687e8e90295f640ab129b9aed6fa50c6abd4ee1e", "PivotTotalDifficulty": "37331807", "HeaderStateDistance": 6 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index 3b207169970..fcb73b1bf13 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -10,8 +10,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 24206000, - "PivotHash": "0x8b93b9748a198442fbbd6fd9cd67950c938d171f7b0a2495abb3f54f8078daf4", + "PivotNumber": 24257000, + "PivotHash": "0x3a3aa93772ec060df348b5824ab9458704873215cc5a4abd354a7c4f83379efe", "PivotTotalDifficulty": "58750003716598352816469", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 15537394, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index 911d8a1c472..2fc85092c3d 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -15,8 +15,8 @@ "FastSyncCatchUpHeightDelta": "10000000000", "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, - "PivotNumber": 146230000, - "PivotHash": "0xeef27226ffcb4cdfae7e9d87ec52b9dcf6317ef79ad077bbe0eeb7d3ce8850a5" + "PivotNumber": 146540000, + "PivotHash": "0x1e8f249641e4863081989fa9a860022caf67f6b759b8369c49d0c919be6edbdb" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index f934cee8c4e..02ba96655f9 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 38130000, - "PivotHash": "0xd6821e58d2ec675660f8abf3e3abef108ced0ebc63737e0f718925a87acc5ac8" + "PivotNumber": 38430000, + "PivotHash": "0x543e91629191a9e2e1dcc36e8b06f92f561b59d01049436078ef66aa77e83c6b" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index 21883b0536b..616f47c76e3 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -17,8 +17,8 @@ "FastSync": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 10017000, - "PivotHash": "0xf7fb54e189b8b3d83606deecd95b186faa00880002ba1e02c111e446f13809b8", + "PivotNumber": 10066000, + "PivotHash": "0xde60cbbff240f3b93b4aad26f3255938eb4b2624dadfd3b58dd2ce4dbc21f601", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 1450409, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index 85d2a54732a..828bc23b74b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 24360000, - "PivotHash": "0x6c135c9b8c463f10a4e52ca08b05c732af6f5b753d26bee65009ab4eabb7b8c6" + "PivotNumber": 24670000, + "PivotHash": "0x842231fe10f01c5322a4410d5a07664cca94e34a9e6794efcf76897b658b285a" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index cfdf41675a0..c82feb5a3d1 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 23760000, - "PivotHash": "0x7256f30608e0e27979b11d13e385b98999979881b6e49aec6670c73d377bccef" + "PivotNumber": 24060000, + "PivotHash": "0xe368ce8e466e95d1888b8201590bdf12acd4f3d062ed3bd785b5f581e58b5037" }, "Discovery": { "DiscoveryVersion": "V5" From df26ddd16f15affc3a6e919ef1356bda74699316 Mon Sep 17 00:00:00 2001 From: "core-repository-dispatch-app[bot]" <173070810+core-repository-dispatch-app[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 11:25:07 +0100 Subject: [PATCH 244/255] Update OP Superchain chains (#10261) Co-authored-by: emlautarom1 From eddd34f0ba2c723acd6a137ada812ec293f0b0bc Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Mon, 19 Jan 2026 20:23:28 +0800 Subject: [PATCH 245/255] Fix/shared blockcache not used (#10263) * Cleaner optimize for hits * Columns db snapshot * Fix block cache * Fix test * Fix test * Fix build * Spell fix * Refactor HyperClockCacheWrapper to use SafeHandle pattern (#10265) * Initial plan * Refactor HyperClockCacheWrapper to use SafeHandle pattern Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --- cspell.json | 1 + .../Nethermind.Db.Rocks/ColumnDb.cs | 2 +- .../Config/AdjustedRocksdbConfig.cs | 6 +- .../Config/IRocksDbConfig.cs | 3 + .../Config/PerTableDbConfig.cs | 1 + .../Nethermind.Db.Rocks/DbOnTheRocks.cs | 77 +++++++++--- .../HyperClockCacheWrapper.cs | 30 +++++ .../Nethermind.Db.Rocks/RocksDbFactory.cs | 20 ++- .../Nethermind.Db.Test/DbOnTheRocksTests.cs | 119 +++++++++++++++++- .../Nethermind.Db.Test/DbTrackerTests.cs | 7 +- src/Nethermind/Nethermind.Db/CompressingDb.cs | 2 +- .../FullPruning/FullPruningDb.cs | 5 +- src/Nethermind/Nethermind.Db/IDb.cs | 2 +- src/Nethermind/Nethermind.Db/MemDb.cs | 2 +- src/Nethermind/Nethermind.Db/ReadOnlyDb.cs | 2 +- .../Nethermind.Init/MemoryHintMan.cs | 4 +- .../Nethermind.Init/Modules/DbModule.cs | 2 + .../Modules/DbMonitoringModule.cs | 10 +- .../ConfigFilesTests.cs | 2 +- .../Nethermind.Runner/configs/mainnet.json | 4 +- 20 files changed, 251 insertions(+), 50 deletions(-) create mode 100644 src/Nethermind/Nethermind.Db.Rocks/HyperClockCacheWrapper.cs diff --git a/cspell.json b/cspell.json index 160440cf2f4..2208a7aab4f 100644 --- a/cspell.json +++ b/cspell.json @@ -511,6 +511,7 @@ "preimage", "preimages", "preinstallation", + "prepopulate", "prestate", "prevop", "prevrandao", diff --git a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs index 3a049de3b6d..46975eb1881 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs @@ -181,7 +181,7 @@ public void Compact() public void Clear() { throw new NotSupportedException(); } // Maybe it should be column specific metric? - public IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) => _mainDb.GatherMetric(includeSharedCache); + public IDbMeta.DbMetric GatherMetric() => _mainDb.GatherMetric(); public byte[]? FirstKey { diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/AdjustedRocksdbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/AdjustedRocksdbConfig.cs index 16ac59bce62..20b220b301d 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/AdjustedRocksdbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/AdjustedRocksdbConfig.cs @@ -1,12 +1,15 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; + namespace Nethermind.Db.Rocks.Config; public class AdjustedRocksdbConfig( IRocksDbConfig baseConfig, string additionalRocksDbOptions, - ulong writeBufferSize + ulong writeBufferSize, + IntPtr? blockCache = null ) : IRocksDbConfig { public ulong? WriteBufferSize => writeBufferSize; @@ -37,4 +40,5 @@ ulong writeBufferSize public double CompressibilityHint => baseConfig.CompressibilityHint; public bool FlushOnExit => baseConfig.FlushOnExit; + public IntPtr? BlockCache => blockCache ?? baseConfig.BlockCache; } diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/IRocksDbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/IRocksDbConfig.cs index f70d96006d3..c1864fdce02 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/IRocksDbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/IRocksDbConfig.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; + namespace Nethermind.Db.Rocks.Config; public interface IRocksDbConfig @@ -19,4 +21,5 @@ public interface IRocksDbConfig bool EnableFileWarmer { get; } double CompressibilityHint { get; } bool FlushOnExit { get; } + IntPtr? BlockCache { get; } } diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs index 0efa1fe7553..7b8967ad4b9 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs @@ -61,6 +61,7 @@ private void EnsureConfigIsAvailable(string propertyName) public bool EnableFileWarmer => ReadConfig(nameof(EnableFileWarmer)); public double CompressibilityHint => ReadConfig(nameof(CompressibilityHint)); public bool FlushOnExit => ReadConfig(nameof(FlushOnExit)) ?? true; + public IntPtr? BlockCache => null; private T? ReadConfig(string propertyName) { diff --git a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs index 4b97f49c69f..42df2e4d457 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs @@ -93,6 +93,7 @@ public partial class DbOnTheRocks : IDb, ITunableDb, IReadOnlyNativeKeyValueStor private ulong _writeBufferSize; private int _maxWriteBufferNumber; private readonly RocksDbReader _reader; + private bool _isUsingSharedBlockCache; public DbOnTheRocks( string basePath, @@ -352,7 +353,7 @@ protected virtual long FetchTotalPropertyValue(string propertyName) return value; } - public IDbMeta.DbMetric GatherMetric(bool isUsingSharedCache = false) + public IDbMeta.DbMetric GatherMetric() { if (_isDisposed) { @@ -369,7 +370,7 @@ public IDbMeta.DbMetric GatherMetric(bool isUsingSharedCache = false) return new IDbMeta.DbMetric() { Size = GetSize(), - CacheSize = GetCacheSize(isUsingSharedCache), + CacheSize = GetCacheSize(), IndexSize = GetIndexSize(), MemtableSize = GetMemtableSize(), TotalReads = _totalReads, @@ -394,11 +395,11 @@ private long GetSize() return 0; } - private long GetCacheSize(bool isUsingSharedCache = false) + private long GetCacheSize() { try { - if (isUsingSharedCache) + if (_isUsingSharedBlockCache) { // returning 0 as we are using shared cache. return 0; @@ -460,6 +461,38 @@ public static IDictionary ExtractOptions(string dbOptions) return asDict; } + private const string OptimizeFiltersForHitsOption = "optimize_filters_for_hits="; + + /// + /// Normalizes a RocksDB options string by removing earlier occurrences of optimize_filters_for_hits, + /// keeping only the last one. This is needed because RocksDB does not allow overriding this option + /// when specified multiple times in the same options string. + /// + public static string NormalizeRocksDbOptions(string dbOptions) + { + if (string.IsNullOrEmpty(dbOptions)) return dbOptions ?? string.Empty; + + int lastIndex = dbOptions.LastIndexOf(OptimizeFiltersForHitsOption, StringComparison.Ordinal); + if (lastIndex == -1) return dbOptions; + + // Remove all earlier occurrences, keep only the last one + int searchStart = 0; + while (true) + { + int index = dbOptions.IndexOf(OptimizeFiltersForHitsOption, searchStart, StringComparison.Ordinal); + if (index == -1 || index == lastIndex) break; + + // Find the end of this option (next semicolon) + int endIndex = dbOptions.IndexOf(';', index); + if (endIndex == -1) break; + + dbOptions = dbOptions.Remove(index, endIndex - index + 1); + lastIndex = dbOptions.LastIndexOf(OptimizeFiltersForHitsOption, StringComparison.Ordinal); + } + + return dbOptions; + } + protected virtual void BuildOptions(IRocksDbConfig dbConfig, Options options, IntPtr? sharedCache, IMergeOperator? mergeOperator) where T : Options { // This section is about the table factory.. and block cache apparently. @@ -475,27 +508,35 @@ protected virtual void BuildOptions(IRocksDbConfig dbConfig, Options optio _writeBufferSize = ulong.Parse(optionsAsDict["write_buffer_size"]); _maxWriteBufferNumber = int.Parse(optionsAsDict["max_write_buffer_number"]); - BlockBasedTableOptions tableOptions = new(); - options.SetBlockBasedTableFactory(tableOptions); - IntPtr optsPtr = Marshal.StringToHGlobalAnsi(dbConfig.RocksDbOptions); - try - { - _rocksDbNative.rocksdb_get_options_from_string(options.Handle, optsPtr, options.Handle); - } - finally - { - Marshal.FreeHGlobal(optsPtr); - } - ulong blockCacheSize = 0; if (optionsAsDict.TryGetValue("block_based_table_factory.block_cache", out string? blockCacheSizeStr)) { blockCacheSize = ulong.Parse(blockCacheSizeStr); } - if (sharedCache is not null && blockCacheSize == 0) + BlockBasedTableOptions? tableOptions = new(); + if (dbConfig.BlockCache is not null) + { + tableOptions.SetBlockCache(dbConfig.BlockCache.Value); + } + else if (sharedCache is not null && blockCacheSize == 0) { tableOptions.SetBlockCache(sharedCache.Value); + _isUsingSharedBlockCache = true; + } + + // Note: the ordering is important. + // changes to the table options must be applied before setting to set. + options.SetBlockBasedTableFactory(tableOptions); + + IntPtr optsPtr = Marshal.StringToHGlobalAnsi(NormalizeRocksDbOptions(dbConfig.RocksDbOptions)); + try + { + _rocksDbNative.rocksdb_get_options_from_string(options.Handle, optsPtr, options.Handle); + } + finally + { + Marshal.FreeHGlobal(optsPtr); } if (dbConfig.WriteBufferSize is not null) @@ -579,7 +620,7 @@ protected virtual void BuildOptions(IRocksDbConfig dbConfig, Options optio if (dbConfig.AdditionalRocksDbOptions is not null) { - optsPtr = Marshal.StringToHGlobalAnsi(dbConfig.AdditionalRocksDbOptions); + optsPtr = Marshal.StringToHGlobalAnsi(NormalizeRocksDbOptions(dbConfig.AdditionalRocksDbOptions)); try { _rocksDbNative.rocksdb_get_options_from_string(options.Handle, optsPtr, options.Handle); diff --git a/src/Nethermind/Nethermind.Db.Rocks/HyperClockCacheWrapper.cs b/src/Nethermind/Nethermind.Db.Rocks/HyperClockCacheWrapper.cs new file mode 100644 index 00000000000..a47654fbd37 --- /dev/null +++ b/src/Nethermind/Nethermind.Db.Rocks/HyperClockCacheWrapper.cs @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2026 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Microsoft.Win32.SafeHandles; +using RocksDbSharp; + +namespace Nethermind.Db.Rocks; + +public class HyperClockCacheWrapper : SafeHandleZeroOrMinusOneIsInvalid +{ + public HyperClockCacheWrapper(ulong capacity = 32_000_000) : base(ownsHandle: true) + { + SetHandle(RocksDbSharp.Native.Instance.rocksdb_cache_create_hyper_clock(new UIntPtr(capacity), 0)); + } + + public IntPtr Handle => DangerousGetHandle(); + + protected override bool ReleaseHandle() + { + RocksDbSharp.Native.Instance.rocksdb_cache_destroy(handle); + return true; + } + + public long GetUsage() + { + ObjectDisposedException.ThrowIf(IsClosed, this); + return (long)Native.Instance.rocksdb_cache_get_usage(DangerousGetHandle()); + } +} diff --git a/src/Nethermind/Nethermind.Db.Rocks/RocksDbFactory.cs b/src/Nethermind/Nethermind.Db.Rocks/RocksDbFactory.cs index 3883bb2d4cb..a008701a9f4 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/RocksDbFactory.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/RocksDbFactory.cs @@ -16,16 +16,16 @@ public class RocksDbFactory : IDbFactory private readonly string _basePath; - private readonly IntPtr _sharedCache; + private readonly HyperClockCacheWrapper _sharedCache; private readonly IRocksDbConfigFactory _rocksDbConfigFactory; - public RocksDbFactory(IRocksDbConfigFactory rocksDbConfigFactory, IDbConfig dbConfig, IInitConfig initConfig, ILogManager logManager) - : this(rocksDbConfigFactory, dbConfig, logManager, initConfig.BaseDbPath) + public RocksDbFactory(IRocksDbConfigFactory rocksDbConfigFactory, IDbConfig dbConfig, IInitConfig initConfig, HyperClockCacheWrapper sharedCache, ILogManager logManager) + : this(rocksDbConfigFactory, dbConfig, sharedCache, logManager, initConfig.BaseDbPath) { } - public RocksDbFactory(IRocksDbConfigFactory rocksDbConfigFactory, IDbConfig dbConfig, ILogManager logManager, string basePath) + public RocksDbFactory(IRocksDbConfigFactory rocksDbConfigFactory, IDbConfig dbConfig, HyperClockCacheWrapper sharedCache, ILogManager logManager, string basePath) { _rocksDbConfigFactory = rocksDbConfigFactory; _dbConfig = dbConfig; @@ -33,20 +33,16 @@ public RocksDbFactory(IRocksDbConfigFactory rocksDbConfigFactory, IDbConfig dbCo _basePath = basePath; ILogger logger = _logManager.GetClassLogger(); + if (logger.IsDebug) logger.Debug($"Shared memory size is {dbConfig.SharedBlockCacheSize}"); - if (logger.IsDebug) - { - logger.Debug($"Shared memory size is {dbConfig.SharedBlockCacheSize}"); - } - - _sharedCache = RocksDbSharp.Native.Instance.rocksdb_cache_create_lru(new UIntPtr(dbConfig.SharedBlockCacheSize)); + _sharedCache = sharedCache; } public IDb CreateDb(DbSettings dbSettings) => - new DbOnTheRocks(_basePath, dbSettings, _dbConfig, _rocksDbConfigFactory, _logManager, sharedCache: _sharedCache); + new DbOnTheRocks(_basePath, dbSettings, _dbConfig, _rocksDbConfigFactory, _logManager, sharedCache: _sharedCache.Handle); public IColumnsDb CreateColumnsDb(DbSettings dbSettings) where T : struct, Enum => - new ColumnsDb(_basePath, dbSettings, _dbConfig, _rocksDbConfigFactory, _logManager, Array.Empty(), sharedCache: _sharedCache); + new ColumnsDb(_basePath, dbSettings, _dbConfig, _rocksDbConfigFactory, _logManager, Array.Empty(), sharedCache: _sharedCache.Handle); public string GetFullDbPath(DbSettings dbSettings) => DbOnTheRocks.GetFullDbPath(dbSettings.DbPath, _basePath); } diff --git a/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs b/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs index 31954292981..2028e252c3a 100644 --- a/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs @@ -31,6 +31,7 @@ namespace Nethermind.Db.Test public class DbOnTheRocksTests { private RocksDbConfigFactory _rocksdbConfigFactory; + private DbConfig _dbConfig = new DbConfig(); string DbPath => "testdb/" + TestContext.CurrentContext.Test.Name; @@ -38,13 +39,13 @@ public class DbOnTheRocksTests public void Setup() { Directory.CreateDirectory(DbPath); - _rocksdbConfigFactory = new RocksDbConfigFactory(new DbConfig(), new PruningConfig(), new TestHardwareInfo(1.GiB()), LimboLogs.Instance); + _rocksdbConfigFactory = new RocksDbConfigFactory(_dbConfig, new PruningConfig(), new TestHardwareInfo(1.GiB()), LimboLogs.Instance); } [TearDown] public void TearDown() { - Directory.Delete(DbPath, true); + if (Directory.Exists(DbPath)) Directory.Delete(DbPath, true); } [Test] @@ -160,6 +161,85 @@ public void CanOpenWithAdditionalConfig(string opts, bool success) } } + [TestCase(true)] + [TestCase(false)] + public void UseSharedCacheIfNoCacheIsSpecified(bool explicitCache) + { + if (Directory.Exists(DbPath)) Directory.Delete(DbPath, true); + long sharedCacheSize = 10.KiB(); + + using HyperClockCacheWrapper cache = new HyperClockCacheWrapper((ulong)sharedCacheSize); + _dbConfig.BlocksDbRocksDbOptions = "block_based_table_factory.block_size=512;block_based_table_factory.prepopulate_block_cache=kFlushOnly;"; + if (explicitCache) + { + _dbConfig.BlocksDbRocksDbOptions += "block_based_table_factory.block_cache=1000000;"; + } + + using DbOnTheRocks db = new("testBlockCache", GetRocksDbSettings("testBlockCache", DbNames.Blocks), _dbConfig, + _rocksdbConfigFactory, LimboLogs.Instance, sharedCache: cache.Handle); + + Random rng = new Random(); + byte[] buffer = new byte[1024]; + for (int i = 0; i < 100; i++) + { + Hash256 someKey = Keccak.Compute(i.ToBigEndianByteArray()); + rng.NextBytes(buffer); + db.PutSpan(someKey.Bytes, buffer, WriteFlags.None); + } + db.Flush(); + + if (explicitCache) + { + Assert.That(db.GatherMetric().CacheSize, Is.GreaterThan(sharedCacheSize)); + } + else + { + Assert.That(db.GatherMetric().CacheSize, Is.LessThan(sharedCacheSize)); + } + } + + [Test] + public void UseExplicitlyGivenCache() + { + _dbConfig.BlocksDbRocksDbOptions = "block_based_table_factory.block_size=512;block_based_table_factory.prepopulate_block_cache=kFlushOnly;"; + + long cacheSize = 10.KiB(); + using HyperClockCacheWrapper cache = new HyperClockCacheWrapper((ulong)cacheSize); + + IRocksDbConfigFactory rocksDbConfigFactory = Substitute.For(); + rocksDbConfigFactory.GetForDatabase(Arg.Any(), Arg.Any()) + .Returns((c) => + { + string? arg1 = (string?)c[0]; + string? arg2 = (string?)c[0]; + + IRocksDbConfig baseConfig = _rocksdbConfigFactory.GetForDatabase(arg1, arg2); + + baseConfig = new AdjustedRocksdbConfig(baseConfig, + "", + 0, + cache.Handle); + + return baseConfig; + }); + + using DbOnTheRocks db = new("testBlockCache", GetRocksDbSettings("testBlockCache", DbNames.Blocks), _dbConfig, + rocksDbConfigFactory, LimboLogs.Instance); + + Random rng = new Random(); + byte[] buffer = new byte[1024]; + for (int i = 0; i < 100; i++) + { + Hash256 someKey = Keccak.Compute(i.ToBigEndianByteArray()); + rng.NextBytes(buffer); + db.PutSpan(someKey.Bytes, buffer, WriteFlags.None); + } + db.Flush(); + + Assert.That(db.GatherMetric().CacheSize, Is.EqualTo(cache.GetUsage())); + Assert.That(cache.GetUsage(), Is.LessThan(cacheSize)); + } + [Test] public void Corrupted_exception_on_open_would_create_marker() { @@ -463,6 +543,41 @@ public void TestExtractOptions() parsedOptions["memtable_whole_key_filtering"].Should().Be("true"); } + [Test] + public void TestNormalizeRocksDbOptions_RemovesDuplicateOptimizeFiltersForHits() + { + string options = "optimize_filters_for_hits=true;compression=kSnappyCompression;optimize_filters_for_hits=false;"; + string normalized = DbOnTheRocks.NormalizeRocksDbOptions(options); + + // Should contain only one optimize_filters_for_hits with the last value (false) + normalized.Should().Be("compression=kSnappyCompression;optimize_filters_for_hits=false;"); + } + + [Test] + public void TestNormalizeRocksDbOptions_HandlesEmptyString() + { + DbOnTheRocks.NormalizeRocksDbOptions("").Should().Be(""); + DbOnTheRocks.NormalizeRocksDbOptions(null!).Should().Be(""); + } + + [Test] + public void TestNormalizeRocksDbOptions_PreservesStringWithoutDuplicates() + { + string options = "compression=kSnappyCompression;block_size=16000;optimize_filters_for_hits=true;"; + string normalized = DbOnTheRocks.NormalizeRocksDbOptions(options); + + normalized.Should().Be(options); + } + + [Test] + public void TestNormalizeRocksDbOptions_HandlesMultipleDuplicates() + { + string options = "optimize_filters_for_hits=true;foo=bar;optimize_filters_for_hits=false;baz=qux;optimize_filters_for_hits=true;"; + string normalized = DbOnTheRocks.NormalizeRocksDbOptions(options); + + normalized.Should().Be("foo=bar;baz=qux;optimize_filters_for_hits=true;"); + } + [Test] public void Can_GetMetric_AfterDispose() { diff --git a/src/Nethermind/Nethermind.Db.Test/DbTrackerTests.cs b/src/Nethermind/Nethermind.Db.Test/DbTrackerTests.cs index 67d041f9c6b..14b5c43bfde 100644 --- a/src/Nethermind/Nethermind.Db.Test/DbTrackerTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/DbTrackerTests.cs @@ -13,6 +13,8 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; +using Nethermind.Db.Rocks; +using Nethermind.Db.Rocks.Config; using Nethermind.Init.Modules; using Nethermind.Logging; using Nethermind.Monitoring; @@ -29,6 +31,8 @@ public void TestTrackOnlyCreatedDb() { using IContainer container = new ContainerBuilder() .AddSingleton() + .AddSingleton(new DbConfig()) + .AddSingleton() .AddSingleton(new MetricsConfig()) .AddSingleton(LimboLogs.Instance) .AddSingleton(NoopMonitoringService.Instance) @@ -105,6 +109,7 @@ public void DoesNotUpdateIfIntervalHasNotPassed() ContainerBuilder builder = new ContainerBuilder() .AddModule(new DbModule(new InitConfig(), new ReceiptConfig(), new SyncConfig())) .AddModule(new DbMonitoringModule()) + .AddSingleton(new DbConfig()) .AddSingleton(new MetricsConfig()) .AddSingleton(LimboLogs.Instance) .AddSingleton(monitoringService) @@ -140,7 +145,7 @@ private class FakeDb(IDbMeta.DbMetric metric) : TestMemDb, IDbMeta { private IDbMeta.DbMetric _metric = metric; - public override IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) + public override IDbMeta.DbMetric GatherMetric() { return _metric; } diff --git a/src/Nethermind/Nethermind.Db/CompressingDb.cs b/src/Nethermind/Nethermind.Db/CompressingDb.cs index a03e69ff103..881b839f25b 100644 --- a/src/Nethermind/Nethermind.Db/CompressingDb.cs +++ b/src/Nethermind/Nethermind.Db/CompressingDb.cs @@ -148,7 +148,7 @@ public IEnumerable GetAllValues(bool ordered = false) => public void Clear() => _wrapped.Clear(); - public IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) => _wrapped.GatherMetric(includeSharedCache); + public IDbMeta.DbMetric GatherMetric() => _wrapped.GatherMetric(); public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) => _wrapped.Set(key, Compress(value), flags); diff --git a/src/Nethermind/Nethermind.Db/FullPruning/FullPruningDb.cs b/src/Nethermind/Nethermind.Db/FullPruning/FullPruningDb.cs index 142eae0379e..32979c96383 100755 --- a/src/Nethermind/Nethermind.Db/FullPruning/FullPruningDb.cs +++ b/src/Nethermind/Nethermind.Db/FullPruning/FullPruningDb.cs @@ -121,10 +121,7 @@ public void Dispose() _pruningContext?.CloningDb.Dispose(); } - public IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) - { - return _currentDb.GatherMetric(includeSharedCache); - } + public IDbMeta.DbMetric GatherMetric() => _currentDb.GatherMetric(); public string Name => _settings.DbName; diff --git a/src/Nethermind/Nethermind.Db/IDb.cs b/src/Nethermind/Nethermind.Db/IDb.cs index 73f9e4ba171..cc2a6fa26c5 100644 --- a/src/Nethermind/Nethermind.Db/IDb.cs +++ b/src/Nethermind/Nethermind.Db/IDb.cs @@ -21,7 +21,7 @@ public interface IDb : IKeyValueStoreWithBatching, IDbMeta, IDisposable // Some metadata options public interface IDbMeta { - DbMetric GatherMetric(bool includeSharedCache = false) => new DbMetric(); + DbMetric GatherMetric() => new DbMetric(); void Flush(bool onlyWal = false); void Clear() { } diff --git a/src/Nethermind/Nethermind.Db/MemDb.cs b/src/Nethermind/Nethermind.Db/MemDb.cs index 72e2087e355..39490693200 100644 --- a/src/Nethermind/Nethermind.Db/MemDb.cs +++ b/src/Nethermind/Nethermind.Db/MemDb.cs @@ -151,7 +151,7 @@ public virtual void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags _spanDb[key] = value; } - public virtual IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) => new() { Size = Count }; + public virtual IDbMeta.DbMetric GatherMetric() => new() { Size = Count }; private IEnumerable> OrderedDb => _db.OrderBy(kvp => kvp.Key, Bytes.Comparer); } diff --git a/src/Nethermind/Nethermind.Db/ReadOnlyDb.cs b/src/Nethermind/Nethermind.Db/ReadOnlyDb.cs index ff73f260a3a..bc734119beb 100644 --- a/src/Nethermind/Nethermind.Db/ReadOnlyDb.cs +++ b/src/Nethermind/Nethermind.Db/ReadOnlyDb.cs @@ -61,7 +61,7 @@ public KeyValuePair[] this[byte[][] keys] public IWriteBatch StartWriteBatch() => this.LikeABatch(); - public IDbMeta.DbMetric GatherMetric(bool includeSharedCache = false) => wrappedDb.GatherMetric(includeSharedCache); + public IDbMeta.DbMetric GatherMetric() => wrappedDb.GatherMetric(); public void Remove(ReadOnlySpan key) { } diff --git a/src/Nethermind/Nethermind.Init/MemoryHintMan.cs b/src/Nethermind/Nethermind.Init/MemoryHintMan.cs index 8582c439e5c..4390d26af06 100644 --- a/src/Nethermind/Nethermind.Init/MemoryHintMan.cs +++ b/src/Nethermind/Nethermind.Init/MemoryHintMan.cs @@ -41,7 +41,7 @@ public void SetMemoryAllowances( ITxPoolConfig txPoolConfig, uint cpuCount) { - TotalMemory = initConfig.MemoryHint ?? 2.GB(); + TotalMemory = initConfig.MemoryHint ?? 1.GB(); ValidateCpuCount(cpuCount); checked @@ -50,7 +50,7 @@ public void SetMemoryAllowances( if (_logger.IsInfo) _logger.Info("Setting up memory allowances"); if (_logger.IsInfo) _logger.Info($" Memory hint: {TotalMemory / 1000 / 1000,5} MB"); - _remainingMemory = initConfig.MemoryHint ?? 2.GB(); + _remainingMemory = initConfig.MemoryHint ?? 1.GB(); _remainingMemory -= GeneralMemory; if (_logger.IsInfo) _logger.Info($" General memory: {GeneralMemory / 1000 / 1000,5} MB"); AssignPeersMemory(networkConfig); diff --git a/src/Nethermind/Nethermind.Init/Modules/DbModule.cs b/src/Nethermind/Nethermind.Init/Modules/DbModule.cs index cd990ccdfe0..1a3400c7e1f 100644 --- a/src/Nethermind/Nethermind.Init/Modules/DbModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/DbModule.cs @@ -70,6 +70,8 @@ protected override void Load(ContainerBuilder builder) .AddColumnDatabase(DbNames.Receipts) .AddColumnDatabase(DbNames.BlobTransactions) + + .AddSingleton((ctx) => new HyperClockCacheWrapper(ctx.Resolve().SharedBlockCacheSize)) ; switch (initConfig.DiagnosticMode) diff --git a/src/Nethermind/Nethermind.Init/Modules/DbMonitoringModule.cs b/src/Nethermind/Nethermind.Init/Modules/DbMonitoringModule.cs index e4bb8c6d874..74065a80626 100644 --- a/src/Nethermind/Nethermind.Init/Modules/DbMonitoringModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/DbMonitoringModule.cs @@ -8,6 +8,7 @@ using Nethermind.Consensus.Processing; using Nethermind.Core; using Nethermind.Db; +using Nethermind.Db.Rocks; using Nethermind.Logging; using Nethermind.Monitoring; using Nethermind.Monitoring.Config; @@ -46,14 +47,16 @@ public class DbTracker { private readonly ConcurrentDictionary _createdDbs = new ConcurrentDictionary(); private readonly int _intervalSec; + private readonly HyperClockCacheWrapper _sharedBlockCache; private long _lastDbMetricsUpdate = 0; private ILogger _logger; - public DbTracker(IMonitoringService monitoringService, IMetricsConfig metricsConfig, ILogManager logManager) + public DbTracker(IMonitoringService monitoringService, IMetricsConfig metricsConfig, HyperClockCacheWrapper sharedBlockCache, ILogManager logManager) { _intervalSec = metricsConfig.DbMetricIntervalSeconds; _logger = logManager.GetClassLogger(); + _sharedBlockCache = sharedBlockCache; if (metricsConfig.EnableDbSizeMetrics) { @@ -88,7 +91,7 @@ private void UpdateDbMetrics() foreach (KeyValuePair kv in GetAllDbMeta()) { // Note: At the moment, the metric for a columns db is combined across column. - IDbMeta.DbMetric dbMetric = kv.Value.GatherMetric(includeSharedCache: kv.Key == DbNames.State); // Only include shared cache if state db + IDbMeta.DbMetric dbMetric = kv.Value.GatherMetric(); Db.Metrics.DbSize[kv.Key] = dbMetric.Size; Db.Metrics.DbBlockCacheSize[kv.Key] = dbMetric.CacheSize; Db.Metrics.DbMemtableSize[kv.Key] = dbMetric.MemtableSize; @@ -96,6 +99,9 @@ private void UpdateDbMetrics() Db.Metrics.DbReads[kv.Key] = dbMetric.TotalReads; Db.Metrics.DbWrites[kv.Key] = dbMetric.TotalWrites; } + + Db.Metrics.DbBlockCacheSize["Shared"] = _sharedBlockCache.GetUsage(); + _lastDbMetricsUpdate = Environment.TickCount64; } catch (Exception e) diff --git a/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs b/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs index 39f7c6a2c49..c166eb5cfdf 100644 --- a/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs @@ -117,7 +117,7 @@ public void Eth_stats_disabled_by_default(string configWildcard) } [TestCase("mainnet archive", 4096000000)] - [TestCase("mainnet ^archive", 2048000000)] + [TestCase("mainnet ^archive", 1024000000)] [TestCase("volta archive", 768000000)] [TestCase("volta ^archive", 768000000)] [TestCase("gnosis archive", 1024000000)] diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index fcb73b1bf13..f399e05da9f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -5,7 +5,7 @@ "GenesisHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "BaseDbPath": "nethermind_db/mainnet", "LogFileName": "mainnet.log", - "MemoryHint": 2048000000 + "MemoryHint": 1024000000 }, "Sync": { "FastSync": true, @@ -38,4 +38,4 @@ "Merge": { "Enabled": true } -} \ No newline at end of file +} From 60aea9805fb1f9b4b116a15086af516791ccc73f Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Mon, 19 Jan 2026 20:24:04 +0800 Subject: [PATCH 246/255] ColumnsDb snapshot (#10262) * ColumnsDb snapshot * Apply PR feedback: use NotSupportedException and simplify lambda syntax (#10264) * Initial plan * Apply PR feedback: use NotSupportedException and simplify lambda syntax Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: asdacap <1841324+asdacap@users.noreply.github.com> --- .../Nethermind.Core.Test/TestMemColumnDb.cs | 7 ++++ .../Nethermind.Db.Rocks/ColumnsDb.cs | 33 +++++++++++++++++++ .../Nethermind.Db.Rpc/RpcColumnsDb.cs | 6 ++++ .../Nethermind.Db.Test/ColumnsDbTests.cs | 17 ++++++++++ src/Nethermind/Nethermind.Db/IColumnsDb.cs | 7 ++++ src/Nethermind/Nethermind.Db/MemColumnsDb.cs | 8 +++++ .../Nethermind.Db/ReadOnlyColumnsDb.cs | 7 ++++ 7 files changed, 85 insertions(+) diff --git a/src/Nethermind/Nethermind.Core.Test/TestMemColumnDb.cs b/src/Nethermind/Nethermind.Core.Test/TestMemColumnDb.cs index 529df1fdfc1..630f69bd37f 100644 --- a/src/Nethermind/Nethermind.Core.Test/TestMemColumnDb.cs +++ b/src/Nethermind/Nethermind.Core.Test/TestMemColumnDb.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using Nethermind.Db; @@ -30,6 +31,12 @@ public IColumnsWriteBatch StartWriteBatch() { return new InMemoryColumnWriteBatch(this); } + + public IColumnDbSnapshot CreateSnapshot() + { + throw new NotSupportedException("Snapshot not implemented"); + } + public void Dispose() { } public void Flush(bool onlyWal = false) { } } diff --git a/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs b/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs index 5a83aa1483b..229b3a1bcb4 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs @@ -156,4 +156,37 @@ public void Merge(ReadOnlySpan key, ReadOnlySpan value, WriteFlags f _writeBatch._writeBatch.Merge(key, value, _column._columnFamily, flags); } } + + IColumnDbSnapshot IColumnsDb.CreateSnapshot() + { + Snapshot snapshot = _db.CreateSnapshot(); + return new ColumnDbSnapshot(this, snapshot); + } + + private class ColumnDbSnapshot( + ColumnsDb columnsDb, + Snapshot snapshot + ) : IColumnDbSnapshot + { + private readonly Dictionary _columnDbs = columnsDb.ColumnKeys.ToDictionary(k => k, k => + (IReadOnlyKeyValueStore)new RocksDbReader( + columnsDb, + () => + { + ReadOptions options = new ReadOptions(); + options.SetSnapshot(snapshot); + return options; + }, + columnFamily: columnsDb._columnDbs[k]._columnFamily)); + + public IReadOnlyKeyValueStore GetColumn(T key) + { + return _columnDbs[key]; + } + + public void Dispose() + { + snapshot.Dispose(); + } + } } diff --git a/src/Nethermind/Nethermind.Db.Rpc/RpcColumnsDb.cs b/src/Nethermind/Nethermind.Db.Rpc/RpcColumnsDb.cs index 8ddcde89941..25de2cef661 100644 --- a/src/Nethermind/Nethermind.Db.Rpc/RpcColumnsDb.cs +++ b/src/Nethermind/Nethermind.Db.Rpc/RpcColumnsDb.cs @@ -45,6 +45,12 @@ public IColumnsWriteBatch StartWriteBatch() { return new InMemoryColumnWriteBatch(this); } + + public IColumnDbSnapshot CreateSnapshot() + { + throw new NotSupportedException("Snapshot not implemented"); + } + public void Dispose() { } public void Flush(bool onlyWal = false) { } } diff --git a/src/Nethermind/Nethermind.Db.Test/ColumnsDbTests.cs b/src/Nethermind/Nethermind.Db.Test/ColumnsDbTests.cs index fa6e59d0b24..c5990b943b1 100644 --- a/src/Nethermind/Nethermind.Db.Test/ColumnsDbTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/ColumnsDbTests.cs @@ -107,4 +107,21 @@ public void TestWriteBatch_WriteToAllColumn() _db.GetColumnDb(ReceiptsColumns.Transactions).Get(TestItem.KeccakA).Should() .BeEquivalentTo(TestItem.KeccakB.BytesToArray()); } + + [Test] + public void SmokeTest_Snapshot() + { + IColumnsDb asColumnsDb = _db; + IDb colA = _db.GetColumnDb(ReceiptsColumns.Blocks); + + colA.Set(TestItem.KeccakA, TestItem.KeccakA.BytesToArray()); + + using IColumnDbSnapshot snapshot = asColumnsDb.CreateSnapshot(); + + colA.Set(TestItem.KeccakA, TestItem.KeccakB.BytesToArray()); + colA.Get(TestItem.KeccakA).Should().BeEquivalentTo(TestItem.KeccakB.BytesToArray()); + + snapshot.GetColumn(ReceiptsColumns.Blocks) + .Get(TestItem.KeccakA).Should().BeEquivalentTo(TestItem.KeccakA.BytesToArray()); + } } diff --git a/src/Nethermind/Nethermind.Db/IColumnsDb.cs b/src/Nethermind/Nethermind.Db/IColumnsDb.cs index 4f1eddcbd44..5ffddced6ab 100644 --- a/src/Nethermind/Nethermind.Db/IColumnsDb.cs +++ b/src/Nethermind/Nethermind.Db/IColumnsDb.cs @@ -13,10 +13,17 @@ public interface IColumnsDb : IDbMeta, IDisposable IEnumerable ColumnKeys { get; } public IReadOnlyColumnDb CreateReadOnly(bool createInMemWriteStore) => new ReadOnlyColumnsDb(this, createInMemWriteStore); IColumnsWriteBatch StartWriteBatch(); + IColumnDbSnapshot CreateSnapshot(); } public interface IColumnsWriteBatch : IDisposable { IWriteBatch GetColumnBatch(TKey key); } + + + public interface IColumnDbSnapshot : IDisposable + { + IReadOnlyKeyValueStore GetColumn(TKey key); + } } diff --git a/src/Nethermind/Nethermind.Db/MemColumnsDb.cs b/src/Nethermind/Nethermind.Db/MemColumnsDb.cs index ea37042e51b..7d145ce1bc1 100644 --- a/src/Nethermind/Nethermind.Db/MemColumnsDb.cs +++ b/src/Nethermind/Nethermind.Db/MemColumnsDb.cs @@ -3,6 +3,8 @@ using System; using System.Collections.Generic; +using System.Linq; +using Nethermind.Core; namespace Nethermind.Db { @@ -38,6 +40,12 @@ public IColumnsWriteBatch StartWriteBatch() { return new InMemoryColumnWriteBatch(this); } + + public IColumnDbSnapshot CreateSnapshot() + { + throw new NotSupportedException("Snapshot not supported"); + } + public void Dispose() { } public void Flush(bool onlyWal = false) { } } diff --git a/src/Nethermind/Nethermind.Db/ReadOnlyColumnsDb.cs b/src/Nethermind/Nethermind.Db/ReadOnlyColumnsDb.cs index 3b7bafd750d..0c8483d09e7 100644 --- a/src/Nethermind/Nethermind.Db/ReadOnlyColumnsDb.cs +++ b/src/Nethermind/Nethermind.Db/ReadOnlyColumnsDb.cs @@ -10,9 +10,11 @@ namespace Nethermind.Db public class ReadOnlyColumnsDb : IReadOnlyColumnDb, IDisposable { private readonly IDictionary _readOnlyColumns; + private readonly IColumnsDb _baseColumnDb; public ReadOnlyColumnsDb(IColumnsDb baseColumnDb, bool createInMemWriteStore) { + _baseColumnDb = baseColumnDb; _readOnlyColumns = baseColumnDb.ColumnKeys .Select(key => (key, db: baseColumnDb.GetColumnDb(key).CreateReadOnly(createInMemWriteStore))) .ToDictionary(it => it.key, it => it.db); @@ -29,6 +31,11 @@ public IColumnsWriteBatch StartWriteBatch() return new InMemoryColumnWriteBatch(this); } + public IColumnDbSnapshot CreateSnapshot() + { + return _baseColumnDb.CreateSnapshot(); + } + public void ClearTempChanges() { foreach (KeyValuePair readOnlyColumn in _readOnlyColumns) From 1a1fdb55d40d2b945099deb21b3d100a4bc82ff1 Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Mon, 19 Jan 2026 14:35:58 +0100 Subject: [PATCH 247/255] Refactor ReleaseSpec (#10251) --- .../Blockchain/TestBlockchain.cs | 2 +- .../Nethermind.Core/Specs/IReleaseSpec.cs | 13 +- .../Specs/ReleaseSpecDecorator.cs | 8 +- .../Nethermind.Evm.Precompiles/Extensions.cs | 2 +- .../OverridableReleaseSpec.cs | 278 ++++++------------ .../Nethermind.Specs/ReleaseSpec.cs | 83 ++---- 6 files changed, 130 insertions(+), 256 deletions(-) diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 4cec9335358..ca9d46d72cc 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -327,7 +327,7 @@ public Block Build() // Eip2935 if (specProvider.GenesisSpec.IsBlockHashInStateAvailable) { - state.CreateAccount(specProvider.GenesisSpec.Eip2935ContractAddress, 1); + state.CreateAccount(specProvider.GenesisSpec.Eip2935ContractAddress!, 1); } state.CreateAccount(TestItem.AddressA, testConfiguration.AccountInitialValue); diff --git a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs index fdaea1e7339..fa50589138e 100644 --- a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Frozen; +using System.Diagnostics.CodeAnalysis; using Nethermind.Int256; namespace Nethermind.Core.Specs @@ -272,20 +273,23 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec /// EIP-6110: Supply validator deposits on chain /// bool IsEip6110Enabled { get; } - Address DepositContractAddress { get; } + [MemberNotNullWhen(true, nameof(IsEip6110Enabled))] + Address? DepositContractAddress { get; } /// /// Execution layer triggerable exits /// bool IsEip7002Enabled { get; } - Address Eip7002ContractAddress { get; } + [MemberNotNullWhen(true, nameof(Eip7002ContractAddress))] + Address? Eip7002ContractAddress { get; } /// /// EIP-7251: triggered consolidations /// bool IsEip7251Enabled { get; } - Address Eip7251ContractAddress { get; } + [MemberNotNullWhen(true, nameof(IsEip7251Enabled))] + Address? Eip7251ContractAddress { get; } /// @@ -297,7 +301,8 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec /// Fetch blockHashes from the state for BLOCKHASH opCode /// bool IsEip7709Enabled { get; } - Address Eip2935ContractAddress { get; } + [MemberNotNullWhen(true, nameof(Eip2935ContractAddress))] + Address? Eip2935ContractAddress { get; } /// /// EIP-2935 ring buffer size for historical block hash storage. diff --git a/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs b/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs index 81200ab400b..eff103b6c29 100644 --- a/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs +++ b/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs @@ -77,14 +77,14 @@ public class ReleaseSpecDecorator(IReleaseSpec spec) : IReleaseSpec public virtual UInt256 BlobBaseFeeUpdateFraction => spec.BlobBaseFeeUpdateFraction; public virtual Address? Eip4788ContractAddress => spec.Eip4788ContractAddress; public virtual bool IsEip6110Enabled => spec.IsEip6110Enabled; - public virtual Address DepositContractAddress => spec.DepositContractAddress; + public virtual Address? DepositContractAddress => spec.DepositContractAddress; public virtual bool IsEip7002Enabled => spec.IsEip7002Enabled; - public virtual Address Eip7002ContractAddress => spec.Eip7002ContractAddress; + public virtual Address? Eip7002ContractAddress => spec.Eip7002ContractAddress; public virtual bool IsEip7251Enabled => spec.IsEip7251Enabled; - public virtual Address Eip7251ContractAddress => spec.Eip7251ContractAddress; + public virtual Address? Eip7251ContractAddress => spec.Eip7251ContractAddress; public virtual bool IsEip2935Enabled => spec.IsEip2935Enabled; public virtual bool IsEip7709Enabled => spec.IsEip7709Enabled; - public virtual Address Eip2935ContractAddress => spec.Eip2935ContractAddress; + public virtual Address? Eip2935ContractAddress => spec.Eip2935ContractAddress; public virtual long Eip2935RingBufferSize => spec.Eip2935RingBufferSize; public virtual bool IsEip6780Enabled => spec.IsEip6780Enabled; public virtual bool IsEip7702Enabled => spec.IsEip7702Enabled; diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/Extensions.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Extensions.cs index ebe22dcda94..d5d6b96e70f 100644 --- a/src/Nethermind/Nethermind.Evm.Precompiles/Extensions.cs +++ b/src/Nethermind/Nethermind.Evm.Precompiles/Extensions.cs @@ -73,7 +73,7 @@ public static OrderedDictionary ListSystemContracts(this IRelea if (spec.IsBeaconBlockRootAvailable) systemContracts[Eip4788Constants.ContractAddressKey] = Eip4788Constants.BeaconRootsAddress; if (spec.ConsolidationRequestsEnabled) systemContracts[Eip7251Constants.ContractAddressKey] = Eip7251Constants.ConsolidationRequestPredeployAddress; - if (spec.DepositsEnabled) systemContracts[Eip6110Constants.ContractAddressKey] = spec.DepositContractAddress; + if (spec.DepositsEnabled) systemContracts[Eip6110Constants.ContractAddressKey] = spec.DepositContractAddress!; if (spec.IsEip2935Enabled) systemContracts[Eip2935Constants.ContractAddressKey] = Eip2935Constants.BlockHashHistoryAddress; if (spec.WithdrawalRequestsEnabled) systemContracts[Eip7002Constants.ContractAddressKey] = Eip7002Constants.WithdrawalRequestPredeployAddress; diff --git a/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs b/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs index bd6810c0564..b70d3abed3c 100644 --- a/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs @@ -16,191 +16,109 @@ namespace Nethermind.Specs.Test public class OverridableReleaseSpec(IReleaseSpec spec) : IReleaseSpec { public string Name => "OverridableReleaseSpec"; - - public long MaximumExtraDataSize => spec.MaximumExtraDataSize; - - public long MaxCodeSize => spec.MaxCodeSize; - - public long MaxInitCodeSize => spec.MaxInitCodeSize; - - public long MinGasLimit => spec.MinGasLimit; - - public long MinHistoryRetentionEpochs => spec.MinHistoryRetentionEpochs; - - public long GasLimitBoundDivisor => spec.GasLimitBoundDivisor; - - private UInt256? _blockReward = spec.BlockReward; - public UInt256 BlockReward - { - get => _blockReward ?? spec.BlockReward; - set => _blockReward = value; - } - - public long DifficultyBombDelay => spec.DifficultyBombDelay; - - public long DifficultyBoundDivisor => spec.DifficultyBoundDivisor; - - public long? FixedDifficulty => spec.FixedDifficulty; - - public int MaximumUncleCount => spec.MaximumUncleCount; - - public bool IsTimeAdjustmentPostOlympic => spec.IsTimeAdjustmentPostOlympic; - - public bool IsEip2Enabled => spec.IsEip2Enabled; - - public bool IsEip7Enabled => spec.IsEip7Enabled; - - public bool IsEip100Enabled => spec.IsEip100Enabled; - - public bool IsEip140Enabled => spec.IsEip140Enabled; - - public bool IsEip150Enabled => spec.IsEip150Enabled; - - public bool IsEip155Enabled => spec.IsEip155Enabled; - - public bool IsEip158Enabled => spec.IsEip158Enabled; - - public bool IsEip160Enabled => spec.IsEip160Enabled; - - public bool IsEip170Enabled => spec.IsEip170Enabled; - - public bool IsEip196Enabled => spec.IsEip196Enabled; - - public bool IsEip197Enabled => spec.IsEip197Enabled; - - public bool IsEip198Enabled => spec.IsEip198Enabled; - - public bool IsEip211Enabled => spec.IsEip211Enabled; - - public bool IsEip214Enabled => spec.IsEip214Enabled; - - public bool IsEip649Enabled => spec.IsEip649Enabled; - - public bool IsEip658Enabled => spec.IsEip658Enabled; - - public bool IsEip145Enabled => spec.IsEip145Enabled; - - public bool IsEip1014Enabled => spec.IsEip1014Enabled; - - public bool IsEip1052Enabled => spec.IsEip1052Enabled; - - public bool IsEip1283Enabled => spec.IsEip1283Enabled; - - public bool IsEip1234Enabled => spec.IsEip1234Enabled; - - public bool IsEip1344Enabled => spec.IsEip1344Enabled; - - public bool IsEip2028Enabled => spec.IsEip2028Enabled; - - public bool IsEip152Enabled => spec.IsEip152Enabled; - - public bool IsEip1108Enabled => spec.IsEip1108Enabled; - - public bool IsEip1884Enabled => spec.IsEip1884Enabled; - - public bool IsEip2200Enabled => spec.IsEip2200Enabled; - - public bool IsEip2537Enabled => spec.IsEip2537Enabled; - - public bool IsEip2565Enabled => spec.IsEip2565Enabled; - - public bool IsEip2929Enabled => spec.IsEip2929Enabled; - - public bool IsEip2930Enabled => spec.IsEip2930Enabled; - - public bool IsEip1559Enabled => spec.IsEip1559Enabled; - public bool IsEip3198Enabled => spec.IsEip3198Enabled; - public bool IsEip3529Enabled => spec.IsEip3529Enabled; - - public bool IsEip3541Enabled => spec.IsEip3541Enabled; - public bool IsEip4844Enabled => spec.IsEip4844Enabled; - public bool IsEip7951Enabled => spec.IsEip7951Enabled; - public bool IsRip7212Enabled => spec.IsRip7212Enabled; - public bool IsOpGraniteEnabled => spec.IsOpGraniteEnabled; - public bool IsOpHoloceneEnabled => spec.IsOpHoloceneEnabled; - public bool IsOpIsthmusEnabled => spec.IsOpIsthmusEnabled; - public bool IsOpJovianEnabled => spec.IsOpJovianEnabled; - - public bool IsEip7623Enabled => spec.IsEip7623Enabled; - public bool IsEip7918Enabled => spec.IsEip7918Enabled; - - public bool IsEip7883Enabled => spec.IsEip7883Enabled; - - public bool IsEip7934Enabled => spec.IsEip7934Enabled; - public int Eip7934MaxRlpBlockSize => spec.Eip7934MaxRlpBlockSize; - public bool ValidateChainId => spec.ValidateChainId; + public long MaximumExtraDataSize { get; set; } = spec.MaximumExtraDataSize; + public long MaxCodeSize { get; set; } = spec.MaxCodeSize; + public long MinGasLimit { get; set; } = spec.MinGasLimit; + public long MinHistoryRetentionEpochs { get; set; } = spec.MinHistoryRetentionEpochs; + public long GasLimitBoundDivisor { get; set; } = spec.GasLimitBoundDivisor; + public UInt256 BlockReward { get; set; } = spec.BlockReward; + public long DifficultyBombDelay { get; set; } = spec.DifficultyBombDelay; + public long DifficultyBoundDivisor { get; set; } = spec.DifficultyBoundDivisor; + public long? FixedDifficulty { get; set; } = spec.FixedDifficulty; + public int MaximumUncleCount { get; set; } = spec.MaximumUncleCount; + public bool IsTimeAdjustmentPostOlympic { get; set; } = spec.IsTimeAdjustmentPostOlympic; + public bool IsEip2Enabled { get; set; } = spec.IsEip2Enabled; + public bool IsEip7Enabled { get; set; } = spec.IsEip7Enabled; + public bool IsEip100Enabled { get; set; } = spec.IsEip100Enabled; + public bool IsEip140Enabled { get; set; } = spec.IsEip140Enabled; + public bool IsEip150Enabled { get; set; } = spec.IsEip150Enabled; + public bool IsEip155Enabled { get; set; } = spec.IsEip155Enabled; + public bool IsEip158Enabled { get; set; } = spec.IsEip158Enabled; + public bool IsEip160Enabled { get; set; } = spec.IsEip160Enabled; + public bool IsEip170Enabled { get; set; } = spec.IsEip170Enabled; + public bool IsEip196Enabled { get; set; } = spec.IsEip196Enabled; + public bool IsEip197Enabled { get; set; } = spec.IsEip197Enabled; + public bool IsEip198Enabled { get; set; } = spec.IsEip198Enabled; + public bool IsEip211Enabled { get; set; } = spec.IsEip211Enabled; + public bool IsEip214Enabled { get; set; } = spec.IsEip214Enabled; + public bool IsEip649Enabled { get; set; } = spec.IsEip649Enabled; + public bool IsEip658Enabled { get; set; } = spec.IsEip658Enabled; + public bool IsEip145Enabled { get; set; } = spec.IsEip145Enabled; + public bool IsEip1014Enabled { get; set; } = spec.IsEip1014Enabled; + public bool IsEip1052Enabled { get; set; } = spec.IsEip1052Enabled; + public bool IsEip1283Enabled { get; set; } = spec.IsEip1283Enabled; + public bool IsEip1234Enabled { get; set; } = spec.IsEip1234Enabled; + public bool IsEip1344Enabled { get; set; } = spec.IsEip1344Enabled; + public bool IsEip2028Enabled { get; set; } = spec.IsEip2028Enabled; + public bool IsEip152Enabled { get; set; } = spec.IsEip152Enabled; + public bool IsEip1108Enabled { get; set; } = spec.IsEip1108Enabled; + public bool IsEip1884Enabled { get; set; } = spec.IsEip1884Enabled; + public bool IsEip2200Enabled { get; set; } = spec.IsEip2200Enabled; + public bool IsEip2537Enabled { get; set; } = spec.IsEip2537Enabled; + public bool IsEip2565Enabled { get; set; } = spec.IsEip2565Enabled; + public bool IsEip2929Enabled { get; set; } = spec.IsEip2929Enabled; + public bool IsEip2930Enabled { get; set; } = spec.IsEip2930Enabled; + public bool IsEip1559Enabled { get; set; } = spec.IsEip1559Enabled; + public bool IsEip3198Enabled { get; set; } = spec.IsEip3198Enabled; + public bool IsEip3529Enabled { get; set; } = spec.IsEip3529Enabled; + public bool IsEip3541Enabled { get; set; } = spec.IsEip3541Enabled; + public bool IsEip4844Enabled { get; set; } = spec.IsEip4844Enabled; + public bool IsEip7951Enabled { get; set; } = spec.IsEip7951Enabled; + public bool IsRip7212Enabled { get; set; } = spec.IsRip7212Enabled; + public bool IsOpGraniteEnabled { get; set; } = spec.IsOpGraniteEnabled; + public bool IsOpHoloceneEnabled { get; set; } = spec.IsOpHoloceneEnabled; + public bool IsOpIsthmusEnabled { get; set; } = spec.IsOpIsthmusEnabled; + public bool IsOpJovianEnabled { get; set; } = spec.IsOpJovianEnabled; + public bool IsEip7623Enabled { get; set; } = spec.IsEip7623Enabled; + public bool IsEip7918Enabled { get; set; } = spec.IsEip7918Enabled; + public bool IsEip7883Enabled { get; set; } = spec.IsEip7883Enabled; + public bool IsEip7934Enabled { get; set; } = spec.IsEip7934Enabled; + public int Eip7934MaxRlpBlockSize { get; set; } = spec.Eip7934MaxRlpBlockSize; + public bool ValidateChainId { get; set; } = spec.ValidateChainId; public bool IsEip3607Enabled { get; set; } = spec.IsEip3607Enabled; - public bool IsEip158IgnoredAccount(Address address) => spec.IsEip158IgnoredAccount(address); - - private long? _overriddenEip1559TransitionBlock; - public long Eip1559TransitionBlock - { - get => _overriddenEip1559TransitionBlock ?? spec.Eip1559TransitionBlock; - set => _overriddenEip1559TransitionBlock = value; - } - - private Address? _overriddenFeeCollector; - public Address? FeeCollector - { - get => _overriddenFeeCollector ?? spec.FeeCollector; - set => _overriddenFeeCollector = value; - } - - private ulong? _overriddenEip4844TransitionTimestamp; - - public ulong Eip4844TransitionTimestamp - { - get - { - return _overriddenEip4844TransitionTimestamp ?? spec.Eip4844TransitionTimestamp; - } - set - { - _overriddenEip4844TransitionTimestamp = value; - } - } - - public ulong TargetBlobCount => spec.TargetBlobCount; - public ulong MaxBlobCount => spec.MaxBlobCount; - public ulong MaxBlobsPerTx => spec.MaxBlobsPerTx; - public UInt256 BlobBaseFeeUpdateFraction => spec.BlobBaseFeeUpdateFraction; - public bool IsEip1153Enabled => spec.IsEip1153Enabled; - public bool IsEip3651Enabled => spec.IsEip3651Enabled; - public bool IsEip3855Enabled => spec.IsEip3855Enabled; - public bool IsEip3860Enabled => spec.IsEip3860Enabled; - public bool IsEip4895Enabled => spec.IsEip4895Enabled; - public ulong WithdrawalTimestamp => spec.WithdrawalTimestamp; - public bool IsEip5656Enabled => spec.IsEip5656Enabled; - public long Eip2935RingBufferSize => spec.Eip2935RingBufferSize; - public bool IsEip6780Enabled => spec.IsEip6780Enabled; - public bool IsEip4788Enabled => spec.IsEip4788Enabled; - public bool IsEip4844FeeCollectorEnabled => spec.IsEip4844FeeCollectorEnabled; - public Address? Eip4788ContractAddress => spec.Eip4788ContractAddress; - public bool IsEip7002Enabled => spec.IsEip7002Enabled; - public Address Eip7002ContractAddress => spec.Eip7002ContractAddress; - public bool IsEip7251Enabled => spec.IsEip7251Enabled; - public Address Eip7251ContractAddress => spec.Eip7251ContractAddress; - public bool IsEip2935Enabled => spec.IsEip2935Enabled; - public bool IsEip7709Enabled => spec.IsEip7709Enabled; - public Address Eip2935ContractAddress => spec.Eip2935ContractAddress; - public bool IsEip7702Enabled => spec.IsEip7702Enabled; - public bool IsEip7823Enabled => spec.IsEip7823Enabled; + public long Eip1559TransitionBlock { get; set; } = spec.Eip1559TransitionBlock; + public Address? FeeCollector { get; set; } = spec.FeeCollector; + public ulong Eip4844TransitionTimestamp { get; set; } = spec.Eip4844TransitionTimestamp; + public ulong TargetBlobCount { get; set; } = spec.TargetBlobCount; + public ulong MaxBlobCount { get; set; } = spec.MaxBlobCount; + public ulong MaxBlobsPerTx { get; set; } = spec.MaxBlobsPerTx; + public UInt256 BlobBaseFeeUpdateFraction { get; set; } = spec.BlobBaseFeeUpdateFraction; + public bool IsEip1153Enabled { get; set; } = spec.IsEip1153Enabled; + public bool IsEip3651Enabled { get; set; } = spec.IsEip3651Enabled; + public bool IsEip3855Enabled { get; set; } = spec.IsEip3855Enabled; + public bool IsEip3860Enabled { get; set; } = spec.IsEip3860Enabled; + public bool IsEip4895Enabled { get; set; } = spec.IsEip4895Enabled; + public ulong WithdrawalTimestamp { get; set; } = spec.WithdrawalTimestamp; + public bool IsEip5656Enabled { get; set; } = spec.IsEip5656Enabled; + public long Eip2935RingBufferSize { get; set; } = spec.Eip2935RingBufferSize; + public bool IsEip6780Enabled { get; set; } = spec.IsEip6780Enabled; + public bool IsEip4788Enabled { get; set; } = spec.IsEip4788Enabled; + public bool IsEip4844FeeCollectorEnabled { get; set; } = spec.IsEip4844FeeCollectorEnabled; + public Address? Eip4788ContractAddress { get; set; } = spec.Eip4788ContractAddress; + public bool IsEip7002Enabled { get; set; } = spec.IsEip7002Enabled; + public Address? Eip7002ContractAddress { get; set; } = spec.Eip7002ContractAddress; + public bool IsEip7251Enabled { get; set; } = spec.IsEip7251Enabled; + public Address? Eip7251ContractAddress { get; set; } = spec.Eip7251ContractAddress; + public bool IsEip2935Enabled { get; set; } = spec.IsEip2935Enabled; + public bool IsEip7709Enabled { get; set; } = spec.IsEip7709Enabled; + public Address? Eip2935ContractAddress { get; set; } = spec.Eip2935ContractAddress; + public bool IsEip7702Enabled { get; set; } = spec.IsEip7702Enabled; + public bool IsEip7823Enabled { get; set; } = spec.IsEip7823Enabled; public bool IsEip7825Enabled { get; set; } = spec.IsEip7825Enabled; - public UInt256 ForkBaseFee => spec.ForkBaseFee; - public UInt256 BaseFeeMaxChangeDenominator => spec.BaseFeeMaxChangeDenominator; - public long ElasticityMultiplier => spec.ElasticityMultiplier; - public IBaseFeeCalculator BaseFeeCalculator => spec.BaseFeeCalculator; - public bool IsEofEnabled => spec.IsEofEnabled; - public bool IsEip6110Enabled => spec.IsEip6110Enabled; - public Address DepositContractAddress => spec.DepositContractAddress; - public bool IsEip7594Enabled => spec.IsEip7594Enabled; - + public UInt256 ForkBaseFee { get; set; } = spec.ForkBaseFee; + public UInt256 BaseFeeMaxChangeDenominator { get; set; } = spec.BaseFeeMaxChangeDenominator; + public long ElasticityMultiplier { get; set; } = spec.ElasticityMultiplier; + public IBaseFeeCalculator BaseFeeCalculator { get; set; } = spec.BaseFeeCalculator; + public bool IsEofEnabled { get; set; } = spec.IsEofEnabled; + public bool IsEip6110Enabled { get; set; } = spec.IsEip6110Enabled; + public Address? DepositContractAddress { get; set; } = spec.DepositContractAddress; + public bool IsEip7594Enabled { get; set; } = spec.IsEip7594Enabled; Array? IReleaseSpec.EvmInstructionsNoTrace { get => spec.EvmInstructionsNoTrace; set => spec.EvmInstructionsNoTrace = value; } Array? IReleaseSpec.EvmInstructionsTraced { get => spec.EvmInstructionsTraced; set => spec.EvmInstructionsTraced = value; } - public bool IsEip7939Enabled => spec.IsEip7939Enabled; - public bool IsEip7907Enabled => spec.IsEip7907Enabled; - public bool IsRip7728Enabled => spec.IsRip7728Enabled; + public bool IsEip7939Enabled { get; set; } = spec.IsEip7939Enabled; + public bool IsEip7907Enabled { get; set; } = spec.IsEip7907Enabled; + public bool IsRip7728Enabled { get; set; } = spec.IsRip7728Enabled; FrozenSet IReleaseSpec.Precompiles => spec.Precompiles; } } diff --git a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs index 2d4f0d50d58..dad707e7f7f 100644 --- a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Frozen; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Nethermind.Core; using Nethermind.Core.Precompiles; using Nethermind.Core.Specs; @@ -56,16 +57,7 @@ public class ReleaseSpec : IReleaseSpec public bool IsEip2565Enabled { get; set; } public bool IsEip2929Enabled { get; set; } public bool IsEip2930Enabled { get; set; } - - // used only in testing - public ReleaseSpec Clone() => (ReleaseSpec)MemberwiseClone(); - - public bool IsEip1559Enabled - { - get => _isEip1559Enabled || IsEip4844Enabled; - set => _isEip1559Enabled = value; - } - + public bool IsEip1559Enabled { get => field || IsEip4844Enabled; set; } public bool IsEip158IgnoredAccount(Address address) => false; public bool IsEip3198Enabled { get; set; } public bool IsEip3529Enabled { get; set; } @@ -76,7 +68,7 @@ public bool IsEip1559Enabled public long Eip1559TransitionBlock { get; set; } public ulong WithdrawalTimestamp { get; set; } public ulong Eip4844TransitionTimestamp { get; set; } - public Address FeeCollector { get; set; } + public Address? FeeCollector { get; set; } public UInt256? Eip1559BaseFeeMinValue { get; set; } public UInt256 ForkBaseFee { get; set; } = Eip1559Constants.DefaultForkBaseFee; public UInt256 BaseFeeMaxChangeDenominator { get; set; } = Eip1559Constants.DefaultBaseFeeMaxChangeDenominator; @@ -109,76 +101,32 @@ public bool IsEip1559Enabled public bool IsEip7934Enabled { get; set; } public int Eip7934MaxRlpBlockSize { get; set; } public bool IsEip7907Enabled { get; set; } - public ulong TargetBlobCount { get; set; } public ulong MaxBlobCount { get; set; } - - public ulong MaxBlobsPerTx => - IsEip7594Enabled ? Math.Min(Eip7594Constants.MaxBlobsPerTx, MaxBlobCount) : MaxBlobCount; - + public ulong MaxBlobsPerTx => IsEip7594Enabled ? Math.Min(Eip7594Constants.MaxBlobsPerTx, MaxBlobCount) : MaxBlobCount; public UInt256 BlobBaseFeeUpdateFraction { get; set; } - - - private Address _eip7251ContractAddress; - - public Address Eip7251ContractAddress - { - get => IsEip7251Enabled ? _eip7251ContractAddress : null; - set => _eip7251ContractAddress = value; - } - - private Address _eip7002ContractAddress; - - public Address Eip7002ContractAddress - { - get => IsEip7002Enabled ? _eip7002ContractAddress : null; - set => _eip7002ContractAddress = value; - } - - private Address _eip4788ContractAddress; - - public Address Eip4788ContractAddress - { - get => IsEip4788Enabled ? _eip4788ContractAddress : null; - set => _eip4788ContractAddress = value; - } - + [MemberNotNullWhen(true, nameof(IsEip7251Enabled))] + public Address? Eip7251ContractAddress { get => IsEip7251Enabled ? field : null; set; } + [MemberNotNullWhen(true, nameof(Eip7002ContractAddress))] + public Address? Eip7002ContractAddress { get => IsEip7002Enabled ? field : null; set; } + [MemberNotNullWhen(true, nameof(IsEip4788Enabled))] + public Address? Eip4788ContractAddress { get => IsEip4788Enabled ? field : null; set; } public bool IsEofEnabled { get; set; } - public bool IsEip6110Enabled { get; set; } - - private Address _depositContractAddress; - - public Address DepositContractAddress - { - get => IsEip6110Enabled ? _depositContractAddress : null; - set => _depositContractAddress = value; - } - + [MemberNotNullWhen(true, nameof(IsEip6110Enabled))] + public Address? DepositContractAddress { get => IsEip6110Enabled ? field : null; set; } public bool IsEip2935Enabled { get; set; } public bool IsEip7709Enabled { get; set; } - - private Address _eip2935ContractAddress; - private bool _isEip1559Enabled; - - public Address Eip2935ContractAddress - { - get => IsEip2935Enabled ? _eip2935ContractAddress : null; - set => _eip2935ContractAddress = value; - } - + [MemberNotNullWhen(true, nameof(Eip2935ContractAddress))] + public Address? Eip2935ContractAddress { get => IsEip2935Enabled ? field : null; set; } public bool IsEip7594Enabled { get; set; } - Array? IReleaseSpec.EvmInstructionsNoTrace { get; set; } - Array? IReleaseSpec.EvmInstructionsTraced { get; set; } public bool IsEip7939Enabled { get; set; } public bool IsRip7728Enabled { get; set; } - private FrozenSet? _precompiles; FrozenSet IReleaseSpec.Precompiles => _precompiles ??= BuildPrecompilesCache(); public long Eip2935RingBufferSize { get; set; } = Eip2935Constants.RingBufferSize; - public virtual FrozenSet BuildPrecompilesCache() { HashSet cache = new(); @@ -214,4 +162,7 @@ public virtual FrozenSet BuildPrecompilesCache() return cache.ToFrozenSet(); } + + // used only in testing + public ReleaseSpec Clone() => (ReleaseSpec)MemberwiseClone(); } From 471bcb95bac677d2ffde5bb2e882e20186841b24 Mon Sep 17 00:00:00 2001 From: Nurbakyt Madibek Date: Mon, 19 Jan 2026 16:53:32 +0300 Subject: [PATCH 248/255] Add taiko debug RPC for integration test support (#10211) * Add taikoAuth_waitForTxPoolSync method * Revert unnecessary changes * Update src/Nethermind/Nethermind.TxPool/ITxPool.cs * Update src/Nethermind/Nethermind.TxPool/TxPool.cs * Update src/Nethermind/Nethermind.TxPool/HashCache.cs * Resolve comments * Simplify, remove needless logic, and rename * Resolve comments --------- Co-authored-by: Ahmad Bitar <33181301+smartprogrammer93@users.noreply.github.com> --- .../Rpc/ITaikoEngineRpcModule.cs | 14 +++++++ .../Rpc/TaikoEngineRpcModule.cs | 7 ++++ src/Nethermind/Nethermind.TxPool/HashCache.cs | 9 +++++ src/Nethermind/Nethermind.TxPool/ITxPool.cs | 6 +++ .../Nethermind.TxPool/NullTxPool.cs | 1 + src/Nethermind/Nethermind.TxPool/TxPool.cs | 40 +++++++++++++++++++ 6 files changed, 77 insertions(+) diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoEngineRpcModule.cs b/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoEngineRpcModule.cs index 45973303f5d..e1294830da6 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoEngineRpcModule.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/ITaikoEngineRpcModule.cs @@ -89,4 +89,18 @@ Task> engine_newPayloadV3(TaikoExecutionPayloadV3 IsSharable = true, IsImplemented = true)] ResultWrapper taikoAuth_setL1OriginSignature(UInt256 blockId, int[] signature); + + /// + /// Clears txpool state (hash cache, account cache, pending transactions) after a chain reorg. + /// This is specifically designed for Taiko integration tests where the chain is reset to a base block. + /// After a reorg, stale txpool caches would reject transaction resubmissions with "already known" or "nonce too low". + /// Pending transactions must also be cleared because tests resubmit transactions with the same hash/nonce, + /// which would be rejected as "ReplacementNotAllowed" if they remain in the pool. + /// + [JsonRpcMethod( + Description = "Clears txpool state after chain reorg for testing/debugging purposes. " + + "Returns true on success.", + IsSharable = true, + IsImplemented = true)] + ResultWrapper taikoDebug_clearTxPoolForReorg(); } diff --git a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs index 7560bc5750e..a2dd860f48d 100644 --- a/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs +++ b/src/Nethermind/Nethermind.Taiko/Rpc/TaikoEngineRpcModule.cs @@ -377,4 +377,11 @@ public ResultWrapper taikoAuth_setL1OriginSignature(UInt256 blockId, i return ResultWrapper.Success(l1Origin); } + + /// + public ResultWrapper taikoDebug_clearTxPoolForReorg() + { + txPool.ResetTxPoolState(); + return ResultWrapper.Success(true); + } } diff --git a/src/Nethermind/Nethermind.TxPool/HashCache.cs b/src/Nethermind/Nethermind.TxPool/HashCache.cs index 429bd42a224..8ce7dd5d3fe 100644 --- a/src/Nethermind/Nethermind.TxPool/HashCache.cs +++ b/src/Nethermind/Nethermind.TxPool/HashCache.cs @@ -58,5 +58,14 @@ public void ClearCurrentBlockCache() { _currentBlockCache.Clear(); } + + /// + /// Clears both long-term and current block caches. + /// + public void ClearAll() + { + _longTermCache.Clear(); + _currentBlockCache.Clear(); + } } } diff --git a/src/Nethermind/Nethermind.TxPool/ITxPool.cs b/src/Nethermind/Nethermind.TxPool/ITxPool.cs index 844cd776963..4e6b9a0d7f9 100644 --- a/src/Nethermind/Nethermind.TxPool/ITxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/ITxPool.cs @@ -62,5 +62,11 @@ bool TryGetBlobAndProofV1(byte[] blobVersionedHash, public bool AcceptTxWhenNotSynced { get; set; } bool SupportsBlobs { get; } long PendingTransactionsAdded { get; } + + /// + /// Resets txpool state by clearing all caches (hash cache, account cache) + /// and removing all pending transactions. Used for integration testing after chain reorgs. + /// + void ResetTxPoolState(); } } diff --git a/src/Nethermind/Nethermind.TxPool/NullTxPool.cs b/src/Nethermind/Nethermind.TxPool/NullTxPool.cs index afb1f5b20e7..9ab7f22ab6b 100644 --- a/src/Nethermind/Nethermind.TxPool/NullTxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/NullTxPool.cs @@ -113,5 +113,6 @@ public event EventHandler? EvictedPending remove { } } public bool AcceptTxWhenNotSynced { get; set; } + public void ResetTxPoolState() { } } } diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index 9f8fcf7706e..367fa9c8f97 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -482,6 +482,46 @@ public void RemovePeer(PublicKey nodeId) public bool SupportsBlobs { get; } public long PendingTransactionsAdded => Volatile.Read(ref _pendingTransactionsAdded); + /// This is a debug/testing method that clears the entire txpool state. + /// Currently only used in the Taiko integration tests after chain reorgs. + public void ResetTxPoolState() + { + _newHeadLock.EnterWriteLock(); + try + { + // Clear hash cache and account cache + _hashCache.ClearAll(); + _accountCache.Reset(); + + // Also clear all pending transactions + // Get snapshot first to avoid modifying collection while iterating + Transaction[] pendingTxs = _transactions.GetSnapshot(); + foreach (Transaction tx in pendingTxs) + { + RemoveTransaction(tx.Hash); + } + + // Clear blob transactions too + Transaction[] pendingBlobTxs = _blobTransactions.GetSnapshot(); + foreach (Transaction tx in pendingBlobTxs) + { + RemoveTransaction(tx.Hash); + } + + // Update metrics after removal + Metrics.TransactionCount = _transactions.Count; + Metrics.BlobTransactionCount = _blobTransactions.Count; + + // Reset snapshots + _transactionSnapshot = null; + _blobTransactionSnapshot = null; + } + finally + { + _newHeadLock.ExitWriteLock(); + } + } + public AcceptTxResult SubmitTx(Transaction tx, TxHandlingOptions handlingOptions) { bool startBroadcast = _txPoolConfig.PersistentBroadcastEnabled From 9ccf900f3715b79f2c883ce6ae04eea96d10196f Mon Sep 17 00:00:00 2001 From: Daniil Ankushin Date: Tue, 20 Jan 2026 13:09:32 +0400 Subject: [PATCH 249/255] feat(tracing): enable external tracer registration and VM inheritance (#10228) --- .../Native/GethLikeNativeTracerFactory.cs | 2 +- .../GasPolicy/EthereumGasPolicy.cs | 6 ++++++ .../Nethermind.Evm/GasPolicy/IGasPolicy.cs | 17 +++++++++++++++++ src/Nethermind/Nethermind.Evm/VirtualMachine.cs | 7 +++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Blockchain/Tracing/GethStyle/Custom/Native/GethLikeNativeTracerFactory.cs b/src/Nethermind/Nethermind.Blockchain/Tracing/GethStyle/Custom/Native/GethLikeNativeTracerFactory.cs index b75fe892ce8..1b84577e64e 100644 --- a/src/Nethermind/Nethermind.Blockchain/Tracing/GethStyle/Custom/Native/GethLikeNativeTracerFactory.cs +++ b/src/Nethermind/Nethermind.Blockchain/Tracing/GethStyle/Custom/Native/GethLikeNativeTracerFactory.cs @@ -31,7 +31,7 @@ private static void RegisterNativeTracers() RegisterTracer(NativeCallTracer.CallTracer, static (options, _, transaction, _) => new NativeCallTracer(transaction, options)); } - private static void RegisterTracer(string tracerName, GethLikeNativeTracerFactoryDelegate tracerDelegate) + public static void RegisterTracer(string tracerName, GethLikeNativeTracerFactoryDelegate tracerDelegate) { _tracers.Add(tracerName, tracerDelegate); } diff --git a/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs b/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs index 243840ccc2e..fddd0f0bd54 100644 --- a/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs +++ b/src/Nethermind/Nethermind.Evm/GasPolicy/EthereumGasPolicy.cs @@ -169,6 +169,12 @@ public static bool ConsumeLogEmission(ref EthereumGasPolicy gas, long topicCount public static void ConsumeDataCopyGas(ref EthereumGasPolicy gas, bool isExternalCode, long baseCost, long dataCost) => Consume(ref gas, baseCost + dataCost); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void OnBeforeInstructionTrace(in EthereumGasPolicy gas, int pc, Instruction instruction, int depth) { } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void OnAfterInstructionTrace(in EthereumGasPolicy gas) { } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static EthereumGasPolicy Max(in EthereumGasPolicy a, in EthereumGasPolicy b) => a.Value >= b.Value ? a : b; diff --git a/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs b/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs index 289b9959717..c1a1801d7d9 100644 --- a/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs +++ b/src/Nethermind/Nethermind.Evm/GasPolicy/IGasPolicy.cs @@ -215,4 +215,21 @@ static abstract bool UpdateMemoryCost(ref TSelf gas, /// Fixed opcode cost. /// Per-word copy cost. static abstract void ConsumeDataCopyGas(ref TSelf gas, bool isExternalCode, long baseCost, long dataCost); + + /// + /// Hook called before instruction execution when tracing is active. + /// Allows gas policies to capture pre-execution state. + /// + /// The current gas state. + /// The program counter before incrementing. + /// The instruction about to be executed. + /// The current call depth. + static abstract void OnBeforeInstructionTrace(in TSelf gas, int pc, Instruction instruction, int depth); + + /// + /// Hook called after instruction execution when tracing is active. + /// Allows gas policies to capture post-execution state. + /// + /// The current gas state after execution. + static abstract void OnAfterInstructionTrace(in TSelf gas); } diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index f3cdf0db249..45611c2385e 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -1250,6 +1250,9 @@ protected virtual unsafe CallResult RunByteCode( if (TCancelable.IsActive && _txTracer.IsCancelled) ThrowOperationCanceledException(); + // Call gas policy hook before instruction execution. + TGasPolicy.OnBeforeInstructionTrace(in gas, programCounter, instruction, VmState.Env.CallDepth); + // If tracing is enabled, start an instruction trace. if (TTracingInst.IsActive) StartInstructionTrace(instruction, TGasPolicy.GetRemainingGas(in gas), programCounter, in stack); @@ -1278,6 +1281,10 @@ protected virtual unsafe CallResult RunByteCode( OpCodeCount += opCodeCount; goto OutOfGas; } + + // Call gas policy hook after instruction execution. + TGasPolicy.OnAfterInstructionTrace(in gas); + // If an exception occurred, exit the loop. if (exceptionType != EvmExceptionType.None) break; From 3409a9a1d0e0b65589d1f8c943dfe361048432d4 Mon Sep 17 00:00:00 2001 From: Damian Orzechowski <114909782+damian-orzechowski@users.noreply.github.com> Date: Tue, 20 Jan 2026 11:43:41 +0100 Subject: [PATCH 250/255] Re-enable prewarmer tx adapter for state pre-warming (#10266) Enable prewarmer tx adapter for state pre-warming --- .../Nethermind.Consensus/Processing/PrewarmerTxAdapter.cs | 2 +- src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/PrewarmerTxAdapter.cs b/src/Nethermind/Nethermind.Consensus/Processing/PrewarmerTxAdapter.cs index f9b0774fce8..c5c1efaf2eb 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/PrewarmerTxAdapter.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/PrewarmerTxAdapter.cs @@ -14,7 +14,7 @@ public class PrewarmerTxAdapter(ITransactionProcessorAdapter baseAdapter, BlockC { public TransactionResult Execute(Transaction transaction, ITxTracer txTracer) { - if (worldState is IPreBlockCaches preBlockCaches && preBlockCaches.IsWarmWorldState) + if (worldState.ScopeProvider is IPreBlockCaches { IsWarmWorldState: true }) { preWarmer.OnBeforeTxExecution(transaction); } diff --git a/src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs b/src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs index ebdc79106b0..935ee73eb4b 100644 --- a/src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs @@ -9,6 +9,7 @@ using Nethermind.Core.Container; using Nethermind.Evm; using Nethermind.Evm.State; +using Nethermind.Evm.TransactionProcessing; using Nethermind.State; using Nethermind.Trie; using Nethermind.Trie.Pruning; @@ -62,7 +63,8 @@ protected override void Load(ContainerBuilder builder) // Note: The use of FrozenDictionary means that this cannot be used for other processing env also due to risk of memory leak. return new CachedCodeInfoRepository(precompileProvider, originalCodeInfoRepository, blocksConfig.CachePrecompilesOnBlockProcessing ? preBlockCaches?.PrecompileCache : null); - }); + }) + .AddDecorator(); } } } From 7b948c57bb8d6a4f14ee944036727d2dcf413291 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Tue, 20 Jan 2026 14:49:12 +0300 Subject: [PATCH 251/255] Validate state test tx as part of a block (#10224) * Add basic block validation to state tests * Some cleanup * Fix review --- .../Ethereum.Test.Base/GeneralStateTest.cs | 2 - .../GeneralStateTestEnvJson.cs | 2 - .../Ethereum.Test.Base/GeneralTestBase.cs | 50 +++++++++---------- .../Ethereum.Test.Base/JsonToEthereumTest.cs | 2 - 4 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/Nethermind/Ethereum.Test.Base/GeneralStateTest.cs b/src/Nethermind/Ethereum.Test.Base/GeneralStateTest.cs index 098b7cc8682..da8142a513f 100644 --- a/src/Nethermind/Ethereum.Test.Base/GeneralStateTest.cs +++ b/src/Nethermind/Ethereum.Test.Base/GeneralStateTest.cs @@ -37,8 +37,6 @@ public class GeneralStateTest : EthereumTest public Hash256? CurrentBeaconRoot { get; set; } public Hash256? CurrentWithdrawalsRoot { get; set; } public ulong? CurrentExcessBlobGas { get; set; } - public UInt256? ParentBlobGasUsed { get; set; } - public UInt256? ParentExcessBlobGas { get; set; } public Hash256? RequestsHash { get; set; } diff --git a/src/Nethermind/Ethereum.Test.Base/GeneralStateTestEnvJson.cs b/src/Nethermind/Ethereum.Test.Base/GeneralStateTestEnvJson.cs index a82748257d9..384b5465b19 100644 --- a/src/Nethermind/Ethereum.Test.Base/GeneralStateTestEnvJson.cs +++ b/src/Nethermind/Ethereum.Test.Base/GeneralStateTestEnvJson.cs @@ -20,7 +20,5 @@ public class GeneralStateTestEnvJson public Hash256? CurrentBeaconRoot { get; set; } public Hash256? CurrentWithdrawalsRoot { get; set; } public ulong? CurrentExcessBlobGas { get; set; } - public UInt256? ParentBlobGasUsed { get; set; } - public UInt256? ParentExcessBlobGas { get; set; } } } diff --git a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs index e402b1716b7..dcf87b0aa5c 100644 --- a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs @@ -7,6 +7,7 @@ using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.ExecutionRequest; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Core.Test.Modules; @@ -21,6 +22,8 @@ using Nethermind.Specs; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; +using Nethermind.State.Proofs; +using Nethermind.Trie; using NUnit.Framework; using System; using System.Collections.Generic; @@ -61,6 +64,7 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) { _logger.Info($"Running {test.Name} at {DateTime.UtcNow:HH:mm:ss.ffffff}"); Assert.That(test.LoadFailure, Is.Null, "test data loading failure"); + Assert.That(test.Transaction, Is.Not.Null, "there is no transaction in the test"); EofValidator.Logger = _logger; @@ -87,6 +91,7 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) IMainProcessingContext mainBlockProcessingContext = container.Resolve(); IWorldState stateProvider = mainBlockProcessingContext.WorldState; using IDisposable _ = stateProvider.BeginScope(null); + IBlockValidator blockValidator = container.Resolve(); ITransactionProcessor transactionProcessor = mainBlockProcessingContext.TransactionProcessor; InitializeTestState(test.Pre, stateProvider, specProvider); @@ -101,6 +106,15 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) stateProvider.RecalculateStateRoot(); } + if (test.Transaction.ChainId is null) + { + test.Transaction.ChainId = test.ChainId; + } + + IReleaseSpec? spec = specProvider.GetSpec((ForkActivation)test.CurrentNumber); + Transaction[] transactions = [test.Transaction]; + Withdrawal[]? withdrawals = spec.WithdrawalsEnabled ? [] : null; + BlockHeader header = new( test.PreviousHash, Keccak.OfAnEmptySequenceRlp, @@ -115,47 +129,29 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) StateRoot = test.PostHash, IsPostMerge = test.CurrentRandom is not null, MixHash = test.CurrentRandom, - WithdrawalsRoot = test.CurrentWithdrawalsRoot, + WithdrawalsRoot = test.CurrentWithdrawalsRoot ?? (spec.WithdrawalsEnabled ? PatriciaTree.EmptyTreeHash : null), ParentBeaconBlockRoot = test.CurrentBeaconRoot, ExcessBlobGas = test.CurrentExcessBlobGas ?? (test.Fork is Cancun ? 0ul : null), BlobGasUsed = BlobGasCalculator.CalculateBlobGas(test.Transaction), - RequestsHash = test.RequestsHash + RequestsHash = test.RequestsHash ?? (spec.RequestsEnabled ? ExecutionRequestExtensions.EmptyRequestsHash : null), + TxRoot = TxTrie.CalculateRoot(transactions), + ReceiptsRoot = test.PostReceiptsRoot, }; + header.Hash = header.CalculateHash(); + Block block = new(header, new BlockBody(transactions, [], withdrawals)); Stopwatch stopwatch = Stopwatch.StartNew(); - IReleaseSpec? spec = specProvider.GetSpec((ForkActivation)test.CurrentNumber); - - if (test.Transaction.ChainId is null) - test.Transaction.ChainId = test.ChainId; - if (test.ParentBlobGasUsed is not null && test.ParentExcessBlobGas is not null) - { - BlockHeader parent = new( - parentHash: Keccak.Zero, - unclesHash: Keccak.OfAnEmptySequenceRlp, - beneficiary: test.CurrentCoinbase, - difficulty: test.CurrentDifficulty, - number: test.CurrentNumber - 1, - gasLimit: test.CurrentGasLimit, - timestamp: test.CurrentTimestamp, - extraData: [] - ) - { - BlobGasUsed = (ulong)test.ParentBlobGasUsed, - ExcessBlobGas = (ulong)test.ParentExcessBlobGas, - }; - header.ExcessBlobGas = BlobGasCalculator.CalculateExcessBlobGas(parent, spec); - } - ValidationResult txIsValid = new TxValidator(test.ChainId).IsWellFormed(test.Transaction, spec); TransactionResult? txResult = null; - if (txIsValid) + + if (blockValidator.ValidateOrphanedBlock(block, out string blockValidationError)) { txResult = transactionProcessor.Execute(test.Transaction, new BlockExecutionContext(header, spec), txTracer); } else { - _logger.Info($"Skipping invalid tx with error: {txIsValid.Error}"); + _logger.Info($"Skipping invalid tx with error: {blockValidationError}"); } stopwatch.Stop(); diff --git a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs index 4c7c5d6317e..0eda74a3459 100644 --- a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs +++ b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs @@ -277,8 +277,6 @@ public static IEnumerable Convert(string name, string category CurrentBeaconRoot = testJson.Env.CurrentBeaconRoot, CurrentWithdrawalsRoot = testJson.Env.CurrentWithdrawalsRoot, CurrentExcessBlobGas = testJson.Env.CurrentExcessBlobGas, - ParentBlobGasUsed = testJson.Env.ParentBlobGasUsed, - ParentExcessBlobGas = testJson.Env.ParentExcessBlobGas, PostReceiptsRoot = stateJson.Logs, PostHash = stateJson.Hash, Pre = testJson.Pre.ToDictionary(p => p.Key, p => p.Value), From b247009e9b38b67120659f1bb768aba0ae81ec08 Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Wed, 21 Jan 2026 09:02:29 +0800 Subject: [PATCH 252/255] Add ProgressLogger to trie verification and full pruning operations (#10273) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: add implementation plan for ProgressLogger trie visitor integration Addresses #8504 - More use of ProgressLogger Detailed step-by-step plan with: - VisitorProgressTracker class implementation - Unit tests for thread-safety and accuracy - Integration into CopyTreeVisitor and TrieStatsCollector Co-Authored-By: Claude Opus 4.5 * feat(trie): add VisitorProgressTracker for path-based progress estimation Addresses #8504 - More use of ProgressLogger - Tracks visited path prefixes at 4 levels (16 to 65536 granularity) - Thread-safe for concurrent traversal - Estimates progress from keyspace position, not node count Co-Authored-By: Claude Opus 4.5 * test(trie): add unit tests for VisitorProgressTracker Tests cover: - Progress tracking at different levels - Thread-safety with concurrent calls - Monotonically increasing progress - Edge cases (short paths, empty path) Co-Authored-By: Claude Opus 4.5 * feat(pruning): integrate VisitorProgressTracker into CopyTreeVisitor Replaces manual every-1M-nodes logging with path-based progress estimation. Progress now shows actual percentage through the keyspace. Co-Authored-By: Claude Opus 4.5 * Improve TrieStatsCollector progress display - Always enable progress tracking in TrieStatsCollector - Add custom formatter to show node count instead of block speed - Track max reported progress to prevent backwards jumps - Display format: "Trie Verification 12.34% [...] nodes: 1.2M" Fixes progress display issues where: - Progress would jump backwards (12% → 5%) due to granularity switching - Showed confusing "Blk/s" units for trie operations - Displayed "11 / 100 (11.00%)" format that looked odd Co-Authored-By: Claude Sonnet 4.5 * docs: remove implementation plan documents Implementation is complete, no need for plan docs in the codebase. Co-Authored-By: Claude Sonnet 4.5 * Track both state and storage nodes in progress display The node count now includes both state and storage nodes, providing a more accurate representation of total work done. Progress estimation still uses state trie paths only. Changes: - Add _totalWorkDone counter for display (state + storage nodes) - Add isStorage parameter to OnNodeVisited() - Always increment total work, only track state nodes for progress Co-Authored-By: Claude Sonnet 4.5 * Optimize progress tracking with active level and startup delay Improvements: - Add 1 second startup delay before logging to prevent early high values from getting stuck in _maxReportedProgress - Only track the deepest level with >5% coverage (active level) - Stop incrementing counts for shallower levels once deeper level has significant coverage - This ensures progress never shows less than 5% and provides more accurate granularity Technical changes: - Add _activeLevel field to track current deepest significant level - Add _startTime field and skip logging for first second - Only increment seen counts at active level or deeper - Automatically promote to deeper level when >5% coverage reached Co-Authored-By: Claude Sonnet 4.5 * Simplify progress tracking to only use level 3 with leaf estimation Changed to a much simpler approach as requested: - Only track progress at level 3 (4 nibbles = 65536 possible nodes) - For nodes at depth 4: increment count by 1 - For LEAF nodes at shallower depths: estimate coverage - Depth 1: covers 16^3 = 4096 level-3 nodes - Depth 2: covers 16^2 = 256 level-3 nodes - Depth 3: covers 16^1 = 16 level-3 nodes - Non-leaf nodes at shallow depths: don't count (will be covered by deeper nodes) - Keep 1 second startup delay to prevent early high percentages This assumes the top of the tree is dense and provides accurate progress estimation based on actual trie structure. Updated tests to mark nodes as leaves where appropriate. Co-Authored-By: Claude Sonnet 4.5 * Fix full pruning progress tracking - Pass isStorage and isLeaf parameters in CopyTreeVisitor - Storage nodes no longer contribute to state trie progress estimation - Leaf nodes at shallow depths now correctly estimate coverage - Increase startup delay to 5 seconds AND require at least 1% progress - Prevents early high estimates from getting stuck in _maxReportedProgress This fixes the issue where full pruning progress would immediately jump to 100% and not show meaningful progress during the copy operation. Co-Authored-By: Claude Sonnet 4.5 * Simplify VisitorProgressTracker to single-level tracking Since we only track level 3 (4 nibbles), remove unnecessary array structure: - Replace int[][] _seen with int[] _seen (65536 entries) - Replace int[] _seenCounts with int _seenCount - Replace int[] MaxAtLevel with const int MaxNodes - Rename MaxLevel to Level3Depth for clarity This reduces memory allocation from 70,304 ints (16+256+4096+65536) to just 65,536 ints, and makes the code clearer. Co-Authored-By: Claude Sonnet 4.5 * Remove unnecessary _seen array from VisitorProgressTracker Since OnNodeVisited is only called once per path, we don't need to track which prefixes we've seen. Just increment _seenCount directly. This eliminates the 65536-int array, reducing memory from 262KB to just a few counters. Co-Authored-By: Claude Sonnet 4.5 * Remove _maxReportedProgress and allow progress to reverse - Remove _maxReportedProgress field and backwards-prevention logic - Report actual progress value even if it goes backwards - Fix path.Length check: only count nodes at exactly Level3Depth - Ignore nodes at depth > Level3Depth for progress calculation - Simplify comment about startup delay Progress should reflect reality, not be artificially constrained. Co-Authored-By: Claude Sonnet 4.5 * Fix lint --------- Co-authored-by: Claude Opus 4.5 --- cspell.json | 1 + .../FullPruning/CopyTreeVisitor.cs | 38 ++--- .../Nethermind.State/StateReaderExtensions.cs | 1 + .../VisitorProgressTrackerTests.cs | 150 ++++++++++++++++++ .../Nethermind.Trie/TrieStatsCollector.cs | 28 ++-- .../Nethermind.Trie/VisitorProgressTracker.cs | 142 +++++++++++++++++ 6 files changed, 328 insertions(+), 32 deletions(-) create mode 100644 src/Nethermind/Nethermind.Trie.Test/VisitorProgressTrackerTests.cs create mode 100644 src/Nethermind/Nethermind.Trie/VisitorProgressTracker.cs diff --git a/cspell.json b/cspell.json index 2208a7aab4f..a4cc1ab2ca1 100644 --- a/cspell.json +++ b/cspell.json @@ -332,6 +332,7 @@ "keccaks", "keepalive", "keyaddrtest", + "keyspace", "keyper", "keypers", "kneth", diff --git a/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs b/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs index c2afa4cf718..82cb1e9b06b 100644 --- a/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs +++ b/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs @@ -24,12 +24,12 @@ public class CopyTreeVisitor : ICopyTreeVisitor, ITreeVisitor true; @@ -68,36 +69,33 @@ public void VisitMissingNode(in TContext ctx, in ValueHash256 nodeHash) throw new TrieException($"Trie {nodeHash} missing"); } - public void VisitBranch(in TContext ctx, TrieNode node) => PersistNode(ctx.Storage, ctx.Path, node); + public void VisitBranch(in TContext ctx, TrieNode node) + { + PersistNode(ctx.Storage, ctx.Path, node, isLeaf: false); + } - public void VisitExtension(in TContext ctx, TrieNode node) => PersistNode(ctx.Storage, ctx.Path, node); + public void VisitExtension(in TContext ctx, TrieNode node) + { + PersistNode(ctx.Storage, ctx.Path, node, isLeaf: false); + } - public void VisitLeaf(in TContext ctx, TrieNode node) => PersistNode(ctx.Storage, ctx.Path, node); + public void VisitLeaf(in TContext ctx, TrieNode node) + { + PersistNode(ctx.Storage, ctx.Path, node, isLeaf: true); + } public void VisitAccount(in TContext ctx, TrieNode node, in AccountStruct account) { } - private void PersistNode(Hash256 storage, in TreePath path, TrieNode node) + private void PersistNode(Hash256? storage, in TreePath path, TrieNode node, bool isLeaf) { if (node.Keccak is not null) { // simple copy of nodes RLP _concurrentWriteBatcher.Set(storage, path, node.Keccak, node.FullRlp.Span, _writeFlags); - Interlocked.Increment(ref _persistedNodes); - - // log message every 1 mln nodes - if (_persistedNodes % Million == 0) - { - LogProgress("In Progress"); - } + _progressTracker.OnNodeVisited(path, isStorage: storage is not null, isLeaf); } } - private void LogProgress(string state) - { - if (_logger.IsInfo) - _logger.Info($"Full Pruning {state}: {_stopwatch.Elapsed} {_persistedNodes / (double)Million:N} mln nodes mirrored."); - } - public void Dispose() { if (_logger.IsWarn && !_finished) @@ -109,7 +107,9 @@ public void Dispose() public void Finish() { _finished = true; - LogProgress("Finished"); + _progressTracker.Finish(); + if (_logger.IsInfo) + _logger.Info($"Full Pruning Finished: {_stopwatch.Elapsed} {_progressTracker.NodeCount / (double)Million:N} mln nodes mirrored."); _concurrentWriteBatcher.Dispose(); } } diff --git a/src/Nethermind/Nethermind.State/StateReaderExtensions.cs b/src/Nethermind/Nethermind.State/StateReaderExtensions.cs index 22f7440e70d..096f05709be 100644 --- a/src/Nethermind/Nethermind.State/StateReaderExtensions.cs +++ b/src/Nethermind/Nethermind.State/StateReaderExtensions.cs @@ -52,6 +52,7 @@ public static TrieStats CollectStats(this IStateReader stateProvider, BlockHeade MaxDegreeOfParallelism = Environment.ProcessorCount, FullScanMemoryBudget = 16.GiB(), // Gonna guess that if you are running this, you have a decent setup. }); + collector.Finish(); return collector.Stats; } diff --git a/src/Nethermind/Nethermind.Trie.Test/VisitorProgressTrackerTests.cs b/src/Nethermind/Nethermind.Trie.Test/VisitorProgressTrackerTests.cs new file mode 100644 index 00000000000..3b3e4b1b2a4 --- /dev/null +++ b/src/Nethermind/Nethermind.Trie.Test/VisitorProgressTrackerTests.cs @@ -0,0 +1,150 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Threading.Tasks; +using FluentAssertions; +using Nethermind.Logging; +using NUnit.Framework; + +namespace Nethermind.Trie.Test; + +public class VisitorProgressTrackerTests +{ + [Test] + public void OnNodeVisited_TracksProgress_AtLevel0() + { + // Arrange + var tracker = new VisitorProgressTracker("Test", LimboLogs.Instance, reportingInterval: 1000); + + // Act - visit leaf paths with single nibble, each covers 16^3 = 4096 level-3 nodes + // Visit half the keyspace (8 out of 16) = 8 * 4096 = 32768 out of 65536 = 50% + for (int i = 0; i < 8; i++) + { + TreePath path = TreePath.FromNibble(new byte[] { (byte)i }); + tracker.OnNodeVisited(path, isStorage: false, isLeaf: true); + } + + // Assert - should be ~50% progress + double progress = tracker.GetProgress(); + progress.Should().BeApproximately(0.5, 0.01); + } + + [Test] + public void OnNodeVisited_UsesDeepestLevelWithCoverage() + { + // Arrange + var tracker = new VisitorProgressTracker("Test", LimboLogs.Instance, reportingInterval: 100000); + + // Act - visit leaf nodes at 2-nibble depth + // Each leaf at depth 2 covers 16^(3-2+1) = 16^2 = 256 level-3 nodes + // Visit 64 leaves = 64 * 256 = 16384 out of 65536 = 25% + for (int i = 0; i < 64; i++) + { + TreePath path = TreePath.FromNibble(new byte[] { (byte)(i / 16), (byte)(i % 16) }); + tracker.OnNodeVisited(path, isStorage: false, isLeaf: true); + } + + // Assert - should be ~25% progress + double progress = tracker.GetProgress(); + progress.Should().BeApproximately(0.25, 0.01); + } + + [Test] + public void OnNodeVisited_IsThreadSafe() + { + // Arrange + var tracker = new VisitorProgressTracker("Test", LimboLogs.Instance, reportingInterval: 100000); + const int threadCount = 8; + const int nodesPerThread = 1000; + + // Act - visit nodes concurrently + Parallel.For(0, threadCount, threadId => + { + for (int i = 0; i < nodesPerThread; i++) + { + int nibble1 = (threadId * nodesPerThread + i) / 4096 % 16; + int nibble2 = (threadId * nodesPerThread + i) / 256 % 16; + int nibble3 = (threadId * nodesPerThread + i) / 16 % 16; + int nibble4 = (threadId * nodesPerThread + i) % 16; + TreePath path = TreePath.FromNibble(new byte[] { (byte)nibble1, (byte)nibble2, (byte)nibble3, (byte)nibble4 }); + tracker.OnNodeVisited(path); + } + }); + + // Assert - node count should match + tracker.NodeCount.Should().Be(threadCount * nodesPerThread); + } + + [Test] + public void OnNodeVisited_ProgressIncreases_WithinLevel() + { + // Arrange + var tracker = new VisitorProgressTracker("Test", LimboLogs.Instance, reportingInterval: 100000); + + // Act - visit leaf nodes with single nibble paths + // Each covers 16^3 = 4096 level-3 nodes + double lastProgress = 0; + for (int i = 0; i < 16; i++) + { + TreePath path = TreePath.FromNibble(new byte[] { (byte)i }); + tracker.OnNodeVisited(path, isStorage: false, isLeaf: true); + + double progress = tracker.GetProgress(); + progress.Should().BeGreaterThanOrEqualTo(lastProgress); + lastProgress = progress; + } + + // Assert - after visiting all 16 single-nibble leaves, progress should be 100% + tracker.GetProgress().Should().Be(1.0); + } + + [Test] + public void Finish_SetsProgressTo100() + { + // Arrange + var tracker = new VisitorProgressTracker("Test", LimboLogs.Instance, reportingInterval: 100000); + TreePath path = TreePath.FromNibble(new byte[] { 0, 0, 0, 0 }); + tracker.OnNodeVisited(path); + + // Act + tracker.Finish(); + + // Assert - GetProgress still returns actual progress, but logger shows 100% + // (We can't easily test logger output, so just verify Finish doesn't throw) + tracker.NodeCount.Should().Be(1); + } + + [Test] + public void OnNodeVisited_HandlesShortPaths() + { + // Arrange + var tracker = new VisitorProgressTracker("Test", LimboLogs.Instance, reportingInterval: 100000); + + // Act - visit paths with fewer than 4 nibbles + TreePath path1 = TreePath.FromNibble(new byte[] { 0 }); + TreePath path2 = TreePath.FromNibble(new byte[] { 1, 2 }); + TreePath path3 = TreePath.FromNibble(new byte[] { 3, 4, 5 }); + + tracker.OnNodeVisited(path1); + tracker.OnNodeVisited(path2); + tracker.OnNodeVisited(path3); + + // Assert - should not throw and should track nodes + tracker.NodeCount.Should().Be(3); + } + + [Test] + public void OnNodeVisited_HandlesEmptyPath() + { + // Arrange + var tracker = new VisitorProgressTracker("Test", LimboLogs.Instance, reportingInterval: 100000); + + // Act + TreePath path = TreePath.Empty; + tracker.OnNodeVisited(path); + + // Assert + tracker.NodeCount.Should().Be(1); + tracker.GetProgress().Should().Be(0); // Empty path doesn't contribute to progress + } +} diff --git a/src/Nethermind/Nethermind.Trie/TrieStatsCollector.cs b/src/Nethermind/Nethermind.Trie/TrieStatsCollector.cs index a49faf1175b..747f8df258f 100644 --- a/src/Nethermind/Nethermind.Trie/TrieStatsCollector.cs +++ b/src/Nethermind/Nethermind.Trie/TrieStatsCollector.cs @@ -14,9 +14,9 @@ public class TrieStatsCollector : ITreeVisitor { private readonly ClockCache _existingCodeHash = new ClockCache(1024 * 8); private readonly IKeyValueStore _codeKeyValueStore; - private long _lastAccountNodeCount = 0; private readonly ILogger _logger; + private readonly VisitorProgressTracker _progressTracker; private readonly CancellationToken _cancellationToken; // Combine both `TreePathContextWithStorage` and `OldStyleTrieVisitContext` @@ -66,6 +66,7 @@ public TrieStatsCollector(IKeyValueStore codeKeyValueStore, ILogManager logManag _logger = logManager.GetClassLogger(); ExpectAccounts = expectAccounts; _cancellationToken = cancellationToken; + _progressTracker = new VisitorProgressTracker("Trie Verification", logManager); } public TrieStats Stats { get; } = new(); @@ -93,7 +94,7 @@ public void VisitMissingNode(in Context nodeContext, in ValueHash256 nodeHash) Interlocked.Increment(ref Stats._missingState); } - IncrementLevel(nodeContext); + IncrementLevel(nodeContext, isLeaf: false); } public void VisitBranch(in Context nodeContext, TrieNode node) @@ -111,7 +112,7 @@ public void VisitBranch(in Context nodeContext, TrieNode node) Interlocked.Increment(ref Stats._stateBranchCount); } - IncrementLevel(nodeContext); + IncrementLevel(nodeContext, isLeaf: false); } public void VisitExtension(in Context nodeContext, TrieNode node) @@ -127,18 +128,11 @@ public void VisitExtension(in Context nodeContext, TrieNode node) Interlocked.Increment(ref Stats._stateExtensionCount); } - IncrementLevel(nodeContext); + IncrementLevel(nodeContext, isLeaf: false); } public void VisitLeaf(in Context nodeContext, TrieNode node) { - long lastAccountNodeCount = _lastAccountNodeCount; - long currentNodeCount = Stats.NodesCount; - if (currentNodeCount - lastAccountNodeCount > 1_000_000 && Interlocked.CompareExchange(ref _lastAccountNodeCount, currentNodeCount, lastAccountNodeCount) == lastAccountNodeCount) - { - _logger.Warn($"Collected info from {Stats.NodesCount} nodes. Missing CODE {Stats.MissingCode} STATE {Stats.MissingState} STORAGE {Stats.MissingStorage}"); - } - if (nodeContext.IsStorage) { Interlocked.Add(ref Stats._storageSize, node.FullRlp.Length); @@ -150,7 +144,7 @@ public void VisitLeaf(in Context nodeContext, TrieNode node) Interlocked.Increment(ref Stats._accountCount); } - IncrementLevel(nodeContext); + IncrementLevel(nodeContext, isLeaf: true); } public void VisitAccount(in Context nodeContext, TrieNode node, in AccountStruct account) @@ -183,15 +177,23 @@ public void VisitAccount(in Context nodeContext, TrieNode node, in AccountStruct IncrementLevel(nodeContext, Stats._codeLevels); } - private void IncrementLevel(Context context) + private void IncrementLevel(Context context, bool isLeaf) { long[] levels = context.IsStorage ? Stats._storageLevels : Stats._stateLevels; IncrementLevel(context, levels); + + // Track all nodes for display; only state nodes used for progress calculation + _progressTracker.OnNodeVisited(context.Path, context.IsStorage, isLeaf); } private static void IncrementLevel(Context context, long[] levels) { Interlocked.Increment(ref levels[context.Level]); } + + public void Finish() + { + _progressTracker.Finish(); + } } } diff --git a/src/Nethermind/Nethermind.Trie/VisitorProgressTracker.cs b/src/Nethermind/Nethermind.Trie/VisitorProgressTracker.cs new file mode 100644 index 00000000000..33817dfece0 --- /dev/null +++ b/src/Nethermind/Nethermind.Trie/VisitorProgressTracker.cs @@ -0,0 +1,142 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Globalization; +using System.Threading; +using Nethermind.Core; +using Nethermind.Logging; + +namespace Nethermind.Trie; + +/// +/// Tracks progress of trie traversal operations using path-based estimation. +/// Uses multi-level prefix tracking to estimate completion percentage even when +/// total node count is unknown and traversal is concurrent/out-of-order. +/// +public class VisitorProgressTracker +{ + private const int Level3Depth = 4; // 4 nibbles + private const int MaxNodes = 65536; // 16^4 possible 4-nibble prefixes + + private int _seenCount; // Count of level-3 nodes seen (or estimated from shallow leaves) + + private long _nodeCount; + private long _totalWorkDone; // Total work done (for display, separate from progress calculation) + private readonly DateTime _startTime; + private readonly ProgressLogger _logger; + private readonly string _operationName; + private readonly int _reportingInterval; + + public VisitorProgressTracker( + string operationName, + ILogManager logManager, + int reportingInterval = 100_000) + { + ArgumentNullException.ThrowIfNull(logManager); + + _operationName = operationName; + _logger = new ProgressLogger(operationName, logManager); + _logger.Reset(0, 10000); // Use 10000 for 0.01% precision + _logger.SetFormat(FormatProgress); + _reportingInterval = reportingInterval; + _startTime = DateTime.UtcNow; + } + + private string FormatProgress(ProgressLogger logger) + { + float percentage = Math.Clamp(logger.CurrentValue / 10000f, 0, 1); + long work = Interlocked.Read(ref _totalWorkDone); + string workStr = work >= 1_000_000 ? $"{work / 1_000_000.0:F1}M" : $"{work:N0}"; + return $"{_operationName,-25} {percentage.ToString("P2", CultureInfo.InvariantCulture),8} " + + Progress.GetMeter(percentage, 1) + + $" nodes: {workStr,8}"; + } + + /// + /// Called when a node is visited during traversal. + /// Thread-safe: can be called concurrently from multiple threads. + /// + /// The path to the node (used for progress estimation) + /// True if this is a storage node (tracked in total but not used for progress) + /// True if this is a leaf node (used to estimate coverage at level 3) + public void OnNodeVisited(in TreePath path, bool isStorage = false, bool isLeaf = false) + { + // Always count the work done + Interlocked.Increment(ref _totalWorkDone); + + // Only track state nodes for progress estimation at level 3 + if (!isStorage) + { + if (path.Length == Level3Depth) + { + // Node at exactly level 3 (4 nibbles): count as 1 node + Interlocked.Increment(ref _seenCount); + } + else if (isLeaf && path.Length > 0 && path.Length < Level3Depth) + { + // Leaf at lower depth: estimate how many level-3 nodes it covers + // Each level has 16 children, so a leaf at depth d covers 16^(4-d) level-3 nodes + int coverageDepth = Level3Depth - path.Length; + int estimatedNodes = 1; + for (int i = 0; i < coverageDepth; i++) + { + estimatedNodes *= 16; + } + + // Add estimated coverage + Interlocked.Add(ref _seenCount, estimatedNodes); + } + // Nodes at depth > Level3Depth are ignored for progress calculation + + // Log progress at intervals (based on state nodes only) + if (Interlocked.Increment(ref _nodeCount) % _reportingInterval == 0) + { + LogProgress(); + } + } + } + + private void LogProgress() + { + // Skip logging for first 5 seconds OR until we've seen at least 1% of nodes + // This avoids showing noisy early estimates + double elapsed = (DateTime.UtcNow - _startTime).TotalSeconds; + int seen = _seenCount; + double progress = Math.Min((double)seen / MaxNodes, 1.0); + + if (elapsed < 5.0 && progress < 0.01) + { + return; + } + + long progressValue = (long)(progress * 10000); + + _logger.Update(progressValue); + _logger.LogProgress(); + } + + /// + /// Call when traversal is complete to log final progress. + /// + public void Finish() + { + _logger.Update(10000); + _logger.MarkEnd(); + _logger.LogProgress(); + } + + /// + /// Gets the current estimated progress (0.0 to 1.0). + /// + public double GetProgress() + { + int seen = _seenCount; + return Math.Min((double)seen / MaxNodes, 1.0); + } + + /// + /// Gets the total number of nodes visited. + /// + public long NodeCount => Interlocked.Read(ref _nodeCount); +} From 726b99e50215df7ff751d1fbff3d4113b3144dc6 Mon Sep 17 00:00:00 2001 From: Anish M Gehlot <35562972+gehlotanish@users.noreply.github.com> Date: Wed, 21 Jan 2026 14:20:58 +0530 Subject: [PATCH 253/255] feat: enable taiko client CI integration tests (#10043) * feat: enable taiko client ci integration tests * fix: gh action structure to run l2_nmc locally * feat: add path for ci-taiko file * Update GitHub Actions checkout reference surge-taiko-mono --- .github/workflows/ci-taiko.yml | 173 +++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 .github/workflows/ci-taiko.yml diff --git a/.github/workflows/ci-taiko.yml b/.github/workflows/ci-taiko.yml new file mode 100644 index 00000000000..d01e2069241 --- /dev/null +++ b/.github/workflows/ci-taiko.yml @@ -0,0 +1,173 @@ +name: "Nethermind/Ethereum Taiko Client CI Tests" + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + paths: + - "src/Nethermind/Nethermind.Taiko/**" + - ".github/workflows/ci-taiko.yml" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + integration_tests: + if: >- + ${{ github.event.pull_request.draft == false + && !startsWith(github.head_ref, 'release-please') }} + name: Integration tests + runs-on: [ubuntu-latest] + timeout-minutes: 30 + env: + OLD_FORK_TAIKO_MONO_DIR: old-fork-taiko-mono + TAIKO_MONO_MAIN_DIR: taiko-mono-main + PACAYA_FORK_TAIKO_MONO_DIR: pacaya-fork-taiko-mono + SHASTA_FORK_TAIKO_MONO_DIR: shasta-fork-taiko-mono + + strategy: + matrix: + execution_node: [l2_nmc] + + steps: + - uses: actions/checkout@v6 + + - uses: actions/checkout@v6 + with: + repository: NethermindEth/surge-taiko-mono + path: ${{ env.TAIKO_MONO_MAIN_DIR }} + ref: surge-shasta + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: ${{ env.TAIKO_MONO_MAIN_DIR }}/go.mod + cache: true + + - name: Set up Git to use HTTPS + shell: bash + run: | + git config --global url."https://github.com/".insteadOf "git@github.com:" + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + run_install: false + + - name: Install Node.js + uses: actions/setup-node@v5 + with: + node-version: 20 + cache: pnpm + cache-dependency-path: ${{ env.TAIKO_MONO_MAIN_DIR }}/pnpm-lock.yaml + + - name: Install dependencies + working-directory: ${{ env.TAIKO_MONO_MAIN_DIR }} + shell: bash + run: pnpm install + + - uses: actions/checkout@v6 + with: + repository: taikoxyz/taiko-mono + path: >- + ${{ format('{0}/{1}', env.TAIKO_MONO_MAIN_DIR, + env.PACAYA_FORK_TAIKO_MONO_DIR) }} + ref: taiko-alethia-protocol-v2.3.0-devnet-shasta-test + + - uses: actions/checkout@v6 + with: + repository: taikoxyz/taiko-mono + path: >- + ${{ format('{0}/{1}', env.TAIKO_MONO_MAIN_DIR, + env.SHASTA_FORK_TAIKO_MONO_DIR) }} + ref: taiko-alethia-protocol-v3.0.0 + + - name: Install pnpm dependencies for pacaya fork taiko-mono + working-directory: >- + ${{ format('{0}/{1}', env.TAIKO_MONO_MAIN_DIR, + env.PACAYA_FORK_TAIKO_MONO_DIR) }} + run: cd ./packages/protocol && pnpm install + + - name: Install pnpm dependencies for shasta fork taiko-mono + working-directory: >- + ${{ format('{0}/{1}', env.TAIKO_MONO_MAIN_DIR, + env.SHASTA_FORK_TAIKO_MONO_DIR) }} + run: cd ./packages/protocol && pnpm install + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Docker Build Nethermind Client + run: | + image_name="nethermindeth/nethermind" + image_tag="${GITHUB_SHA:0:8}" + full_image="${image_name}:${image_tag}" + + echo "Building Docker image: ${full_image}" + + docker buildx build . \ + --platform linux/amd64 \ + -f Dockerfile \ + -t "${full_image}" \ + --load \ + --build-arg BUILD_CONFIG=release \ + --build-arg CI=true \ + --build-arg COMMIT_HASH=${{ github.sha }} \ + --build-arg SOURCE_DATE_EPOCH=$(git log -1 --format=%ct) + + echo "IMAGE_TAG=${full_image}" >> $GITHUB_ENV + + echo "Verifying image exists locally:" + docker images | grep "${image_name}" | grep "${image_tag}" || (echo "Error: Image not found locally" && exit 1) + + - name: Install yq + run: | + sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 + sudo chmod +x /usr/local/bin/yq + yq --version + + - name: Update taiko-client docker-compose.yml with new image + working-directory: >- + ${{ env.TAIKO_MONO_MAIN_DIR }}/packages/taiko-client/internal/docker/nodes + run: | + docker_compose_file="docker-compose.yml" + if [ -f "$docker_compose_file" ]; then + echo "Current image in docker-compose.yml:" + yq eval '.services.l2_nmc.image' "$docker_compose_file" + + echo "Updating docker-compose.yml with image: ${IMAGE_TAG}" + yq eval '.services.l2_nmc.image = "'"${IMAGE_TAG}"'"' -i "$docker_compose_file" + + yq eval '.services.l2_nmc.pull_policy = "never"' -i "$docker_compose_file" + + echo "Updated image in docker-compose.yml:" + yq eval '.services.l2_nmc.image' "$docker_compose_file" + + echo "Pull policy set to:" + yq eval '.services.l2_nmc.pull_policy' "$docker_compose_file" + else + echo "Warning: docker-compose.yml not found at expected path" + exit 1 + fi + + - name: Run Tests on ${{ matrix.execution_node }} execution engine + working-directory: >- + ${{ env.TAIKO_MONO_MAIN_DIR }}/packages/taiko-client + env: + L2_NODE: ${{ matrix.execution_node }} + run: >- + SHASTA_FORK_TAIKO_MONO=${GITHUB_WORKSPACE}/${{ format('{0}/{1}', env.TAIKO_MONO_MAIN_DIR, env.SHASTA_FORK_TAIKO_MONO_DIR) }} + PACAYA_FORK_TAIKO_MONO=${GITHUB_WORKSPACE}/${{ format('{0}/{1}', env.TAIKO_MONO_MAIN_DIR, env.PACAYA_FORK_TAIKO_MONO_DIR) }} + make test + + - name: Codecov.io + uses: codecov/codecov-action@v5 + with: + files: ${{ env.TAIKO_MONO_MAIN_DIR }}/packages/taiko-client/coverage.out + flags: taiko-client + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} From bb67834e55be75ee2038856c2439a47a3e154bfd Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Wed, 21 Jan 2026 20:24:39 +0000 Subject: [PATCH 254/255] Merge conflicts --- .../BlockAccessListTests.cs | 13 +++++++++---- .../Validators/BlockValidator.cs | 11 ++++++++++- .../Nethermind.Core/Specs/IReleaseSpec.cs | 2 ++ .../Nethermind.Db.Rocks/Config/DbConfig.cs | 2 ++ .../Nethermind.Db.Rocks/Config/IDbConfig.cs | 3 +++ .../Nethermind.Evm/State/IPreBlockCaches.cs | 2 +- .../State/TracedAccessWorldState.cs | 4 ++-- .../TracedAccessWorldStateScopeProvider.cs | 17 +++++++++++++++++ .../Nethermind.Evm/State/WrappedWorldState.cs | 4 +--- .../Modules/BlockProcessingModule.cs | 1 + .../Nethermind.Runner/packages.lock.json | 3 ++- src/Nethermind/Nethermind.State/WorldState.cs | 5 ----- .../WorldStateMetricsDecorator.cs | 8 -------- 13 files changed, 50 insertions(+), 25 deletions(-) create mode 100644 src/Nethermind/Nethermind.Evm/State/TracedAccessWorldStateScopeProvider.cs diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockAccessListTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockAccessListTests.cs index 9ad09d35432..b87c3781781 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockAccessListTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockAccessListTests.cs @@ -269,11 +269,16 @@ public async Task Can_construct_BAL() { using BasicTestBlockchain testBlockchain = await BasicTestBlockchain.Create(BuildContainer()); - IWorldState worldState = testBlockchain.WorldStateManager.GlobalWorldState; - using IDisposable _ = worldState.BeginScope(IWorldState.PreGenesis); - InitWorldState(worldState); + // Get the main world state which should be a TracedAccessWorldState after DI fix + IWorldState mainWorldState = testBlockchain.MainWorldState; + TracedAccessWorldState? tracedWorldState = mainWorldState as TracedAccessWorldState; + Assert.That(tracedWorldState, Is.Not.Null, "Main world state should be TracedAccessWorldState"); - (worldState as TracedAccessWorldState)!.BlockAccessList = new(); + // Begin scope and initialize state + using IDisposable _ = mainWorldState.BeginScope(IWorldState.PreGenesis); + InitWorldState(mainWorldState); + + tracedWorldState!.BlockAccessList = new(); const long gasUsed = 167340; const long gasUsedBeforeFinal = 92100; diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index fdca5665fbb..adf89564515 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -132,13 +132,22 @@ private bool ValidateBlockSize(Block block, IReleaseSpec spec, ref string? error if (spec.BlockLevelAccessListsEnabled) { - if (block.BlockAccessList is null || block.BlockAccessListHash is null) + // Genesis blocks don't have a BlockAccessList (only the hash of an empty list) + bool isGenesis = block.IsGenesis; + if (!isGenesis && (block.BlockAccessList is null || block.BlockAccessListHash is null)) { if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Block-level access list was missing or empty"); errorMessage = BlockErrorMessages.InvalidBlockLevelAccessList; return false; } + if (isGenesis && block.BlockAccessListHash is null) + { + if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Genesis block missing BlockAccessListHash"); + errorMessage = BlockErrorMessages.InvalidBlockLevelAccessList; + return false; + } + // try // { // block.DecodedBlockAccessList = Rlp.Decode(block.BlockAccessList); diff --git a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs index 590ea6d57bb..b41dc5a6614 100644 --- a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs @@ -451,5 +451,7 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec /// EIP-7928: Block-Level Access Lists /// public bool IsEip7928Enabled { get; } + + bool BlockLevelAccessListsEnabled => IsEip7928Enabled; } } diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs index c6004bcfc71..6fd3f06a9e4 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs @@ -87,6 +87,8 @@ public class DbConfig : IDbConfig public string BadBlocksDbRocksDbOptions { get; set; } = ""; public string? BadBlocksDbAdditionalRocksDbOptions { get; set; } + public string BlockAccessListsDbRocksDbOptions { get; set; } = ""; + public string? BlockAccessListsDbAdditionalRocksDbOptions { get; set; } public string BlobTransactionsDbRocksDbOptions { get; set; } = "block_based_table_factory.block_cache=32000000;"; diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs index fa7c8e2023b..2d569b411c5 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs @@ -38,6 +38,9 @@ public interface IDbConfig : IConfig string BadBlocksDbRocksDbOptions { get; set; } string? BadBlocksDbAdditionalRocksDbOptions { get; set; } + string BlockAccessListsDbRocksDbOptions { get; set; } + string? BlockAccessListsDbAdditionalRocksDbOptions { get; set; } + string BlobTransactionsDbRocksDbOptions { get; set; } string? BlobTransactionsDbAdditionalRocksDbOptions { get; set; } diff --git a/src/Nethermind/Nethermind.Evm/State/IPreBlockCaches.cs b/src/Nethermind/Nethermind.Evm/State/IPreBlockCaches.cs index 2e29278e9c6..7bb0793dcfe 100644 --- a/src/Nethermind/Nethermind.Evm/State/IPreBlockCaches.cs +++ b/src/Nethermind/Nethermind.Evm/State/IPreBlockCaches.cs @@ -5,6 +5,6 @@ namespace Nethermind.Evm.State; public interface IPreBlockCaches { - PreBlockCaches Caches { get; } + PreBlockCaches? Caches { get; } bool IsWarmWorldState { get; } } diff --git a/src/Nethermind/Nethermind.Evm/State/TracedAccessWorldState.cs b/src/Nethermind/Nethermind.Evm/State/TracedAccessWorldState.cs index 17c10cb9a8a..b20b13c22ac 100644 --- a/src/Nethermind/Nethermind.Evm/State/TracedAccessWorldState.cs +++ b/src/Nethermind/Nethermind.Evm/State/TracedAccessWorldState.cs @@ -15,9 +15,9 @@ public class TracedAccessWorldState(IWorldState innerWorldState) : WrappedWorldS public bool Enabled { get; set; } = false; public BlockAccessList BlockAccessList = new(); - public PreBlockCaches Caches => (_innerWorldState as IPreBlockCaches).Caches; + public PreBlockCaches? Caches => (_innerWorldState as IPreBlockCaches)?.Caches; - public bool IsWarmWorldState => (_innerWorldState as IPreBlockCaches).IsWarmWorldState; + public bool IsWarmWorldState => (_innerWorldState as IPreBlockCaches)?.IsWarmWorldState ?? false; public override void AddToBalance(Address address, in UInt256 balanceChange, IReleaseSpec spec) => AddToBalance(address, balanceChange, spec, out _); diff --git a/src/Nethermind/Nethermind.Evm/State/TracedAccessWorldStateScopeProvider.cs b/src/Nethermind/Nethermind.Evm/State/TracedAccessWorldStateScopeProvider.cs new file mode 100644 index 00000000000..5b2c9ffbadf --- /dev/null +++ b/src/Nethermind/Nethermind.Evm/State/TracedAccessWorldStateScopeProvider.cs @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core; + +namespace Nethermind.Evm.State; + +/// +/// A decorator for that enables block access list tracing +/// when is used. +/// +public class TracedAccessWorldStateScopeProvider(IWorldStateScopeProvider innerProvider) : IWorldStateScopeProvider +{ + public bool HasRoot(BlockHeader? baseBlock) => innerProvider.HasRoot(baseBlock); + + public IWorldStateScopeProvider.IScope BeginScope(BlockHeader? baseBlock) => innerProvider.BeginScope(baseBlock); +} diff --git a/src/Nethermind/Nethermind.Evm/State/WrappedWorldState.cs b/src/Nethermind/Nethermind.Evm/State/WrappedWorldState.cs index d07e28624e8..17516549b38 100644 --- a/src/Nethermind/Nethermind.Evm/State/WrappedWorldState.cs +++ b/src/Nethermind/Nethermind.Evm/State/WrappedWorldState.cs @@ -16,6 +16,7 @@ public class WrappedWorldState(IWorldState innerWorldState) : IWorldState { protected IWorldState _innerWorldState = innerWorldState; public bool IsInScope => _innerWorldState.IsInScope; + public IWorldStateScopeProvider ScopeProvider => _innerWorldState.ScopeProvider; public Hash256 StateRoot => _innerWorldState.StateRoot; @@ -40,9 +41,6 @@ public virtual IDisposable BeginScope(BlockHeader? baseBlock) public virtual void ClearStorage(Address address) => _innerWorldState.ClearStorage(address); - public virtual void Commit(IReleaseSpec releaseSpec, bool isGenesis = false, bool commitRoots = true) - => _innerWorldState.Commit(releaseSpec, isGenesis, commitRoots); - public virtual void Commit(IReleaseSpec releaseSpec, IWorldStateTracer tracer, bool isGenesis = false, bool commitRoots = true) => _innerWorldState.Commit(releaseSpec, tracer, isGenesis, commitRoots); diff --git a/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs b/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs index 9ad13948399..130b86d37d8 100644 --- a/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs +++ b/src/Nethermind/Nethermind.Init/Modules/BlockProcessingModule.cs @@ -52,6 +52,7 @@ protected override void Load(ContainerBuilder builder) .AddScoped() .AddSingleton() .AddScoped() + .AddDecorator() .AddScoped() .AddScoped() .AddSingleton() diff --git a/src/Nethermind/Nethermind.Runner/packages.lock.json b/src/Nethermind/Nethermind.Runner/packages.lock.json index 31ec3ddbf6b..e87c9544f20 100644 --- a/src/Nethermind/Nethermind.Runner/packages.lock.json +++ b/src/Nethermind/Nethermind.Runner/packages.lock.json @@ -800,7 +800,8 @@ "Nethermind.Core": "[1.37.0-unstable, )", "Nethermind.Crypto": "[1.37.0-unstable, )", "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )", - "Nethermind.Specs": "[1.37.0-unstable, )" + "Nethermind.Specs": "[1.37.0-unstable, )", + "Nethermind.Trie": "[1.37.0-unstable, )" } }, "nethermind.evm.precompiles": { diff --git a/src/Nethermind/Nethermind.State/WorldState.cs b/src/Nethermind/Nethermind.State/WorldState.cs index 5c059bdbdc1..a5cb906e1e5 100644 --- a/src/Nethermind/Nethermind.State/WorldState.cs +++ b/src/Nethermind/Nethermind.State/WorldState.cs @@ -219,11 +219,6 @@ public void SubtractFromBalance(Address address, in UInt256 balanceChange, IRele } public void SubtractFromBalance(Address address, in UInt256 balanceChange, IReleaseSpec spec) => SubtractFromBalance(address, balanceChange, spec, out _); - public void UpdateStorageRoot(Address address, Hash256 storageRoot) - { - DebugGuardInScope(); - _stateProvider.UpdateStorageRoot(address, storageRoot); - } public void IncrementNonce(Address address, UInt256 delta) => IncrementNonce(address, delta, out _); public void IncrementNonce(Address address, UInt256 delta, out UInt256 oldNonce) diff --git a/src/Nethermind/Nethermind.State/WorldStateMetricsDecorator.cs b/src/Nethermind/Nethermind.State/WorldStateMetricsDecorator.cs index 9a9142d8b56..8d88701f850 100644 --- a/src/Nethermind/Nethermind.State/WorldStateMetricsDecorator.cs +++ b/src/Nethermind/Nethermind.State/WorldStateMetricsDecorator.cs @@ -62,14 +62,6 @@ public override void DecrementNonce(Address address, UInt256 delta) public override void SetNonce(Address address, in UInt256 nonce) => _innerWorldState.SetNonce(address, nonce); - public override void Commit(IReleaseSpec releaseSpec, bool isGenesis = false, bool commitRoots = true) - { - long start = Stopwatch.GetTimestamp(); - _innerWorldState.Commit(releaseSpec, isGenesis, commitRoots); - if (commitRoots) - StateMerkleizationTime += Stopwatch.GetElapsedTime(start).TotalMilliseconds; - } - public override void Commit(IReleaseSpec releaseSpec, IWorldStateTracer tracer, bool isGenesis = false, bool commitRoots = true) { long start = Stopwatch.GetTimestamp(); From c335c5753793149d2bd54bbed1cbea2ae6d60be1 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Wed, 21 Jan 2026 20:56:35 +0000 Subject: [PATCH 255/255] spelling --- cspell.json | 1 + 1 file changed, 1 insertion(+) diff --git a/cspell.json b/cspell.json index a4cc1ab2ca1..d7998dc7512 100644 --- a/cspell.json +++ b/cspell.json @@ -47,6 +47,7 @@ "autofac", "autogen", "auxdata", + "BALS", "badreq", "barebone", "baseblock",

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 tr9P@p&KbSw_WKi%AAPSAI$SU`*+@R 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�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 Y`2Pwb^;obbc}87OP^YF6reEj(2WQw@hX4Qo diff --git a/src/Nethermind/Chains/soneium-mainnet.json.zst b/src/Nethermind/Chains/soneium-mainnet.json.zst index 599c866c5a192170b6103583f54deba5a78c639b..33c9ba2e85ee272059bc925274075eec35b6ca7f 100644 GIT binary patch delta 18155 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 delta 18703 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 diff --git a/src/Nethermind/Chains/soneium-minato-sepolia.json.zst b/src/Nethermind/Chains/soneium-minato-sepolia.json.zst index 801859ffe85b35420e823d9881d5a35ea6fa6cc4..13e2e36ea52595cf69055da4df88f98d0b7cc26d 100644 GIT binary patch delta 14626 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 D$noo{ delta 14639 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 bpR7FaILk*t$b#5ZPc96Ck8L`nGQIsD46@f^ delta 7358 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 diff --git a/src/Nethermind/Chains/swan-mainnet.json.zst b/src/Nethermind/Chains/swan-mainnet.json.zst index dee04cb636328e21f4203c26f09903f0bfa2ab3c..8c1d0552d6ad8717e91ee0a42504ccc7c36d07a4 100644 GIT binary patch delta 7018 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 Yc#d$TTN24mZzdsJ?4{0fmaNnN1K&exivR!s diff --git a/src/Nethermind/Chains/swell-mainnet.json.zst b/src/Nethermind/Chains/swell-mainnet.json.zst index 8deb4ab15dfbaad721eb3c6ad3bd793db2ac2673..b0e270c4f8aaf6993756f4bd341b90d974bddffd 100644 GIT binary patch delta 14739 zcmXxLQ+S?T7p@&Vv2EK<8r!zhxUm~2cVpXb?4+?9+qP{r)_T|azyI7AbLX1duZDRR=)EO-Q10~T4&UXeSN`dMebr*L?Aa}`QZcAb;FurQAyFY(GE-6C? zhldFP1_rhR9uHcBoQL#!shsg?r7dPWwNFm0ufOA50O&TuXu3z&RLRHJG>DO@$cDFK zE!N^v4tfNK=F?Q^wSGz=>@{4O;FwNlS{6LjAFlvM>X!E|7cS9BE}RyeOv4IERt;*y z2ch1t-z|?;x8yDixxMJ5By(%DtVda>zMJZ7l3^q$VXMl;kO|C{XlHhyRdvLvl);m; zxb|IyG;yD?@;1uasj+cz$;ZD()5pILEHSFi#h2h}%6)DA53^{tA>990#9#rkU{o>K z|H}V=ios6&kBlPH;zIq!JG+^YLg4NSpno)alILR%|Il0d@08G7+w`M2)yC16Hc?d^QOx z3hElAGqG4W1ga+PgE-Fx5^?Z*Vxc@?s6WjYO>ra}zp3XSsdM^7xBjT&?F;<&E6~H& zebtOB+{z#XUnfA{Ce+f?T=LS=Ur!|_LvHYjTpLcUJG9B^|Jjs6S zmY1O8OhGqCT8S-i1Pa)F%~wk)0#lpi9J=h8x+g)zPRvkh59sNDWd3+Jm^)Bwhfow- zD6%tpx(`LHQn7Bct5jaRiOGO3@sZD$=||3*#bJ~{GvSzaSJydwrb(p|Rr! z`1!{b80&>EtpcI@InOQ3i%Q|}5$Aqc8Dlsh5h~2=1VAEE8bhMs2ScMU|3SvJ(iaJY zG5O|1+8fA5uF{YNcY1Pi;5=ncEnUJMr6xppWAqywl*~bmQ(0>GL194+am|9p1aTSx zkm4AF;Aw3UQz68m5X7Ki`>2R>PfSt+JwTpe_v`S?lBiN3u0C#6*_!|aDp&}Iwu$$C z2xxrV8HlKzTtr;hAkK+DA^{Kx8YqO!xX_#^*|M&qWWR;u3taTzv9Y3mLwOc`dj=bW zMC=RHcR~#CBn{RI5V5a<&}Ha>fMi?&U>?B{!ofgRR6D;`!A6N%Sy2gXUa@H*(Nc_q zzM}_|LL_j`%;CafwCO4q;cv2ML0*>;gD%mL=0ofFLSdPzh}%P=$#AvYBj6b%vr%Fe z4&cC`QGY?Chcr7SoC+J$;QqFvpEBs1-2mlV{q^dRpdH61OQ@PNBZ?~Zl>5F21lCB< z9qabX?5bcZfPzv20!wLiX86R=XjKl(+U%xa`XJ3F3QtL6CuXDDFC>2GppO zPB*^-FO7kDCW%g~F`oT1e66eoD! zPICUtXj0F*So=43xu=cG$}1Jsi4GiQ`IyliSs$^c;Mvcqe$F7(OxJ1vYJJx!F}`hK z(?9$vt!9c~*O*J6|NJQ9U)wDnb-lY2ved=TWum8}U{n{k6c$c2sYp&}8)N9E*`wz| ztRpe4!gPQVL#qejO!i>$Wsu9@D4~u9_LZo9;!88p03HNm0~FMp7?JXAyvb=&uS)%R zM;ALLev?H%$94xovl?uHcbo5$o)I#`RdruU0uKpl=FzxctO(*Y6#eQ4&xwr^%l0(v z>fd4(9896=o|TK9uNUs_f}o0PBJ?BCzmlJ?CF;jU4u3{JqozFPCzb>zy2hVWBSwED%ohTb8%4=-u2S-cCS&~Ceo7~@tc*SAL5Dk4@DXS%X-qp0?+NzRvxiF z`8GQCod&X!@)$g{0rqq|j{Rq2@pTAcE3g>UX>8LPb|VEB{0wQ4^TQzWUO!F+3J7PS znCo0Ir3SZVDxgS*VD{g$jthf3Nk^W|X^P^k%mv#ZeKe*9w(l(=r#SA-=uMKT$_LWIq5?ZcJ0RCrsMxk2)qL>>x z#^jJdlCl?F@;pgo8vp&af!_1Gw8DPrP&qkPmq3^C3*I7Npy1DYiue+8Xqfi>?*S(z zGL|3tC_v7m%I$n0k&!J&k?2L0m?fs&=GGe49E-Tlq!DMG$t0YB;xZ2B-s>XkT%Lb$ zW;K8_1Si*_h0ayuLG_o4t5QBl(qYLzFi{QqKq&RQp*S1;<%`R#^X;H*pJH3e@fq@G zRd}?7q|pmd5mC;rZJu*B<1C1?_fFauvu}8m7qiA+G%saSRR2C?0Slx0zC;(J19Bp(qPvNop(tpOO6BO75Id| z1hJ1rS3@zv1@U@K>-Bd>^@Js$@4{>>VZ{_j>g}dmd@CH6`c{1BYVSM2ebjS?USYD) zp~n^@OK&DL)Jl+*SF&kNtj-|0Cbf1{z+pEMj5MhXvR@cFNKXEuJk>Fb(bQ8Li#i}T zbB_Z!(xrIF=gn$ftnHCv{=TM=at>uCsg;-rh25ne@n}&N=<*fa_h)Ql`u7>vM~_lQ zB*Qb_vrpO{Sv+>vWxpj2&9dQiB`}F1o*tYi!hehriffCJ?M7b0J0@Ev;Zd?@pqmfa ziNkWT3*seeB(7=Hj((hdl_{uRL_Zd7Jq`koNl6^)2e@ogPZ1dMT_Yor3RhNZ!x~%-%nuG4iO{d7baZDYsC(U|7L)cZm+*seCA7@s#KE0+6v-t) z19NtVG9Iv@sDZHbriE$Wc|fOsNhyY3Lh?pps<=k+@S73gs%3jvnY+hXN;?-0)y;qb zUjn_fHCY#w4&@9s4b~k87F0}SKwAr2x zN^ljcxh+tB@yktqkD{(!eLC$tm6ir*YSkVIJHLeNzTldAv!*=G8y*;1Vz9{EYI2)) z=yDnLW}}j+z$1oW>79p}LN6!fKn{MbR-Nbxw3=n!nM!(x=5im}y7(vezq(zGLWbVC zetHp%OLWbTGpXKN^AvLOt!2eceC56a>YNQ`%vc16XP&ZY@+E+I4Rwi3 zi-9Clw8{O{8W{=k9fF3YB{j?9&}@Ks`Erc}uaMq|e8@WpZgx8EXUGPvb3d06Jf1n) z&0o(=S07QS8I&-xDEI(rO+ked6SLIfWmZ?tF`T<`)B_$rQGW)WcS%c0ZN0lDb5q2% znNi=QWVLdv^|e{{TXjUFdw75wPfQT?96hFZjH=%EjE*l}^3O;ad!J|*!4F!Bsn%Fk zYFmF^HGiHiBh#7@2DIuO(rU`b%6T-;3Th#x&5-?Bf(y4Y8{5hFUZz!hUA_=(t$POH z!p_tjTF%GtB`YHfO{^qDVX32)>fF>=he+r}b@jP(mV1s^b@lZ4U~#}%KJcEOY!uN; z3NP`}yWNY*MUBf+7Jz4qDN23F&O2azF-)&M^V9s7o-!?&l!lBPi}g9Qdx|!;fMhGD z%sN{lRnI-+kujhFq-JMkW7OZFmnRerjMQ+k(O^}p#9SO%4vwV9e;YVa#XIB;coNK3 z=Uh+7nq-%aG4Qcddj%9ifBKK&2s{}1(}%fC-&Da>M%c&{@DvS)3Q;0fIUooImrwbW zUBzJY2g{7d{V2rhpzC7@D$8iS>(?i2D&)2}^r;p<lc_KM)Fmf@?R_1xp5& zATAMWSIo60whYkXU`FHABXfI_PJjX$;7p7ioP(h+#`g5=2* zrbSG>t)Hl_&tsBli^85!zTpY>;*OR2shQ3ysTF1Ss|BqjNaCjtKL*mp7q4k@XPjsGew8^;&c4l4pX`Wnra*AG4{ZRjbI?&#epMgK9j(<0?itJ_qc4A3fNS$Gxn zdINlhm_c|n_#b40?n1dKrv9?!Jk`YYbGamjkMFB_MFQH>jx$B1bsBZHw0++xuqX3p z)Mwes=K`G&;lw%!UC&bAXX{*;N0*Qv>m zz#L-}izr`djIXIUvT5);R8mSlL3B?xp#{uCd2>M@jKKLcP|`ChQ5TN^U(jn_q9FXcm1Ic7ifg|l;0+OBS0{1XPjRe;gR6IG7GL2M6T|g z_FTz{ThO;uC|f6#1>3mD*`nh%K>$QV*myj+_iyJp)5?JqYkQ@?AA4z+jw-8h`_uvc z3$%M`|1b=eZgqa_)GAZ%^W1;cL_eRxpA;*prqJd988oodEVN42-hNcWFakRT%+62Y zN^*tomILxqN1p$+SouzEl>UD|3U9uyjF+gDS~0(aB@~jE77wnfGb4WD{slhBr+Zz7 zHPjuij3)O3w@C)imeup**xX3Afg>`%dpaw*4A_ym&DqhKf#Sso%Uk^iTTBC&U)pX5 z#FBgCJz4ZoB|B?T)CDvFK@QW0(}V9BAiI{*pI5dya~sjujD!VfHZOc^5D5m|`qvaW zVQC&lV^Psq8)GT3s+ANvb3h_Y2tJ1HNkZrfHQ50O?*8eMN!_<$1`pknFYTgC^mn<| z$UN#T6GCte1Z|PNh(6-4Oo)ZRg+#V%M+wrK4`@qJaWM84i%)Cr?aqY@ff7`>{2*+f zC0cx5>5T?Y(b7FmsoKC;hf&2}jJ$+jD?;AlEPpnmLfaSIc1R?Boq*I3SKa`vHeF5h zp%zkJYs>a*{^G;zyE??Y*YtER&y3HQo@_oQh~Zi}!-rjrNP?L+b{^YSsH&TA4B*@e ztD-}Oe(}RgzuJG#Sw^3ZbTdOdo{6=nYuk3DxWi7B+lWT*h>$bL;MAl6d(}P-q%h1n z?H9PYCidcUA|!u-1`G?NB#KgZM1jfD%AiTk~ND`l3lGt4#wZrx*rF7si5T7T$!D zAHdhlHq(P)Q7#Q?I+rGjhUDo7q=zH<%q{ zKyGZjH=;M=kKgZz567GCZNl8&rbkCzrd)t15Q*m2Q%%dhRsdqI!)8Qv+2DY!t5@r zM}2xT=p_DZAT!$R-NK2B?k!=(MdgB0V;@$i{ss=64#27M2-V8Q)?+nR{_+kg*y$COnQL7b>%Z$pECT+9e8?WJ4Gw;z^@#<+;Qe9XCyo)ZcY7Q(MdsPi{otf z>>1WpL!og6SoapW<2*?QRR4d-!ebm}FCGI4#}BpabE?ez8?LNuZ!V_`Zo_<#;7_BD z?vNXw8eaQ&t;y5o3~*mf#$6@7or-5UT3g|BnmHaC@`oUmGsG6hpFfeO!npFW$U;9! zfUrHtzqo{Vp;!HQJEuGfc_BGbI(r!`qoot!+Q}V4UBwrlw5!!rP{hsBxhIG$#P+R! zypy*Y`O03`#F&@}iUy(Vd|EI>XNKWlQ`{7=voL|!8O_m-(YN{=P9KHrEXqGu)TV|hbvjZJbR{M6K={WB6n zboCB8bi3@GDG#(M)uFP!K$ZmQ1C2ovVmL4#r@?2Vxg~1PW6mem*?#T<&|w1w8^3l0%HlZ6#yOP1Kr4&&JEnWTs&;Y| z3GmJ#$!TPQ&?u* zShpu_Sv8n^n;IO#jATAzcbr8W)vBYr zkeG(u;^5;8&$Eq=?VzCq;L*O>Ucsk;DoX-7zql!GY|PQYDE#E{|K32Q(YYW)C`!1p zz`=<=N#2olWZMT7a+3PjQV_G=zcZfZxb%R%QHE|X;jSeZ#~fNWS`;OZ4`QA>Lso0S3@QWn=+y>l%F2O&uTo&Ix`1_zwH7m2B`6vo(3mqbBAbCw4Us}&XV_0y4x|~L*6W~^9HP|?Ld1ssvFTY$e zz@G>OBNqo5T=0G}0$!vII{M|k);QrEJlRXUa5KEIN2b4foiKZBK!n=o0wtneKV&~r znzC;;B*{u0q*K)92k zIYzdy&PYwmDJIo!buS^ruD7%UhIM_#OJ2vFpU*9xNyF z>2=B8A+WRCqK(8N-)o*6J17%mb4RCnO0^QTmoWQ4M^g6DOnh0mLQ+=v40*zIulr$8 zW^!Nz+edcmM1_}S6pYGP)XfM(%+$%%$@+ei8ECb#(C~gDT#}r7H`D%$MOiTEWhdjUk z744q4`+|pbB(=+0Y-VOG^2^O!b~vVj*ke>1ah*C-%?5MtS|n||Q#X*>u&HrUOL-hV z{j^#Enmz?8c=cjT9!e6~Sr{H}BP{5R;mf2ozXwQ#q~CVaD-vC#+AeNWX^M>u=9TOX zyn}Ow>t!5ADoISx0*jh?KU!l)c}J5S!u3ZFG?fa>6a8&>c~Td9#~0iuf2QnwC8G$x z*cpYA`Hr*;lzVB7yqbI=nx)vaCjrQFmfL~=#@`p&mKdbcijFb`U4}QMLje*&ZOT;X z{%QM#T&CPeH|M)LWM9gLagH%;B}n#H`R=bsUVj$ELb`oqN`2)1i1Scn*;nF-gc4Dq zsCQL|L!wd!QKL-yvbzT-HRTWnd5ViolnHqps;qI&(q$NRUki*`rtGfW-x2wUYc(}M z{T4e7V>-QLNa@=E@g!wb^S6UZ4il$pvmHFd{c@)I)(h?;mOzfK$=Y=70-x!@6z#JGnMYc`GBAB0nA-NCMNQOKWo?*=L<){0Vjd-u64T@qvzD|E+j!hiiO zy@x7cK=my&WXL(0zXAF<`Q2vRZkTrjMN=LfS{aSkW4|#|9S+ZB=6fX5Q~?9<=4`=NH;7H5=mO`n zz#p{-lS-kWgm9I~d=a?O*YQqe-f!3&@u@feNy`-VvQPPcv&}S_o>vK67PNPpl!xf+CUJ012l<~J+KE*3aFpOgmdA-CJ zei=+!CK7zL(+Id^gcW2=WxSmzzb%}?`ZqMJmt z;mjB6Z^#t?>ZW?w*D+ME9C15;7X0_Co-|5x(w*39k+KxM6eRNuthDrXzSY*BmVL54>lSiY3c$q zhrG{scO6D(iV_=SLkS`-m!;MVcbf!&-Wf`DbO0f<|5s%(%} z)ZZ8N7%P=WQk5=D)$Rq)Im$9_7H66u(ZU_dERil2eGXn%UtVrO7=~ z${+u;H5U@jluQ$*c(B7XRkZj#g&?z$pK4AY&f`T{yXh*6b{&!(Z1c$*w{6*s`6zrg zdhGO{$@N zMzOLphlOW_)fz(o9<`m6G>XC&o3HG&CaSv4fOTpm0QYhm(a=@p5dwJYxo3ZFC>gty zQYIrf$Uj+5YUg9`{%J~po*Q-a`9KXq_Be4z86S0J9-re$v>Nfps`l~HSK@xN`D0uJ zg!$U$Rvp)p^fVnD-@~p;M2kpUv8>T7zNPgPvp90j&od8`w?~~ZU{`XwaH9IU<$s$e zw-{D?Za5`mF^y{ubKy!!ch226sE})lni%$>ojx+zj@}uicf~2OvrJ7?ba5 zO=WO(Zz_tyNr*N!KY@CfCWrR+8566j7jqMNfq!0L56W`GWOk|OL=*jf%;*BZ!@Jdq zLv;_w3ahh|y8TDi1>rS)gL$%NUrqWx@H?nC`0t^Umoa;lpV zie|w3yx^WHht||I?qupfnD|vqf>0kbuI&uD^K;e4!N5-sk8g}QZ&!-qhCb(Z!Z$8~ z_%><3xC>dX3J?CuwcwsjI(!lVDNplH6NMTt!ymbUIc^6R%aVzy<1AXpoj)m!Tw9RC}_sNM81?+7{O8HAJx0X z@5nw{vqDvRIJjS^ozDW1U&vtg!Vy5gKhswF-{zLb)0$KRx!YWGB3g_=X*zx(l~4d% zQ|fp>EM=KMD+>j{Sa_1z$KuB+I#k-nTp)&K)#nlR#3@H{+N3Pgt=OK!!|EP+yXY4G zqo6@(PUJq##;UF$^F^R1U#(&I_2&Qqk>b^Wv>2>KS0+TU$ft+Iowph%OmJh3`$e9< ze{qKMC?5$-ePyR&%v{Srt9zJsoE5e&!&W@sN*|g9>iIw5*~ydYP|)>Q>fAgr%bH4k z<>g@HJ@;LGZ?%9|W;)l7Gy~JAFIyooFz_$Ily2lt|CMQYbJu||gfbTk=W@9HNWmD< zuGe#teryN4k-l!SCbS+6y{4GvDM$F_#JpqWTRS@)s{=;EY8v1BQiY11$J0B)#=d)I zauqB3BFYIs0UnL_hImJ&23tLwtLKM(rD-_-~oFOo2Ng)w)oY|%OZ4v(k#IRnH%NDWh0%k*s7AS2NO zv{EkQkiq<235Uf?7-P>81h9tus6&qS`&j{JxCl1gc(qp^fzuT==l$DUaaqn%0}#2b%ug9M`hU_2sY}cWux%X+KBsC+%YG z$xuphmhRJbp%Yxptqp}T06dW__UIog{b5hQj|e1;m_^o#Qv<^&FzO7A>zmyA)GobR zq;FEbrlsrAX_RyY_b2L{J=zu<{tXmRz%2K2ifFYH{Gjev>^p}>FX=q|woYBTY<54VcTERH#ln+Y!Sa6S^pxmJY|laq}|vUrh- zw>CP_@OrE?RG)Mqj^fPM<9yPbh%UuI_JMONv;^V3s(#LaC|z3nqq9#)7Xi3 z+)%vpg(LJcn;jz=@a3o&Ftt`3b_`7~%q9?u zo_NIcewsmbNBClJ^!tNN%re_#+7ns#t2Zmoyrk?^nKti$jQ2#64uj)K%$ z-L3Ctd{&u=(Dp1OzdChH)V`Mj%piX$9jXd)G~7HenY60L^lXHgODowixJ3N1t0T$C z%B$H3!7zL=HF_~QM5NQ{(RRz!=#6~b48`4R27|2C&1Ted(yale7oPoVNw-1cy9TMB zRDO%>6aI}CzKYjy^(b9YnrtvIrKFXD1O?V(hu_u*1V&lS@F$y?0&!&0!kysgQ60MPOB?`b_aE;&zruxvNbS z#&b1JBC+!-fTO(ck-1de@{v%`>Ib!5f6=(bDV0`h$?N@ih1?yu9_KKT zV5leVm(ECRJ&7d$!5YOX{zTx0u&nv%+H_;ui6~p#{0hW1h~#H?+Eo-7RHS{kT3y^J zFqMaYoYa_??E8onhqYT2(X2ag);eN#e!SH$UVrz9Rdb}qpmzoA{tV7kK2rG?EU>vu z5FDp&&T}j7A+CR;RnQU>T)XMh2kB_M7TU2LIZLp^QTioDvlrmKX+&+ix999cmiwHB zgRm&v)X_w%tG@X6b&KQzv=BVg2dVKl5$)(9Bdn~}&cP-^#jL?v$LXBCKiE<66k zH8Dg#n6y+o{bvZkgps4-auEA#JYx=Dn7>yqbqVWFKQQG0a|GSg#GZ8D7q#wsim$WF za-lxQkxi)a->wwbC{vKIFG~}o2@g|fxGvU1ap^?!^}Qz<9`h3*q+n(-qT-|53+J65 zUlK9=Uh&;fQA(KF>NTd@*dufzaU8EABbd%UGE{47!(pl3(cd#P8puvhHJ9*Xl%!@! z%03zi_wChbd%JEJ_ESM0ul_zf$& zMF%LDk%t&MF2pCL?NLcQ|6sfS{U`izkWL+Zh%KaRwI6OC@w*@TBqKQZAcsz=0@49c zDW2^g2B3ZeWw_meMAAzoL}@i=sfiG21=Gc*1%dzX7)}>*7P-vv(+THanA$&>AD@80$2j2f z`B8B49Y6d2ltpt4^a5My&;Sr7b+V z7NNcQBcW!4Muz-GdIF1448Mj{sTmLk-ED4f(yLxBDR(;TVHrY|;YiuQPS#>%+>*2Y zN)0h2R-_=Sb@1ioBEMyZtj7cBnW{BmCbxa+9Me}eH@Koaiy&J~=@RqA;{pjA3d|_X z7HjPW;)u1oE?O&yB3S2W30v-)u-x?UUl84fu44q8CAf08_YW9KHTmnH5rAeI!)}o_ z=aQ-jU6DNVk!G~XC*0@l-{@2L_|P2zOx?ma|;hJR1rmCgh7 zs2}fVm|;gAm=|xn^i1Gfxqy>f@Ma1}YbVLdE0ji{&NoJNu0`dC><+&8kHh^eq!v#9iHYZ>m zTW(Z}fyEpX&iTz(zh9=^f$#bemYjAE!@cMZ76Xb5Pt-;5R5&&V8ZB7jeH{}?xu+7c zU!MCDpf-hgZ*l%6P5})IfoWT7#WF5<@XK-;njcL^pStSjn9W!!?b7(T-Dk5lLQ0An^ zxG`IImgySugU@!fy{RR~U^=k{Q?vK_@1s3@N6&=|OMtDpcVY-isHmi1s z6Rjb0NQbydYrWGR_2{UbN5Da=fhV0k5yy<}znBAJoPL&lrwOa; z&&hRS6YK`O`QMhei}gAawI!LU{U3ciW?A8@id^n-x*hgg?BQ+gV+6!p9l9|ltp7L0 zwC4fLD@2LEA63>VY%nUYrAk*XVmsnTx3!%q#${|WMq4;FJUe7yU-Qf>j+^-3E~YCC zRFx3SQ!EYr7uzr}cuE~kAG90dOkedg!Nb0Asyzr?%mqkLfjAa)@d{vbi$6 zZyuho#5TiE*7a?&i+Ua8{J*g`Q#%X}fIvO^P}R0!lK|1wq2?7y3U%n-q#>h|gZQSs zTwxeYilg}0w-0^eWtKRRR0-6HUvRWzwDjuZL7aFu3%TI)Qks)JtQglGb$;rBmgYFK zEoC!XB#sMBgy%PZN>ChoNDi|IMRO}`1Nf8hj}_;1ACw+St-~++r$?h6*7s}x0jOe1 z-*E9^xU)S5k$#GH?bz12d{Weg^>Qi}HM1B^&sdP_mJWYD%O_;DhO3+gET5LLz?;W8 zRXhJcBp4*pcz04Z@&mSRP=(Q1(!vqMaxEs=yHk~Eu-wkZ>+0w`+O>Dng9e8**#)=B z`^wTRutKNa0DW9ttlP*6;Y@m9^^M*X6X{L$nr~F<<@oKxDA-(5Ye9x|Zdhu?+1K>c zFg^i^w+^c2^dC$Um0Jx}Q(odw!(C3J^BJlR54w=;T$D6kJw=z_uDP=1S5H%Em-#+d zfi9fqP-4`L#g7|{e4HO2M~06TwjPh;ojc7NH)uB}#ohJaPi}bG=m+cp17k0{^GK8A zG7xR#;2Xs{>5Ns+zDxSMo75*5+VA1d`3|UhrY?!sWDB;O-dbYK>o_Q>s*hb_@Q=YT z#x{S2txEsa59+TIyob(~H4{1g()NBIsW<}L4gb?*tiJ7!aj*u6i1gUMQkkH0N-3zi z7m&q6^OXO(a^wn+6aNVylo>`rtXhQJYAjK{3M$wRI62&#M4lFGbHAhg+ZllC{FHgh zZ(#wkjr&~D(r1=2nY?m0t^JI~Qy2cqEQ;^kM%eA;24Hr#72L=9CfnQZUaHZ{+Po$< zYGbpbGjf9zWnki&8@v&vh@He4I8jF5Wx1s(Z6wv zb8xV;3rg%5E}G+G;f6@V;>3m+=X0k{r-gf1auK(l@tDeAG>Jiz(H0H5iHF~X6_kb_ zxq7V}_Ok|sLgjeWNo=JNlRLrKmfapECUZX`u|dnx1_TdB@}nEG;$ouq!uB$N5Cd63 zxV@Oeq#$@{R005fA7)EBxi)|fK2B%@)c{GrpzOgUR1fmE#&}3xw00uS?;bo(mDk^I zH*bGv;6c9wGFQkc@KNQaL)0Q6hIR0*ip6G7ufbKK%1N$A1pHu&`@|ot@IA+BBq7MILIlfYEul$qgsyPNXAr0U_f-Na7TgNxNs%|E|8JJ-ZIx#vHmGwt zW2~)7C;}-ST>~-v4c{uIAYkGIB9G)Vf^G^2e$&cBfeuU8fq%6Zh6J0pOOgl+@7~6oLy4sH(EQGk6R0p*L9ec2EX4=PxUCv+d>n<7a2nT>QO!}#it+h z)BIMph5p%*c&~;n;94SZwJx48Kvt&9C(}IaHgva2no+U4KjMn@Af-c{r_$T uYN+ox>XR+nwtw$-IByNmPOJNKQLA29hTR_=%uYv;#| zl~WOrdl8U8>egRh;95~k+E`B=pfU%41j(5aWbAY8;K!gX1rbO>sbMlakC|=Hf7B<_ zc6+-#_bBk}K@vbQ3~ zpK3s_<7W=5aDk+l+ zJxQY1U0M>nUNCdzA&)<-J}(qK{)f9?T`YgLUUc_yT`dQ`Rw^h%5@J_G5^??_wgrPW zG|W>8RA%y#&{^1!YnWi@Dk=SanwC9)58G>bgBEtCc?7) zSU1ZRcRqH^`m-R%kwxVs@W21(G27O1wl?yR6V6rL>#)%qXGG0tdj^$V<&7j0hPmDk@ z`67jap-rN|1wcqpl;wPT6DTB~5rvjhkkr_{(*prp z=txQ|En6trq8p2e${s`9t(9n8nY+V{4Vz| zyL1m7Jv^By46UHz5!C(X0SSg5lDGmH!j^Dhvby43l(0lQxhW>*YCqxaLK~te65Zl5-D8?Cdqws5ez=*>t3_Cl!BByXlekDW z`}@Q#vL#i82{YNK+_mJIA_Ur=z?cPdb{mn1@(f<|%s4x?|2{Wf625=t!mq*23O_t{ zCOej0Ol(Z)Ws&YZG3nYMH^>9itY(s!H{G__C2|`^L(C;&2`D&%A&YiwoVsDStCgG@ z??6x^*eLR6cVXu}-)f_nCX)85mb;VBpP9Qi%sKV`&=l4Ce7}yrri=P z#}*3i$QZg=&B9Z#pzc=UW>YB8^96}5RWtEha@f=C~Ote6+Z{^{%3 zt>&ux0@zWB%a>l*^i9REJ_;z?M}4>+bpKQ$7BMB~d824bx}%cg(4aQiuO%l?(AYYs zCR~+lyPujcJ?==I*gzk1b62}3KemjEJO0S^U)p%~@(3;%MV}`?AK`*nB6nBwG0IJ5D8K7${Wa6Uh@nPTT*jUMYv8^`n ztv*r7Gk`+lP8O+%$l+^YPG{%J`{kd$n90pjhmB}b#(ceR z^z~E~%e?ocQlkqfCy~+d|KL_3Yh5G{cZ1*^kEJ~(mGa8*?JrctAtO~sA4Ul;?VL|N z0+QI(vmCuEeUege=N~)deT<{fh#)M*JAs-%QXJz8YWC*5pMq_Yl`4>hF3HnIshb?j zj1hEi)8IU7`;-a0htS}_rp31JnXQ;lCtnIoLTp0SiqNq{!3akapw`*my+$f7Ma$!a z>4|L%Q@{$B;z>&MCNU~_f5>rXyO@!?0M$6-qpzeK_3F2uRC-X;H$A#rE5}{u&g%Wt zqe%eT_B1g&aM_Czf5O&w0M<%13G9KBcQC9bu?Ot~G!^1z$U2xLWO{Ew2mh80UCBcLoP)Ez&{EC-2 z*?Gb$B{39VSqkdFVZ4M9gW}j|oopGIv4%xYvV8|s^ATlRDM2Ixe+FL{ixga zkXErsl9rbmx{=gi6RBJ0WM#lBPzEvo)EuYkcP}ap-%H00bHe1rT|gPhhS+R@GdT+` z_~P5J%bbo1JU3=gTRDw~3PnV%_ngjyBz8BUEh{93dBaI=tcYvz&OJTUQQl@A=IM`4KYn2X~#$ubqswu@LS$WLynmcTF2~#If ze=)L`oBLonAlr&U0#Pu{&?T{l=xNW>lU@6f1RkTq?&VJtk`Y*eL$RpMvNGZbT3S#V zmtlc~T}k&R6&ij408Cx5O@)V~z`nicN!?|k|Z6DsvclTx_VioG?; zCFq)Nz%xJ%@lrPq9niX4bngzqAT%h9X!fP8%mL#}gg)i195S_5XRlX-3xi`5gI$GFw{w^nR;^N(nN~a!xoT8eYtZo$OkLuO*T8B#px2;;~9mjiHiU3x#GiT{0HE)R~Gbb&H6_b^ZWm(EvxE?z^5+Dy_l^-Hgp#bE@m94kb>) z;apBbI_TaS6rTg z#l~WhVNQ|7=O)SU(Mdjs{YMeo)YWRE!IadHioe8SF~M?~CU8Do`GGFUo;OJQ(c9J* zt06-8eOcn`W;IgCTP;PFy*Mppnp|4ZZh<3hf*8Jzm41)W5N@%VPQ&dQo3WzAy+Q^| z@1e3_CAX?B>Mw1np;4eco}Qc1sL@Ij_0CRW0gBYFN>+$MAy%QP6{RLjluDN2OV8X8n0V`Y=fD6~u`-y^`*}03?mQWV#gQ}_dh_KTlD^93Sbm-iX`{A6+WG^Xx3I9_;?BW^8Y~qdd*%f9fPMfiwI`8ed zr!hq&3653eku;alRIjf-oa2pDH#2qGpvI2Sz*alLK5_duM4c3Ne#sx8h};f5g)yrk z2^ldLLomzbp^Y2;mT6$wvZd<7P$gQ_VhJZZ^i2%?4aMJA1)l&>d6FPc(UqBoga`rx z20{!~f*wdrjDZjl8hlu&R?H}f0Rk1^#u&`QmJng0%mj!nMhOifh7v{z2Souf0z{S) zFQ~CGfgIjB5>4F-q$aRjzz+erkumr4VACbB-JmyyAVyqF_52Bnm<<;?Sog12J-xPK=^>MHU_H82ATy+$fS2f^?w2 zFD;I{+8TrU>jV&n1VZ$%pAD2K_6>mF`;ikOQH_7pBwLx&?iS=85wC$KhI<-n#4*M% z{3pAiDmTMfORnx#v5;x_CPmP5Wd?8t{C=k`&Ey@aD@BV0!o4QZ+$^-(_!w;M4n9e!Xfu&WgpO6|4RVR5feXKFKwfPq*}&2Da%$u_i^DbJTw%dO-@4Q!FoJcb z3VfyX+S`KEwQ?FxRg39Q64CRaCWt~KGNIX>Xwbi!OC)ayGG&36bTCgE_BO3u{2WO;}g6;zVB6M%>Lyckf5#KmD3kn#xR%kS|6(;=;=U0h)L-QmE} z7+>(#q_O{0&rc_CjzF*~w<-Z_MU{GRF>VU_Cm0ro=Zk~VEWTCc@Ac zA^gso7_J+5L3tcO(3)1G@)l%uQ7Ru>StmYXKJff%66JgnE2l<9O)6byRS+3uA(5Gr3l#C$j$ir$A442lu^xuk}##*YtpkrYrYKIj^ToAv2d5fz1^Pm!MI?9G*(w zufg{EiTrZ6qMm`>;&w1e$LpB55`kABZC7{@{AnL>xjP5d`RSY3>lXqURxyd#Ut~VL z49Sw`IjlFVAeS%1#VmUvk2I+@X122Bh~H5V%cb9CE6E@2TE)obx%`cT+wNzWXm}u% zbjO({bQkWYGRR$T`D-3786AJWft{kl>0|}2o@=>~@{M7{jTxQJcGq1c&ritZJ;?!kdc|%# z6{hb<{E)QebPC+)e=mx3KWY6r?$d6g(JR%m5lJEMzsmuX*dvO8yY4?o&jI1j;(!T2 z#k%x({XRAF9N_(3VW0t$Qu~Kb*bP+t@o4z$2zfW^p2KmHF0>(%m3Z~zS-|NQR zEmr=48raP3h+CVpH- z?@*kS0@KX|IC|5DUAR42WN5(y)y1-YA#h)#wtnKpKT31Cd*@&Mb-hw)a%ZiTrliMG z3`87bD4ejUpNn7gu3N(BVxu|2VRY?^hEb4|akMSlwkyrq;!zuaYOYWGu)!;Ur^@=; z{)bxJR{kqnZFWf1N0?c8NLzm5<2rRwy;Un_z^DhLQ z9##WTWxGNVHa~5ORq3$r?{V0T_r{C{Dl)ZbAwm+e71B#erM`6cn7#)Of8`M!*y&}n zSw01o!I$6^2+)vZs3PEBpbiz|hXa|L4PYIw2<1z=MRABc+Fmh3 zzP;&M@J!3!oJuB2bb5t=?~gsZ(~2xtFMDA3a3jk>X_l=$iTFeeYq+IHCX|2TavW}~ zllmV@*Pz^_sQ>E!b>_r%dTwMR1WT9~q<3IQp_?P=^1V%8w}{`5R`?3mZLx*N8O~4; zJD_3)`=NDQ#**o2jmQSi8BBEND%3C_*;*fgu0W{lqeKw1edo0Y)^(myb!b*7O~;h$ zPviHSpF_nRBjVFCL;j$6h)@;wo6&h{Fr3~2@?eZi!CN3Fd_`pQJho^$ckTUIwGH!h z_mk4wUo=ehsip5B59LeCh?Wq0JA|BKp$2W}YJ1Q=Pj0N^ZgrMD8<}@DM7!-&Kc`n{ zKOAeuB!6U;ZuumD$A4MMgVGm;;t_pvoia zA9FW{VbOd|=rZ7HAWq{(qMNq(V`#$))4bHis8^tQkNDGppY9(*ub78_y30eUc_D-` z1=#jK!cX3SBh23YixXI0hm!G4D2psYxM90;yj||7L3h5((_mWVhDdru1dU0?_y_*` zSNcOACv7v1eFtyKrZT42!qf~mh57JTIT!5fw-+A;B`wJx}qzt*wp>`vkRqZ?D*8@^umnV0D3e45+%G3q5j!2*LjX4)ut4n=xigDzsy8_TxQ99MyZO+lmtF zIab+#y%qLzD~1Yo4CNOk^&#WzWyclQ95siI4GXHtE6;bqv`qROc*`sZ)@1Q@EQJwH zbuKt(M32P)Fa69>eBW>$xsiUbd0oGt0n^^Q0NZJC8j!3&&xuy0iEL8NmZ^l&laOgU zPF*B9C!(^Yr0k8Qrd}(qs^Fdi?58upj(Z!>r-AKkH+YllGOpPLlcS<_|NPgFa`ceY z`5JbqN|$xldsMwk)u!nm9-X*KJDe*DJF4`T)I)CXc0;HY#6-TmOlz$7|H2jWauU(# z@r{=1E=BWTQ5MP_KVQ_l2kPbKH<_-9L)Q!$Xo47xd>timlsxzM4lhGFK?D2S{SHB3 zsyrkRBWNHGSCp;L7BH^i@E8Sqw!{@msPnH#lMY{GCDKAxlOxA)u5&A!p-(=l@Upn6 zpd)`7pRK3T#eB(dBoSTI5jyaqW?agV=66n(F*R$|-C=D&zxY8fz_a{dbAOh4PH4L} zq2X9HH>R=v(D3lKPnBB%GI-Uel+Pc?8=B$-dWNSadTcuV;XkKu%~q7J1NTNb=0#OMy-}x!L*U`XQaXN zk4eIt*$cREe1flaBiStF>>`7}Ir?Kk+gG2d09`&aVBC@#a#4x+DRCKEltAx#32pWpuBJOZ-Jj_>lJ8swMJsltG8MkVMIS0qvw ztBk=TG7=c2#*@oeS|4@P1?T!8@j$vuj1>a_C~7Wkx;CxW8Ce-J!_URTMA)`QQtw%y z6lGRr>%qR6W9?nYt9vjT~UR~qS!;4roaqQ)_PGF7KuCInUlc+v`x2we{cKpt7< zXZ3QlbcYB#ldF;<)?AZlalsH3j;w{pJ4XQH=adSyHxj5&lPKjQJy9c!U2L>oE2Xc) zJTgNaFX;;7tYub)9IyxwOW9yBAE zK^LzJq5<`tgYT>RhC9Y~LY2;{Y0PH?P*vkWtw3y4IwE%d0NacDlLBKphRVq;|K36t zG$_73;Tsun>K;lp$JSc!B0$LJ*+rmAsV@f=o1KlA1RZhEKx_w;UR74omD5nF=F;Dm zZ;1_^d@8t^eq&lo9j&rkAcBc9d{@oZD{jjoT!2^j9D<*&g`ShEToXOJeh1inuB1YZ zMjbC46tB+PjmM{ztCb9wWa?dXB3xv5YJQKMJo`+6ysI12{ktXXy2x{;UeE;99R zTJDd2h5l0u|G@*o7fc_OSglnOy{=MTU9G+kFKZ8~idy1sP%J0*JD01z+U&U%vLsEL zp|*3vbxMA~U0=T4U+yH>|Ad$dSm@5ER8|Y@^YDndMaBOpV3e7EcF26XnIc^~__m+v zqVgv=Eb~Xm_Ncemc|j-XZgHuHYQs(hX2Xl%O@pH@;|2g(m8}hi5g^5e^(`u-O_0HRfw=l zv)*uI#>5Y&!30)gWk%P7qm{v$cJ@H)=JJREBc3VY$x9Y+M^VoMZoZ1j`DN3h>;We% z;$EQg(U}euua=^~9%ER*B>LH+d58|iN2J46+x*42Z@HZ9jUeawX7iGs3+4uLfB3`d5i*trv9R5#JyXQ=|OM8TTC#sWb$&Y>}7*Pv*gx z`TVDrVWUuh3M%pQ#V>^@&|NaZJ3G~%inpVD6f1F0{x&5Fg5V~dR$_G#4iPC6 zJtQ)a)x^&mQO_4+Nu=zW#2`M7G#lNxNY+fb-8FDgK(J}07Z4Si=z@fxcx%OSvp$lS zc=T^+N@;|k-{&vm(01bNq=o%0Swv>l&eC&B$n@XJ6(L)fXOmT|D1@KNtTpqy!z1WN z%K+nC%=51KG{3k;w*NweNB+lMf6^)>BuXXV>y)PeL%!s0C)K`FymX<4lQ{13Z!rx! zbx+eNLt8?#CG>SBq0hZC2ATYweoEpGj5z}rX1xYn!1yd;7lg|-cm-~!4|TaH7KA^G zHq?;CIgw%edAnXqD|>dGVqn@%Fs=76lYkEF?O$gD%YBMTegO*kO_9l|m%0rb5_osu zyq0g>>z_=qv4E0E4)Xxn_!RhmdR=9LO+QBcrqi+Et@Vbv@$C^Lm%SU5t|P6(N%a2+ z`i;O5R{%mzcFv2Nc82|8QT8)K93Ht|5EZ)meWa`hW^czNf^Uq*4T3oo#sT9{uX#^0 zH^i!%;IGmb?$pdQf!uRmY~0X(``tyrc{b!dr>77}H{Jf@&oub)dcFy^>) ze0D1F`*xlkl^Sb#l|Gy#Q4Y(Id`{3rd&JTz9Pm>}COG2B@?oU$w~g$@ZCtXmt(COh zDE&!-_*@%gB79SWoW*=r~$q; z%zhjqG@u9zH$)q?N4E46?)oRJgX!>6{ETUO8}9K(=7@aGd^oq)Bj5`t1U&B);wP&@ zjdzvUKZ(OSjU9p|nD|Te5AWXfs<$2O@aLo{wUk*kZJe_{wpuPX(F^6py5Z4(tibOs zfsb*DINBc#1qH@+^=+WMN3WiHV8Et&?49+J^NNNmsp=Gpp%6sSzJGe+b?OnI`$LrL zI@zFu#KzyC6Dh_tmv3Lq=OU5ZLHGu{u6A=IOw&lPt`gP9LOpH*3@7r;j^@X;PII zBe_q~iJa%SF=5W;)EefQdZpZIcmc6^6Q=L*;BStxyyGE~u*9hKp>^>}@0o}QqL}1j z#zQ{tY_LuhN8J=v<1xnf-G)E_XavkWd4njp7rwua50U`e{+Y7xm7m5~;mkKN*PJms z8iF^%DjBW)JKn7oZ~nkJ3bfM4Yh8VyP(sJPh@$&sY`rR?TqW1hB}T#sr6PcUZ|k~o z61On<73AncxO5wrgSI^VNGW)l2Zv;q6xQaUup~`W`m+cVhj8^n@FbpYuX9D+>_7;B zH=~h#PNV_;`+}A6w#I>kI(@bL!InO4AqIJn;YhaXKZZSr+0sfGG#M>G#YK$0;1dH= zr8M$!=BZ-R-k^%mGG>35g2MKfnk4pG{MoQjFF~C2E{9$Yl6(AU3SZh_%b&83!;gJS^J4oT7|JvvBC=bEt0dweh#o+v}= zy;)h)Xjemk8Asb-U~gWyyw*S#^Wbyny+He?nix*QW+-AahyqY-?AOA$vxW%!j0a&G^t+h*0f+zH9;d@XGF zT7(!VWBE=3_k#j*>ORtwm7I+c?ZIHwBD&_Vu?@A71+y?_+T7fw0XMk+dV;vvbor#f zyoB@|tJ0C_ZVv(sBfhMJ0W+;#`*GBV5~(mjK`gGav@N`LDMz&Yr(En6R_jEwMs+nk zQpCr}z^U0YSb?x8{Ajhd3X%nle_vg8$~+0I_Fzf&-Sk}T<+Jr3(fGtpN+hqDZoK!1 zNvQrwpt&gJy6uz+OL%EEK8j zxjcNl@AU@1dsaa~v$3NbgTGTLM2xi(PlZkjvy1a7VIu-; z<0kq*$BWqTJF~8OC%A*aMm5tNB&Okc>kaWl^-?bzLVyI(63qI6+!4#|7~Hf6oq!$y z2C7pLb4$RiaVV?WL~c5!0gBkkMqVEq-i4|k5S|B)Rn+@>e29odW2y`?s|H3{-LPOC zBXnZ`w6kkfXkPOnMb8G|3?6H?whcf9bgwI6aUJ}pq$Y0S_WB~V`D67yiHL`-3SWqz zuWseNN--sGOy!_s4#wL#=$F>!+NgS)JDqCdoT^SVHwkwn{VK8`=o-du>0!v!@PHMc z@t^l9twRoNczGDZ_nCw4L7SwjKEmmV{r>j?%gvbYidv@6^bl_ir{!cX#AskH9wVLo z82WZkfGb9B`CoD&H6}oGE}O34MmonP=`U&!f2)$H79GSlyOr(zn-^L*MVrFTDm7E| z+0T^q-11DsSD!Z{3Q+1M9Gy&+CrT(sUKYyK3$Ir;Ut=uOx~*b;l-KR|pB8BaWlSR2jG z4DDk{-b;QDJ-P68Q}kmZNUzF=f=nWw3T-GsWs4ktDm^QdAyJ#R zQ@q0@z|?GBU@xHttA5!qB|FA>o}#70`yF4Xhke#BcUxuVNs3^r@1tYZy{tL?;`|D- zpXuRf>mUZN6+nbO>bAq2Zms)t zz(F+j37-+Go$fIux;jDYV09Sck*=orNf8?Y%Ex9XOA`W5HWgqOZsZk|vWAKEmK7XF@zr%$uz|yO2ZX7>2l$Qw9gav{1 zoH*{Zq2PNVUeG&rgSm^L}j!i|s&SXm%(%q!!w>W}Ok z9gX6P#wJFDegw`${@Xlrr_e-#^|o92GF;57FHJszuw;{odH%WCI!u?oEPW~OP0S(C zA!>D5vIUZu8aHW#{>r4EwiYge{{6$&<4hvJ-jDf0nUzBu+`J36&jQ!CU!sYz%SR*C z;1^kgQrfxz&@8X?HR^P{n=q+QWEU}~fyP{Ud)KX~?x5tQm6v=Y9mho=SBXF>BB#__A|b-Ktic-5KO4+h>GS~c6D!LKuf4*Du43ME}iB)PWu zbw`PoZ6R`(T5s$EzqC#+7HVi$VpH_Z(AR-^*F)X}iw9?a zj*po2S|2g;y=yhsh$Ls+d7%UoSIBCF1>{B03CLIAKot|BL1s>UEH&<0LX1XOu)O#H ztO0o#N3a<|=4oJu!+t*kpjZTsn^hxnjKg!F3g*}W3N-~oM`dw1 znB?x#S;lEO{h9%K_YF|@RwYmY?TjT#1E2YeOe&obP7g0s@5G>%X+9HzhiXhV$M^bV zTiU;$&5MufN>R1gka9rB@c@z#GbZ>!a_EcAtihx3nHge$n7cY~7R6l}z~a*Yvp zNoBU*=JKE_*HICPk3lAgA8!P-zkn4E9ijcM$9$6LQ;gsUmGS6C&>R0tv^acx&&}3*w#asJLgHPjUn5F{G{1OXjx7)6^Whm zdLnL`&{X;Z&cc@_Kr2yYweNG=YwG59Z)k~V}7zdD3qI!vE{Celff zfNvjJfuyukfJIr#4Z?cl3If7IikOShI%DwQ+~^<%cZSBwdN#NQbfR^ne9WCC4R@uk zH!`p=v@{hwoC#;;A&Aing}TvcdyAky#OYMpg|Hw~lugRux1WC(O7>cnjYV&wivIST ziCc|WeB^<;BO@u{(oOv06-LaG$Ff#=egDjbGPS#=D~qzMiErAI76KaDPF=|?Y1ty$ z64U(T-$*wK!T}`PlJaoOFP>ZMPtvAl)LezuSlRn)X`sWl)J9~DpZshC-lip&X3v`g zA$ElwiDW0rcXA8VPcwy^sW2A3JmjtT8#_?0lJ@af;8AVO2`k-6Ag@Cu#ss1PY2rMGELQ-CV2G+7^*n$NcLpqhWE2tDQ>p&UC7Ha2Y z$_1QN7s|RpytDj$93Nu%)-V6p=(N1P2d#EBvq7<~lWzk=!-zD2&XLIflwS)Q{hBTL@sVUDkn zU&L{i%_*1p_h8uoPGP*gw8iGDY;f~HHR$4^;{fAcAaLDB+|Y3~4|POKi4$uYU1o2HRQCx70lg!wsh}7-<}RSk z!OdX<0KGt}rFnCeb#i!qyb@2(!pl)+h7Kbt?q8E2(S32mHGvD-09Ya?t}D#__Lv>%AtW z=7w2qq*nNHw_%a2T@6c~mR-5~@G#Em+Bp}iZnj!H`kk6KuI}M0hpKk1%1t|GkBAL+ z)oyzd3-cIOe2dp|?`e_QAr4FK6~@dZM0j%#-Moth57tpUti75xp6R0Nr51+ob;)i_U`4P+p`#s zT3*dtm-G>BvddkAL$fw9&Ac-=jt=m{88f{#|#vYE@?er`3cCP87 z*TFQq4N4a6t650)oT@#>hqE@-&G=i4K>5E=@SOkeJpO+fM-3h16)ws$-Fhg6+6gGdQ=rg_wN z{pZ>p22>&!#lJ60Z;`DpDlzvJsY%QU-Px;kZEM7GH$)Vo?ezC!7kKV>$gFg8UUXNz zWC?2Vy=xu1*ksb{@PPD*+_d0Ds^yrdRJSPcFACJWIUM`4lNpJA(&P>+VEV=h)G$#0Jemm{bUEtCreQ6;m_zsxQ`r%9p`CZlw`mhfF2 za3bif^Ur!MzMZe!_t2dH4q-vN+x5I9@EpZ8i1`IKB&y<4w)*YhssG>#V?uS^+P1bb z%WS<;E-}u*Bc+j2ZF18nH!CwSP-aQA`dK@h1{$IEgR-kkhrFPT9rS5n?E#-0N`GSO zHhjPTr4ZNNDgrV&Y8H|#khEEMX3G=n3E?)>6iV~`>@if6xRk5>?q)P%-WGZq=<{`1 z1215$e^tL0^h;Op!)kh`tDVCfd7^0q9^^O@O05`~&67B!r3 z^B{0utcTSEbtaZ=ZA?dAFLsiqRY|J+atuGrPTj1DzYnFGY6|R>I%2m42V3#Kdn`1| z%0YVy8uf60aAqhO>Y&i@ST8gopb#-iq*3SrgfMY%Cx>i88ss81Nfd| zYE=+Tbh1E?aU~QXBjA02q&i502fLC6$T9{3>40ZMjlI`(_~XPL__5$$`OzS-v(JU= zCF5e8S`9X?g&V0tW;H>EP-<97bUTqL5LhgvjAj6NFy+)`4xsDXH2_vS?J z+t3@${)MlvO~~#2{+YlHR{!(=)s4u%7X9_n(C>e~De%;U{BLGpFK_ky=gh+`Uq8>rzj$Mv)$r{~K&a004-XCt3=!;<@ ziZ$iI{Xs$Wf+04*XTgOjk5B4E?+y!-8;jcjGLw^&DuAC7SEAf6N*l=tdK;A?2moo~ zTk7xmTn*Onc@v|*gC!EwFZ@Px6bIUY&{n&+svMM$0N7;!r!zx|`vEn50WaViziOpvjm*0VIZ>VT$ z#>Zx{>HH0=5)71DS;Lf=Y${Dq6LaMd6ArdBXcUN6k${rty`BFtGyOmKMsa{9(JZ4l zCeb9pC?YWbZ$bV4caq@xuK!V0`9Cr<{zpXk|M2wq9~S2SLtX8Eh>QIXcDDcV^z(nr zA>)gML8V6$UY&29g| z)MXx?z%Nr15lzyF1Jc%!8%HFU8S|ZAu?ZIa5b&^`DZRM%qH;H#&}hGt-+IGH=_3jz zat2I@PY}p+0=__QYl)!P=;D_8x3ipFX$eeu!#+dha3o0h*WHV`8@N%3WYs_Ad#=ZVX*G|74ichNcW-t z?>tz&T_Bg#cyN%?B+4+Zw3g;SK9pYrL9jyk`@-OGLi_$?+n za3s8YP<$an5NH&PeozPqN00%ZdEp=!@`u@3R`jTAMPBE5fB7bT2??+Ngb6U?0P%hf z&wk+`Xk=9oP;Ae6A$Cup0N;Ml8yI3w;`ab(Vx|6Rp&5J1;-aFYG47-c{ESI@8E!$8 zR4_y=rP*}d>Rfl=OI-2>iV={j(nC3u#U$VVw#}bLm_LAa{g9o+dazw+*pOk}k*sMf znGI^21e8(=AM(n-6t5_71S(h_CmJ$!pPdtjdE8zI1H5Wf`NWi%r)ldLKK2XBejaZ= z4nVn;&K+NdfJQAvUI1Yr1nb-sV3gk526jjY{)3&45jaafRjAVQW>0vBdG`pSjHzSQET<1S_aXfDBKR({X!yrkhUNj+~lMA8oRYUGXE6KKy z7eWgwG{gZqDna9U%7DXZONI-BM;-*~x{pJM1e}1uKEu3&q44edVd}3-(jTG-FVRr&roP2!XKGTVUyD|a^uJ4LKb$dOkqXT z;9Y5y&Pj4@#+kX+wOeOyD_k@yTNJ0EnVtrWC-x+HGl?u$cAs;u%p3+0N z_97L#;SI-N{1O}zB?Sh-z`5r;zO0x#^}W2{Vc!VNkF9}OwrA8#mVqh6<_2da7($WNz?c0Rphis z{!}Z3C*h^Y$47ttC-yVAxRB8h4 zx^<<+WqDp(vXf)HSgL+chg%~JfFiOySb zQq691Y`82TYSq|^D$j&pcC3Ca;4ZkbXu~XC)G&rYH$YQv6dXsjgiz3L(eA>WVXlCh z_0&(nL%f)4iO*oxpuv7sQr&G;x~m36f1;&HNistgq@e?7*HyIw^h`ADOw=_@b?X`$ z(MI;Jet+cmX8X>2SK-M@+SCqm@SfUxDNYzY@0Eua?lrm==O<5*0m3r4WvFCW#Hd&n zqR%o8lG8-Eebu|SGk#7NhtCAzh6OnkFe}baE+pgg05c=UX-P;^Ov1ZvA16Rr1#!}< zb9CwNUmYD0WK@#~73`!L8l)ZEt{lk7^Twzy6T4;TsVNGjcPkCF>Hz z48rybTdm0yy?bdK=_ogK4jUbt-$+u^l=RPIA8Tj;KvP~1oB`kOha3l`+mkMC&_H!D zi9)ivgGw4Dv)geVHTB-yxCfvk%kV?U4vODsi-%NM%(B$K$p%$!kJFrk>VdP?yj>+xhG z>jQ1lc_?lSKtToLTtHhL*Y;T;gzE8D*i6D$Id)sMCrzewGPrr0oEC^E8928vW8zl; zYBstGkqU!EG9+Lr|E>q6ADt}K-fy?FpjlZ?!3beqh`nt_uTXK&F?zN!YFf=$km>KO z!CU(9n5gPGJMCfewA7q6ZDL&_wI#Ln<+>hfyFULVHZLKsApN137`w8fSwd0LEyXz4 zh{2RLyNI7fw(wJVM-9R?m7}yO zPKIG+TIx2}H~%?8>=3lVKj}DkY7J*8PTI~Q|C=&VO;;H2IOZPld$M_gIYO=!2A4&L z1R_RGF_Ju`m~+J@)b9nTTFT`v;jQfOY4VB7YI-`(0>?#F-vDH1lDGNW#F_Z~V6bl> zPl4|8OiD(_+EHXhq_Q&Ixy)Njj`_T#qPz?sJnAbmo3U%Vfg6h}f& zwrX`Qo(dF!VF`|0KR;Q+6zNnPA9wOQq;e*+k#`OaWe^pyAyv9R@%T7NPV4lsjuvTe zSUvf})(6k_hz|@gUX!q!wOVNZkAL&;Uo6z1@kZJO<{ADVwg3mRW<9Q&UTiFn2t-_Kb6;Ro zj2bN^nUqsu$PaN)}bX7HTN~V=jfQ0&G3mxFGBdptX++iN&-&f#mJW*}?=oCqi5llCe z{@ZqLJnpk7Cqhv$jIJ6sS*G1|<1?*!ti({*mom(Ud|v$CBqA_DYau1ohhbx1*d%BA zw=_+PHlz;krqBVm=16z2JRATU!!_c+XpI)+1H7b}#4&|9pe4g!<`odlaKgF-n>3wa z;y&?Mx}rFZ?M7ROB`!`G_H*L_S6sn}Rq;3kdxPUOQ?sivI+#z~Ni9*aH0J1gWSg|v zh!8W0vy3@aQ&(e|xS!4_D=Eq<6nR-re*Qc4bsw^fPf330xShEFr69#Bo(qUXaOdCY z2BL9S;58Ksj-^W|PkGHMCd&H}nOAukVDg)vxGWr(1O=Id2nz7=i)3^f$zQ-yZZ1o$ z!u_=;W?9KIlbVSqYkWkjNGKj2ujOE&!mLq>xjr=?gNc(m9^j`fGP2+IMLxrraX&V1 z3MiJS<>#dFr9^l2!)5fm?D1c%76#R?q*|)0Vakw zD)@Oc8BKC*IHj6I&lhK%hqx7brz9v%SP}=2jzr2a_s&AtqPiurl+%5Hm&NK44M4#m z+4>++Ha^h)W&_CLPU?O@0<;qIB30FpI_s1=;EV=`rDEC(bYbz(=p84JoC-y2XUo-_ zlvpjBgU@eW65t|GX{Q>b|3n#60uN{QRipmi!?cdioOtyaoiE)ZRp~p+eSA^Oh#pG@ z2^`ZGLEUbcn;nZBOAMkIS0orXK{~0k|91&@X3(R6nYaVWptDqdSw2fo^Jn7Qi-Zh2 zGjdH2MkUVh=Cvs;j$2l9iXKFSu55H?4PuPsuyZ_%39bkfLQUE4qGOa;;FT}~DOo!7 zr2Sj@WF(f+cr@-ItGRWMlQs=gVQTa4xiaifavmC6sbUK1(j9H|#ZZv`7zI=g)l}%t zu6aMKdZY{IHk$S05#=(~1@TiwF3(P_|C(nS5xr&Od}+uypCU|W@!`JRt|rGke$~MOb32 z>crxS{Ic9#ssUVxjFxMsmJMlGYGX1pg?z*2@I|Jihp)mQR|eura{|YoTmp$Y#v1jP zgBiCX>VK5P{50w17wHM+QhysL|GCN^CyejVGFVw%Xb{XZsyHNJ15*;>CU}4GV;SF7 zCi;fL_t@fPZQvN?UmKNCnq1mMpGvui6=H!7_~TW#agl&sQ@}=)kLp2EUZ`-Rmcn< zA<-w*kn_~!Jk3P&0xVq-Ro{Fnn#vXYOiD&xc{0hwCr_ny#}t3J87}0;_oAIlqUDGA zV~Mg!F;{Wc=F5E;YE<3ey7Er{JnW2USFFSug{IPA zMWUxRvx4-R!rK8TQdtK?k|fZadg48^1@I^Rl~|PRIypHt1&-6jG7Bb7JzQW*FfwXA zfBt6blC`)FKRc1|k-BBIeBY=Q_1Tv$91IjBnQChAYh=zXz z!uyn8&;~nPJ9iJftlvlfeny%#Y&6IWsDIi$Fn(Qf3AOu;4mJ7|Q|g$= z#hfXjy_zfGYubX@qsjNwtWQ{MDXP$|Uan}_AyxkK2d3RTLWRdaxg0*1KO89+lXylv ze^~Sz%EHZk0ZA+cxlMb;s_>|33k_6_2B!iEXt|qtND{uF?+;RL?JtT;`}ekrCsKKK zGg7<`oL_`^E@-f4%~-ht^3c=n8H9Xm#(TUI_)pMBiH6{m>HL@}{``BRG~jwX-hYzx z{qU+(2hy)Bp^(5Jd2M^?UHd~lKPy`@KJH(S zAI{hE{KrVU%5$3|8LMag z1u{T^kRJkyFbtAP?501hW0Z~P)0M;(s4oH^FvO2f^#`SE8ww80sinM7wn^%jf=X}f zr`q$^nf`?Mi4}w0Jgi5tb4%P&61JnmY(Y5(L550%V6>T$tKGDkm&S2$f^mF6(u(Ve zAJD3U^EG5B!!4SUU!neI{7sbv-EphpFLcV1 ze6d@dsDTdK5_b6pIRN%Od@V{jA?rRRak1Blw)e~`r;tD?)|rXxNKZ?MA%82yyLkd~ zLCjKxgxdGyC@;C?s(C&=p7}?(@kC#irhFmQ0UYZG z=Y(?J)Do&A&#W4J?qRO1a^&V3xd$T^ny+kF;%n5;A-15ytD8x~RHwR7V=AzYzA6i& z9Pf%LO~zHyN=TJNbTQXGmI=k!QLpv@iSI8ehL+V2 za-!TSO6GlLYglqnOBk2@9K@3fI}nFE7^h6`J>cK@EF_iY09o)s#3wH+zNWRBr8QIV!Qb#vNf`P6a19eT#OFED@6^!SC5 zp1#8g4d+ztxd6rL!xx1J&{Gm{--WziN6#N9k)Ut6e~$_Y_WYe;QtV?(@r%L4;m~&7 zcS?rQlc)$7$I@~+r0-5;B%h7#z~vvhs5ZH(24a-wbE72*uYe9oo5{FLzbok#M-eI; ztD-uEq|dph;MW}95^C5=4oo@0G;5Wb-lzFFJ-;-w!vMK`?0u5)N? z#gR$9a%k75nh;*z!$CK-ig@^I;2+=gQ;uTgZno;B4(Z|q5rkRmqVqQjp*|wmez_VK zi5##;Ox(hiSPKrZSaSdbId$$IvpR5;`4A0!B4bZG=XYrdTeh9-1;Vh;@Gnj(FyDZz zFcWt9as1B$DB;FKe0BN&!(sXyQ{xD@hyMc_pd-UM%7 zpufZ%iCKp8;qIUCfTc4-vtkSnS&Y&u=EI+pdK=oszwfCpjzl5-^vUKZ#j4BomeL!S zp>n$-D0kMO2V)4|?|hp-7ftY)cYG&&?7dL_A*oVRLN(16iNs$u99Qa#8m*b5d;|u) ziO^ePGA#E~&LS~NK}0Q}iO!C8z~C3PVF&M>2n3AD3Q#Lu0XfhgEM#sygfsm?uPWC} zwo=HU3oi)IIm_)o+*{i~c2Z%$y9m$(=!o!9yY$k^ngiG>%<>U#M^^Y|pu*w;^TBy) zcKmaLUggElHb+2zxKq5EQ8FFr?3^>IQ=Z}}QbH-dZ6kst?^PoPOcj`I9$KOY2;8uP z>WDOOV?DTJfa>ADqfIO`XD_%CKy{DO!*#o$W(cgY&W;QFHlPhinq%!%J9Bn!CtK81 zsvOPQQoB<5cf&6vRMWhMI`*W$29^?BHd&EPpWv#eSoI{g*SU1@*fBI;N0F#LVU;hv zYOB#7*A$j%Fa9En2eevNh}oDs`6}c1I3MBpFK!W-58rj2YHlo9Co?T z{Lcq4?{s!neb;7@m01h2)|$~6nG?;qHQvK2`;qY{@jOwNddc5u62pq_Q=+(&OS0U2~}(VbSyH~i6T zPhW`>0h4vbvxyIn&UnR+>+Sd@@x5H33sZllwCX?h__TQRTb+nRSLY?-^ zyO8(8zQ%z{4y6V;5Wnypjo*&RKO(^aPta!L7O1Xo7ly6^&3V9-x!G>HJF{zJe54ZU zWblN6Rp>{!mt?B^IIms2d8ql>#)rUqDl&RMSW1v_n}X}v=ai;%*Z2`!PG`19Zj)M> zR;=OE0_iA7Qm2r%oUFUS-2jmbzHw11@z;I@BvX%i=N!J1Vgl`!pxi$1m|nL<L(;d(r77pmvC77zW_=6e3fHW1p5ja6?u!8svQ{zag^C?zSExMp&fO7-*~&uJ zbka?!?0f6**s#DtxeXr)Pou9abye5g92ppazBlKOaS+I#O6&)S$BEn>Qi~NKks?nc ztg0tcLqU1HwT`%$f-z1$gy2xK;Mc}e00TZ(_@b;FcePl7Ap)#E7lq948-+3z(iFLQ zI3u?Mw?AWOLGm8B1&vc-D6jy_qc|)ma70@O*3+qdDhI3Iji8MwaHQGRXncYt#ZLTf zZAIBkhke~tBLFpFEut)Bb>k&gMEJLq{Z`>cALs7V-)S*Kisrl|5J8apU_cBJ;4;1; z3@7xY#J_?YhR1`YL$+GD86~sWT5K%UA*qQjX%zz!C039JYqY{WZy-ADTFQ=JUc*I* zqTmEkmBJ_jx?N=Kw#W|jev<5K!Lw}=vxm;dOIHQ5TZo*>WprS$3D&Fx*u9~MqAq$Q z6}qeV)ul_}Mv7Lznu^gp)VYxju!$+W>lk}2KwykdFqZfz{@b3`_d5*J&wE8kK}b%* zNh#k|+Bz@5{ylRVbRY;J1^OU_-pvlb3x4XC-jm zzYHTgsT__0ZIyhJOSubOqGSSJeOXJ3ZkeLj;_~-pj)h{XsLTQhXwBrPB(9h3SuKh^ zac!R1*r76C>Vx4-Kx=S&Njcy6KLSwR|?L;$ zOyWM&uF%Tt)kP2}VEZ1;Gt(}=qO-)QUvNZqxavTXS^4!}{*Bd^mWE+~OkE^R|92<8 zsLE-mhV)3aOPRm0mzVV372>VLy<2JK{$NoN(p@wBWer1!+f_(nf=@gg6jwzNnH!GZ zqUFq=s0Cp4#65&uKmkjWhn0=yyqT?%iSMintn9H!NN0OSh(4|#S$krbup)mb>dAG! zpbfS~WZb6*c73-8{MYw_wVfxtK@o(<0HQz)A6p{AP$c0veW(u4wSLdsi$NRp7BGb= zTPGGZ{4p5C8r{CmY}X+d_^nciG0j2KMwIT^pW|u9$V}@w0#4siymfd&oiliHe6`J$ zs<5t0;IT~R*p&SA?NY$=u9KAZ+Fc&n=CaR{WcafJymw$_ReC46=aGL>Q2Rn{keN79 z{0eP>s``t#@o#hgH|)9~Sta;;a)K)*+muzGnx;r6$-$`#+_Sr-63JBvohy@FjtSiY^wfAYuWsHv#S=HJoV+3xN; zNm8r>fGjKPUWdN?hyJT8hBbKn!cg18v%8hsQ`O@Ndtn~mo@p`c*nFj&DLSr4X24}InJ)1HEo zCD?}~!m?ykE-?(g&ErmjY0<-5 zmBE=h+k|qe-a+keQnAYD?>UvLa{1Qez>@dYw4mGtbrlI;?kjDDGbeZK6{c`odggF)4zDMmTz_4v_$_3n z;dJ0vxS4y<6TG&7K3Y|d#!3GI+c21|HboER48A6u>7Q`oAIJ>ktgBnTWJckL~k|BSMt-^99-2GBs{6r^6l z?7EzNV*#QKyE`48{TkQ*Z82l^S^@EDjefWUYHcH1Wd^?Ij35zcKOOz=4VSE45_(LF z<=4e9?vgrF?s%us!4TC(&^GRXSnFDtXuoB`PgC$#Q8k75>lG)5JVyLBzlL%#35M~? zk=`+VPk4mn!=kwOd^~82+Y)CV@06Z_&W$e^=S1^&q5ICiMzaGkj$CULtin>B|M2DQ zJ-O2&U*I`f-?dH3F;uq{kv4@T7%?!4q<_lpIAI>F<2Ska)-E{4UC81P0x#5H6pcU;Xoqt zh(?UMn+tbgG|VF%0IEI^??tioId}u5t!7upI>p`JFGoMy)4|T^XkV6aON$L!;tH%X z36nxW+`tldVP*Hs(!eBW%%=Kuyn7OwAN))}MGe{sz1;4dqn@Vrb=K$87_Gk+;j&J! zha0!(ax~t#*#uf^;+j*UyUbjKhXUEa0NvIvGJLPQeXId*c`ODvW5Bv07ayGurcY}b z{nj$v-=5tqHqP?wBFam1`4-8LBSC9KCy)nJ)>$OZ$sHu3YTJ^Qw?7JW8qizm5!Na2 z4&c}C64+<@K&&>f4>}BVXgKI#n{(@Y*2#>%mbC1Iwm3a*sAHi=K)-MRh`i#rO*gdv zbfXl2mRX+XeiZ`G*yMlE(Epijj|`Kd26g5BCbTqY9!kKvS622VdSQ4d$X<{N)HM`1fCDvVEZw80N2 z$mn(B7$p!;zu$XKjkR~I`zwfb2fk*_avseVgkAgS6sF{Nk#`PFcFEk|5UZq2a020h5XUh@I%y-;(qMuhsfzP9 zHhA8}f00**Twm%2=ZOzY8~DE~`5o`yXf{Yz3__7grGp3oxjeqZAmsxz%YvLDhT5faX=;(!xY~u$8z8_)I%JSV8g2aT6J4bG= zzy&zgfN00fISpmUkHDwymnPQ6%rf4=Yl8O|WkqyEFuMdaZ!&^1X9pW%>QLuhLAcYw zv^QUc__Fk-Z768l@Qbo&w>o)u?U?v*yeF>IhUw<9+<)T>=ZY6&n3dY+pKi|;2UQNj z7Eeq(7^lAA)ifnC2X{wbxzQc zoFSbWf0qK9d|H`(`$Zrz{d7ZPK~ag8kF5*R-{3xjO7s$2&uT1p@}ZQsFSdqEa2nuK z3URpAEJ-Two}$4oIf6a*0>^L=r36r)Lek({HvTKO4=qoVPo@J#a5YNF4nd4I07*e$ z*xF-d(G_U#AbRe+AgF?gCw)FnxX40J4hkyFrBpsP{ZJu{AL_~>2FpxJlqCcYzfXN{ zG)C#-jhr!$PvG?EU@dAPx8ERHSQ^keSt7kAY|A&~=WrrHv4}N~_ zBe9UoGg@B&bbek@Ms!GGz{To4=ROHs@yBpp(rJo|m8GXMG~d#lTKdm%_7`yXheo*J zYs4?EeZ3wbm=BVkpUP5sY1xC!Pqyb?vi2B{Q)Q*yUtI$$1s_$fAq=y%s&DVe*6B?M z<(Yt$1vGevR@;6`3EGJ61M-+=A_j9H&eo>3rM@kH24SN|F%1S~sD7R_JJg)0*yCqhr8|R;9Q6=yw6vDJH?s^OKkMO)gUU!SRze0874e^ooCE7{&Eq;5? zmxXS4kkn*pITrNVL%$;l0qsgzZ!gqNw9TWk_|y0B*!~TG%7vbJQ+Ze&Hm@9O{MZuR zni!G5fMRMx*v@0`@+G%(kE@`k3hJ30T4NdaJn0>i5+Jt@wa zjvC?*WU1|EtyqsmX(;ZQry{Dng{*wU>~ zAUcf++e_eRGlxjioGB1vYRPE?e5kAK9f!+)4}A4!mr1xFcq3CDF~FvDhW=4NgHEpK zN#2xEV+w`)-(_u$K}I%}ruNEiH-T3Qa!;v62Kc(@|1ap*8hF4~$Yc08GX-KIMYc#bq(rW3E>KLFWWutfll);Uu4vh(d z#dlME(U-1KEgqai8jbl6AsmCJOZ-HSyWm1#gBYn4-24+&G?wtiif)heaQB_C`RJ$( z4nK8aIpYRbhQd+L`bFTG-5B(l4Iit8jbs7 zPm6eo%s#o18A6~yVJxH6@zo0QTdnD zN_=}ES)qu%m5ZsJY>_*&*YDEzC{ZWGU+P-EWKAFI*Ah$-Qjm1b&y4dBUill`D^ovn zO^At8BDY4Ws-!sD+bu`2acmFcmcyM=&k;IhW8FaR)uKr_-FH7OamITPSgk?c*@deRDbOV1A$?KNs2Wad;TdKI6K6$%-kapzyRy*g!NV8)Zb% zv0KwzXkbA`GjE6-!I&#cIGhpv=5XF7AR5$wsPvno>8oMCs}BYI&BKB%cDRwbEx2jy z+ENhftNH#TQ2p+k(Tn2Bbk2dQE79*4*rvb8W(r(HlWkk0p!qEoD&(GmO;bxKP4&9% z056RQN0Y!oZllneY5M3BrW(&V)HC35!{`;Y)L=r1O67infQzdIvo$e}x03v$cF$Z? z)N|G|cxI6Ihjo;!v+)*hPdfB$08MyeVaWN_qvcGJM4xR{(hQA|IT<&Ws?^&T!ci5_ zY6sjWZs@OkaGG2@-!8TGd~CG&elo-tw4tYJ5R8d0r+e{6Oj8>cr*dNE$m8^p2A zST3NZe$BY`;-7O3uem2%|IFUm=UrBt`I0Zpku>r9X%3nI>>p7(o5;VcG*XlF}Z248dgmDm#2UF4JcvkM$8y`7(LID|loL zM}HOha3NG23Tf0vYKDRRe$Yv3C4?m^^AuZ?&Zwt=`4gSYVy++wv>Ed(m<1A^eqASU z=rHjIb+6(z4Zi+Zd}AODZ3h6G&;xHQTtvh#OId3mucXSb`*hB*&akz# zSBtZErHFf_3!2@YEE_3AVu2@9`w8?aup_kp6&so{POjjTYaZ5N=eQjCWsN;fy_)to zWbY)ov9nW!2|W4`Ua&{k>jz>YAp%);5-Y(U6>z(;mi7Wscdg6D*a|~~rRnRh{G2iV z5nzsf6FRdK2}hfGQzCtJaF+1mHnq8{>QI=ivP3lFiua~Z2sL~s+XJVRNH}haSQ{6N z8c#{HES@v)gBtbzte-i6cymW#=kxMB?4rZ{Kp(Ykcyi?8fz=tT;o^9P(a$Z;bHXs3 z4DJ7|N^i)t+#|SsvQS5|E*P}dp)_oiGxYm&_+Im{MJhsG2f*i^pN1#~u$FlETw?3` zBQit;3}U1zuV%%basXdMAcBR~u#8wSP7Qmw44TuOO1FPsI)fD-h|(6;Q^zOzo?2&C z;Q2Wijt~5^qFpgtB~+ny4+Q_WgFBpHBjDb@zJ?e2mhUL3Oq4)3anO@pH0+rP*61kU z9Crk+OuaW)|BC5mUrk|fcwpzN5h!t;(UV63|MQ-(tcVaZb`Fd}7lg~8_#5|euE|0k zE6QlGadBWStJ4wzngr#38yiX$iyHz`hU81xYp$l1?P%kFFjDtx&;Wq|R#oc}{_hn2 zS6TPR%HTRNNJmKgzwaG@@f}m{Z;$O)rZAFUu%8~|tw8Xp!WLdiu2<-tRzW-`pwI)+ z((X^e^&X+q&oeMOtOsbSR=OFNFTA@7^JLHRa_S_Zu8{i3 zE0NzQNIA%7CD<2kr_D2R1R?aIe_`YhV%ZUmYJ?E$Un(H7Y^uvUI;&!LD>&%Oe--DV zk4j1NUvLPHk_Xh1Disq~+eSzyQq`al(_?9H3h*n!vhRc{9MP6sZP$fyt{@YdaKF!( zz2xj6-NNTI3zJL!P8_MR73#X^k>20oey{xzLD8dQ&nrJ}f1tjjMu{I&;rW<--K?d0 z`0rDG!{iMN&gQTo9i7*JgtO0n=Qp3tf}uc8_fva&ejp2^eKlWnYmyNehzQ(GUl{dl zUN|RAJPg>rlNiegV^K+$6rF}Xe@Vv`vw0MjIfXwtTWBW8&uvheYT?c(|?leyKge-j?K$ZaB8hb-7e_1s5;lRaQl$vmzBu_=$ zJPvUx?TF#e49qbo2?B5~k!;?NTu=xXXZ^d*ltKq~H#}?8mUbvs9+V_s>NiT2)-{HP zy45qE3#VWEO0+HBjzsSPLIm}^as?;z)gdiQb`GVz_gRjap><{%>jFyh1pRjK-ZO`2 z@Ic^FciF_g*N&MwPUzh-jFf%7K*>XC(KYT>fl}!@$R}zA@*zW@oU$4SKjp7$!-%HV z51+j8jMBIv+w-3~n5KUYWEgf0zZ{pbRN>;3?KR*6jF3j5D^M7F>iTa9#LfJCU$iC7 zrU)PfDG>u9iVkH?!~9mIuuB2rC#nMbsYgJvJ9jwF&x&^!Ld!?w>1ZeF3k)H`O?OSC zJ^rBvwJG0K4Ng_MfQt}5a(=^%1(Ox3Cz@CuUX|StlFr(&nt%c&W^YsZ^HXZ_PGPiqcYwVXHVxFsBX5oZwH&w9@>WDB?*tiWyIb7BR+{)f~-ym^xr| zeBko>pH~aGdecvwd%bf1_;ZlvUy3x96rsJvJm*EU+VdJ!+zgsrN~E z*F!)SiMmk>BYf%=mgk*+n6mKQ3b~a(5~q(rk+3}amlRR zo@#52t?LsEbB`$gYIBXP_Nnq)>!_ZZNyggrCADjN8*i-{hSCn`s*M$OZ*JfW{kA=F z)%uLO2TNwxrZsZaRtnvzqgvOx{hYc>7R{|0rhC&$t^!+@&iWRud&5kQ#F2gL<`S*D zM+&#@NNwx-R^^U)rnlw{qis`}%FHRJcYUXxty3CcC&uozxl&K}Hd|w znTt;%Qu$TK+g7`p56d8`JJ&iujitzL-A)-3^wgJy}5Mh2on*VGV1Y9lK4FRv2 z{9!H!X_rN2%FD!xJ^ffUyra#T9z5VJ(%_8L(~^18T)$L3cLx6$hp4z{=t*w!6q4LWAKKv}p>!MsR(Vs7d#FynY}NV@oQofOQxN>=xoY?8<}Z1p;;X z?}4*&f?Y$KJI9>DP|NTjMdPTRoT6-OtgJJl!Fns#>X>YdyjBYqZJFDw<%-06o8*T% zS`>-Ixb4kng&a;+!o$LW`{-mok(L5!aeA{$NTfc=v1foP%_kD zurpd0XoiM3!DLD(ff_J45JoV}fi$tgFhGo0Vovf=mlU2wf>7DFj9C0d{2%9R zhMod7+?z6k^>bv9yBK8XvK^2JboKuR_&I_!Y`ASvcQHkOBcykro(|3(cpMg39m zKJU@{e1jlwMws=Yj7owHl|0Ykm4N3}5@4NUee*APgvs(CU83zUksx6p(I7Ng&(qUr z3rTrGUHI~=`%W;En2-^s*~g@=$yx;mJd*YePOiA{MGH3waoZU$HnS$gRqg4l@^j&H z*H6Pa3Ku$z#pA)%ojT9*am;!>^#@NV>8YQNEmHWJ!RR6v;q8>wXc49qN5JmHBP=6o4C6J`ez>4&W_$4`aG|{IRT-HzW6ue>X-fVDobay~X*9ukwhK8~|?i1<& zVoat2bsB!VXOmWFPM8|G{J>QK+eZq<3 zYQYHWn9Rl$v_%uvvo#aIcyoB;&O$W}1hh5)SEj_V0L#rZqCmvw_h_ShYlLRj3%Qgb zp;}i%@?bRL(28Ee4jKkgeToDChQk&ha=#7bWC7z92w^lnnw*NF1k_TEn&M{R#pjRS z%a_fH=jIK6AFiV}D&~sBx8E3lUaNyR3$&+8Cv;w6CXl}*9#n#|K_K@NSU5C=K|YYc z7s1E9c@VzC*1}AQ5p_b-NAHV(BNM=fu)x6y*7GE0(eeE>KxCxEBz1^q_EJXqrRX$% zD{La{f$^XOPswi*4n!pLWJgJfHfQLQBnZLJWXk+SKW^c z(}@BK`%RiV9ers;LYFTF&@qQmsL7*Uf9u(>AO_ZyFBYqkqRK0)m&}6>!lFP3qd*lA zBN@Y>1q-6(GXo-_g(C-v%@A1r-;^mBDRFQ(1Storh;kwjiM|mOpUNO{n2hojulx?fNn>GY`8s&%QKJVx-exmh<222_ zToob)+4&!@G{0^90tP|l`ii-Fm&J7@o%WC@lv}y8 z^t}a8ahtq<*`3on`~d8f*k3`h#aT{{?))P93y(XM9S=v5(h81~~4`Y%F`n^vV zd3LHZm^J-;zlDtT7}g49wX|QrhigZ*n3-U+*j*UL(0g9FcCrAx zG;uavuDe>e6BCgB$9m)Bw=(sde9ITe0M#zcDaMk1!1)XMEI8o#3Ouup7|b%I_sB;y zszW9Ylrh6>U-&1OSY;rh_whwh2$goPqcoDd$Y;L9Y_kTgR!Uf89O`{BycZDd*zG$tCv^{C>&p_tR{Vz)^G6aE$z?l}) znn(>ck+y`LD90*fe*RXux^&RpEO-CU4{w(B4f>IgiW-j}QW}t@^Zq~y@J)~%*o`tc zIt`Jsdlu-HeIFE>%EZ=I#h@)n+c}w^#2Yeu_S4j?H3mMZfil)I9bSIBXCMO;UWS_> zIqw#^c?s0$BtFJ0zDrIi>)nBHQ(04ZKDY|^%A12r2V2lJG0!Zx9#wr2>tP|sHNz|= zPTz@K^7t&U5-=&HPc$xL@*iWa1>uSo+D?Uf@N_ztn&nTrR_guFjH#ljNQuF@v(t~{a?j_UDS+IqEYiPgjq+NEQYizGa<(9Q2jA!n z8wUv;A~hSMNjW^A2lf!Jm!R;Z)n?bRABc=N8Q~Ieo1I?U^hlX{W6Dbzom4-rME!oe!@Y+dp1aG4Cm%wH&!}~SD0uxZ*_4da9V&DPOKAiMh!fD=tq@DVjSn_IJ-qlvy@`&>Q27=iObJFEKrhV|f57g`f zE&K2x(TZ9Fe-NV$F~~Kr5HU)9;JOd%_QAG&;B_C+?!!&{;BgHV-HW4Qh zz$G2;+-_t)@bH#0r6d#o&lw{CApjr%^il#aq?3*ej|^{2k$+%l7ly;(X%4~=B}!e* zQci&`pWTcTY?&oMl!BDB5xruIBvqJU8wJj(oayo9s5*>DAEO`o1Q&=PjsMdpz(L#; zPpX66=cEV4L(ZgO+GoOK(P2Y}dz+%Q}8A?*UjTI9S1cQFHXV{*N=Y-_A? z1RTmL`_$2r(FTYnmw>B%u-k|3J|y1<%03Y81N42s?0*C5KG5F>&ORXS1N}Y_>;pjV zLvj>n?M##kR>tRX?{M~37ioIeVnfwE9MIVh*&{gMi)U2c8*;mm43{dj;Q9UsmHm|B zn;{?166z2vm8rYdFud9hzcLa3!hjkOJ;mbtsn|Nku$MeP8FpLGDo7Gd@aJm@=y2gu zCeeiEtbdM>34JzlCR$~SEh$xz26FO%>?JaSoE#n#Jl6vuF7vH<^2!5sn7|5y0VEH7 z^kU+jb0CB{UbW&c@nDJzI=an^%iFevZz&th2p2FrLZ?n*eFD3D@SR6~e5wkw^Eklw zt4C_G8K}>j18j0Wt%?NI&Lfu)OxOZVBw)EY<$q_}Ci`LZ2C23p%jrj)7N+gpnH-!7Q&BU#O zT$G%CoYF%%NP)H<_jD-`?7t-0p~NRb>vZKjG3oD@lc@A=@k+WWBqyrwP_?!!7KLL6ai^M9OwXOzzVi7r0V#YXiE%A}|<8GdF^)TazN zb57K$a^0LNu&a|QWHeWAMP0H)r#`-@bBGi3a{kPd}edesB45I(F|X7H?Sm z7GQmV!kM1aCTWsj1HuSTW6Q@~+V)#!+dSZtyZzSM0}mRZPa&q!%8*jZjB{+tnSY1% zYa;0>)huoB+O!1tS2oVTlJ=Q+4Wr1qLSK&gk1A zFSb$-U8SL_5#gKvsKat$2CZ~`_SJ$^lTq`*@yk@L(lf1mwo7OA572TF#ph-&Gw;}edteI6|w=d3P~aY L0^zB%E=yhZ-OmuN delta 18781 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 W++-9XhNd@WKNx6}CLgxo`~L$%r#f8# delta 11332 zcmXw;Wl){L(yehe?iyqx8wl#llwY_jEJH*+Nn4Rt6i`6998$BD0!EYfIu0T=qdD zoSAXz*v}RbT{O8VwsHRlr~kVu`X40!4?_M2?*9Xe|AEH;;NbsSNR%}GR)AuiRbjR? z=?kpRNPjY(nFUG&OLpJ=Y;5e!O$sWZ?L??+YXbs9!{L!+0-!NaEOw!x%>sjlgwWA2 z1{rl`159H2DKj1HorWZS`l!AM3#>5`!a$=SJ(0Wxd8PHh}B#g5vP7IP^@2t zSLP1F3h94V7F8>&#Q}3OifCXbC-x>&;wHn