diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml index 5b152ec6ee7..97614abfb71 100644 --- a/.github/workflows/publish-packages.yml +++ b/.github/workflows/publish-packages.yml @@ -60,7 +60,7 @@ jobs: needs: publish-ppa steps: - name: Wait for PPA package to be published - run: sleep 1.5h + run: sleep 2h - name: Install PPA dependencies run: | sudo apt-get update diff --git a/.github/workflows/sync-supported-chains.yml b/.github/workflows/sync-supported-chains.yml index 6e388dab2ea..ba7333ba0e3 100644 --- a/.github/workflows/sync-supported-chains.yml +++ b/.github/workflows/sync-supported-chains.yml @@ -3,9 +3,13 @@ name: Sync Supported Chains on: workflow_run: workflows: ["Publish Docker image"] - branches: [master, release/*] + branches: [release/*] types: - completed + + schedule: + - cron: "0 0 * * *" + workflow_dispatch: inputs: nethermind_image: diff --git a/src/Nethermind/Directory.Build.props b/src/Nethermind/Directory.Build.props index 9c91f2af9e1..15866e5a1dc 100644 --- a/src/Nethermind/Directory.Build.props +++ b/src/Nethermind/Directory.Build.props @@ -15,7 +15,7 @@ Demerzel Solutions Limited Nethermind $(Commit) - 1.30.0 + 1.31.0 unstable diff --git a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs index fac8ee33244..a6d60dda916 100644 --- a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs +++ b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs @@ -323,7 +323,6 @@ public static IEnumerable Convert(string json) List tests = new(); foreach (KeyValuePair namedTest in testsInFile) { - Console.WriteLine($"Loading {namedTest.Key}\n {namedTest.Value.Post}"); tests.AddRange(Convert(namedTest.Key, namedTest.Value)); } diff --git a/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs b/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs index b646bb29407..cf6136e7d67 100644 --- a/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs +++ b/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs @@ -300,15 +300,15 @@ public static BlockParameter GetBlockParameter(string? value) { case null: case { } empty when string.IsNullOrWhiteSpace(empty): - case { } latest when latest.Equals("latest", StringComparison.InvariantCultureIgnoreCase): + case { } latest when latest.Equals("latest", StringComparison.OrdinalIgnoreCase): return BlockParameter.Latest; - case { } earliest when earliest.Equals("earliest", StringComparison.InvariantCultureIgnoreCase): + case { } earliest when earliest.Equals("earliest", StringComparison.OrdinalIgnoreCase): return BlockParameter.Earliest; - case { } pending when pending.Equals("pending", StringComparison.InvariantCultureIgnoreCase): + case { } pending when pending.Equals("pending", StringComparison.OrdinalIgnoreCase): return BlockParameter.Pending; - case { } finalized when finalized.Equals("finalized", StringComparison.InvariantCultureIgnoreCase): + case { } finalized when finalized.Equals("finalized", StringComparison.OrdinalIgnoreCase): return BlockParameter.Finalized; - case { } safe when safe.Equals("safe", StringComparison.InvariantCultureIgnoreCase): + case { } safe when safe.Equals("safe", StringComparison.OrdinalIgnoreCase): return BlockParameter.Safe; case { Length: 66 } hash when hash.StartsWith("0x"): return new BlockParameter(new Hash256(hash)); diff --git a/src/Nethermind/Nethermind.Config/ConfigProvider.cs b/src/Nethermind/Nethermind.Config/ConfigProvider.cs index ce5b5100184..d9459720657 100644 --- a/src/Nethermind/Nethermind.Config/ConfigProvider.cs +++ b/src/Nethermind/Nethermind.Config/ConfigProvider.cs @@ -53,7 +53,7 @@ public object GetRawValue(string category, string name) return Categories.TryGetValue(category, out object value) ? value.GetType() .GetProperties(BindingFlags.Instance | BindingFlags.Public) - .SingleOrDefault(p => string.Equals(p.Name, name, StringComparison.InvariantCultureIgnoreCase)) + .SingleOrDefault(p => string.Equals(p.Name, name, StringComparison.OrdinalIgnoreCase)) ?.GetValue(value) : null; } diff --git a/src/Nethermind/Nethermind.Config/ConfigSourceHelper.cs b/src/Nethermind/Nethermind.Config/ConfigSourceHelper.cs index 462e5ca74fa..5edfede868b 100644 --- a/src/Nethermind/Nethermind.Config/ConfigSourceHelper.cs +++ b/src/Nethermind/Nethermind.Config/ConfigSourceHelper.cs @@ -99,7 +99,7 @@ public static object ParseValue(Type valueType, string valueString, string categ } private static bool IsNullString(string valueString) => - string.IsNullOrEmpty(valueString) || valueString.Equals("null", StringComparison.InvariantCultureIgnoreCase); + string.IsNullOrEmpty(valueString) || valueString.Equals("null", StringComparison.OrdinalIgnoreCase); public static object GetDefault(Type type) => type.IsValueType ? (false, Activator.CreateInstance(type)) : (false, null); diff --git a/src/Nethermind/Nethermind.Consensus.Ethash/Ethash.cs b/src/Nethermind/Nethermind.Consensus.Ethash/Ethash.cs index ad57e69a64a..1ab94f174a8 100644 --- a/src/Nethermind/Nethermind.Consensus.Ethash/Ethash.cs +++ b/src/Nethermind/Nethermind.Consensus.Ethash/Ethash.cs @@ -247,7 +247,15 @@ private IEthashDataSet BuildCache(uint epoch) _cacheStopwatch.Restart(); IEthashDataSet dataSet = new EthashCache(cacheSize, seed.Bytes); _cacheStopwatch.Stop(); - if (_logger.IsInfo) _logger.Info($"Cache for epoch {epoch} with size {cacheSize} and seed {seed.Bytes.ToHexString()} built in {_cacheStopwatch.ElapsedMilliseconds}ms"); + if (_logger.IsInfo) + { + var seedText = seed.Bytes.ToHexString(withZeroX: true); + if (seedText.Length > 17) + { + seedText = $"{seedText[..8]}...{seedText[^6..]}"; + } + _logger.Info($"Cache for epoch {epoch} with size {cacheSize} and seed {seedText} built in {_cacheStopwatch.ElapsedMilliseconds}ms"); + } return dataSet; } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockExtensions.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockExtensions.cs index a0287bb1d0f..bf3e081e048 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockExtensions.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockExtensions.cs @@ -40,7 +40,7 @@ public static bool TrySetTransactions(this Block block, Transaction[] transactio public static bool IsByNethermindNode(this BlockHeader block) => Ascii.IsValid(block.ExtraData) && Encoding.ASCII.GetString(block.ExtraData ?? []) - .Contains(BlocksConfig.DefaultExtraData, StringComparison.InvariantCultureIgnoreCase); + .Contains(BlocksConfig.DefaultExtraData, StringComparison.OrdinalIgnoreCase); public static string ParsedExtraData(this Block block) { diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs index b302da9177e..afca3e291db 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs @@ -2,11 +2,11 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; +using System.Threading.Channels; using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Blockchain.Find; @@ -14,6 +14,7 @@ using Nethermind.Core.Attributes; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Core.Threading; using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Evm.Tracing.ParityStyle; @@ -27,10 +28,10 @@ namespace Nethermind.Consensus.Processing; public sealed class BlockchainProcessor : IBlockchainProcessor, IBlockProcessingQueue { public int SoftMaxRecoveryQueueSizeInTx = 10000; // adjust based on tx or gas - public const int MaxProcessingQueueSize = 2000; // adjust based on tx or gas + public const int MaxProcessingQueueSize = 2048; // adjust based on tx or gas - [ThreadStatic] private static bool _isMainProcessingThread; - public static bool IsMainProcessingThread => _isMainProcessingThread; + private static AsyncLocal _isMainProcessingThread = new(); + public static bool IsMainProcessingThread => _isMainProcessingThread.Value; public bool IsMainProcessor { get; init; } public ITracerBag Tracers => _compositeBlockTracer; @@ -42,10 +43,10 @@ public sealed class BlockchainProcessor : IBlockchainProcessor, IBlockProcessing private readonly IBlockTree _blockTree; private readonly ILogger _logger; - private readonly BlockingCollection _recoveryQueue = new(new ConcurrentQueue()); + private readonly Channel _recoveryQueue = Channel.CreateUnbounded(); + private bool _recoveryComplete = false; - private readonly BlockingCollection _blockQueue = new(new ConcurrentQueue(), - MaxProcessingQueueSize); + private readonly Channel _blockQueue = Channel.CreateBounded(MaxProcessingQueueSize); private int _queueCount; @@ -122,19 +123,19 @@ public void Enqueue(Block block, ProcessingOptions processingOptions) ? new BlockRef(blockHash, processingOptions) : new BlockRef(block, processingOptions); - if (!_recoveryQueue.IsAddingCompleted) + if (!_recoveryComplete) { Interlocked.Increment(ref _queueCount); try { - _recoveryQueue.Add(blockRef); + _recoveryQueue.Writer.TryWrite(blockRef); if (_logger.IsTrace) _logger.Trace($"A new block {block.ToString(Block.Format.Short)} enqueued for processing."); } catch (Exception e) { Interlocked.Decrement(ref _queueCount); BlockRemoved?.Invoke(this, new BlockRemovedEventArgs(blockHash, ProcessingResult.QueueException, e)); - if (e is not InvalidOperationException || !_recoveryQueue.IsAddingCompleted) + if (e is not InvalidOperationException || !_recoveryComplete) { throw; } @@ -151,59 +152,42 @@ public void Start() public async Task StopAsync(bool processRemainingBlocks = false) { + _recoveryComplete = true; if (processRemainingBlocks) { - _recoveryQueue.CompleteAdding(); + _recoveryQueue.Writer.TryComplete(); await (_recoveryTask ?? Task.CompletedTask); - _blockQueue.CompleteAdding(); + _blockQueue.Writer.TryComplete(); } else { _loopCancellationSource?.Cancel(); - _recoveryQueue.CompleteAdding(); - _blockQueue.CompleteAdding(); + _recoveryQueue.Writer.TryComplete(); + _blockQueue.Writer.TryComplete(); } await Task.WhenAll(_recoveryTask ?? Task.CompletedTask, _processorTask ?? Task.CompletedTask); if (_logger.IsInfo) _logger.Info("Blockchain Processor shutdown complete.. please wait for all components to close"); } - private Task RunRecovery() + private async Task RunRecovery() { - TaskCompletionSource tcs = new(); - - Thread thread = new(() => + try { - try - { - RunRecoveryLoop(); - if (_logger.IsDebug) _logger.Debug("Sender address recovery complete."); - } - catch (OperationCanceledException) - { - if (_logger.IsDebug) _logger.Debug("Sender address recovery stopped."); - } - catch (Exception ex) - { - if (_logger.IsError) _logger.Error("Sender address recovery encountered an exception.", ex); - } - finally - { - tcs.SetResult(); - } - }) + await RunRecoveryLoop(); + if (_logger.IsDebug) _logger.Debug("Sender address recovery complete."); + } + catch (OperationCanceledException) { - IsBackground = true, - Name = "Block Recovery", - // Boost priority to make sure we process blocks as fast as possible - Priority = ThreadPriority.AboveNormal, - }; - thread.Start(); - - return tcs.Task; + if (_logger.IsDebug) _logger.Debug("Sender address recovery stopped."); + } + catch (Exception ex) + { + if (_logger.IsError) _logger.Error("Sender address recovery encountered an exception.", ex); + } } - private void RunRecoveryLoop() + private async Task RunRecoveryLoop() { void DecrementQueue(Hash256 blockHash, ProcessingResult processingResult, Exception? exception = null) { @@ -212,9 +196,9 @@ void DecrementQueue(Hash256 blockHash, ProcessingResult processingResult, Except FireProcessingQueueEmpty(); } - if (_logger.IsDebug) _logger.Debug($"Starting recovery loop - {_blockQueue.Count} blocks waiting in the queue."); + if (_logger.IsDebug) _logger.Debug($"Starting recovery loop - {_blockQueue.Reader.Count} blocks waiting in the queue."); _lastProcessedBlock = DateTime.UtcNow; - foreach (BlockRef blockRef in _recoveryQueue.GetConsumingEnumerable(_loopCancellationSource.Token)) + await foreach (BlockRef blockRef in _recoveryQueue.Reader.ReadAllAsync(_loopCancellationSource.Token)) { try { @@ -226,9 +210,9 @@ void DecrementQueue(Hash256 blockHash, ProcessingResult processingResult, Except try { - _blockQueue.Add(blockRef); + await _blockQueue.Writer.WriteAsync(blockRef); } - catch (Exception e) + catch (Exception e) when (e is not OperationCanceledException) { DecrementQueue(blockRef.BlockHash, ProcessingResult.QueueException, e); @@ -255,54 +239,37 @@ void DecrementQueue(Hash256 blockHash, ProcessingResult processingResult, Except } } - private Task RunProcessing() + private async Task RunProcessing() { - TaskCompletionSource tcs = new(); + _isMainProcessingThread.Value = IsMainProcessor; - Thread thread = new(() => + try { - _isMainProcessingThread = IsMainProcessor; - - try - { - RunProcessingLoop(); - if (_logger.IsDebug) _logger.Debug($"{nameof(BlockchainProcessor)} complete."); - } - catch (OperationCanceledException) - { - if (_logger.IsDebug) _logger.Debug($"{nameof(BlockchainProcessor)} stopped."); - } - catch (Exception ex) - { - if (_logger.IsError) _logger.Error($"{nameof(BlockchainProcessor)} encountered an exception.", ex); - } - finally - { - tcs.SetResult(); - } - }) + await RunProcessingLoop(); + if (_logger.IsDebug) _logger.Debug($"{nameof(BlockchainProcessor)} complete."); + } + catch (OperationCanceledException) { - IsBackground = true, - Name = "Block Processor", - // Boost priority to make sure we process blocks as fast as possible - Priority = ThreadPriority.Highest, - }; - thread.Start(); - - return tcs.Task; + if (_logger.IsDebug) _logger.Debug($"{nameof(BlockchainProcessor)} stopped."); + } + catch (Exception ex) + { + if (_logger.IsError) _logger.Error($"{nameof(BlockchainProcessor)} encountered an exception.", ex); + } } - private void RunProcessingLoop() + private async Task RunProcessingLoop() { - if (_logger.IsDebug) _logger.Debug($"Starting block processor - {_blockQueue.Count} blocks waiting in the queue."); + if (_logger.IsDebug) _logger.Debug($"Starting block processor - {_blockQueue.Reader.Count} blocks waiting in the queue."); FireProcessingQueueEmpty(); GCScheduler.Instance.SwitchOnBackgroundGC(0); - foreach (BlockRef blockRef in _blockQueue.GetConsumingEnumerable(_loopCancellationSource.Token)) + await foreach (BlockRef blockRef in _blockQueue.Reader.ReadAllAsync(_loopCancellationSource.Token)) { + using var handle = Thread.CurrentThread.BoostPriorityHighest(); // Have block, switch off background GC timer - GCScheduler.Instance.SwitchOffBackgroundGC(_blockQueue.Count); + GCScheduler.Instance.SwitchOffBackgroundGC(_blockQueue.Reader.Count); try { @@ -329,7 +296,7 @@ private void RunProcessingLoop() BlockRemoved?.Invoke(this, new BlockRemovedEventArgs(blockRef.BlockHash, ProcessingResult.Success)); } } - catch (Exception exception) + catch (Exception exception) when (exception is not OperationCanceledException) { if (_logger.IsWarn) _logger.Warn($"Processing loop threw an exception. Block: {blockRef}, Exception: {exception}"); BlockRemoved?.Invoke(this, new BlockRemovedEventArgs(blockRef.BlockHash, ProcessingResult.Exception, exception)); @@ -339,10 +306,10 @@ private void RunProcessingLoop() Interlocked.Decrement(ref _queueCount); } - if (_logger.IsTrace) _logger.Trace($"Now {_blockQueue.Count} blocks waiting in the queue."); + if (_logger.IsTrace) _logger.Trace($"Now {_blockQueue.Reader.Count} blocks waiting in the queue."); FireProcessingQueueEmpty(); - GCScheduler.Instance.SwitchOnBackgroundGC(_blockQueue.Count); + GCScheduler.Instance.SwitchOnBackgroundGC(_blockQueue.Reader.Count); } if (_logger.IsInfo) _logger.Info("Block processor queue stopped."); @@ -389,6 +356,9 @@ private void FireProcessingQueueEmpty() return null; } + bool readonlyChain = options.ContainsFlag(ProcessingOptions.ReadOnlyChain); + if (!readonlyChain) _stats.CaptureStartStats(); + ProcessingBranch processingBranch = PrepareProcessingBranch(suggestedBlock, options); PrepareBlocksToProcess(suggestedBlock, options, processingBranch); @@ -412,14 +382,12 @@ private void FireProcessingQueueEmpty() if (_logger.IsDebug) _logger.Debug($"Skipped processing of {suggestedBlock.ToString(Block.Format.FullHashAndNumber)}, last processed is null: {true}, processedBlocks.Length: {processedBlocks.Length}"); } - bool readonlyChain = options.ContainsFlag(ProcessingOptions.ReadOnlyChain); if (!readonlyChain) { long blockProcessingTimeInMicrosecs = _stopwatch.ElapsedMicroseconds(); Metrics.LastBlockProcessingTimeInMs = blockProcessingTimeInMicrosecs / 1000; - Metrics.RecoveryQueueSize = _recoveryQueue.Count; - Metrics.ProcessingQueueSize = _blockQueue.Count; - + Metrics.RecoveryQueueSize = _recoveryQueue.Reader.Count; + Metrics.ProcessingQueueSize = _blockQueue.Reader.Count; _stats.UpdateStats(lastProcessed, processingBranch.Root, blockProcessingTimeInMicrosecs); } @@ -761,8 +729,9 @@ private bool RunSimpleChecksAheadOfProcessing(Block suggestedBlock, ProcessingOp public void Dispose() { - _recoveryQueue.Dispose(); - _blockQueue.Dispose(); + _recoveryComplete = true; + _recoveryQueue.Writer.TryComplete(); + _blockQueue.Writer.TryComplete(); _loopCancellationSource?.Dispose(); _blockTree.NewBestSuggestedBlock -= OnNewBestBlock; _blockTree.NewHeadBlock -= OnNewHeadBlock; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs index 980a4197764..ce7c15307b8 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs @@ -22,32 +22,35 @@ internal class ProcessingStats : IThreadPoolWorkItem private readonly IStateReader _stateReader; private readonly ILogger _logger; private readonly Stopwatch _runStopwatch = new(); + + private Block? _lastBlock; + private Hash256? _lastBranchRoot; + private double _lastTotalMGas; private long _lastBlockNumber; private long _lastElapsedRunningMicroseconds; - private double _lastTotalMGas; private long _lastTotalTx; - private long _lastTotalCalls; - private long _lastTotalEmptyCalls; - private long _lastTotalSLoad; - private long _lastTotalSStore; - private long _lastSelfDestructs; + private long _runningMicroseconds; + private long _runMicroseconds; private long _chunkProcessingMicroseconds; - private long _lastTotalCreates; + private long _currentReportMs; private long _lastReportMs; + + private long _lastCallOps; + private long _currentCallOps; + private long _lastEmptyCalls; + private long _currentEmptyCalls; + private long _lastSLoadOps; + private long _currentSLoadOps; + private long _lastSStoreOps; + private long _currentSStoreOps; + private long _lastSelfDestructOps; + private long _currentSelfDestructOps; + private long _lastCreateOps; + private long _currentCreatesOps; private long _lastContractsAnalyzed; + private long _currentContractsAnalyzed; private long _lastCachedContractsUsed; - private long _runningMicroseconds; - private long _runMicroseconds; - private long _reportMs; - private Block? _lastBlock; - private Hash256? _lastBranchRoot; - private long _sloadOpcodeProcessing; - private long _sstoreOpcodeProcessing; - private long _callsProcessing; - private long _emptyCallsProcessing; - private long _codeDbCacheProcessing; - private long _contractAnalysedProcessing; - private long _createsProcessing; + private long _currentCachedContractsUsed; public ProcessingStats(IStateReader stateReader, ILogger logger) { @@ -61,6 +64,18 @@ public ProcessingStats(IStateReader stateReader, ILogger logger) #endif } + public void CaptureStartStats() + { + _lastSLoadOps = Evm.Metrics.ThreadLocalSLoadOpcode; + _lastSStoreOps = Evm.Metrics.ThreadLocalSStoreOpcode; + _lastCallOps = Evm.Metrics.ThreadLocalCalls; + _lastEmptyCalls = Evm.Metrics.ThreadLocalEmptyCalls; + _lastCachedContractsUsed = Db.Metrics.ThreadLocalCodeDbCache; + _lastContractsAnalyzed = Evm.Metrics.ThreadLocalContractsAnalysed; + _lastCreateOps = Evm.Metrics.ThreadLocalCreates; + _lastSelfDestructOps = Evm.Metrics.ThreadLocalSelfDestructs; + } + public void UpdateStats(Block? block, Hash256 branchRoot, long blockProcessingTimeInMicros) { if (block is null) return; @@ -85,19 +100,20 @@ public void UpdateStats(Block? block, Hash256 branchRoot, long blockProcessingTi _runningMicroseconds = _runStopwatch.ElapsedMicroseconds(); _runMicroseconds = (_runningMicroseconds - _lastElapsedRunningMicroseconds); - long reportMs = _reportMs = Environment.TickCount64; + long reportMs = _currentReportMs = Environment.TickCount64; if (reportMs - _lastReportMs > 1000 || _logger.IsDebug) { - _lastReportMs = _reportMs; + _lastReportMs = _currentReportMs; _lastBlock = block; _lastBranchRoot = branchRoot; - _sloadOpcodeProcessing = Evm.Metrics.ThreadLocalSLoadOpcode; - _sstoreOpcodeProcessing = Evm.Metrics.ThreadLocalSStoreOpcode; - _callsProcessing = Evm.Metrics.ThreadLocalCalls; - _emptyCallsProcessing = Evm.Metrics.ThreadLocalEmptyCalls; - _codeDbCacheProcessing = Db.Metrics.ThreadLocalCodeDbCache; - _contractAnalysedProcessing = Evm.Metrics.ThreadLocalContractsAnalysed; - _createsProcessing = Evm.Metrics.ThreadLocalCreates; + _currentSLoadOps = Evm.Metrics.ThreadLocalSLoadOpcode; + _currentSStoreOps = Evm.Metrics.ThreadLocalSStoreOpcode; + _currentCallOps = Evm.Metrics.ThreadLocalCalls; + _currentEmptyCalls = Evm.Metrics.ThreadLocalEmptyCalls; + _currentCachedContractsUsed = Db.Metrics.ThreadLocalCodeDbCache; + _currentContractsAnalyzed = Evm.Metrics.ThreadLocalContractsAnalysed; + _currentCreatesOps = Evm.Metrics.ThreadLocalCreates; + _currentSelfDestructOps = Evm.Metrics.ThreadLocalSelfDestructs; GenerateReport(); } } @@ -160,8 +176,6 @@ void Execute() if (_logger.IsError) _logger.Error("Error when calculating block rewards", ex); } - long currentSelfDestructs = Evm.Metrics.SelfDestructs; - long chunkBlocks = Metrics.Blocks - _lastBlockNumber; double chunkMicroseconds = _chunkProcessingMicroseconds; @@ -184,13 +198,13 @@ void Execute() if (_logger.IsInfo) { long chunkTx = Metrics.Transactions - _lastTotalTx; - long chunkCalls = _callsProcessing - _lastTotalCalls; - long chunkEmptyCalls = _emptyCallsProcessing - _lastTotalEmptyCalls; - long chunkCreates = _createsProcessing - _lastTotalCreates; - long chunkSload = _sloadOpcodeProcessing - _lastTotalSLoad; - long chunkSstore = _sstoreOpcodeProcessing - _lastTotalSStore; - long contractsAnalysed = _contractAnalysedProcessing - _lastContractsAnalyzed; - long cachedContractsUsed = _codeDbCacheProcessing - _lastCachedContractsUsed; + long chunkCalls = _currentCallOps - _lastCallOps; + long chunkEmptyCalls = _currentEmptyCalls - _lastEmptyCalls; + long chunkCreates = _currentCreatesOps - _lastCreateOps; + long chunkSload = _currentSLoadOps - _lastSLoadOps; + long chunkSstore = _currentSStoreOps - _lastSStoreOps; + long contractsAnalysed = _currentContractsAnalyzed - _lastContractsAnalyzed; + long cachedContractsUsed = _currentCachedContractsUsed - _lastCachedContractsUsed; double txps = chunkMicroseconds == 0 ? -1 : chunkTx / chunkMicroseconds * 1_000_000.0; double bps = chunkMicroseconds == 0 ? -1 : chunkBlocks / chunkMicroseconds * 1_000_000.0; double chunkMs = (chunkMicroseconds == 0 ? -1 : chunkMicroseconds / 1000.0); @@ -271,7 +285,7 @@ void Execute() var recoveryQueue = Metrics.RecoveryQueueSize; var processingQueue = Metrics.ProcessingQueueSize; - _logger.Info($" Block{(chunkBlocks > 1 ? $"s x{chunkBlocks,-9:N0} " : $"{(isMev ? " mev" : " ")} {rewards.ToDecimal(null) / weiToEth,5:N4}{BlocksConfig.GasTokenTicker,4}")}{(chunkBlocks == 1 ? mgasColor : "")} {chunkMGas,7:F2}{resetColor} MGas | {chunkTx,8:N0} txs | calls {callsColor}{chunkCalls,6:N0}{resetColor} {darkGreyText}({chunkEmptyCalls,3:N0}){resetColor} | sload {chunkSload,7:N0} | sstore {sstoreColor}{chunkSstore,6:N0}{resetColor} | create {createsColor}{chunkCreates,3:N0}{resetColor}{(currentSelfDestructs - _lastSelfDestructs > 0 ? $"{darkGreyText}({-(currentSelfDestructs - _lastSelfDestructs),3:N0}){resetColor}" : "")}"); + _logger.Info($" Block{(chunkBlocks > 1 ? $"s x{chunkBlocks,-9:N0} " : $"{(isMev ? " mev" : " ")} {rewards.ToDecimal(null) / weiToEth,5:N4}{BlocksConfig.GasTokenTicker,4}")}{(chunkBlocks == 1 ? mgasColor : "")} {chunkMGas,7:F2}{resetColor} MGas | {chunkTx,8:N0} txs | calls {callsColor}{chunkCalls,6:N0}{resetColor} {darkGreyText}({chunkEmptyCalls,3:N0}){resetColor} | sload {chunkSload,7:N0} | sstore {sstoreColor}{chunkSstore,6:N0}{resetColor} | create {createsColor}{chunkCreates,3:N0}{resetColor}{(_currentSelfDestructOps - _lastSelfDestructOps > 0 ? $"{darkGreyText}({-(_currentSelfDestructOps - _lastSelfDestructOps),3:N0}){resetColor}" : "")}"); if (recoveryQueue > 0 || processingQueue > 0) { _logger.Info($" Block throughput {mgasPerSecondColor}{mgasPerSecond,11:F2}{resetColor} MGas/s{(mgasPerSecond > 1000 ? "🔥" : " ")}| {txps,10:N1} tps | {bps,7:F2} Blk/s | recover {recoveryQueue,5:N0} | process {processingQueue,5:N0}"); @@ -282,18 +296,10 @@ void Execute() } } - _lastCachedContractsUsed = _codeDbCacheProcessing; - _lastContractsAnalyzed = _contractAnalysedProcessing; _lastBlockNumber = Metrics.Blocks; _lastTotalMGas = Metrics.Mgas; _lastElapsedRunningMicroseconds = _runningMicroseconds; _lastTotalTx = Metrics.Transactions; - _lastTotalCalls = _callsProcessing; - _lastTotalEmptyCalls = _emptyCallsProcessing; - _lastTotalCreates = _createsProcessing; - _lastTotalSLoad = _sloadOpcodeProcessing; - _lastTotalSStore = _sstoreOpcodeProcessing; - _lastSelfDestructs = currentSelfDestructs; _chunkProcessingMicroseconds = 0; } diff --git a/src/Nethermind/Nethermind.Core/Eip7702Constants.cs b/src/Nethermind/Nethermind.Core/Eip7702Constants.cs index 53c4ce355ea..cdef95be066 100644 --- a/src/Nethermind/Nethermind.Core/Eip7702Constants.cs +++ b/src/Nethermind/Nethermind.Core/Eip7702Constants.cs @@ -1,15 +1,24 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core.Crypto; using System; namespace Nethermind.Core; public static class Eip7702Constants { + private readonly static byte[] _delegationHeader = [0xef, 0x01, 0x00]; public const byte Magic = 0x05; - public static ReadOnlySpan DelegationHeader => [0xef, 0x01, 0x00]; + public static ReadOnlySpan DelegationHeader => _delegationHeader.AsSpan(); + /// + /// Any code reading operation will only act on the first two bytes of the header + /// + public static ReadOnlyMemory FirstTwoBytesOfHeader => _delegationHeader.AsMemory(0, 2); + private static readonly int HeaderLength = DelegationHeader.Length; public static bool IsDelegatedCode(ReadOnlySpan code) => code.Length == HeaderLength + Address.Size && DelegationHeader.SequenceEqual(code[..DelegationHeader.Length]); + + public static readonly Hash256 HashOfDelegationCode = Keccak.Compute(FirstTwoBytesOfHeader.Span); } diff --git a/src/Nethermind/Nethermind.Core/Threading/ThreadExtensions.cs b/src/Nethermind/Nethermind.Core/Threading/ThreadExtensions.cs index 002c6dadbe5..4206df64442 100644 --- a/src/Nethermind/Nethermind.Core/Threading/ThreadExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Threading/ThreadExtensions.cs @@ -13,11 +13,11 @@ public static class ThreadExtensions private readonly Thread? _thread; private readonly ThreadPriority _previousPriority; - internal Disposable(Thread thread) + internal Disposable(Thread thread, ThreadPriority priority = ThreadPriority.AboveNormal) { _thread = thread; _previousPriority = thread.Priority; - thread.Priority = ThreadPriority.AboveNormal; + thread.Priority = priority; } public void Dispose() @@ -33,4 +33,9 @@ public static Disposable BoostPriority(this Thread thread) { return new Disposable(thread); } + + public static Disposable BoostPriorityHighest(this Thread thread) + { + return new Disposable(thread, ThreadPriority.Highest); + } } diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip7702Tests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip7702Tests.cs index 15af8d38b30..e5d19fbf2eb 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip7702Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip7702Tests.cs @@ -490,32 +490,19 @@ public void Execute_FirstTxHasAuthorizedCodeThatIncrementsAndSecondDoesNot_Stora public static IEnumerable OpcodesWithEXT() { - //EXTCODESIZE should return the size of the delegated code + //EXTCODESIZE should return the size of the two bytes of the delegation header yield return new object[] { Prepare.EvmCode .PushData(TestItem.AddressA) .Op(Instruction.EXTCODESIZE) .Op(Instruction.PUSH0) - .Op(Instruction.SSTORE) - .Done, - new byte[]{ 2 + 22 } }; - //EXTCODEHASH should return the HASH of the delegated code - yield return new object[] { - Prepare.EvmCode - .PushData(TestItem.AddressA) - .Op(Instruction.EXTCODEHASH) + .Op(Instruction.MSTORE8) + .PushData(1) .Op(Instruction.PUSH0) - .Op(Instruction.SSTORE) + .Op(Instruction.RETURN) .Done, - Keccak.Compute( - Prepare.EvmCode - .PushData(TestItem.AddressA) - .Op(Instruction.EXTCODEHASH) - .Op(Instruction.PUSH0) - .Op(Instruction.SSTORE) - .Done).Bytes.ToArray() - }; - //EXTCOPYCODE should copy the delegated code + new byte[]{ 2 } }; + //EXTCOPYCODE should copy only the first two bytes of the delegation header byte[] code = Prepare.EvmCode .PushData(TestItem.AddressA) .Op(Instruction.DUP1) @@ -524,16 +511,14 @@ public static IEnumerable OpcodesWithEXT() .Op(Instruction.PUSH0) .Op(Instruction.DUP4) .Op(Instruction.EXTCODECOPY) + .PushData(2) .Op(Instruction.PUSH0) - .Op(Instruction.MLOAD) - .Op(Instruction.PUSH0) - .Op(Instruction.SSTORE) - .Op(Instruction.STOP) + .Op(Instruction.RETURN) .Done; yield return new object[] { code, - code + Eip7702Constants.FirstTwoBytesOfHeader.ToArray() }; } [TestCaseSource(nameof(OpcodesWithEXT))] @@ -561,58 +546,59 @@ public void Execute_DelegatedCodeUsesEXTOPCODES_StoresExpectedValue(byte[] code, .WithTimestamp(MainnetSpecProvider.PragueBlockTimestamp) .WithTransactions(tx) .WithGasLimit(10000000).TestObject; - _ = _transactionProcessor.Execute(tx, block.Header, NullTxTracer.Instance); - Assert.That(_stateProvider.Get(new StorageCell(signer.Address, 0)).ToArray(), Is.EquivalentTo(expectedValue)); + CallOutputTracer callOutputTracer = new(); + _ = _transactionProcessor.Execute(tx, block.Header, callOutputTracer); + + Assert.That(callOutputTracer.ReturnValue.ToArray(), Is.EquivalentTo(expectedValue)); } public static IEnumerable EXTCODEHASHAccountSetup() { yield return new object[] { - (IWorldState state, Address account) => + (IWorldState state, Address account, Address target) => { //Account does not exists }, - true }; - yield return new object[] { - (IWorldState state, Address account) => - { - //Account is empty - state.CreateAccount(account, 0); - }, - true}; + new byte[] { 0x0 } + }; yield return new object[] { - (IWorldState state, Address account) => + (IWorldState state, Address account, Address target) => { - //Account has balance - state.CreateAccount(account, 1); + //Account is delegated + byte[] code = [.. Eip7702Constants.DelegationHeader, .. target.Bytes]; + state.CreateAccountIfNotExists(account, 0); + state.InsertCode(account, ValueKeccak.Compute(code), code, Prague.Instance); + }, - false}; + Eip7702Constants.HashOfDelegationCode.BytesToArray() + }; yield return new object[] { - (IWorldState state, Address account) => + (IWorldState state, Address account, Address target) => { - //Account has nonce - state.CreateAccount(account, 0, 1); + //Account exists but is not delegated + state.CreateAccountIfNotExists(account, 1); }, - false}; - + Keccak.OfAnEmptyString.ValueHash256.ToByteArray() + }; yield return new object[] { - (IWorldState state, Address account) => + (IWorldState state, Address account, Address target) => { - //Account has code - state.CreateAccount(account, 0); - state.InsertCode(account, Prepare.EvmCode.RETURN().Done, Prague.Instance); + //Account is dead + state.CreateAccountIfNotExists(account, 0); }, - false}; + new byte[] { 0x0 } + }; } + [TestCaseSource(nameof(EXTCODEHASHAccountSetup))] - public void Execute_CodeSavesEXTCODEHASHWithDifferentAccountSetup_SavesZeroIfAccountDoesNotExistsOrIsEmpty(Action setupAccount, bool expectZero) + public void Execute_CodeSavesEXTCODEHASHWhenAccountIsDelegatedOrNot_SavesExpectedValue(Action setupAccount, byte[] expected) { PrivateKey signer = TestItem.PrivateKeyA; PrivateKey sender = TestItem.PrivateKeyB; Address codeSource = TestItem.AddressC; Address target = TestItem.AddressD; - setupAccount(_stateProvider, target); + setupAccount(_stateProvider, signer.Address, target); _stateProvider.CreateAccount(sender.Address, 1.Ether()); @@ -624,7 +610,6 @@ public void Execute_CodeSavesEXTCODEHASHWithDifferentAccountSetup_SavesZeroIfAcc .Done; DeployCode(codeSource, code); - DeployCode(signer.Address, [.. Eip7702Constants.DelegationHeader, .. target.Bytes]); _stateProvider.Commit(Prague.Instance, true); @@ -639,7 +624,8 @@ public void Execute_CodeSavesEXTCODEHASHWithDifferentAccountSetup_SavesZeroIfAcc .WithGasLimit(10000000).TestObject; _ = _transactionProcessor.Execute(tx, block.Header, NullTxTracer.Instance); - Assert.That(new UInt256(_stateProvider.Get(new StorageCell(codeSource, 0))), expectZero ? Is.EqualTo((UInt256)0) : Is.Not.EqualTo((UInt256)0)); + ReadOnlySpan actual = _stateProvider.Get(new StorageCell(codeSource, 0)); + Assert.That(actual.ToArray(), Is.EquivalentTo(expected)); } public static IEnumerable CountsAsAccessedCases() @@ -793,6 +779,53 @@ public void Execute_SetNormalDelegationAndThenSetDelegationWithZeroAddress_Accou Assert.That(_stateProvider.HasCode(authority.Address), Is.False); } + [TestCase(true)] + [TestCase(false)] + public void Execute_EXTCODESIZEOnDelegatedThatTriggersOptimization_ReturnsZeroIfDelegated(bool isDelegated) + { + PrivateKey signer = TestItem.PrivateKeyA; + PrivateKey sender = TestItem.PrivateKeyB; + Address codeSource = TestItem.AddressC; + + _stateProvider.CreateAccount(sender.Address, 1.Ether()); + + byte[] code = Prepare.EvmCode + .Op(Instruction.PUSH0) + .PushData(signer.Address) + .Op(Instruction.EXTCODESIZE) + .Op(Instruction.EQ) + .Op(Instruction.PUSH0) + .Op(Instruction.MSTORE8) + .PushData(1) + .Op(Instruction.PUSH0) + .Op(Instruction.RETURN) + .Done; + + DeployCode(codeSource, code); + + if (isDelegated) + { + byte[] delegation = [.. Eip7702Constants.DelegationHeader, .. codeSource.Bytes]; + DeployCode(signer.Address, delegation); + } + + _stateProvider.Commit(Prague.Instance, true); + + Transaction tx = Build.A.Transaction + .WithTo(codeSource) + .WithGasLimit(100_000) + .SignedAndResolved(_ethereumEcdsa, sender, true) + .TestObject; + Block block = Build.A.Block.WithNumber(long.MaxValue) + .WithTimestamp(MainnetSpecProvider.PragueBlockTimestamp) + .WithTransactions(tx) + .WithGasLimit(10000000).TestObject; + CallOutputTracer tracer = new(); + _ = _transactionProcessor.Execute(tx, block.Header, tracer); + + Assert.That(tracer.ReturnValue, Is.EquivalentTo(new byte[] { Convert.ToByte(!isDelegated) })); + } + private void DeployCode(Address codeSource, byte[] code) { _stateProvider.CreateAccountIfNotExists(codeSource, 0); diff --git a/src/Nethermind/Nethermind.Evm/Metrics.cs b/src/Nethermind/Nethermind.Evm/Metrics.cs index 40d0dcbeea3..3dadc87c2a9 100644 --- a/src/Nethermind/Nethermind.Evm/Metrics.cs +++ b/src/Nethermind/Nethermind.Evm/Metrics.cs @@ -16,8 +16,13 @@ public class Metrics [Description("Number of EVM exceptions thrown by contracts.")] public static long EvmExceptions { get; set; } + [CounterMetric] [Description("Number of SELFDESTRUCT calls.")] - public static long SelfDestructs { get; set; } + public static long SelfDestructs => _selfDestructs.GetTotalValue(); + private static readonly ZeroContentionCounter _selfDestructs = new(); + [Description("Number of calls to other contracts on thread.")] + public static long ThreadLocalSelfDestructs => _selfDestructs.ThreadLocalValue; + public static void IncrementSelfDestructs() => _selfDestructs.Increment(); [CounterMetric] [Description("Number of calls to other contracts.")] diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/PairingCheckPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/PairingCheckPrecompile.cs index 6be90e9054a..75cd9167364 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/PairingCheckPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/PairingCheckPrecompile.cs @@ -46,6 +46,7 @@ private PairingCheckPrecompile() { } var acc = GT.One(buf.AsSpan()); GT p = new(buf.AsSpan()[GT.Sz..]); + bool hasInf = false; for (int i = 0; i < inputData.Length / PairSize; i++) { int offset = i * PairSize; @@ -61,6 +62,7 @@ private PairingCheckPrecompile() { } // x == inf || y == inf -> e(x, y) = 1 if (x.IsInf() || y.IsInf()) { + hasInf = true; continue; } @@ -68,7 +70,7 @@ private PairingCheckPrecompile() { } acc.Mul(p); } - bool verified = acc.FinalExp().IsOne(); + bool verified = hasInf || acc.FinalExp().IsOne(); byte[] res = new byte[32]; if (verified) { diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index 2d12fccfef9..c7c32b01ded 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -1347,7 +1347,12 @@ private CallResult ExecuteCode externalCode = txCtx.CodeInfoRepository.GetCachedCodeInfo(_state, address, spec).MachineCode; + Address delegation; + ReadOnlyMemory externalCode = txCtx.CodeInfoRepository.GetCachedCodeInfo(_state, address, spec, out delegation).MachineCode; + if (delegation is not null) + { + externalCode = Eip7702Constants.FirstTwoBytesOfHeader; + } slice = externalCode.SliceWithZeroPadding(b, (int)result); vmState.Memory.Save(in a, in slice); if (typeof(TTracingInstructions) == typeof(IsTracing)) @@ -1905,18 +1910,20 @@ private CallResult ExecuteCode [MethodImpl(MethodImplOptions.NoInlining)] private void InstructionExtCodeSize(Address address, ref EvmStack stack, ICodeInfoRepository codeInfoRepository, IReleaseSpec spec) where TTracingInstructions : struct, IIsTracing { - ReadOnlyMemory accountCode = codeInfoRepository.GetCachedCodeInfo(_state, address, spec).MachineCode; + Address delegation; + ReadOnlyMemory accountCode = codeInfoRepository.GetCachedCodeInfo(_state, address, spec, out delegation).MachineCode; UInt256 result = (UInt256)accountCode.Span.Length; + if (delegation is not null) + { + //If the account has been delegated only the first two bytes of the delegation header counts as size + result = (UInt256)Eip7702Constants.FirstTwoBytesOfHeader.Length; + } stack.PushUInt256(in result); } @@ -2292,7 +2305,7 @@ private static EvmExceptionType InstructionReturn(EvmState vmState, re private EvmExceptionType InstructionSelfDestruct(EvmState vmState, ref EvmStack stack, ref long gasAvailable, IReleaseSpec spec) where TTracing : struct, IIsTracing { - Metrics.SelfDestructs++; + Metrics.IncrementSelfDestructs(); Address inheritor = stack.PopAddress(); if (inheritor is null) return EvmExceptionType.StackUnderflow; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcLocalStats.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcLocalStats.cs index 8365e784e7f..20bfc3a8e3a 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcLocalStats.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcLocalStats.cs @@ -149,8 +149,8 @@ public async Task Orders_alphabetically() await localStats.ReportCall("B", 3, false); MakeTimePass(); await localStats.ReportCall("A", 300, true); - _testLogger.LogList[0].IndexOf("A ", StringComparison.InvariantCulture).Should().BeLessThan(_testLogger.LogList[0].IndexOf("B ", StringComparison.InvariantCulture)); - _testLogger.LogList[0].IndexOf("B ", StringComparison.InvariantCulture).Should().BeLessThan(_testLogger.LogList[0].IndexOf("C ", StringComparison.InvariantCulture)); + _testLogger.LogList[0].IndexOf("A ", StringComparison.Ordinal).Should().BeLessThan(_testLogger.LogList[0].IndexOf("B ", StringComparison.Ordinal)); + _testLogger.LogList[0].IndexOf("B ", StringComparison.Ordinal).Should().BeLessThan(_testLogger.LogList[0].IndexOf("C ", StringComparison.Ordinal)); } private void MakeTimePass(int seconds) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index 34664070484..6021c262061 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -363,6 +363,18 @@ public async Task Eth_get_storage_at_default_block() Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x0000000000000000000000000000000000000000000000000000000000abcdef\",\"id\":67}")); } + [Test] + public async Task Eth_get_storage_at_missing_trie_node() + { + using Context ctx = await Context.Create(); + ctx.Test.StateDb.Clear(); + BlockParameter? blockParameter = null; + BlockHeader? header = ctx.Test.BlockFinder.FindHeader(blockParameter); + string serialized = await ctx.Test.TestEthRpc("eth_getStorageAt", TestItem.AddressA.Bytes.ToHexString(true), "0x1"); + var expected = $"{{\"jsonrpc\":\"2.0\",\"error\":{{\"code\":-32000,\"message\":\"missing trie node {header?.StateRoot} (path ) state {header?.StateRoot} is not available\"}},\"id\":67}}"; + Assert.That(serialized, Is.EqualTo(expected)); + } + [Test] public async Task Eth_get_block_number() { diff --git a/src/Nethermind/Nethermind.JsonRpc/JsonRpcUrl.cs b/src/Nethermind/Nethermind.JsonRpc/JsonRpcUrl.cs index 8d3fb8498bd..f3777012d62 100644 --- a/src/Nethermind/Nethermind.JsonRpc/JsonRpcUrl.cs +++ b/src/Nethermind/Nethermind.JsonRpc/JsonRpcUrl.cs @@ -58,7 +58,7 @@ public static JsonRpcUrl Parse(string packedUrlValue) if (enabledModules.Length == 0) throw new FormatException("Third part must contain at least one module delimited by ';'"); - bool isAuthenticated = enabledModules.Contains(ModuleType.Engine, StringComparison.InvariantCultureIgnoreCase); + bool isAuthenticated = enabledModules.Contains(ModuleType.Engine, StringComparison.OrdinalIgnoreCase); // Check if authentication disabled for this url if (parts.Length == 4) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index 973d739aeab..1a1989f322f 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -33,6 +33,7 @@ using Nethermind.State; using Nethermind.State.Proofs; using Nethermind.Synchronization.ParallelSync; +using Nethermind.Trie; using Nethermind.TxPool; using Nethermind.Wallet; using Block = Nethermind.Core.Block; @@ -178,8 +179,16 @@ public ResultWrapper eth_getStorageAt(Address address, UInt256 positionI } BlockHeader? header = searchResult.Object; - ReadOnlySpan storage = _stateReader.GetStorage(header!.StateRoot!, address, positionIndex); - return ResultWrapper.Success(storage.IsEmpty ? Bytes32.Zero.Unwrap() : storage!.PadLeft(32)); + try + { + ReadOnlySpan storage = _stateReader.GetStorage(header!.StateRoot!, address, positionIndex); + return ResultWrapper.Success(storage.IsEmpty ? Bytes32.Zero.Unwrap() : storage!.PadLeft(32)); + } + catch (MissingTrieNodeException e) + { + var hash = e.TrieNodeException.NodeHash; + return ResultWrapper.Fail($"missing trie node {hash} (path ) state {hash} is not available", ErrorCodes.InvalidInput); + } } public Task> eth_getTransactionCount(Address address, BlockParameter? blockParameter) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/TransactionsOption.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/TransactionsOption.cs index 8dceee0a0c9..63c01c5a3f7 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/TransactionsOption.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/TransactionsOption.cs @@ -42,8 +42,8 @@ public void ReadJson(JsonElement jsonValue, JsonSerializerOptions options) } string? text = jsonValue.GetString(); - bool isTrue = string.Equals(text, bool.TrueString, StringComparison.InvariantCultureIgnoreCase); - bool isFalse = string.Equals(text, bool.FalseString, StringComparison.InvariantCultureIgnoreCase); + bool isTrue = string.Equals(text, bool.TrueString, StringComparison.OrdinalIgnoreCase); + bool isFalse = string.Equals(text, bool.FalseString, StringComparison.OrdinalIgnoreCase); IncludeTransactions = isTrue || isFalse ? isTrue diff --git a/src/Nethermind/Nethermind.KeyStore/FileKeyStore.cs b/src/Nethermind/Nethermind.KeyStore/FileKeyStore.cs index 937fe237588..65b9937fe4b 100644 --- a/src/Nethermind/Nethermind.KeyStore/FileKeyStore.cs +++ b/src/Nethermind/Nethermind.KeyStore/FileKeyStore.cs @@ -71,7 +71,7 @@ public FileKeyStore( _jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer)); _symmetricEncrypter = symmetricEncrypter ?? throw new ArgumentNullException(nameof(symmetricEncrypter)); _cryptoRandom = cryptoRandom ?? throw new ArgumentNullException(nameof(cryptoRandom)); - _keyStoreEncoding = _config.KeyStoreEncoding.Equals("UTF-8", StringComparison.InvariantCultureIgnoreCase) + _keyStoreEncoding = _config.KeyStoreEncoding.Equals("UTF-8", StringComparison.OrdinalIgnoreCase) ? new UTF8Encoding(false) : Encoding.GetEncoding(_config.KeyStoreEncoding); _privateKeyGenerator = new PrivateKeyGenerator(_cryptoRandom); diff --git a/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs b/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs index 9351177bdb1..426736e4d6d 100644 --- a/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs +++ b/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs @@ -20,6 +20,11 @@ public class NLogManager : ILogManager, IDisposable private const string DefaultFileTargetName = "file-async_wrapped"; private const string DefaultFolder = "logs"; + /// + /// The constructor to use when the configuration is not yet initialized. + /// + public NLogManager() { /* Log in temp dir? */ } + public NLogManager(string logFileName, string logDirectory = null, string logRules = null) { Setup(logFileName, logDirectory, logRules); diff --git a/src/Nethermind/Nethermind.Logging/PathUtils.cs b/src/Nethermind/Nethermind.Logging/PathUtils.cs index 9a16cedbfca..564d531032a 100644 --- a/src/Nethermind/Nethermind.Logging/PathUtils.cs +++ b/src/Nethermind/Nethermind.Logging/PathUtils.cs @@ -16,8 +16,8 @@ public static class PathUtils static PathUtils() { Process process = Process.GetCurrentProcess(); - if (process.ProcessName.StartsWith("dotnet", StringComparison.InvariantCultureIgnoreCase) - || process.ProcessName.Equals("ReSharperTestRunner", StringComparison.InvariantCultureIgnoreCase)) + if (process.ProcessName.StartsWith("dotnet", StringComparison.OrdinalIgnoreCase) + || process.ProcessName.Equals("ReSharperTestRunner", StringComparison.OrdinalIgnoreCase)) { ExecutingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs index 49651d8ae49..e0202c101b3 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Blockchain.Synchronization; @@ -12,6 +13,7 @@ using Nethermind.Core; using Nethermind.Core.Caching; using Nethermind.Core.Crypto; +using Nethermind.Core.Threading; using Nethermind.Crypto; using Nethermind.Int256; using Nethermind.JsonRpc; @@ -202,6 +204,7 @@ public async Task> HandleAsync(ExecutionPayload r // Otherwise, we can just process this block and we don't need to do BeaconSync anymore. _mergeSyncController.StopSyncing(); + using var handle = Thread.CurrentThread.BoostPriority(); // Try to execute block (ValidationResult result, string? message) = await ValidateBlockAndProcess(block, parentHeader, processingOptions); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs index 8e7789d913d..f96a6ece876 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs @@ -192,14 +192,14 @@ private void EnsureJsonRpcUrl() EnsureEngineModuleIsConfigured(); - if (!jsonRpcConfig.EnabledModules.Contains(ModuleType.Engine, StringComparison.InvariantCultureIgnoreCase)) + if (!jsonRpcConfig.EnabledModules.Contains(ModuleType.Engine, StringComparison.OrdinalIgnoreCase)) { // Disable it jsonRpcConfig.EnabledModules = []; } jsonRpcConfig.AdditionalRpcUrls = jsonRpcConfig.AdditionalRpcUrls - .Where((url) => JsonRpcUrl.Parse(url).EnabledModules.Contains(ModuleType.Engine, StringComparison.InvariantCultureIgnoreCase)) + .Where((url) => JsonRpcUrl.Parse(url).EnabledModules.Contains(ModuleType.Engine, StringComparison.OrdinalIgnoreCase)) .ToArray(); } else @@ -213,7 +213,7 @@ private void EnsureEngineModuleIsConfigured() JsonRpcUrlCollection urlCollection = new(_api.LogManager, _api.Config(), false); bool hasEngineApiConfigured = urlCollection .Values - .Any(rpcUrl => rpcUrl.EnabledModules.Contains(ModuleType.Engine, StringComparison.InvariantCultureIgnoreCase)); + .Any(rpcUrl => rpcUrl.EnabledModules.Contains(ModuleType.Engine, StringComparison.OrdinalIgnoreCase)); if (!hasEngineApiConfigured) { diff --git a/src/Nethermind/Nethermind.Network.Dns/EnrTreeParser.cs b/src/Nethermind/Nethermind.Network.Dns/EnrTreeParser.cs index 7a5385bc493..884f844e9a6 100644 --- a/src/Nethermind/Nethermind.Network.Dns/EnrTreeParser.cs +++ b/src/Nethermind/Nethermind.Network.Dns/EnrTreeParser.cs @@ -62,17 +62,17 @@ public static EnrTreeRoot ParseEnrRoot(string enrTreeRootText) EnrTreeRoot enrTreeRoot = new(); - int ensRootIndex = enrTreeRootText.IndexOf("e=", StringComparison.InvariantCulture); + int ensRootIndex = enrTreeRootText.IndexOf("e=", StringComparison.Ordinal); enrTreeRoot.EnrRoot = enrTreeRootText.Substring(ensRootIndex + 2, HashLengthBase32); - int linkRootIndex = enrTreeRootText.IndexOf("l=", StringComparison.InvariantCulture); + int linkRootIndex = enrTreeRootText.IndexOf("l=", StringComparison.Ordinal); enrTreeRoot.LinkRoot = enrTreeRootText.Substring(linkRootIndex + 2, HashLengthBase32); - int seqIndex = enrTreeRootText.IndexOf("seq=", StringComparison.InvariantCulture); + int seqIndex = enrTreeRootText.IndexOf("seq=", StringComparison.Ordinal); int seqLength = enrTreeRootText.IndexOf(' ', seqIndex) - (seqIndex + 4); enrTreeRoot.Sequence = int.Parse(enrTreeRootText.AsSpan(seqIndex + 4, seqLength)); - int sigIndex = enrTreeRootText.IndexOf("sig=", StringComparison.InvariantCulture); + int sigIndex = enrTreeRootText.IndexOf("sig=", StringComparison.Ordinal); enrTreeRoot.Signature = enrTreeRootText.Substring(sigIndex + 4, SigLengthBase32); return enrTreeRoot; diff --git a/src/Nethermind/Nethermind.Network/StaticNodes/StaticNodesManager.cs b/src/Nethermind/Nethermind.Network/StaticNodes/StaticNodesManager.cs index d4d9a3bdd06..18bb6c8c142 100644 --- a/src/Nethermind/Nethermind.Network/StaticNodes/StaticNodesManager.cs +++ b/src/Nethermind/Nethermind.Network/StaticNodes/StaticNodesManager.cs @@ -131,7 +131,7 @@ public bool IsStatic(string enode) { NetworkNode node = new(enode); return _nodes.TryGetValue(node.NodeId, out NetworkNode staticNode) && string.Equals(staticNode.Host, - node.Host, StringComparison.InvariantCultureIgnoreCase); + node.Host, StringComparison.OrdinalIgnoreCase); } private Task SaveFileAsync() diff --git a/src/Nethermind/Nethermind.Optimism.Test/RlpDecoderTests.cs b/src/Nethermind/Nethermind.Optimism.Test/RlpDecoderTests.cs index ffd084d7eb3..666792bffb3 100644 --- a/src/Nethermind/Nethermind.Optimism.Test/RlpDecoderTests.cs +++ b/src/Nethermind/Nethermind.Optimism.Test/RlpDecoderTests.cs @@ -3,6 +3,7 @@ using FluentAssertions; using Nethermind.Core; +using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Serialization.Rlp; using NUnit.Framework; @@ -11,19 +12,26 @@ namespace Nethermind.Optimism.Test; public class RlpDecoderTests { + private TxDecoder _decoder = null!; + + [SetUp] + public void Setup() + { + _decoder = TxDecoder.Instance; + _decoder.RegisterDecoder(new OptimismTxDecoder()); + _decoder.RegisterDecoder(new OptimismLegacyTxDecoder()); + } + [Test] public void Can_decode_non_null_Transaction() { - TxDecoder decoder = TxDecoder.Instance; - decoder.RegisterDecoder(new OptimismTxDecoder()); - Transaction tx = Build.A.Transaction.WithType(TxType.DepositTx).TestObject; - RlpStream rlpStream = new(decoder.GetLength(tx, RlpBehaviors.None)); - decoder.Encode(rlpStream, tx); + RlpStream rlpStream = new(_decoder.GetLength(tx, RlpBehaviors.None)); + _decoder.Encode(rlpStream, tx); rlpStream.Reset(); - Transaction? decodedTx = decoder.Decode(rlpStream); + Transaction? decodedTx = _decoder.Decode(rlpStream); decodedTx.Should().NotBeNull(); } @@ -31,17 +39,32 @@ public void Can_decode_non_null_Transaction() [Test] public void Can_decode_non_null_Transaction_through_Rlp() { - TxDecoder decoder = TxDecoder.Instance; - decoder.RegisterDecoder(new OptimismTxDecoder()); + _decoder.RegisterDecoder(new OptimismTxDecoder()); Transaction tx = Build.A.Transaction.WithType(TxType.DepositTx).TestObject; - RlpStream rlpStream = new(decoder.GetLength(tx, RlpBehaviors.None)); - decoder.Encode(rlpStream, tx); + RlpStream rlpStream = new(_decoder.GetLength(tx, RlpBehaviors.None)); + _decoder.Encode(rlpStream, tx); rlpStream.Reset(); Transaction? decodedTx = Rlp.Decode(rlpStream); decodedTx.Should().NotBeNull(); } + + [Test] + public void Can_decode_Legacy_Empty_Signature() + { + _decoder.RegisterDecoder(new OptimismTxDecoder()); + + // See: https://github.com/NethermindEth/nethermind/issues/7880 + var hexBytes = + "f901c9830571188083030d4094420000000000000000000000000000000000000780b901a4cbd4ece9000000000000000000000000420000000000000000000000000000000000001000000000000000000000000099c9fc46f92e8a1c0dec1b1747d010903e884be10000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000005711800000000000000000000000000000000000000000000000000000000000000e4662a633a000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58000000000000000000000000117274dde02bc94006185af87d78beab28ceae06000000000000000000000000117274dde02bc94006185af87d78beab28ceae06000000000000000000000000000000000000000000000000000000000c3d8b8000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808080"; + var bytes = Bytes.FromHexString(hexBytes); + var context = bytes.AsRlpValueContext(); + + var transaction = _decoder.Decode(ref context); + + transaction.Should().NotBeNull(); + } } diff --git a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs index e1c185d2aea..d3003a98dc5 100644 --- a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs +++ b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs @@ -14,9 +14,11 @@ using Nethermind.Core; using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; +using Nethermind.Facade.Eth.RpcTransaction; using Nethermind.Init.Steps; using Nethermind.Merge.Plugin.InvalidChainTracker; using Nethermind.Optimism.Rpc; +using Nethermind.Serialization.Rlp.TxDecoders; using Nethermind.TxPool; namespace Nethermind.Optimism; @@ -36,6 +38,7 @@ protected override async Task InitBlockchain() await base.InitBlockchain(); api.RegisterTxType(new OptimismTxDecoder(), Always.Valid); + api.RegisterTxType(new OptimismLegacyTxDecoder(), new OptimismLegacyTxValidator(api.SpecProvider!.ChainId)); } protected override ITransactionProcessor CreateTransactionProcessor(CodeInfoRepository codeInfoRepository, VirtualMachine virtualMachine) diff --git a/src/Nethermind/Nethermind.Optimism/OptimismLegacyTxDecoder.cs b/src/Nethermind/Nethermind.Optimism/OptimismLegacyTxDecoder.cs new file mode 100644 index 00000000000..605656f384c --- /dev/null +++ b/src/Nethermind/Nethermind.Optimism/OptimismLegacyTxDecoder.cs @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Consensus.Validators; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; +using Nethermind.Serialization.Rlp; +using Nethermind.Serialization.Rlp.TxDecoders; +using Nethermind.TxPool; + +namespace Nethermind.Optimism; + +public sealed class OptimismLegacyTxDecoder : LegacyTxDecoder +{ + protected override Signature? DecodeSignature(ulong v, ReadOnlySpan rBytes, ReadOnlySpan sBytes, Signature? fallbackSignature = null, + RlpBehaviors rlpBehaviors = RlpBehaviors.None) + { + if (v == 0 && rBytes.IsEmpty && sBytes.IsEmpty) + { + return null; + } + return base.DecodeSignature(v, rBytes, sBytes, fallbackSignature, rlpBehaviors); + } +} + +public sealed class OptimismLegacyTxValidator(ulong chainId) : ITxValidator +{ + private ITxValidator _postBedrockValidator = new CompositeTxValidator([ + IntrinsicGasTxValidator.Instance, + new LegacySignatureTxValidator(chainId), + ContractSizeTxValidator.Instance, + NonBlobFieldsTxValidator.Instance, + NonSetCodeFieldsTxValidator.Instance + ]); + + public ValidationResult IsWellFormed(Transaction transaction, IReleaseSpec releaseSpec) + { + // In Optimism, EIP1559 is activated in Bedrock + var isPreBedrock = !releaseSpec.IsEip1559Enabled; + if (isPreBedrock) + { + // Pre-Bedrock we peform no validation at all + return ValidationResult.Success; + } + + return _postBedrockValidator.IsWellFormed(transaction, releaseSpec); + } +} diff --git a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs index 277aadbbd25..91956235e67 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs @@ -24,12 +24,14 @@ using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; using Nethermind.Core; +using Nethermind.Facade.Eth.RpcTransaction; using Nethermind.Merge.Plugin.Synchronization; using Nethermind.HealthChecks; using Nethermind.Serialization.Json; using Nethermind.Specs.ChainSpecStyle; using Nethermind.Serialization.Rlp; using Nethermind.Optimism.Rpc; +using Nethermind.Serialization.Rlp.TxDecoders; using Nethermind.Synchronization; namespace Nethermind.Optimism; @@ -84,6 +86,7 @@ public void InitTxTypesAndRlpDecoders(INethermindApi api) if (ShouldRunSteps(api)) { api.RegisterTxType(new OptimismTxDecoder(), Always.Valid); + api.RegisterTxType(new OptimismLegacyTxDecoder(), new OptimismLegacyTxValidator(api.SpecProvider!.ChainId)); Rlp.RegisterDecoders(typeof(OptimismReceiptMessageDecoder).Assembly, true); } } diff --git a/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs b/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs index 31cefdabec5..f2d54ef61aa 100644 --- a/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs @@ -346,9 +346,9 @@ public void Arena_order_is_default(string configWildcard) [TestCase("chiado", 17_000_000L, 5UL, 3000)] [TestCase("gnosis", 17_000_000L, 5UL, 3000)] - [TestCase("mainnet", 30_000_000L)] - [TestCase("sepolia", 30_000_000L)] - [TestCase("holesky", 30_000_000L)] + [TestCase("mainnet", 36_000_000L)] + [TestCase("sepolia", 36_000_000L)] + [TestCase("holesky", 36_000_000L)] [TestCase("^chiado ^gnosis ^mainnet ^sepolia ^holesky")] public void Blocks_defaults_are_correct(string configWildcard, long? targetBlockGasLimit = null, ulong secondsPerSlot = 12, int blockProductionTimeout = 4000) { diff --git a/src/Nethermind/Nethermind.Runner/Program.cs b/src/Nethermind/Nethermind.Runner/Program.cs index 7444a9830c8..f98f3503dc6 100644 --- a/src/Nethermind/Nethermind.Runner/Program.cs +++ b/src/Nethermind/Nethermind.Runner/Program.cs @@ -348,7 +348,7 @@ void ConfigureLogger(ParseResult parseResult) return; } - using NLogManager logManager = new("nethermind.log"); + using NLogManager logManager = new(); logger = logManager.GetClassLogger(); diff --git a/src/Nethermind/Nethermind.Runner/configs/holesky.json b/src/Nethermind/Nethermind.Runner/configs/holesky.json index c662bd62c59..a19f827bba4 100644 --- a/src/Nethermind/Nethermind.Runner/configs/holesky.json +++ b/src/Nethermind/Nethermind.Runner/configs/holesky.json @@ -17,7 +17,7 @@ "NodeName": "Holesky" }, "Blocks": { - "TargetBlockGasLimit": 30000000 + "TargetBlockGasLimit": 36000000 }, "JsonRpc": { "Enabled": true, diff --git a/src/Nethermind/Nethermind.Runner/configs/holesky_archive.json b/src/Nethermind/Nethermind.Runner/configs/holesky_archive.json index 7162f96ad34..50f3c4e26ab 100644 --- a/src/Nethermind/Nethermind.Runner/configs/holesky_archive.json +++ b/src/Nethermind/Nethermind.Runner/configs/holesky_archive.json @@ -12,7 +12,7 @@ "NodeName": "Holesky Archive" }, "Blocks": { - "TargetBlockGasLimit": 30000000 + "TargetBlockGasLimit": 36000000 }, "Receipt": { "TxLookupLimit": 0 diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index 048566d399b..5720d7d929a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -21,7 +21,7 @@ "NodeName": "Mainnet" }, "Blocks": { - "TargetBlockGasLimit": 30000000 + "TargetBlockGasLimit": 36000000 }, "JsonRpc": { "Enabled": true, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet_archive.json b/src/Nethermind/Nethermind.Runner/configs/mainnet_archive.json index 504f5098a03..d11c95a89a9 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet_archive.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet_archive.json @@ -17,7 +17,7 @@ "NodeName": "Mainnet Archive" }, "Blocks": { - "TargetBlockGasLimit": 30000000 + "TargetBlockGasLimit": 36000000 }, "Receipt": { "TxLookupLimit": 0 diff --git a/src/Nethermind/Nethermind.Runner/configs/mekong.json b/src/Nethermind/Nethermind.Runner/configs/mekong.json index 2a5d7a2626b..95790d7858e 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mekong.json +++ b/src/Nethermind/Nethermind.Runner/configs/mekong.json @@ -17,7 +17,7 @@ "UseGethLimitsInFastBlocks": true }, "Blocks": { - "TargetBlockGasLimit": 30000000 + "TargetBlockGasLimit": 36000000 }, "JsonRpc": { "Enabled": true, diff --git a/src/Nethermind/Nethermind.Runner/configs/mekong_archive.json b/src/Nethermind/Nethermind.Runner/configs/mekong_archive.json index df60d00ee7f..ece457408ab 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mekong_archive.json +++ b/src/Nethermind/Nethermind.Runner/configs/mekong_archive.json @@ -12,7 +12,7 @@ "NodeName": "Mekong archive" }, "Blocks": { - "TargetBlockGasLimit": 30000000 + "TargetBlockGasLimit": 36000000 }, "Receipt": { "TxLookupLimit": 0 diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index cb8e0364cbe..60fb166704e 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -23,7 +23,7 @@ "FastSyncCatchUpHeightDelta": "10000000000" }, "Blocks": { - "TargetBlockGasLimit": 30000000 + "TargetBlockGasLimit": 36000000 }, "JsonRpc": { "Enabled": true, diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia_archive.json b/src/Nethermind/Nethermind.Runner/configs/sepolia_archive.json index ce210b68bb7..7d99df7dbff 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia_archive.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia_archive.json @@ -14,7 +14,7 @@ "NodeName": "Sepolia Archive" }, "Blocks": { - "TargetBlockGasLimit": 30000000 + "TargetBlockGasLimit": 36000000 }, "Receipt": { "TxLookupLimit": 0 diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoders/LegacyTxDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoders/LegacyTxDecoder.cs index 3937f0c0ae2..99aba5bf70d 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoders/LegacyTxDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoders/LegacyTxDecoder.cs @@ -7,7 +7,7 @@ namespace Nethermind.Serialization.Rlp.TxDecoders; -public sealed class LegacyTxDecoder(Func? transactionFactory = null) : BaseTxDecoder(TxType.Legacy, transactionFactory) where T : Transaction, new() +public class LegacyTxDecoder(Func? transactionFactory = null) : BaseTxDecoder(TxType.Legacy, transactionFactory) where T : Transaction, new() { private static bool IncludeSigChainIdHack(bool isEip155Enabled, ulong chainId) => isEip155Enabled && chainId != 0; diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs index 10ae78bd3f0..49f18d5ec7b 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs @@ -56,7 +56,7 @@ private void LoadParameters(ChainSpecJson chainSpecJson, ChainSpec chainSpec) { long? GetTransitions(string builtInName, Predicate> predicate) { - var allocation = chainSpecJson.Accounts?.Values.FirstOrDefault(v => v.BuiltIn?.Name.Equals(builtInName, StringComparison.InvariantCultureIgnoreCase) == true); + var allocation = chainSpecJson.Accounts?.Values.FirstOrDefault(v => v.BuiltIn?.Name.Equals(builtInName, StringComparison.OrdinalIgnoreCase) == true); if (allocation is null) return null; KeyValuePair[] pricing = allocation.BuiltIn.Pricing.Where(o => predicate(o)).ToArray(); if (pricing.Length > 0) diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs index 2fe3f1f14ef..78c372b98cd 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs @@ -65,9 +65,24 @@ public SyncDispatcher( private TaskCompletionSource? _dormantStateTask = new(TaskCreationOptions.RunContinuationsAsynchronously); + public async Task Start(CancellationToken cancellationToken) { UpdateState(Feed.CurrentState); + + try + { + _activeTasks.AddCount(1); + await DispatchLoop(cancellationToken); + } + finally + { + _activeTasks.Signal(); + } + } + + private async Task DispatchLoop(CancellationToken cancellationToken) + { while (true) { try @@ -116,27 +131,18 @@ public async Task Start(CancellationToken cancellationToken) // Use Task.Run to make sure it queues it instead of running part of it synchronously. _activeTasks.AddCount(); - Task task; - try - { - task = Task.Run( - () => + Task task = Task.Run( + () => + { + try { - try - { - return DoDispatch(cancellationToken, allocatedPeer, request, allocation); - } - finally - { - _activeTasks.Signal(); - } - }); - } - catch - { - _activeTasks.Signal(); - throw; - } + return DoDispatch(cancellationToken, allocatedPeer, request, allocation); + } + finally + { + _activeTasks.Signal(); + } + }); if (!Feed.IsMultiFeed) { @@ -302,11 +308,10 @@ private void UpdateState(SyncFeedState state) public ValueTask DisposeAsync() { - if (_disposed) + if (Interlocked.CompareExchange(ref _disposed, true, false)) { return ValueTask.CompletedTask; } - _disposed = true; _activeTasks.Signal(); if (!_activeTasks.Wait(ActiveTaskDisposeTimeout)) diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index f01b5215e22..993126ab29d 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -771,11 +771,11 @@ void TopLevelPersist(TrieNode tn, Hash256? address2, TreePath path) if (_pruningStrategy.PruningEnabled) { - if (_logger.IsInfo) _logger.Info($"Persisting from root {commitSet.Root?.Keccak} in block {commitSet.BlockNumber}"); + if (_logger.IsInfo) _logger.Info($"Persisting from root {commitSet.Root?.Keccak?.ToShortString()} in block {commitSet.BlockNumber}"); } else { - if (_logger.IsDebug) _logger.Debug($"Persisting from root {commitSet.Root?.Keccak} in block {commitSet.BlockNumber}"); + if (_logger.IsDebug) _logger.Debug($"Persisting from root {commitSet.Root?.Keccak?.ToShortString()} in block {commitSet.BlockNumber}"); } long start = Stopwatch.GetTimestamp();