diff --git a/.github/workflows/nethermind-tests.yml b/.github/workflows/nethermind-tests.yml
index b95d724b9ed..c5b1ee08652 100644
--- a/.github/workflows/nethermind-tests.yml
+++ b/.github/workflows/nethermind-tests.yml
@@ -64,6 +64,7 @@ jobs:
- Nethermind.Overseer.Test
- Nethermind.Runner.Test
- Nethermind.Serialization.Ssz.Test
+ - Nethermind.Shutter.Test
- Nethermind.Sockets.Test
- Nethermind.Specs.Test
- Nethermind.State.Test
diff --git a/.github/workflows/sync-supported-chains.yml b/.github/workflows/sync-supported-chains.yml
index 0d8363e0053..3ca8427a262 100644
--- a/.github/workflows/sync-supported-chains.yml
+++ b/.github/workflows/sync-supported-chains.yml
@@ -85,7 +85,7 @@ jobs:
- name: Setup Go environment
uses: actions/setup-go@v5
with:
- go-version: '1.21.0'
+ go-version: 'stable'
check-latest: true
cache: true
diff --git a/src/Nethermind/Chains/chiado.json b/src/Nethermind/Chains/chiado.json
index b692dfa2ecf..4aae438e2d6 100644
--- a/src/Nethermind/Chains/chiado.json
+++ b/src/Nethermind/Chains/chiado.json
@@ -64,6 +64,7 @@
"eip3529Transition": "0x0",
"eip3541Transition": "0x0",
"eip1559Transition": "0x0",
+ "beaconChainGenesisTimestamp": "0x6343ee4c",
"eip3651TransitionTimestamp": "0x646e0e4c",
"eip3855TransitionTimestamp": "0x646e0e4c",
"eip3860TransitionTimestamp": "0x646e0e4c",
diff --git a/src/Nethermind/Chains/foundation.json b/src/Nethermind/Chains/foundation.json
index 674e828bc20..aeff1d38644 100644
--- a/src/Nethermind/Chains/foundation.json
+++ b/src/Nethermind/Chains/foundation.json
@@ -181,6 +181,7 @@
"eip3198Transition": "0xC5D488",
"eip3529Transition": "0xC5D488",
"eip3541Transition": "0xC5D488",
+ "beaconChainGenesisTimestamp": "0x5fc63057",
"eip3651TransitionTimestamp": "0x64373057",
"eip3855TransitionTimestamp": "0x64373057",
"eip3860TransitionTimestamp": "0x64373057",
diff --git a/src/Nethermind/Chains/gnosis.json b/src/Nethermind/Chains/gnosis.json
index 79ff843ce6e..c316f9fcf3d 100644
--- a/src/Nethermind/Chains/gnosis.json
+++ b/src/Nethermind/Chains/gnosis.json
@@ -70,6 +70,7 @@
"eip3529Transition": 19040000,
"eip3541Transition": 19040000,
"eip1559Transition": 19040000,
+ "beaconChainGenesisTimestamp": "0x61b10dbc",
"eip3651TransitionTimestamp": "0x64c8edbc",
"eip3855TransitionTimestamp": "0x64c8edbc",
"eip3860TransitionTimestamp": "0x64c8edbc",
diff --git a/src/Nethermind/Chains/hive.json b/src/Nethermind/Chains/hive.json
index 805c6aaa175..0e0d1f800a6 100644
--- a/src/Nethermind/Chains/hive.json
+++ b/src/Nethermind/Chains/hive.json
@@ -26,7 +26,7 @@
"eip155Transition": "0x0",
"maxCodeSizeTransition": "0x0",
"maxCodeSize": 24576,
- "maximumExtraDataSize": 102400,
+ "maximumExtraDataSize": "0x400",
"eip140Transition": "0x0",
"eip211Transition": "0x0",
"eip214Transition": "0x0",
@@ -51,57 +51,45 @@
"eip3529Transition": "0x0",
"eip3541Transition": "0x0",
"eip3198Transition": "0x0",
- "MergeForkIdTransition": "0x64",
- "networkID": "0x7",
- "chainID": "0x7"
+ "eip3651TransitionTimestamp": "0x0",
+ "eip3855TransitionTimestamp": "0x0",
+ "eip3860TransitionTimestamp": "0x0",
+ "eip4895TransitionTimestamp": "0x0",
+ "eip4844TransitionTimestamp": "0x0",
+ "eip4788TransitionTimestamp": "0x0",
+ "eip1153TransitionTimestamp": "0x0",
+ "eip5656TransitionTimestamp": "0x0",
+ "eip6780TransitionTimestamp": "0x0",
+ "eip7702TransitionTimestamp": "0x0",
+ "chainID": "0x1"
},
"genesis": {
"seal": {
"ethereum": {
- "nonce": "0x0000000000000000"
+ "nonce": "0x0000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
- "difficulty": "0x30000",
+ "difficulty": "0x00",
"author": "0x0000000000000000000000000000000000000000",
- "timestamp": "0x1234",
- "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000658bdf435d810c91414ec09147daa6db624063790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "gasLimit": "0x2fefd8"
+ "timestamp": "0x00",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "extraData": "0x00",
+ "gasLimit": "0x016345785d8a0000",
+ "baseFeePerGas": "0x07"
},
"accounts": {
- "0xcf49fda3be353c69b41ed96333cd24302da4556f": {
- "balance": "0x123450000000000000000"
- },
- "0x0161e041aad467a890839d5b08b138c1e6373072": {
- "balance": "0x123450000000000000000"
- },
- "0x87da6a8c6e9eff15d703fc2773e32f6af8dbe301": {
- "balance": "0x123450000000000000000"
- },
- "0xb97de4b8c857e4f6bc354f226dc3249aaee49209": {
- "balance": "0x123450000000000000000"
- },
- "0xc5065c9eeebe6df2c2284d046bfc906501846c51": {
- "balance": "0x123450000000000000000"
- },
- "0x0000000000000000000000000000000000000314": {
- "balance": "0x0",
- "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029",
- "storage": {
- "0x0000000000000000000000000000000000000000000000000000000000000000": "0x1234",
- "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9": "0x01"
- }
- },
- "0x0000000000000000000000000000000000000315": {
- "balance": "0x9999999999999999999999999999999",
- "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef2769ca1461003e575b610000565b3461000057610078600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061007a565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f1935050505015610106578173ffffffffffffffffffffffffffffffffffffffff167f30a3c50752f2552dcc2b93f5b96866280816a986c0c0408cb6778b9fa198288f826040518082815260200191505060405180910390a25b5b50505600a165627a7a72305820637991fabcc8abad4294bf2bb615db78fbec4edff1635a2647d3894e2daf6a610029"
- },
- "0x0000000000000000000000000000000000000316": {
- "balance": "0x0",
- "code": "0x444355"
- },
- "0x0000000000000000000000000000000000000317": {
- "balance": "0x0",
- "code": "0x600160003555"
+ "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": {
+ "nonce": "0x01",
+ "balance": "0x00",
+ "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500",
+ "storage": {}
+ },
+ "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
+ "nonce": "0x00",
+ "balance": "0x1d6329f1c35ca4bfabb9f5610000000000",
+ "code": "0x",
+ "storage": {}
},
"0x0000000000000000000000000000000000000001": {
"builtin": {
@@ -206,4 +194,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Nethermind/Chains/holesky.json b/src/Nethermind/Chains/holesky.json
index a5effdc1d96..5ca2e40da40 100644
--- a/src/Nethermind/Chains/holesky.json
+++ b/src/Nethermind/Chains/holesky.json
@@ -35,6 +35,7 @@
"eip3198Transition": "0x0",
"eip3529Transition": "0x0",
"eip3541Transition": "0x0",
+ "beaconChainGenesisTimestamp": "0x65156994",
"eip3651TransitionTimestamp": "0x6516eac0",
"eip3855TransitionTimestamp": "0x6516eac0",
"eip3860TransitionTimestamp": "0x6516eac0",
diff --git a/src/Nethermind/Chains/sepolia.json b/src/Nethermind/Chains/sepolia.json
index 957fdfb0f01..3fa415123d4 100644
--- a/src/Nethermind/Chains/sepolia.json
+++ b/src/Nethermind/Chains/sepolia.json
@@ -57,6 +57,7 @@
"eip3541Transition": "0x0",
"terminalTotalDifficulty": "3C6568F12E8000",
"mergeForkIdTransition": "0x1A7ACB",
+ "beaconChainGenesisTimestamp": "0x62b07d60",
"eip4895TransitionTimestamp": "0x63FD7D60",
"eip3855TransitionTimestamp": "0x63FD7D60",
"eip3651TransitionTimestamp": "0x63FD7D60",
diff --git a/src/Nethermind/Directory.Packages.props b/src/Nethermind/Directory.Packages.props
index db504de060a..253c598a39d 100644
--- a/src/Nethermind/Directory.Packages.props
+++ b/src/Nethermind/Directory.Packages.props
@@ -19,8 +19,8 @@
-
-
+
+
@@ -51,6 +51,7 @@
+
diff --git a/src/Nethermind/Ethereum.Blockchain.Pyspec.Test/PragueBlockChainTests.cs b/src/Nethermind/Ethereum.Blockchain.Pyspec.Test/PragueBlockChainTests.cs
new file mode 100644
index 00000000000..2474c0cfa2b
--- /dev/null
+++ b/src/Nethermind/Ethereum.Blockchain.Pyspec.Test/PragueBlockChainTests.cs
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Ethereum.Test.Base;
+using NUnit.Framework;
+
+namespace Ethereum.Blockchain.Pyspec.Test;
+
+[TestFixture]
+[Parallelizable(ParallelScope.All)]
+[Explicit("These tests are not ready yet")]
+public class PragueBlockChainTests : BlockchainTestBase
+{
+ [TestCaseSource(nameof(LoadTests))]
+ public async Task Test(BlockchainTest test) => await RunTest(test);
+
+ private static IEnumerable LoadTests()
+ {
+ TestsSourceLoader loader = new(new LoadPyspecTestsStrategy(), $"fixtures/blockchain_tests/prague");
+ return loader.LoadTests().OfType();
+ }
+}
diff --git a/src/Nethermind/Ethereum.Blockchain.Pyspec.Test/PragueStateTests.cs b/src/Nethermind/Ethereum.Blockchain.Pyspec.Test/PragueStateTests.cs
new file mode 100644
index 00000000000..107b4e249f1
--- /dev/null
+++ b/src/Nethermind/Ethereum.Blockchain.Pyspec.Test/PragueStateTests.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Linq;
+using Ethereum.Test.Base;
+using FluentAssertions;
+using NUnit.Framework;
+
+namespace Ethereum.Blockchain.Pyspec.Test;
+
+[TestFixture]
+[Parallelizable(ParallelScope.All)]
+[Explicit("These tests are not ready yet")]
+public class PragueStateTests : GeneralStateTestBase
+{
+ [TestCaseSource(nameof(LoadTests))]
+ public void Test(GeneralStateTest test) => RunTest(test).Pass.Should().BeTrue();
+
+ private static IEnumerable LoadTests()
+ {
+ TestsSourceLoader loader = new(new LoadPyspecTestsStrategy(), $"fixtures/state_tests/prague");
+ return loader.LoadTests().Cast();
+ }
+}
diff --git a/src/Nethermind/Ethereum.Test.Base/AuthorizationListJson.cs b/src/Nethermind/Ethereum.Test.Base/AuthorizationListJson.cs
new file mode 100644
index 00000000000..a2b8b6cfcbc
--- /dev/null
+++ b/src/Nethermind/Ethereum.Test.Base/AuthorizationListJson.cs
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using Nethermind.Core;
+
+namespace Ethereum.Test.Base;
+public class AuthorizationListJson
+{
+ public ulong ChainId { get; set; }
+ public Address Address { get; set; }
+ public ulong Nonce { get; set; }
+ public ulong V { get; set; }
+ public byte[] R { get; set; }
+ public byte[] S { get; set; }
+ public Address Signer { get; set; }
+}
diff --git a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs
index 120c146c6d3..47487e7e212 100644
--- a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs
+++ b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs
@@ -137,12 +137,16 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer)
Block block = Build.A.Block.WithTransactions(test.Transaction).WithHeader(header).TestObject;
- bool isValid = _txValidator.IsWellFormed(test.Transaction, spec) && IsValidBlock(block, specProvider);
+ ValidationResult txIsValid = _txValidator.IsWellFormed(test.Transaction, spec);
- if (isValid)
+ if (txIsValid)
{
transactionProcessor.Execute(test.Transaction, new BlockExecutionContext(header), txTracer);
}
+ else
+ {
+ _logger.Info($"Skipping invalid tx with error: {txIsValid.Error}");
+ }
stopwatch.Stop();
diff --git a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs
index 8ac509a9672..7d41065cd52 100644
--- a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs
+++ b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs
@@ -127,6 +127,7 @@ public static Transaction Convert(PostStateJson postStateJson, TransactionJson t
{
Transaction transaction = new();
+ transaction.Type = transactionJson.Type;
transaction.Value = transactionJson.Value[postStateJson.Indexes.Value];
transaction.GasLimit = transactionJson.GasLimit[postStateJson.Indexes.Gas];
transaction.GasPrice = transactionJson.GasPrice ?? transactionJson.MaxPriorityFeePerGas ?? 0;
@@ -157,6 +158,23 @@ public static Transaction Convert(PostStateJson postStateJson, TransactionJson t
if (transaction.BlobVersionedHashes?.Length > 0)
transaction.Type = TxType.Blob;
+ if (transactionJson.AuthorizationList is not null)
+ {
+ transaction.AuthorizationList =
+ transactionJson.AuthorizationList
+ .Select(i => new AuthorizationTuple(
+ i.ChainId,
+ i.Address,
+ i.Nonce,
+ i.V,
+ i.R,
+ i.S)).ToArray();
+ if (transaction.AuthorizationList.Any())
+ {
+ transaction.Type = TxType.SetCode;
+ }
+ }
+
return transaction;
}
@@ -291,6 +309,7 @@ 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/Ethereum.Test.Base/LegacyTransactionJson.cs b/src/Nethermind/Ethereum.Test.Base/LegacyTransactionJson.cs
index db932e48913..0d93af017d5 100644
--- a/src/Nethermind/Ethereum.Test.Base/LegacyTransactionJson.cs
+++ b/src/Nethermind/Ethereum.Test.Base/LegacyTransactionJson.cs
@@ -14,6 +14,7 @@ public class LegacyTransactionJson
public UInt256 Nonce { get; set; }
public Address To { get; set; }
public UInt256 Value { get; set; }
+ public string Sender { get; set; }
public byte[] R { get; set; }
public byte[] S { get; set; }
public ulong V { get; set; }
diff --git a/src/Nethermind/Ethereum.Test.Base/TransactionJson.cs b/src/Nethermind/Ethereum.Test.Base/TransactionJson.cs
index 59658f8e876..83c4884f835 100644
--- a/src/Nethermind/Ethereum.Test.Base/TransactionJson.cs
+++ b/src/Nethermind/Ethereum.Test.Base/TransactionJson.cs
@@ -8,6 +8,8 @@ namespace Ethereum.Test.Base
{
public class TransactionJson
{
+ public TxType Type { get; set; }
+ public Address Sender { get; set; }
public byte[][]? Data { get; set; }
public long[]? GasLimit { get; set; }
public UInt256? GasPrice { get; set; }
@@ -19,6 +21,7 @@ public class TransactionJson
public byte[]? SecretKey { get; set; }
public AccessListItemJson[]?[]? AccessLists { get; set; }
public AccessListItemJson[]? AccessList { get; set; }
+ public AuthorizationListJson[]? AuthorizationList { get; set; }
public byte[]?[]? BlobVersionedHashes { get; set; }
public UInt256? MaxFeePerBlobGas { get; set; }
}
diff --git a/src/Nethermind/Nethermind.Api/Extensions/IConsensusWrapperPlugin.cs b/src/Nethermind/Nethermind.Api/Extensions/IConsensusWrapperPlugin.cs
index b81722632bc..becb062362d 100644
--- a/src/Nethermind/Nethermind.Api/Extensions/IConsensusWrapperPlugin.cs
+++ b/src/Nethermind/Nethermind.Api/Extensions/IConsensusWrapperPlugin.cs
@@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
-using System.Threading.Tasks;
using Nethermind.Consensus;
using Nethermind.Consensus.Transactions;
diff --git a/src/Nethermind/Nethermind.Api/Extensions/IPluginConfig.cs b/src/Nethermind/Nethermind.Api/Extensions/IPluginConfig.cs
index d519e3d3b5a..370b9ae0dd0 100644
--- a/src/Nethermind/Nethermind.Api/Extensions/IPluginConfig.cs
+++ b/src/Nethermind/Nethermind.Api/Extensions/IPluginConfig.cs
@@ -8,6 +8,6 @@ namespace Nethermind.Api.Extensions;
[ConfigCategory(DisabledForCli = false, HiddenFromDocs = true)]
public interface IPluginConfig : IConfig
{
- [ConfigItem(Description = "Order of plugin initialization", DefaultValue = "[Clique, Aura, Ethash, Optimism, AuRaMerge, Merge, MEV, HealthChecks, Hive]")]
+ [ConfigItem(Description = "Order of plugin initialization", DefaultValue = "[Clique, Aura, Ethash, Optimism, Shutter, AuRaMerge, Merge, MEV, HealthChecks, Hive]")]
string[] PluginOrder { get; set; }
}
diff --git a/src/Nethermind/Nethermind.Api/Extensions/PluginConfig.cs b/src/Nethermind/Nethermind.Api/Extensions/PluginConfig.cs
index 43b49b27342..b5ffe466585 100644
--- a/src/Nethermind/Nethermind.Api/Extensions/PluginConfig.cs
+++ b/src/Nethermind/Nethermind.Api/Extensions/PluginConfig.cs
@@ -5,5 +5,5 @@ namespace Nethermind.Api.Extensions;
public class PluginConfig : IPluginConfig
{
- public string[] PluginOrder { get; set; } = { "Clique", "Aura", "Ethash", "Optimism", "AuRaMerge", "Merge", "MEV", "HealthChecks", "Hive" };
+ public string[] PluginOrder { get; set; } = { "Clique", "Aura", "Ethash", "Optimism", "Shutter", "AuRaMerge", "Merge", "MEV", "HealthChecks", "Hive" };
}
diff --git a/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs b/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs
index a3a510e7c89..61bceb25ae4 100644
--- a/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs
+++ b/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs
@@ -88,6 +88,7 @@ public interface IApiWithBlockchain : IApiWithStores, IBlockchainBridgeFactory
IGasLimitCalculator? GasLimitCalculator { get; set; }
IBlockProducerEnvFactory? BlockProducerEnvFactory { get; set; }
+ IBlockImprovementContextFactory? BlockImprovementContextFactory { get; set; }
IGasPriceOracle? GasPriceOracle { get; set; }
diff --git a/src/Nethermind/Nethermind.Api/IApiWithStores.cs b/src/Nethermind/Nethermind.Api/IApiWithStores.cs
index f6e02313adc..fa2911c2ebe 100644
--- a/src/Nethermind/Nethermind.Api/IApiWithStores.cs
+++ b/src/Nethermind/Nethermind.Api/IApiWithStores.cs
@@ -8,6 +8,7 @@
using Nethermind.Consensus;
using Nethermind.Crypto;
using Nethermind.Db.Blooms;
+using Nethermind.Facade.Find;
using Nethermind.State.Repositories;
using Nethermind.TxPool;
using Nethermind.Wallet;
diff --git a/src/Nethermind/Nethermind.Api/NethermindApi.cs b/src/Nethermind/Nethermind.Api/NethermindApi.cs
index ceee96957d1..56193492d01 100644
--- a/src/Nethermind/Nethermind.Api/NethermindApi.cs
+++ b/src/Nethermind/Nethermind.Api/NethermindApi.cs
@@ -57,6 +57,7 @@
using Nethermind.Sockets;
using Nethermind.Trie;
using Nethermind.Consensus.Processing.CensorshipDetector;
+using Nethermind.Facade.Find;
namespace Nethermind.Api
{
@@ -214,6 +215,7 @@ public ISealEngine SealEngine
public IGasLimitCalculator? GasLimitCalculator { get; set; }
public IBlockProducerEnvFactory? BlockProducerEnvFactory { get; set; }
+ public IBlockImprovementContextFactory? BlockImprovementContextFactory { get; set; }
public IGasPriceOracle? GasPriceOracle { get; set; }
public IEthSyncingInfo? EthSyncingInfo { get; set; }
diff --git a/src/Nethermind/Nethermind.Api/PluginPriorities.cs b/src/Nethermind/Nethermind.Api/PluginPriorities.cs
index 1b0eaec2880..2a6af5a1065 100644
--- a/src/Nethermind/Nethermind.Api/PluginPriorities.cs
+++ b/src/Nethermind/Nethermind.Api/PluginPriorities.cs
@@ -6,4 +6,5 @@ namespace Nethermind.Api;
public class PluginPriorities
{
public const int Merge = 1000;
+ public const int Shutter = 2000;
}
diff --git a/src/Nethermind/Nethermind.Benchmark/Core/RecoverSignaturesBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Core/RecoverSignaturesBenchmark.cs
new file mode 100644
index 00000000000..0b7655985fe
--- /dev/null
+++ b/src/Nethermind/Nethermind.Benchmark/Core/RecoverSignaturesBenchmark.cs
@@ -0,0 +1,203 @@
+using BenchmarkDotNet.Attributes;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Specs;
+using Nethermind.Core.Test.Builders;
+using Nethermind.Core;
+using Nethermind.Crypto;
+using Nethermind.Logging;
+using Nethermind.Serialization.Rlp;
+using Nethermind.Specs;
+using System;
+using System.Collections.Generic;
+using Nethermind.Consensus.Processing;
+using Nethermind.TxPool;
+using Nethermind.Int256;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Nethermind.Benchmarks.Core
+{
+ [MemoryDiagnoser]
+ public class RecoverSignaturesBenchmark
+ {
+ private ISpecProvider _specProvider = MainnetSpecProvider.Instance;
+
+ private static EthereumEcdsa _ethereumEcdsa;
+ private static RecoverSignatures _sut;
+
+ private Block _block100TxWith100AuthSigs;
+ private Block _block100TxWith10AuthSigs;
+ private Block _block100TxWith1AuthSigs;
+ private Block _block3TxWith1AuthSigs;
+ private Block _block10TxWith0AuthSigs;
+ private Block _block10TxWith10AuthSigs;
+
+ private static PrivateKey[] _privateKeys = Enumerable.Range(0, 1000)
+ .Select(i => Build.A.PrivateKey.TestObject)
+ .ToArray();
+
+ [GlobalSetup]
+ public void GlobalSetup()
+ {
+ _ethereumEcdsa = new(_specProvider.ChainId);
+ _sut = new(_ethereumEcdsa, NullTxPool.Instance, _specProvider, NullLogManager.Instance);
+
+ var rnd = new Random();
+
+ _block100TxWith100AuthSigs = Build.A.Block
+ .WithHeader(new BlockHeader()
+ {
+ Timestamp = ulong.MaxValue,
+ Number = long.MaxValue
+ })
+ .WithTransactions(CreateTransactions(100, 100))
+ .TestObject;
+ _block100TxWith10AuthSigs = Build.A.Block
+ .WithHeader(new BlockHeader()
+ {
+ Timestamp = ulong.MaxValue,
+ Number = long.MaxValue
+ })
+ .WithTransactions(CreateTransactions(100, 10))
+ .TestObject;
+
+ _block100TxWith1AuthSigs = Build.A.Block
+ .WithHeader(new BlockHeader()
+ {
+ Timestamp = ulong.MaxValue,
+ Number = long.MaxValue
+ })
+ .WithTransactions(CreateTransactions(100, 1))
+ .TestObject;
+
+ _block10TxWith10AuthSigs = Build.A.Block
+ .WithHeader(new BlockHeader()
+ {
+ Timestamp = ulong.MaxValue,
+ Number = long.MaxValue
+ })
+ .WithTransactions(CreateTransactions(10, 10))
+ .TestObject;
+
+ _block3TxWith1AuthSigs = Build.A.Block
+ .WithHeader(new BlockHeader()
+ {
+ Timestamp = ulong.MaxValue,
+ Number = long.MaxValue
+ })
+ .WithTransactions(CreateTransactions(3, 1))
+ .TestObject;
+
+ _block10TxWith0AuthSigs = Build.A.Block
+ .WithHeader(new BlockHeader()
+ {
+ Timestamp = ulong.MaxValue,
+ Number = long.MaxValue
+ })
+ .WithTransactions(CreateTransactions(10, 0))
+ .TestObject;
+
+ Transaction[] CreateTransactions(int txCount, int authPerTx)
+ {
+ var list = new List();
+ for (int i = 0; i < txCount; i++)
+ {
+ PrivateKey signer = _privateKeys[i];
+
+ Transaction tx = Build.A.Transaction
+ .WithType(TxType.SetCode)
+ .WithAuthorizationCode(
+ Enumerable.Range(0, authPerTx).Select(y =>
+ {
+ PrivateKey authority = _privateKeys[i + y + _privateKeys.Length / 2];
+ return CreateAuthorizationTuple(
+ authority,
+ (ulong)rnd.NextInt64(),
+ Address.Zero,
+ (ulong)rnd.NextInt64());
+ }).ToArray()
+ )
+ .SignedAndResolved(signer)
+ .WithSenderAddress(null)
+ .TestObject;
+ list.Add(tx);
+ }
+ return list.ToArray();
+ }
+
+ static AuthorizationTuple CreateAuthorizationTuple(PrivateKey signer, ulong chainId, Address codeAddress, ulong nonce)
+ {
+ AuthorizationTupleDecoder decoder = new();
+ RlpStream rlp = decoder.EncodeWithoutSignature(chainId, codeAddress, nonce);
+ Span code = stackalloc byte[rlp.Length + 1];
+ code[0] = Eip7702Constants.Magic;
+ rlp.Data.AsSpan().CopyTo(code.Slice(1));
+
+ Signature sig = _ethereumEcdsa.Sign(signer, Keccak.Compute(code));
+
+ return new AuthorizationTuple(chainId, codeAddress, nonce, sig);
+ }
+ }
+
+ [IterationCleanup]
+ public void IterationCleanup()
+ {
+ ResetSigs(_block100TxWith100AuthSigs);
+ ResetSigs(_block100TxWith10AuthSigs);
+ ResetSigs(_block100TxWith1AuthSigs);
+ ResetSigs(_block10TxWith10AuthSigs);
+ ResetSigs(_block10TxWith0AuthSigs);
+ ResetSigs(_block3TxWith1AuthSigs);
+
+ void ResetSigs(Block block)
+ {
+ Parallel.ForEach(block.Transactions, (t) =>
+ {
+ t.SenderAddress = null;
+ t.Hash = null;
+ Parallel.ForEach(t.AuthorizationList, (tuple) =>
+ {
+ tuple.Authority = null;
+ });
+ });
+ }
+ }
+
+ [Benchmark]
+ public void Recover100TxSignatureswith100AuthoritySignatures()
+ {
+ _sut.RecoverData(_block100TxWith100AuthSigs);
+ }
+
+ [Benchmark]
+ public void Recover100TxSignatureswith10AuthoritySignatures()
+ {
+ _sut.RecoverData(_block100TxWith10AuthSigs);
+ }
+
+ [Benchmark]
+ public void Recover100TxSignaturesWith1AuthoritySignatures()
+ {
+ _sut.RecoverData(_block100TxWith1AuthSigs);
+ }
+
+ [Benchmark]
+ public void Recover10TxSignaturesWith10AuthoritySignatures()
+ {
+ _sut.RecoverData(_block10TxWith10AuthSigs);
+ }
+
+ [Benchmark]
+ public void Recover3TxSignaturesWith1AuthoritySignatures()
+ {
+ _sut.RecoverData(_block3TxWith1AuthSigs);
+ }
+
+ [Benchmark]
+ public void Recover10TxSignaturesWith0AuthoritySignatures()
+ {
+ _sut.RecoverData(_block10TxWith0AuthSigs);
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs
index a270e0c9d2c..1fa64a27c27 100644
--- a/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs
+++ b/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs
@@ -20,6 +20,7 @@
using Nethermind.Logging;
using Nethermind.Db.Blooms;
using Nethermind.Facade.Filters;
+using Nethermind.Facade.Find;
using NSubstitute;
using NUnit.Framework;
diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs
index 840c63e6f9f..88274cfd17b 100644
--- a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs
+++ b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs
@@ -48,16 +48,16 @@ public void Setup()
.WithSpecProvider(specProvider)
.TestObject;
+ CodeInfoRepository codeInfoRepository = new();
TxPool.TxPool txPool = new(
ecdsa,
new BlobTxStorage(),
- new ChainHeadInfoProvider(specProvider, _blockTree, stateProvider),
+ new ChainHeadInfoProvider(specProvider, _blockTree, stateProvider, codeInfoRepository),
new TxPoolConfig(),
new TxValidator(specProvider.ChainId),
LimboLogs.Instance,
transactionComparerProvider.GetDefaultComparer());
BlockhashProvider blockhashProvider = new(_blockTree, specProvider, stateProvider, LimboLogs.Instance);
- CodeInfoRepository codeInfoRepository = new();
VirtualMachine virtualMachine = new(
blockhashProvider,
specProvider,
diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs
index c7cd07b95e1..f52adce9ba7 100644
--- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs
+++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs
@@ -6,6 +6,7 @@
using System.Linq;
using System.Numerics;
using FluentAssertions;
+using Nethermind.Consensus.Messages;
using Nethermind.Consensus.Validators;
using Nethermind.Core;
using Nethermind.Core.Crypto;
@@ -58,7 +59,7 @@ public void Zero_r_is_not_valid()
txValidator.IsWellFormed(tx, MuirGlacier.Instance).AsBool().Should().BeFalse();
}
- private static byte CalculateV() => (byte)EthereumEcdsa.CalculateV(TestBlockchainIds.ChainId);
+ private static byte CalculateV() => (byte)EthereumEcdsaExtensions.CalculateV(TestBlockchainIds.ChainId);
[Test, MaxTime(Timeout.MaxTestTime)]
public void Zero_s_is_not_valid()
@@ -522,6 +523,129 @@ public void IsWellFormed_BlobTxHasProofOverTheSizeLimit_ReturnFalse()
Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance).AsBool(), Is.False);
}
+ [Test]
+ public void IsWellFormed_CreateTxInSetCode_ReturnsFalse()
+ {
+ TransactionBuilder txBuilder = Build.A.Transaction
+ .WithType(TxType.SetCode)
+ .WithAuthorizationCode(new AuthorizationTuple(0, TestItem.AddressA, 0, 0, [], []))
+ .WithMaxFeePerGas(100000)
+ .WithGasLimit(1000000)
+ .WithChainId(TestBlockchainIds.ChainId)
+ .SignedAndResolved()
+ .WithTo(null);
+
+ Transaction tx = txBuilder.TestObject;
+ TxValidator txValidator = new(TestBlockchainIds.ChainId);
+
+ Assert.Multiple(() =>
+ {
+ ValidationResult validationResult = txValidator.IsWellFormed(tx, Prague.Instance);
+ Assert.That(validationResult.AsBool(), Is.False);
+ Assert.That(validationResult.Error, Is.EqualTo(TxErrorMessages.NotAllowedCreateTransaction));
+ });
+ }
+
+ [Test]
+ public void IsWellFormed_AuthorizationListTxInPragueSpec_ReturnsTrue()
+ {
+ TransactionBuilder txBuilder = Build.A.Transaction
+ .WithType(TxType.SetCode)
+ .WithTo(TestItem.AddressA)
+ .WithAuthorizationCode(new AuthorizationTuple(0, TestItem.AddressA, 0, 0, [], []))
+ .WithMaxFeePerGas(100000)
+ .WithGasLimit(1000000)
+ .WithChainId(TestBlockchainIds.ChainId)
+ .SignedAndResolved();
+
+ Transaction tx = txBuilder.TestObject;
+ TxValidator txValidator = new(TestBlockchainIds.ChainId);
+
+ Assert.That(txValidator.IsWellFormed(tx, Prague.Instance).AsBool, Is.True);
+ }
+
+ [Test]
+ public void IsWellFormed_EmptyAuthorizationList_ReturnsFalse()
+ {
+ TransactionBuilder txBuilder = Build.A.Transaction
+ .WithType(TxType.SetCode)
+ .WithTo(TestItem.AddressA)
+ .WithAuthorizationCode([])
+ .WithMaxFeePerGas(100000)
+ .WithGasLimit(1000000)
+ .WithChainId(TestBlockchainIds.ChainId)
+ .SignedAndResolved();
+
+ Transaction tx = txBuilder.TestObject;
+ TxValidator txValidator = new(TestBlockchainIds.ChainId);
+
+ Assert.That(txValidator.IsWellFormed(tx, Prague.Instance).AsBool, Is.False);
+ }
+ [Test]
+ public void IsWellFormed_NullAuthorizationList_ReturnsFalse()
+ {
+ TransactionBuilder txBuilder = Build.A.Transaction
+ .WithType(TxType.SetCode)
+ .WithTo(TestItem.AddressA)
+ .WithAuthorizationCode((AuthorizationTuple[])null!)
+ .WithMaxFeePerGas(100000)
+ .WithGasLimit(1000000)
+ .WithChainId(TestBlockchainIds.ChainId)
+ .SignedAndResolved();
+
+ Transaction tx = txBuilder.TestObject;
+ TxValidator txValidator = new(TestBlockchainIds.ChainId);
+
+ Assert.That(txValidator.IsWellFormed(tx, Prague.Instance).AsBool, Is.False);
+ }
+
+ private static object[] BadSignatures =
+ {
+ new object[] { 1ul, (UInt256)1, Secp256K1Curve.HalfNPlusOne, false},
+ new object[] { 1ul, UInt256.Zero, Secp256K1Curve.HalfN, true },
+ new object[] { 0ul, UInt256.Zero, UInt256.Zero, true },
+ };
+ [TestCaseSource(nameof(BadSignatures))]
+ public void IsWellFormed_AuthorizationTupleHasBadSignature_ReturnsFalse(ulong yParity, UInt256 r, UInt256 s, bool expected)
+ {
+ TransactionBuilder txBuilder = Build.A.Transaction
+ .WithType(TxType.SetCode)
+ .WithTo(TestItem.AddressA)
+ .WithAuthorizationCode(new AuthorizationTuple(0, Address.Zero, 0, new Signature(r, s, yParity + Signature.VOffset)))
+ .WithMaxFeePerGas(100000)
+ .WithGasLimit(1000000)
+ .WithChainId(TestBlockchainIds.ChainId)
+ .SignedAndResolved();
+
+ Transaction tx = txBuilder.TestObject;
+ TxValidator txValidator = new(TestBlockchainIds.ChainId);
+
+ Assert.That(txValidator.IsWellFormed(tx, Prague.Instance).AsBool, Is.EqualTo(expected));
+ }
+
+ private static IEnumerable NonSetCodeTypes() =>
+ Enum.GetValues().Where(t => t != TxType.SetCode && t != TxType.DepositTx);
+
+ [TestCaseSource(nameof(NonSetCodeTypes))]
+ public void IsWellFormed_NonSetCodeTxHasAuthorizationList_ReturnsFalse(TxType type)
+ {
+ var x = Enum.GetValues().Where(t => t != TxType.SetCode);
+ TransactionBuilder txBuilder = Build.A.Transaction
+ .WithType(type)
+ .WithTo(TestItem.AddressA)
+ .WithMaxFeePerGas(100000)
+ .WithGasLimit(1000000)
+ .WithChainId(TestBlockchainIds.ChainId)
+ .WithShardBlobTxTypeAndFieldsIfBlobTx()
+ .WithAuthorizationCode(new AuthorizationTuple(TestBlockchainIds.ChainId, TestItem.AddressA, 0, new Signature(new byte[65])))
+ .SignedAndResolved();
+
+ Transaction tx = txBuilder.TestObject;
+ TxValidator txValidator = new(TestBlockchainIds.ChainId);
+
+ Assert.That(txValidator.IsWellFormed(tx, Prague.Instance).Error, Is.EqualTo(TxErrorMessages.NotAllowedAuthorizationList));
+ }
+
private static byte[] MakeArray(int count, params byte[] elements) =>
elements.Take(Math.Min(count, elements.Length))
.Concat(new byte[Math.Max(0, count - elements.Length)])
diff --git a/src/Nethermind/Nethermind.Blockchain/ChainHeadInfoProvider.cs b/src/Nethermind/Nethermind.Blockchain/ChainHeadInfoProvider.cs
index f843345bc38..3c90e3dc736 100644
--- a/src/Nethermind/Nethermind.Blockchain/ChainHeadInfoProvider.cs
+++ b/src/Nethermind/Nethermind.Blockchain/ChainHeadInfoProvider.cs
@@ -17,28 +17,31 @@ namespace Nethermind.Blockchain
{
public class ChainHeadInfoProvider : IChainHeadInfoProvider
{
- public ChainHeadInfoProvider(ISpecProvider specProvider, IBlockTree blockTree, IStateReader stateReader)
- : this(new ChainHeadSpecProvider(specProvider, blockTree), blockTree, new ChainHeadReadOnlyStateProvider(blockTree, stateReader))
+ public ChainHeadInfoProvider(ISpecProvider specProvider, IBlockTree blockTree, IStateReader stateReader, ICodeInfoRepository codeInfoRepository)
+ : this(new ChainHeadSpecProvider(specProvider, blockTree), blockTree, new ChainHeadReadOnlyStateProvider(blockTree, stateReader), codeInfoRepository)
{
}
- public ChainHeadInfoProvider(ISpecProvider specProvider, IBlockTree blockTree, IAccountStateProvider stateProvider)
- : this(new ChainHeadSpecProvider(specProvider, blockTree), blockTree, stateProvider)
+ public ChainHeadInfoProvider(ISpecProvider specProvider, IBlockTree blockTree, IReadOnlyStateProvider stateProvider, ICodeInfoRepository codeInfoRepository)
+ : this(new ChainHeadSpecProvider(specProvider, blockTree), blockTree, stateProvider, codeInfoRepository)
{
}
- public ChainHeadInfoProvider(IChainHeadSpecProvider specProvider, IBlockTree blockTree, IAccountStateProvider stateProvider)
+ public ChainHeadInfoProvider(IChainHeadSpecProvider specProvider, IBlockTree blockTree, IReadOnlyStateProvider stateProvider, ICodeInfoRepository codeInfoRepository)
{
SpecProvider = specProvider;
- AccountStateProvider = stateProvider;
+ ReadOnlyStateProvider = stateProvider;
HeadNumber = blockTree.BestKnownNumber;
+ CodeInfoRepository = codeInfoRepository;
blockTree.BlockAddedToMain += OnHeadChanged;
}
public IChainHeadSpecProvider SpecProvider { get; }
- public IAccountStateProvider AccountStateProvider { get; }
+ public IReadOnlyStateProvider ReadOnlyStateProvider { get; }
+
+ public ICodeInfoRepository CodeInfoRepository { get; }
public long HeadNumber { get; private set; }
diff --git a/src/Nethermind/Nethermind.Blockchain/Contracts/LogEntryAddressAndTopicsMatchTemplateEqualityComparer.cs b/src/Nethermind/Nethermind.Blockchain/Contracts/LogEntryAddressAndTopicsMatchTemplateEqualityComparer.cs
index 72a90023c3a..795a0b8d754 100644
--- a/src/Nethermind/Nethermind.Blockchain/Contracts/LogEntryAddressAndTopicsMatchTemplateEqualityComparer.cs
+++ b/src/Nethermind/Nethermind.Blockchain/Contracts/LogEntryAddressAndTopicsMatchTemplateEqualityComparer.cs
@@ -26,7 +26,7 @@ public bool Equals(LogEntry logEntry, LogEntry searchedEntryTemplate)
Hash256[] matchEntryTopics = searchedEntryTemplate?.Topics ?? Array.Empty();
return ReferenceEquals(logEntry, searchedEntryTemplate) || (
logEntry is not null
- && logEntry.LoggersAddress == searchedEntryTemplate?.LoggersAddress
+ && logEntry.Address == searchedEntryTemplate?.Address
&& logEntry.Topics.Length >= matchEntryTopics.Length
&& logEntry.Topics.Take(matchEntryTopics.Length).SequenceEqual(matchEntryTopics)
);
@@ -34,7 +34,7 @@ logEntry is not null
public int GetHashCode(LogEntry obj)
{
- return obj.Topics.Aggregate(obj.LoggersAddress.GetHashCode(), (i, keccak) => i ^ keccak.GetHashCode());
+ return obj.Topics.Aggregate(obj.Address.GetHashCode(), (i, keccak) => i ^ keccak.GetHashCode());
}
}
}
diff --git a/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs b/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs
index ee41061fcad..5d868bf60fb 100644
--- a/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs
+++ b/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs
@@ -53,7 +53,7 @@ public CopyTreeVisitor(
public void VisitTree(in TContext nodeContext, Hash256 rootHash, TrieVisitContext trieVisitContext)
{
_stopwatch.Start();
- if (_logger.IsWarn) _logger.Warn($"Full Pruning Started on root hash {rootHash}: do not close the node until finished or progress will be lost.");
+ if (_logger.IsInfo) _logger.Info($"Full Pruning Started on root hash {rootHash}: do not close the node until finished or progress will be lost.");
}
[DoesNotReturn]
diff --git a/src/Nethermind/Nethermind.Blockchain/Spec/ChainHeadSpecProvider.cs b/src/Nethermind/Nethermind.Blockchain/Spec/ChainHeadSpecProvider.cs
index f1d38e94778..05680546eb9 100644
--- a/src/Nethermind/Nethermind.Blockchain/Spec/ChainHeadSpecProvider.cs
+++ b/src/Nethermind/Nethermind.Blockchain/Spec/ChainHeadSpecProvider.cs
@@ -34,6 +34,8 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD
public long? DaoBlockNumber => _specProvider.DaoBlockNumber;
+ public ulong? BeaconChainGenesisTimestamp => _specProvider.BeaconChainGenesisTimestamp;
+
public ulong NetworkId => _specProvider.NetworkId;
public ulong ChainId => _specProvider.ChainId;
diff --git a/src/Nethermind/Nethermind.Cli/NodeManager.cs b/src/Nethermind/Nethermind.Cli/NodeManager.cs
index c392a499e59..75cfe3df20f 100644
--- a/src/Nethermind/Nethermind.Cli/NodeManager.cs
+++ b/src/Nethermind/Nethermind.Cli/NodeManager.cs
@@ -69,11 +69,9 @@ public async Task PostJint(string method, params object[] parameters)
}
else
{
- Stopwatch stopwatch = new();
- stopwatch.Start();
+ long startTime = Stopwatch.GetTimestamp();
object? result = await _currentClient.Post