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