diff --git a/Directory.Packages.props b/Directory.Packages.props
index 74e1fde4d82..87cd3cf32b8 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -48,7 +48,6 @@
-
@@ -57,6 +56,7 @@
+
diff --git a/README.md b/README.md
index a989abb7d9b..5b34a6e61d3 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@ The standalone release builds are available on [GitHub Releases](https://github.
On Windows, Nethermind can be installed via Windows Package Manager:
```powershell
- winget install nethermind
+ winget install --id Nethermind.Nethermind
```
- **macOS**
diff --git a/nuget.config b/nuget.config
index 9c3244f50fa..647f42894be 100644
--- a/nuget.config
+++ b/nuget.config
@@ -3,14 +3,14 @@
-
+
-
+ -->
diff --git a/src/Nethermind/Benchmarks.slnx b/src/Nethermind/Benchmarks.slnx
index 7ba0c11e37f..1466a214d66 100644
--- a/src/Nethermind/Benchmarks.slnx
+++ b/src/Nethermind/Benchmarks.slnx
@@ -14,6 +14,7 @@
+
diff --git a/src/Nethermind/Nethermind.Api/BasicApiExtensions.cs b/src/Nethermind/Nethermind.Api/BasicApiExtensions.cs
index 6afb0a78299..9f8fa9db333 100644
--- a/src/Nethermind/Nethermind.Api/BasicApiExtensions.cs
+++ b/src/Nethermind/Nethermind.Api/BasicApiExtensions.cs
@@ -12,10 +12,5 @@ public static T Config(this IBasicApi api) where T : IConfig
{
return api.ConfigProvider.GetConfig();
}
-
- public static T Db(this IBasicApi api, string dbName) where T : class, IDb
- {
- return api.DbProvider!.GetDb(dbName);
- }
}
}
diff --git a/src/Nethermind/Nethermind.Api/IApiWithStores.cs b/src/Nethermind/Nethermind.Api/IApiWithStores.cs
index e14288276da..5ee936c38d6 100644
--- a/src/Nethermind/Nethermind.Api/IApiWithStores.cs
+++ b/src/Nethermind/Nethermind.Api/IApiWithStores.cs
@@ -17,7 +17,7 @@ namespace Nethermind.Api
{
public interface IApiWithStores : IBasicApi
{
- IBlobTxStorage? BlobTxStorage { get; set; }
+ IBlobTxStorage BlobTxStorage { get; }
IBlockTree? BlockTree { get; set; }
IBloomStorage? BloomStorage { get; set; }
IChainLevelInfoRepository? ChainLevelInfoRepository { get; set; }
diff --git a/src/Nethermind/Nethermind.Api/IBasicApi.cs b/src/Nethermind/Nethermind.Api/IBasicApi.cs
index 0cc05b460cb..f8ff0fa9055 100644
--- a/src/Nethermind/Nethermind.Api/IBasicApi.cs
+++ b/src/Nethermind/Nethermind.Api/IBasicApi.cs
@@ -31,8 +31,7 @@ public interface IBasicApi
[SkipServiceCollection]
IConfigProvider ConfigProvider { get; }
ICryptoRandom CryptoRandom { get; }
- IDbProvider? DbProvider { get; set; }
- IDbFactory? DbFactory { get; set; }
+ IDbProvider DbProvider { get; }
IEthereumEcdsa EthereumEcdsa { get; }
[SkipServiceCollection]
IJsonSerializer EthereumJsonSerializer { get; }
diff --git a/src/Nethermind/Nethermind.Api/NethermindApi.cs b/src/Nethermind/Nethermind.Api/NethermindApi.cs
index 853f0e71fa0..bf9f7af369c 100644
--- a/src/Nethermind/Nethermind.Api/NethermindApi.cs
+++ b/src/Nethermind/Nethermind.Api/NethermindApi.cs
@@ -4,7 +4,6 @@
using System.Collections.Generic;
using System.IO.Abstractions;
using Autofac;
-using Nethermind.Abi;
using Nethermind.Api.Extensions;
using Nethermind.Blockchain;
using Nethermind.Blockchain.Blocks;
@@ -71,7 +70,7 @@ public IBlockchainBridge CreateBlockchainBridge()
return Context.Resolve().CreateBlockchainBridge();
}
- public IBlobTxStorage? BlobTxStorage { get; set; }
+ public IBlobTxStorage BlobTxStorage => Context.Resolve();
public CompositeBlockPreprocessorStep BlockPreprocessor { get; } = new();
public IBlockProcessingQueue? BlockProcessingQueue { get; set; }
public IBlockProducer? BlockProducer { get; set; }
@@ -82,8 +81,7 @@ public IBlockchainBridge CreateBlockchainBridge()
public IChainLevelInfoRepository? ChainLevelInfoRepository { get; set; }
public IConfigProvider ConfigProvider => _dependencies.ConfigProvider;
public ICryptoRandom CryptoRandom => Context.Resolve();
- public IDbProvider? DbProvider { get; set; }
- public IDbFactory? DbFactory { get; set; }
+ public IDbProvider DbProvider => Context.Resolve();
public ISigner? EngineSigner { get; set; }
public ISignerStore? EngineSignerStore { get; set; }
public IEnode? Enode { get; set; }
diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuRaPluginTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuRaPluginTests.cs
index 7e5c393078a..d520f50b3c1 100644
--- a/src/Nethermind/Nethermind.AuRa.Test/AuRaPluginTests.cs
+++ b/src/Nethermind/Nethermind.AuRa.Test/AuRaPluginTests.cs
@@ -43,7 +43,6 @@ public void Init_when_not_AuRa_doesnt_trow()
Substitute.For(),
testNethermindContainer);
AuRaNethermindApi api = new AuRaNethermindApi(apiDependencies);
- api.DbProvider = TestMemDbProvider.Init();
Action init = () => auRaPlugin.Init(api);
init.Should().NotThrow();
}
diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs
index 2851766175b..411681ccf17 100644
--- a/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs
+++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs
@@ -524,7 +524,7 @@ public async Task Can_process_fast_sync()
new FixedForkActivationChainHeadSpecProvider(specProvider, fixedBlock: 10_000_000),
blockTree,
readOnlyState,
- new CodeInfoRepository())
+ new EthereumCodeInfoRepository())
{
HasSynced = true
};
diff --git a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs
index e01f5edfb9f..735c602aa5d 100644
--- a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs
+++ b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs
@@ -10,6 +10,7 @@
using System.Threading.Tasks;
using Autofac;
using FluentAssertions;
+using Nethermind.Api;
using Nethermind.Blockchain.FullPruning;
using Nethermind.Config;
using Nethermind.Core;
@@ -75,16 +76,14 @@ protected override async Task Build(Action? co
return chain;
}
- protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder, IConfigProvider configProvider)
- {
- IDbProvider dbProvider = new DbProvider();
- RocksDbFactory rocksDbFactory = new(new DbConfig(), LimboLogs.Instance, TempDirectory.Path);
- StandardDbInitializer standardDbInitializer = new(dbProvider, rocksDbFactory, new FileSystem());
- standardDbInitializer.InitStandardDbs(true);
-
- return base.ConfigureContainer(builder, configProvider)
- .AddSingleton(dbProvider);
- }
+ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder, IConfigProvider configProvider) =>
+ // Reenable rocksdb
+ base.ConfigureContainer(builder, configProvider)
+ .AddSingleton()
+ .Intercept((initConfig) =>
+ {
+ initConfig.BaseDbPath = TempDirectory.Path;
+ });
public override void Dispose()
{
diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs
index d2cb2d48d99..87e39b16a3a 100644
--- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs
+++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs
@@ -2,31 +2,16 @@
// SPDX-License-Identifier: LGPL-3.0-only
using System.Threading;
+using Autofac;
using FluentAssertions;
-using Nethermind.Blockchain.BeaconBlockRoot;
-using Nethermind.Blockchain.Blocks;
-using Nethermind.Blockchain.Receipts;
-using Nethermind.Config;
+using Nethermind.Api;
using Nethermind.Consensus;
-using Nethermind.Consensus.ExecutionRequests;
-using Nethermind.Consensus.Processing;
using Nethermind.Consensus.Producers;
-using Nethermind.Consensus.Rewards;
using Nethermind.Consensus.Transactions;
using Nethermind.Consensus.Validators;
-using Nethermind.Consensus.Withdrawals;
using Nethermind.Core;
-using Nethermind.Core.Specs;
-using Nethermind.Core.Test;
using Nethermind.Core.Test.Builders;
-using Nethermind.Db;
-using Nethermind.Evm;
-using Nethermind.Evm.Config;
-using Nethermind.Evm.TransactionProcessing;
-using Nethermind.Logging;
-using Nethermind.Specs;
-using Nethermind.Evm.State;
-using Nethermind.State;
+using Nethermind.Core.Test.Modules;
using NUnit.Framework;
namespace Nethermind.Blockchain.Test.Producers;
@@ -36,70 +21,18 @@ public class DevBlockProducerTests
[Test, MaxTime(Timeout.MaxTestTime)]
public void Test()
{
- ISpecProvider specProvider = MainnetSpecProvider.Instance;
- DbProvider dbProvider = new();
- dbProvider.RegisterDb(DbNames.BlockInfos, new MemDb());
- dbProvider.RegisterDb(DbNames.Blocks, new MemDb());
- dbProvider.RegisterDb(DbNames.Headers, new MemDb());
- dbProvider.RegisterDb(DbNames.State, new MemDb());
- dbProvider.RegisterDb(DbNames.Code, new MemDb());
- dbProvider.RegisterDb(DbNames.Metadata, new MemDb());
+ using IContainer container = new ContainerBuilder()
+ .AddModule(new TestNethermindModule())
+ .AddSingleton(Always.Valid)
+ .AddSingleton()
+ .AddScoped>()
+ .Build();
- BlockTree blockTree = Build.A.BlockTree()
- .WithoutSettingHead
- .TestObject;
+ IBlockTree blockTree = container.Resolve();
+ IManualBlockProductionTrigger trigger = container.Resolve();
- IWorldStateManager worldStateManager = TestWorldStateFactory.CreateForTest(dbProvider, LimboLogs.Instance);
- IWorldState stateProvider = worldStateManager.GlobalWorldState;
- IStateReader stateReader = worldStateManager.GlobalStateReader;
- BlockhashProvider blockhashProvider = new(blockTree, specProvider, stateProvider, LimboLogs.Instance);
- CodeInfoRepository codeInfoRepository = new();
- VirtualMachine virtualMachine = new(
- blockhashProvider,
- specProvider,
- LimboLogs.Instance);
- TransactionProcessor txProcessor = new(
- specProvider,
- stateProvider,
- virtualMachine,
- codeInfoRepository,
- LimboLogs.Instance);
- BlockProcessor blockProcessor = new BlockProcessor(
- specProvider,
- Always.Valid,
- NoBlockRewards.Instance,
- new BlockProcessor.BlockValidationTransactionsExecutor(new ExecuteTransactionProcessorAdapter(txProcessor), stateProvider),
- stateProvider,
- NullReceiptStorage.Instance,
- new BeaconBlockRootHandler(txProcessor, stateProvider),
- new BlockhashStore(specProvider, stateProvider),
- LimboLogs.Instance,
- new WithdrawalProcessor(stateProvider, LimboLogs.Instance),
- new ExecutionRequestsProcessor(txProcessor));
- BlockchainProcessor blockchainProcessor = new(
- blockTree,
- blockProcessor,
- NullRecoveryStep.Instance,
- stateReader,
- LimboLogs.Instance,
- BlockchainProcessor.Options.Default);
- BuildBlocksWhenRequested trigger = new();
- ManualTimestamper timestamper = new ManualTimestamper();
- DevBlockProducer devBlockProducer = new(
- EmptyTxSource.Instance,
- blockchainProcessor,
- stateProvider,
- blockTree,
- timestamper,
- specProvider,
- new BlocksConfig(),
- LimboLogs.Instance);
-
- StandardBlockProducerRunner blockProducerRunner = new StandardBlockProducerRunner(trigger, blockTree, devBlockProducer);
-
- blockchainProcessor.Start();
- blockProducerRunner.Start();
- ProducedBlockSuggester _ = new ProducedBlockSuggester(blockTree, blockProducerRunner);
+ container.Resolve().BlockchainProcessor.Start();
+ container.Resolve().Start();
AutoResetEvent autoResetEvent = new(false);
@@ -112,4 +45,12 @@ public void Test()
autoResetEvent.WaitOne(1000).Should().BeTrue("1");
blockTree.Head!.Number.Should().Be(1);
}
+
+ private class EmptyTxSourceFactory : IBlockProducerTxSourceFactory
+ {
+ public ITxSource Create()
+ {
+ return EmptyTxSource.Instance;
+ }
+ }
}
diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs
index f363de705bb..7fb0dbc214e 100644
--- a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs
+++ b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs
@@ -17,6 +17,7 @@
using Nethermind.Core.Specs;
using Nethermind.Core.Test;
using Nethermind.Core.Test.Builders;
+using Nethermind.Core.Test.Db;
using Nethermind.Crypto;
using Nethermind.Db;
using Nethermind.Evm;
@@ -73,7 +74,7 @@ public void Setup()
.WithSpecProvider(specProvider)
.TestObject;
- CodeInfoRepository codeInfoRepository = new();
+ EthereumCodeInfoRepository codeInfoRepository = new();
TxPool.TxPool txPool = new(
ecdsa,
new BlobTxStorage(),
diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs
index 5d2096cd3b7..c1365b1f81e 100644
--- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs
+++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorEip7702Tests.cs
@@ -19,6 +19,7 @@
using Nethermind.Core.Crypto;
using System;
using System.Linq;
+using Nethermind.Blockchain;
using Nethermind.Blockchain.Tracing;
using Nethermind.Core.Test;
using Nethermind.Int256;
@@ -40,7 +41,7 @@ public void Setup()
_specProvider = new TestSpecProvider(Prague.Instance);
IWorldStateManager worldStateManager = TestWorldStateFactory.CreateForTest();
_stateProvider = worldStateManager.GlobalWorldState;
- CodeInfoRepository codeInfoRepository = new();
+ EthereumCodeInfoRepository codeInfoRepository = new();
VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance);
_transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance);
_ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId);
diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs
index 99fe538bc62..e515a2480ec 100644
--- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs
+++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionProcessorTests.cs
@@ -25,6 +25,7 @@
using NUnit.Framework;
using Nethermind.Config;
using System.Collections.Generic;
+using Nethermind.Blockchain;
using Nethermind.Blockchain.Tracing;
using Nethermind.Core.Test;
using Nethermind.State;
@@ -60,7 +61,7 @@ public void Setup()
_stateProvider.Commit(_specProvider.GenesisSpec);
_stateProvider.CommitTree(0);
- CodeInfoRepository codeInfoRepository = new();
+ EthereumCodeInfoRepository codeInfoRepository = new();
VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance);
_transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance);
_ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId);
diff --git a/src/Nethermind/Nethermind.Blockchain/CachedCodeInfoRepository.cs b/src/Nethermind/Nethermind.Blockchain/CachedCodeInfoRepository.cs
new file mode 100644
index 00000000000..8ce1fbc8099
--- /dev/null
+++ b/src/Nethermind/Nethermind.Blockchain/CachedCodeInfoRepository.cs
@@ -0,0 +1,56 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Frozen;
+using System.Collections.Generic;
+using Nethermind.Core;
+using Nethermind.Core.Specs;
+using Nethermind.Evm;
+using Nethermind.Evm.CodeAnalysis;
+using Nethermind.Evm.Precompiles;
+using Nethermind.State;
+
+namespace Nethermind.Blockchain;
+
+public class CachedCodeInfoRepository(
+ FrozenDictionary precompiles,
+ ConcurrentDictionary? precompileCache) : CodeInfoRepository(
+ precompileCache is null
+ ? precompiles
+ : precompiles.ToFrozenDictionary(kvp => kvp.Key, kvp => CreateCachedPrecompile(kvp, precompileCache)))
+{
+ private static PrecompileInfo CreateCachedPrecompile(
+ in KeyValuePair originalPrecompile,
+ ConcurrentDictionary cache) =>
+ new PrecompileInfo(new CachedPrecompile(originalPrecompile.Key.Value, originalPrecompile.Value.Precompile!, cache));
+
+ private class CachedPrecompile(
+ Address address,
+ IPrecompile precompile,
+ ConcurrentDictionary cache) : IPrecompile
+ {
+ public static Address Address => Address.Zero;
+
+ public static string Name => "";
+
+ public long BaseGasCost(IReleaseSpec releaseSpec) => precompile.BaseGasCost(releaseSpec);
+
+ public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec) => precompile.DataGasCost(inputData, releaseSpec);
+
+ public (byte[], bool) Run(ReadOnlyMemory inputData, IReleaseSpec releaseSpec)
+ {
+ PreBlockCaches.PrecompileCacheKey key = new(address, inputData);
+ if (!cache.TryGetValue(key, out (byte[], bool) result))
+ {
+ result = precompile.Run(inputData, releaseSpec);
+ // we need to rebuild the key with data copy as the data can be changed by VM processing
+ key = new PreBlockCaches.PrecompileCacheKey(address, inputData.ToArray());
+ cache.TryAdd(key, result);
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.Blockchain/EthereumCodeInfoRepository.cs b/src/Nethermind/Nethermind.Blockchain/EthereumCodeInfoRepository.cs
new file mode 100644
index 00000000000..c306c6abab4
--- /dev/null
+++ b/src/Nethermind/Nethermind.Blockchain/EthereumCodeInfoRepository.cs
@@ -0,0 +1,48 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System.Collections.Concurrent;
+using System.Collections.Frozen;
+using System.Collections.Generic;
+using Nethermind.Core;
+using Nethermind.Evm.CodeAnalysis;
+using Nethermind.Evm.Precompiles;
+using Nethermind.Evm.Precompiles.Bls;
+using Nethermind.State;
+
+namespace Nethermind.Blockchain;
+
+public class EthereumCodeInfoRepository(
+ ConcurrentDictionary? precompileCache = null)
+ : CachedCodeInfoRepository(Precompiles, precompileCache)
+{
+ private static FrozenDictionary Precompiles
+ {
+ get => new Dictionary
+ {
+ [EcRecoverPrecompile.Address] = new(EcRecoverPrecompile.Instance),
+ [Sha256Precompile.Address] = new(Sha256Precompile.Instance),
+ [Ripemd160Precompile.Address] = new(Ripemd160Precompile.Instance),
+ [IdentityPrecompile.Address] = new(IdentityPrecompile.Instance),
+
+ [BN254AddPrecompile.Address] = new(BN254AddPrecompile.Instance),
+ [BN254MulPrecompile.Address] = new(BN254MulPrecompile.Instance),
+ [BN254PairingPrecompile.Address] = new(BN254PairingPrecompile.Instance),
+ [ModExpPrecompile.Address] = new(ModExpPrecompile.Instance),
+
+ [Blake2FPrecompile.Address] = new(Blake2FPrecompile.Instance),
+
+ [G1AddPrecompile.Address] = new(G1AddPrecompile.Instance),
+ [G1MSMPrecompile.Address] = new(G1MSMPrecompile.Instance),
+ [G2AddPrecompile.Address] = new(G2AddPrecompile.Instance),
+ [G2MSMPrecompile.Address] = new(G2MSMPrecompile.Instance),
+ [PairingCheckPrecompile.Address] = new(PairingCheckPrecompile.Instance),
+ [MapFpToG1Precompile.Address] = new(MapFpToG1Precompile.Instance),
+ [MapFp2ToG2Precompile.Address] = new(MapFp2ToG2Precompile.Instance),
+
+ [PointEvaluationPrecompile.Address] = new(PointEvaluationPrecompile.Instance),
+
+ [Secp256r1Precompile.Address] = new(Secp256r1Precompile.Instance),
+ }.ToFrozenDictionary();
+ }
+}
diff --git a/src/Nethermind/Nethermind.Blockchain/Metrics.cs b/src/Nethermind/Nethermind.Blockchain/Metrics.cs
index a778115dde6..91864c136fb 100644
--- a/src/Nethermind/Nethermind.Blockchain/Metrics.cs
+++ b/src/Nethermind/Nethermind.Blockchain/Metrics.cs
@@ -6,105 +6,104 @@
using Nethermind.Core.Attributes;
using Nethermind.Core.Metric;
using Nethermind.Int256;
+
// ReSharper disable InconsistentNaming
-namespace Nethermind.Blockchain
+namespace Nethermind.Blockchain;
+
+public static class Metrics
{
- public static class Metrics
- {
- [CounterMetric]
- [Description("Total MGas processed")]
- public static double Mgas { get; set; }
-
- [GaugeMetric]
- [Description("MGas processed per second")]
- public static double MgasPerSec { get; set; }
-
- [CounterMetric]
- [Description("Total number of transactions processed")]
- public static long Transactions { get; set; }
-
- [GaugeMetric]
- [Description("Total number of blocks processed")]
- public static long Blocks { get; set; }
-
- [CounterMetric]
- [Description("Total number of chain reorganizations")]
- public static long Reorganizations { get; set; }
-
- [GaugeMetric]
- [Description("Number of blocks awaiting for recovery of public keys from signatures.")]
- public static long RecoveryQueueSize { get; set; }
-
- [GaugeMetric]
- [Description("Number of blocks awaiting for processing.")]
- public static long ProcessingQueueSize { get; set; }
-
- [CounterMetric]
- [Description("Total number of sealed blocks")]
- public static long BlocksSealed { get; set; }
-
- [CounterMetric]
- [Description("Total number of failed block seals")]
- public static long FailedBlockSeals { get; set; }
-
- [GaugeMetric]
- [Description("Gas Used in processed blocks")]
- public static long GasUsed { get; set; }
-
- [GaugeMetric]
- [Description("Gas Limit for processed blocks")]
- public static long GasLimit { get; set; }
-
- [GaugeMetric]
- [Description("Total difficulty on the chain")]
- public static UInt256 TotalDifficulty { get; set; }
-
- [GaugeMetric]
- [Description("Difficulty of the last block")]
- public static UInt256 LastDifficulty { get; set; }
-
- [GaugeMetric]
- [Description("Indicator if blocks can be produced")]
- public static long CanProduceBlocks;
-
- [GaugeMetric]
- [Description("Number of ms to process the last processed block.")]
- public static long LastBlockProcessingTimeInMs;
-
- //EIP-2159: Common Prometheus Metrics Names for Clients
- [GaugeMetric]
- [Description("The current height of the canonical chain.")]
- [DataMember(Name = "ethereum_blockchain_height")]
- public static long BlockchainHeight { get; set; }
-
- //EIP-2159: Common Prometheus Metrics Names for Clients
- [GaugeMetric]
- [Description("The estimated highest block available.")]
- [DataMember(Name = "ethereum_best_known_block_number")]
- public static long BestKnownBlockNumber { get; set; }
-
- [GaugeMetric]
- [Description("Number of invalid blocks.")]
- public static long BadBlocks;
-
- [GaugeMetric]
- [Description("Number of invalid blocks with extra data set to 'Nethermind'.")]
- public static long BadBlocksByNethermindNodes;
-
- [GaugeMetric]
- [Description("State root calculation time")]
- public static double StateMerkleizationTime { get; set; }
-
- [DetailedMetric]
- [ExponentialPowerHistogramMetric(Start = 10, Factor = 1.2, Count = 30)]
- [Description("Histogram of block MGas per second")]
- public static IMetricObserver BlockMGasPerSec { get; set; } = new NoopMetricObserver();
-
- [DetailedMetric]
- [ExponentialPowerHistogramMetric(Start = 100, Factor = 1.25, Count = 50)]
- [Description("Histogram of block prorcessing time")]
- public static IMetricObserver BlockProcessingTimeMicros { get; set; } = new NoopMetricObserver();
-
- }
+ [CounterMetric]
+ [Description("Total MGas processed")]
+ public static double Mgas { get; set; }
+
+ [GaugeMetric]
+ [Description("MGas processed per second")]
+ public static double MgasPerSec { get; set; }
+
+ [CounterMetric]
+ [Description("Total number of transactions processed")]
+ public static long Transactions { get; set; }
+
+ [GaugeMetric]
+ [Description("Total number of blocks processed")]
+ public static long Blocks { get; set; }
+
+ [CounterMetric]
+ [Description("Total number of chain reorganizations")]
+ public static long Reorganizations { get; set; }
+
+ [GaugeMetric]
+ [Description("Number of blocks awaiting for recovery of public keys from signatures.")]
+ public static long RecoveryQueueSize { get; set; }
+
+ [GaugeMetric]
+ [Description("Number of blocks awaiting for processing.")]
+ public static long ProcessingQueueSize { get; set; }
+
+ [CounterMetric]
+ [Description("Total number of sealed blocks")]
+ public static long BlocksSealed { get; set; }
+
+ [CounterMetric]
+ [Description("Total number of failed block seals")]
+ public static long FailedBlockSeals { get; set; }
+
+ [GaugeMetric]
+ [Description("Gas Used in processed blocks")]
+ public static long GasUsed { get; set; }
+
+ [GaugeMetric]
+ [Description("Gas Limit for processed blocks")]
+ public static long GasLimit { get; set; }
+
+ [GaugeMetric]
+ [Description("Total difficulty on the chain")]
+ public static UInt256 TotalDifficulty { get; set; }
+
+ [GaugeMetric]
+ [Description("Difficulty of the last block")]
+ public static UInt256 LastDifficulty { get; set; }
+
+ [GaugeMetric]
+ [Description("Indicator if blocks can be produced")]
+ public static long CanProduceBlocks;
+
+ [GaugeMetric]
+ [Description("Number of ms to process the last processed block.")]
+ public static long LastBlockProcessingTimeInMs;
+
+ //EIP-2159: Common Prometheus Metrics Names for Clients
+ [GaugeMetric]
+ [Description("The current height of the canonical chain.")]
+ [DataMember(Name = "ethereum_blockchain_height")]
+ public static long BlockchainHeight { get; set; }
+
+ //EIP-2159: Common Prometheus Metrics Names for Clients
+ [GaugeMetric]
+ [Description("The estimated highest block available.")]
+ [DataMember(Name = "ethereum_best_known_block_number")]
+ public static long BestKnownBlockNumber { get; set; }
+
+ [GaugeMetric]
+ [Description("Number of invalid blocks.")]
+ public static long BadBlocks;
+
+ [GaugeMetric]
+ [Description("Number of invalid blocks with extra data set to 'Nethermind'.")]
+ public static long BadBlocksByNethermindNodes;
+
+ [GaugeMetric]
+ [Description("State root calculation time")]
+ public static double StateMerkleizationTime { get; set; }
+
+ [DetailedMetric]
+ [ExponentialPowerHistogramMetric(Start = 10, Factor = 1.2, Count = 30)]
+ [Description("Histogram of block MGas per second")]
+ public static IMetricObserver BlockMGasPerSec { get; set; } = new NoopMetricObserver();
+
+ [DetailedMetric]
+ [ExponentialPowerHistogramMetric(Start = 100, Factor = 1.25, Count = 50)]
+ [Description("Histogram of block prorcessing time")]
+ public static IMetricObserver BlockProcessingTimeMicros { get; set; } = new NoopMetricObserver();
}
diff --git a/src/Nethermind/Nethermind.Blockchain/Nethermind.Blockchain.csproj b/src/Nethermind/Nethermind.Blockchain/Nethermind.Blockchain.csproj
index 548e4443439..a760ccb873b 100644
--- a/src/Nethermind/Nethermind.Blockchain/Nethermind.Blockchain.csproj
+++ b/src/Nethermind/Nethermind.Blockchain/Nethermind.Blockchain.csproj
@@ -12,6 +12,7 @@
+
diff --git a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs
index 7d75114dc6a..76427295f53 100644
--- a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs
+++ b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs
@@ -122,7 +122,7 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f
ITransactionComparerProvider transactionComparerProvider =
new TransactionComparerProvider(specProvider, blockTree);
- CodeInfoRepository codeInfoRepository = new();
+ EthereumCodeInfoRepository codeInfoRepository = new();
TxPool.TxPool txPool = new(_ethereumEcdsa,
new BlobTxStorage(),
new ChainHeadInfoProvider(new FixedForkActivationChainHeadSpecProvider(SepoliaSpecProvider.Instance), blockTree, stateProvider, codeInfoRepository),
diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs
index f0222a28601..7d6b1015565 100644
--- a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs
+++ b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Autofac;
using Autofac.Features.AttributeFilters;
using Nethermind.Abi;
using Nethermind.Blockchain;
@@ -64,13 +65,14 @@ public class StartBlockProducerAuRa(
ITxPool txPool,
IStateReader apiStateReader,
ITransactionComparerProvider transactionComparerProvider,
- CompositeBlockPreprocessorStep compositeBlockPreprocessorStep,
[KeyFilter(IProtectedPrivateKey.NodeKey)] IProtectedPrivateKey protectedPrivateKey,
ICryptoRandom cryptoRandom,
IBlockValidator blockValidator,
IRewardCalculatorSource rewardCalculatorSource,
IAuRaStepCalculator stepCalculator,
AuRaGasLimitOverrideFactory gasLimitOverrideFactory,
+ IWorldStateManager worldStateManager,
+ ILifetimeScope lifetimeScope,
ILogManager logManager)
{
private readonly AuRaChainSpecEngineParameters _parameters = chainSpec.EngineChainSpecParametersProvider
@@ -125,14 +127,14 @@ public IBlockProducer BuildProducer()
return blockProducer;
}
- private BlockProcessor CreateBlockProcessor(IReadOnlyTxProcessingScope changeableTxProcessingEnv)
+ private BlockProcessor CreateBlockProcessor(ITransactionProcessor txProcessor, IWorldState worldState)
{
ITxFilter auRaTxFilter = apiTxAuRaFilterBuilders.CreateAuRaTxFilter(
new LocalTxFilter(engineSigner));
_validator = new AuRaValidatorFactory(abiEncoder,
- changeableTxProcessingEnv.WorldState,
- changeableTxProcessingEnv.TransactionProcessor,
+ worldState,
+ txProcessor,
blockTree,
readOnlyTxProcessingEnvFactory.Create(),
receiptStorage,
@@ -158,9 +160,6 @@ private BlockProcessor CreateBlockProcessor(IReadOnlyTxProcessingScope changeabl
IDictionary> rewriteBytecode = _parameters.RewriteBytecode;
ContractRewriter? contractRewriter = rewriteBytecode?.Count > 0 ? new ContractRewriter(rewriteBytecode) : null;
- ITransactionProcessor txProcessor = changeableTxProcessingEnv.TransactionProcessor;
- IWorldState worldState = changeableTxProcessingEnv.WorldState;
-
var transactionExecutor = new BlockProcessor.BlockProductionTransactionsExecutor(
new BuildUpTransactionProcessorAdapter(txProcessor),
worldState,
@@ -258,24 +257,17 @@ BlockProducerEnv Create()
{
ReadOnlyBlockTree readOnlyBlockTree = blockTree.AsReadOnly();
- IReadOnlyTxProcessorSource txProcessingEnv = readOnlyTxProcessingEnvFactory.Create();
- IReadOnlyTxProcessingScope scope = txProcessingEnv.Build(null);
- BlockProcessor blockProcessor = CreateBlockProcessor(scope);
-
- IBlockchainProcessor blockchainProcessor =
- new BlockchainProcessor(
- readOnlyBlockTree,
- blockProcessor,
- compositeBlockPreprocessorStep,
- apiStateReader,
- logManager,
- BlockchainProcessor.Options.NoReceipts);
+ IWorldState worldState = worldStateManager.CreateResettableWorldState();
+ ILifetimeScope innerLifetime = lifetimeScope.BeginLifetimeScope((builder) => builder
+ .AddSingleton(worldState)
+ .AddSingleton(BlockchainProcessor.Options.NoReceipts)
+ .AddSingleton(CreateBlockProcessor)
+ .AddDecorator());
+ lifetimeScope.Disposer.AddInstanceForAsyncDisposal(innerLifetime);
- OneTimeChainProcessor chainProcessor = new(
- scope.WorldState,
- blockchainProcessor);
+ IBlockchainProcessor chainProcessor = innerLifetime.Resolve();
- return new BlockProducerEnv(readOnlyBlockTree, chainProcessor, scope.WorldState, CreateTxSourceForProducer());
+ return new BlockProducerEnv(readOnlyBlockTree, chainProcessor, worldState, CreateTxSourceForProducer());
}
return _blockProducerContext ??= Create();
diff --git a/src/Nethermind/Nethermind.Consensus.Clique/SnapshotManager.cs b/src/Nethermind/Nethermind.Consensus.Clique/SnapshotManager.cs
index f909b71f131..e782eac5931 100644
--- a/src/Nethermind/Nethermind.Consensus.Clique/SnapshotManager.cs
+++ b/src/Nethermind/Nethermind.Consensus.Clique/SnapshotManager.cs
@@ -67,7 +67,7 @@ public Address GetBlockSealer(BlockHeader header)
Signature signature = new(signatureBytes);
signature.V += Signature.VOffset;
ValueHash256 message = CalculateCliqueHeaderHash(header);
- Address address = _ecdsa.RecoverAddress(signatureBytes, in message);
+ Address address = _ecdsa.RecoverAddress(signature, in message);
_signatures.Set(header.Hash, address);
return address;
}
diff --git a/src/Nethermind/Nethermind.Consensus.Test/CensorshipDetectorTests.cs b/src/Nethermind/Nethermind.Consensus.Test/CensorshipDetectorTests.cs
index d2797b8a1d5..8c5650976ba 100644
--- a/src/Nethermind/Nethermind.Consensus.Test/CensorshipDetectorTests.cs
+++ b/src/Nethermind/Nethermind.Consensus.Test/CensorshipDetectorTests.cs
@@ -259,7 +259,7 @@ private TxPool.TxPool CreatePool(bool eip1559Enabled = true)
return new(
_ethereumEcdsa,
new BlobTxStorage(),
- new ChainHeadInfoProvider(_specProvider, _blockTree, _stateProvider, new CodeInfoRepository()),
+ new ChainHeadInfoProvider(_specProvider, _blockTree, _stateProvider, new EthereumCodeInfoRepository()),
new TxPoolConfig(),
new TxValidator(_specProvider.ChainId),
_logManager,
diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs
index 9ef10276ead..04aac92a486 100644
--- a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs
+++ b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs
@@ -73,7 +73,7 @@ public void CaptureStartStats()
_startSStoreOps = Evm.Metrics.ThreadLocalSStoreOpcode;
_startCallOps = Evm.Metrics.ThreadLocalCalls;
_startEmptyCalls = Evm.Metrics.ThreadLocalEmptyCalls;
- _startCachedContractsUsed = Db.Metrics.ThreadLocalCodeDbCache;
+ _startCachedContractsUsed = Evm.Metrics.ThreadLocalCodeDbCache;
_startContractsAnalyzed = Evm.Metrics.ThreadLocalContractsAnalysed;
_startCreateOps = Evm.Metrics.ThreadLocalCreates;
_startSelfDestructOps = Evm.Metrics.ThreadLocalSelfDestructs;
@@ -106,7 +106,7 @@ public void UpdateStats(Block? block, BlockHeader? baseBlock, long blockProcessi
blockData.CurrentSStoreOps = Evm.Metrics.ThreadLocalSStoreOpcode;
blockData.CurrentCallOps = Evm.Metrics.ThreadLocalCalls;
blockData.CurrentEmptyCalls = Evm.Metrics.ThreadLocalEmptyCalls;
- blockData.CurrentCachedContractsUsed = Db.Metrics.ThreadLocalCodeDbCache;
+ blockData.CurrentCachedContractsUsed = Evm.Metrics.ThreadLocalCodeDbCache;
blockData.CurrentContractsAnalyzed = Evm.Metrics.ThreadLocalContractsAnalysed;
blockData.CurrentCreatesOps = Evm.Metrics.ThreadLocalCreates;
blockData.CurrentSelfDestructOps = Evm.Metrics.ThreadLocalSelfDestructs;
diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs
index 967729a330a..b9fac250056 100644
--- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs
+++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs
@@ -41,6 +41,7 @@
using Nethermind.Specs.ChainSpecStyle;
using Nethermind.Specs.Test;
using Nethermind.Evm.State;
+using Nethermind.Network;
using Nethermind.State;
using Nethermind.State.Repositories;
using Nethermind.TxPool;
@@ -58,6 +59,7 @@ public class TestBlockchain : IDisposable
public IMainProcessingContext MainProcessingContext => _fromContainer.MainProcessingContext;
public IReceiptStorage ReceiptStorage => _fromContainer.ReceiptStorage;
public ITxPool TxPool => _fromContainer.TxPool;
+ public IForkInfo ForkInfo => _fromContainer.ForkInfo;
public IWorldStateManager WorldStateManager => _fromContainer.WorldStateManager;
public IReadOnlyTxProcessingEnvFactory ReadOnlyTxProcessingEnvFactory => _fromContainer.ReadOnlyTxProcessingEnvFactory;
public IShareableTxProcessorSource ShareableTxProcessorSource => _fromContainer.ShareableTxProcessorSource;
@@ -162,7 +164,8 @@ private record FromContainer(
ManualTimestamper ManualTimestamper,
IManualBlockProductionTrigger BlockProductionTrigger,
IShareableTxProcessorSource ShareableTxProcessorSource,
- ISealer Sealer
+ ISealer Sealer,
+ IForkInfo ForkInfo
)
{
}
diff --git a/src/Nethermind/Nethermind.Core.Test/Container/KeyedMapperRegistrationSourceTests.cs b/src/Nethermind/Nethermind.Core.Test/Container/KeyedMapperRegistrationSourceTests.cs
new file mode 100644
index 00000000000..9b697e1c3c6
--- /dev/null
+++ b/src/Nethermind/Nethermind.Core.Test/Container/KeyedMapperRegistrationSourceTests.cs
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using Autofac;
+using FluentAssertions;
+using NUnit.Framework;
+
+namespace Nethermind.Core.Test.Container;
+
+public class KeyedMapperRegistrationSourceTests
+{
+ [Test]
+ public void TestCanMap()
+ {
+ using IContainer cont = new ContainerBuilder()
+ .AddKeyedSingleton("Key", new ClassA("Property1"))
+ .AddKeyedAdapter((a) => new ClassB(a.Property))
+ .Build();
+
+ cont.ResolveKeyed("Key").Property.Should().Be("Property1");
+ }
+
+ private record ClassA(string Property);
+ private record ClassB(string Property);
+}
diff --git a/src/Nethermind/Nethermind.Core.Test/Db/TestMemDbProvider.cs b/src/Nethermind/Nethermind.Core.Test/Db/TestMemDbProvider.cs
new file mode 100644
index 00000000000..b13c69f5aff
--- /dev/null
+++ b/src/Nethermind/Nethermind.Core.Test/Db/TestMemDbProvider.cs
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+
+using System;
+using System.Threading.Tasks;
+using Autofac;
+using Nethermind.Api;
+using Nethermind.Blockchain.Receipts;
+using Nethermind.Blockchain.Synchronization;
+using Nethermind.Db;
+using Nethermind.Init.Modules;
+
+namespace Nethermind.Core.Test.Db
+{
+ public class TestMemDbProvider
+ {
+ public static Task InitAsync()
+ {
+ return Task.FromResult(Init());
+ }
+
+ public static IDbProvider Init()
+ {
+ return new ContainerBuilder()
+ .AddModule(new DbModule(new InitConfig() { DiagnosticMode = DiagnosticMode.MemDb }, new ReceiptConfig(), new SyncConfig()))
+ .AddSingleton()
+ .Build()
+ .Resolve();
+ }
+ }
+
+ ///
+ /// Like , but also dispose lifetime scope. Useful for existing test to make sure
+ /// container is disposed properly.
+ ///
+ public class ContainerOwningDbProvider(ILifetimeScope ctx) : DbProvider(ctx), IDisposable
+ {
+ public override void Dispose()
+ {
+ ctx.Dispose();
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNethermindModule.cs b/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNethermindModule.cs
index c141f4418e9..5d2a0f13e2a 100644
--- a/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNethermindModule.cs
+++ b/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNethermindModule.cs
@@ -61,7 +61,6 @@ protected override void Load(ContainerBuilder builder)
initConfig.BackgroundTaskMaxNumber,
logManager))
.AddSingleton(new FileSystem())
- .AddSingleton(new DbProvider())
.AddSingleton(new ProcessExitSource(default))
.AddSingleton()
diff --git a/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs b/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs
index d9fcb974266..07434083950 100644
--- a/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs
+++ b/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs
@@ -38,7 +38,7 @@ protected override void Load(ContainerBuilder builder)
{
IWorldState worldState = ctx.Resolve().GlobalWorldState;
PreBlockCaches? preBlockCaches = (worldState as IPreBlockCaches)?.Caches;
- return new CodeInfoRepository(preBlockCaches?.PrecompileCache);
+ return new EthereumCodeInfoRepository(preBlockCaches?.PrecompileCache);
})
.AddSingleton()
@@ -115,7 +115,7 @@ private MainBlockProcessingContext ConfigureMainBlockProcessingContext(ILifetime
return innerScope.Resolve();
}
- private class AutoBlockProducerFactory(ILifetimeScope rootLifetime, IBlockProducerEnvFactory producerEnvFactory) : IBlockProducerFactory where T : IBlockProducer
+ public class AutoBlockProducerFactory(ILifetimeScope rootLifetime, IBlockProducerEnvFactory producerEnvFactory) : IBlockProducerFactory where T : IBlockProducer
{
public IBlockProducer InitBlockProducer()
{
diff --git a/src/Nethermind/Nethermind.Core.Test/Modules/TestEnvironmentModule.cs b/src/Nethermind/Nethermind.Core.Test/Modules/TestEnvironmentModule.cs
index 664c4a0c3cb..90b4e668fb9 100644
--- a/src/Nethermind/Nethermind.Core.Test/Modules/TestEnvironmentModule.cs
+++ b/src/Nethermind/Nethermind.Core.Test/Modules/TestEnvironmentModule.cs
@@ -39,7 +39,6 @@ protected override void Load(ContainerBuilder builder)
builder
.AddSingleton(new TestLogManager(LogLevel.Error)) // Limbologs actually have IsTrace set to true, so actually slow.
.AddSingleton((_) => new MemDbFactory())
- .AddSingleton(TestMemDbProvider.Init())
// These two dont use db provider
.AddKeyedSingleton(DbNames.PeersDb, (_) => new MemDb())
.AddKeyedSingleton(DbNames.DiscoveryNodes, (_) => new MemDb())
diff --git a/src/Nethermind/Nethermind.Core.Test/TestWorldStateFactory.cs b/src/Nethermind/Nethermind.Core.Test/TestWorldStateFactory.cs
index 27517c12d8f..afe1a55f29a 100644
--- a/src/Nethermind/Nethermind.Core.Test/TestWorldStateFactory.cs
+++ b/src/Nethermind/Nethermind.Core.Test/TestWorldStateFactory.cs
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only
using Nethermind.Consensus.Validators;
+using Nethermind.Core.Test.Db;
using Nethermind.Db;
using Nethermind.Logging;
using Nethermind.Evm.State;
diff --git a/src/Nethermind/Nethermind.Core/Container/KeyedMapperRegistrationSource.cs b/src/Nethermind/Nethermind.Core/Container/KeyedMapperRegistrationSource.cs
new file mode 100644
index 00000000000..dd0e7b21ed1
--- /dev/null
+++ b/src/Nethermind/Nethermind.Core/Container/KeyedMapperRegistrationSource.cs
@@ -0,0 +1,48 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Autofac;
+using Autofac.Core;
+using Autofac.Core.Activators.Delegate;
+using Autofac.Core.Lifetime;
+using Autofac.Core.Registration;
+
+namespace Nethermind.Core.Container;
+
+///
+/// Utility that map between two type that act on keyed service.
+///
+///
+///
+///
+public class KeyedMapperRegistrationSource(Func mapper) : IRegistrationSource where TFrom : notnull
+{
+ public IEnumerable RegistrationsFor(Service service, Func> registrationAccessor)
+ {
+ if (service is not KeyedService keyedService || keyedService.ServiceType != typeof(TTo))
+ {
+ // Not a keyed service
+ return Enumerable.Empty();
+ }
+
+ ComponentRegistration registration = new ComponentRegistration(
+ Guid.NewGuid(),
+ new DelegateActivator(keyedService.ServiceType, (c, p) =>
+ {
+ TFrom from = c.ResolveKeyed(keyedService.ServiceKey);
+ return mapper(from)!;
+ }),
+ new RootScopeLifetime(),
+ InstanceSharing.Shared,
+ InstanceOwnership.OwnedByLifetimeScope,
+ new[] { service },
+ new Dictionary());
+
+ return [registration];
+ }
+
+ public bool IsAdapterForIndividualComponents => true;
+}
diff --git a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs
index b33a3e412c4..0fe01a8c5ca 100644
--- a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs
+++ b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs
@@ -486,6 +486,11 @@ public static IRegistrationBuilder Fixed(this
reg.RegistrationData.Options |= RegistrationOptions.Fixed;
return reg;
}
+
+ public static ContainerBuilder AddKeyedAdapter(this ContainerBuilder builder, Func mapper) where TFrom : notnull
+ {
+ return builder.AddSource(new KeyedMapperRegistrationSource(mapper));
+ }
}
///
diff --git a/src/Nethermind/Nethermind.Core/Eip2935Constants.cs b/src/Nethermind/Nethermind.Core/Eip2935Constants.cs
index 63664121d6a..1cfd0c1efc0 100644
--- a/src/Nethermind/Nethermind.Core/Eip2935Constants.cs
+++ b/src/Nethermind/Nethermind.Core/Eip2935Constants.cs
@@ -8,6 +8,8 @@ namespace Nethermind.Core;
///
public static class Eip2935Constants
{
+ public const string ContractAddressKey = "HISTORY_STORAGE_ADDRESS";
+
///
/// The HISTORY_STORAGE_ADDRESS parameter.
///
diff --git a/src/Nethermind/Nethermind.Core/Eip4788Constants.cs b/src/Nethermind/Nethermind.Core/Eip4788Constants.cs
index fed5db663d8..af10e162a95 100644
--- a/src/Nethermind/Nethermind.Core/Eip4788Constants.cs
+++ b/src/Nethermind/Nethermind.Core/Eip4788Constants.cs
@@ -8,6 +8,8 @@ namespace Nethermind.Core;
///
public static class Eip4788Constants
{
+ public const string ContractAddressKey = "BEACON_ROOTS_ADDRESS";
+
///
/// Gets the BEACON_ROOTS_ADDRESS parameter.
///
diff --git a/src/Nethermind/Nethermind.Core/Eip6110Constants.cs b/src/Nethermind/Nethermind.Core/Eip6110Constants.cs
index 98eb35fa328..2fadd552747 100644
--- a/src/Nethermind/Nethermind.Core/Eip6110Constants.cs
+++ b/src/Nethermind/Nethermind.Core/Eip6110Constants.cs
@@ -5,6 +5,8 @@ namespace Nethermind.Core;
public static class Eip6110Constants
{
+ public const string ContractAddressKey = "DEPOSIT_CONTRACT_ADDRESS";
+
public static readonly Address MainnetDepositContractAddress = new("0x00000000219ab540356cbb839cbe05303d7705fa");
public static readonly Address HoleskyDepositContractAddress = new("0x4242424242424242424242424242424242424242");
public static readonly Address SepoliaDepositContractAddress = new("0x7f02c3e3c98b133055b8b348b2ac625669ed295d");
diff --git a/src/Nethermind/Nethermind.Core/Eip7002Constants.cs b/src/Nethermind/Nethermind.Core/Eip7002Constants.cs
index b786664cd81..f7033eae7c4 100644
--- a/src/Nethermind/Nethermind.Core/Eip7002Constants.cs
+++ b/src/Nethermind/Nethermind.Core/Eip7002Constants.cs
@@ -5,5 +5,7 @@ namespace Nethermind.Core;
public static class Eip7002Constants
{
+ public const string ContractAddressKey = "WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS";
+
public static readonly Address WithdrawalRequestPredeployAddress = new("0x00000961Ef480Eb55e80D19ad83579A64c007002");
}
diff --git a/src/Nethermind/Nethermind.Core/Eip7251Constants.cs b/src/Nethermind/Nethermind.Core/Eip7251Constants.cs
index a0a453010e4..171c30d2abf 100644
--- a/src/Nethermind/Nethermind.Core/Eip7251Constants.cs
+++ b/src/Nethermind/Nethermind.Core/Eip7251Constants.cs
@@ -5,5 +5,7 @@ namespace Nethermind.Core;
public static class Eip7251Constants
{
+ public const string ContractAddressKey = "CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS";
+
public static readonly Address ConsolidationRequestPredeployAddress = new("0x0000BBdDc7CE488642fb579F8B00f3a590007251");
}
diff --git a/src/Nethermind/Nethermind.Core/Extensions/ByteArrayExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/ByteArrayExtensions.cs
index 92bda49291a..94c1c12f86a 100644
--- a/src/Nethermind/Nethermind.Core/Extensions/ByteArrayExtensions.cs
+++ b/src/Nethermind/Nethermind.Core/Extensions/ByteArrayExtensions.cs
@@ -56,18 +56,23 @@ public static byte[] SliceWithZeroPaddingEmptyOnError(this byte[] bytes, int sta
return slice;
}
- public static byte[] SliceWithZeroPaddingEmptyOnError(this ReadOnlySpan bytes, int startIndex, int length)
+ public static ReadOnlySpan SliceWithZeroPaddingEmptyOnError(this ReadOnlySpan bytes, int startIndex, int length)
{
int copiedFragmentLength = Math.Min(bytes.Length - startIndex, length);
if (copiedFragmentLength <= 0)
{
- return [];
+ return default;
}
- byte[] slice = new byte[length];
+ ReadOnlySpan sliced = bytes.Slice(startIndex, copiedFragmentLength);
+ if (copiedFragmentLength < length)
+ {
+ byte[] extended = new byte[length];
+ sliced.CopyTo(extended);
+ sliced = extended;
+ }
- bytes.Slice(startIndex, copiedFragmentLength).CopyTo(slice.AsSpan(0, copiedFragmentLength));
- return slice;
+ return sliced;
}
}
diff --git a/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs b/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs
index 0f78e509169..39158a6c10b 100644
--- a/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs
+++ b/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs
@@ -182,7 +182,7 @@ public static bool IsZero(this ReadOnlySpan bytes)
return bytes.IndexOfAnyExcept((byte)0) < 0;
}
- public static int LeadingZerosCount(this Span bytes, int startIndex = 0)
+ public static int LeadingZerosCount(this ReadOnlySpan bytes, int startIndex = 0)
{
int nonZeroIndex = bytes[startIndex..].IndexOfAnyExcept((byte)0);
return nonZeroIndex < 0 ? bytes.Length - startIndex : nonZeroIndex;
diff --git a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs
index f3250d2437f..ef0163a626c 100644
--- a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs
+++ b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs
@@ -402,7 +402,7 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec
public bool ModExpEnabled => IsEip198Enabled;
- public bool Bn128Enabled => IsEip196Enabled && IsEip197Enabled;
+ public bool BN254Enabled => IsEip196Enabled && IsEip197Enabled;
public bool BlakeEnabled => IsEip152Enabled;
diff --git a/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs b/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs
index 2da9efc5a45..65aef9301ec 100644
--- a/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs
+++ b/src/Nethermind/Nethermind.Core/Specs/ReleaseSpecDecorator.cs
@@ -112,7 +112,7 @@ public class ReleaseSpecDecorator(IReleaseSpec spec) : IReleaseSpec
public virtual bool UseTxAccessLists => spec.UseTxAccessLists;
public virtual bool AddCoinbaseToTxAccessList => spec.AddCoinbaseToTxAccessList;
public virtual bool ModExpEnabled => spec.ModExpEnabled;
- public virtual bool Bn128Enabled => spec.Bn128Enabled;
+ public virtual bool BN254Enabled => spec.BN254Enabled;
public virtual bool BlakeEnabled => spec.BlakeEnabled;
public virtual bool Bls381Enabled => spec.Bls381Enabled;
public virtual bool ChargeForTopLevelCreate => spec.ChargeForTopLevelCreate;
diff --git a/src/Nethermind/Nethermind.Crypto/EthereumEcdsa.cs b/src/Nethermind/Nethermind.Crypto/EthereumEcdsa.cs
index 00fd2905cef..73f844d8aca 100644
--- a/src/Nethermind/Nethermind.Crypto/EthereumEcdsa.cs
+++ b/src/Nethermind/Nethermind.Crypto/EthereumEcdsa.cs
@@ -4,10 +4,8 @@
using System;
using System.Globalization;
using System.Numerics;
-using System.Runtime.CompilerServices;
using Nethermind.Core;
using Nethermind.Core.Crypto;
-using Nethermind.Core.Specs;
namespace Nethermind.Crypto
{
@@ -27,15 +25,9 @@ public class EthereumEcdsa(ulong chainId) : Ecdsa, IEthereumEcdsa
public ulong ChainId => chainId;
- public EthereumEcdsa(ISpecProvider specProvider) : this(specProvider.ChainId)
- {
- }
-
public Address? RecoverAddress(Signature signature, in ValueHash256 message) => RecoverAddress(signature.Bytes, signature.RecoveryId, message.Bytes);
- public Address? RecoverAddress(Span signatureBytes65, in ValueHash256 message) => RecoverAddress(signatureBytes65[..64], signatureBytes65[64], message.Bytes);
-
- public static Address? RecoverAddress(Span signatureBytes64, byte v, ReadOnlySpan message)
+ private static Address? RecoverAddress(Span signatureBytes64, byte v, ReadOnlySpan message)
{
Span publicKey = stackalloc byte[65];
bool success = SpanSecP256k1.RecoverKeyFromCompact(
diff --git a/src/Nethermind/Nethermind.Crypto/IEthereumEcdsa.cs b/src/Nethermind/Nethermind.Crypto/IEthereumEcdsa.cs
index ed03f79d939..b4a02f65c09 100644
--- a/src/Nethermind/Nethermind.Crypto/IEthereumEcdsa.cs
+++ b/src/Nethermind/Nethermind.Crypto/IEthereumEcdsa.cs
@@ -14,8 +14,5 @@ public interface IEthereumEcdsa : IEcdsa
=> RecoverAddress(signature, in message.ValueHash256);
Address? RecoverAddress(Signature signature, in ValueHash256 message);
- Address? RecoverAddress(Span signatureBytes, Hash256 message)
- => RecoverAddress(signatureBytes, in message.ValueHash256);
- Address? RecoverAddress(Span signatureBytes, in ValueHash256 message);
}
}
diff --git a/src/Nethermind/Nethermind.Crypto/NullEthereumEcdsa.cs b/src/Nethermind/Nethermind.Crypto/NullEthereumEcdsa.cs
index 739d61d290c..9274ff54140 100644
--- a/src/Nethermind/Nethermind.Crypto/NullEthereumEcdsa.cs
+++ b/src/Nethermind/Nethermind.Crypto/NullEthereumEcdsa.cs
@@ -37,11 +37,6 @@ public Address RecoverAddress(Transaction tx, bool useSignatureChainId = false)
throw new InvalidOperationException($"{nameof(NullEthereumEcdsa)} does not expect any calls");
}
- public Address RecoverAddress(Span signatureBytes, in ValueHash256 message)
- {
- throw new InvalidOperationException($"{nameof(NullEthereumEcdsa)} does not expect any calls");
- }
-
public bool Verify(Address sender, Transaction tx)
{
throw new InvalidOperationException($"{nameof(NullEthereumEcdsa)} does not expect any calls");
diff --git a/src/Nethermind/Nethermind.Db.Rocks/RocksDbFactory.cs b/src/Nethermind/Nethermind.Db.Rocks/RocksDbFactory.cs
index 53eb3eb7c50..e0c02bbbe04 100644
--- a/src/Nethermind/Nethermind.Db.Rocks/RocksDbFactory.cs
+++ b/src/Nethermind/Nethermind.Db.Rocks/RocksDbFactory.cs
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only
using System;
+using Nethermind.Api;
using Nethermind.Db.Rocks.Config;
using Nethermind.Logging;
@@ -17,6 +18,12 @@ public class RocksDbFactory : IDbFactory
private readonly IntPtr _sharedCache;
+ public RocksDbFactory(IDbConfig dbConfig, IInitConfig initConfig, ILogManager logManager)
+ : this(dbConfig, logManager, initConfig.BaseDbPath)
+ {
+
+ }
+
public RocksDbFactory(IDbConfig dbConfig, ILogManager logManager, string basePath)
{
_dbConfig = dbConfig;
diff --git a/src/Nethermind/Nethermind.Db.Test/DbProviderTests.cs b/src/Nethermind/Nethermind.Db.Test/DbProviderTests.cs
deleted file mode 100644
index edc441243f8..00000000000
--- a/src/Nethermind/Nethermind.Db.Test/DbProviderTests.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
-// SPDX-License-Identifier: LGPL-3.0-only
-
-using System;
-using NUnit.Framework;
-
-namespace Nethermind.Db.Test;
-
-[Parallelizable(ParallelScope.All)]
-public class DbProviderTests
-{
- [Test]
- public void DbProvider_CanRegisterMemDb()
- {
- MemDbFactory memDbFactory = new MemDbFactory();
- using (DbProvider dbProvider = new DbProvider())
- {
- IDb memDb = memDbFactory.CreateDb(new DbSettings("MemDb", "MemDb"));
- dbProvider.RegisterDb("MemDb", memDb);
- IDb db = dbProvider.GetDb("MemDb");
- Assert.That(db, Is.EqualTo(memDb));
- }
- }
-
- [Test]
- public void DbProvider_CanRegisterColumnsDb()
- {
- using (DbProvider dbProvider = new DbProvider())
- {
- MemDbFactory memDbFactory = new MemDbFactory();
- IColumnsDb memSnapshotableDb = memDbFactory.CreateColumnsDb("ColumnsDb");
- dbProvider.RegisterColumnDb("ColumnsDb", memSnapshotableDb);
- IColumnsDb columnsDb = dbProvider.GetColumnDb("ColumnsDb");
- Assert.That(columnsDb, Is.EqualTo(memSnapshotableDb));
- Assert.That(memSnapshotableDb is IColumnsDb, Is.True);
- }
- }
-
- [Test]
- public void DbProvider_ThrowExceptionOnRegisteringTheSameDb()
- {
- using (DbProvider dbProvider = new DbProvider())
- {
- MemDbFactory memDbFactory = new MemDbFactory();
- IColumnsDb memSnapshotableDb = memDbFactory.CreateColumnsDb("ColumnsDb");
- dbProvider.RegisterColumnDb("ColumnsDb", memSnapshotableDb);
- Assert.Throws(() => dbProvider.RegisterColumnDb("columnsdb", new MemColumnsDb()));
- }
- }
-
- [Test]
- public void DbProvider_ThrowExceptionOnGettingNotRegisteredDb()
- {
- using (DbProvider dbProvider = new DbProvider())
- {
- MemDbFactory memDbFactory = new MemDbFactory();
- IColumnsDb memSnapshotableDb = memDbFactory.CreateColumnsDb("ColumnsDb");
- dbProvider.RegisterColumnDb("ColumnsDb", memSnapshotableDb);
- Assert.Throws(() => dbProvider.GetColumnDb("differentdb"));
- }
- }
-}
diff --git a/src/Nethermind/Nethermind.Db.Test/DbTrackerTests.cs b/src/Nethermind/Nethermind.Db.Test/DbTrackerTests.cs
new file mode 100644
index 00000000000..27a1344fc3f
--- /dev/null
+++ b/src/Nethermind/Nethermind.Db.Test/DbTrackerTests.cs
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System.Linq;
+using Autofac;
+using FluentAssertions;
+using Nethermind.Core;
+using NUnit.Framework;
+
+namespace Nethermind.Db.Test;
+
+public class DbTrackerTests
+{
+ [Test]
+ public void TestTrackOnlyCreatedDb()
+ {
+ using IContainer container = new ContainerBuilder()
+ .AddSingleton()
+ .AddDecorator()
+ .AddSingleton()
+ .Build();
+
+ IDbFactory dbFactory = container.Resolve();
+
+ DbTracker tracker = container.Resolve();
+ tracker.GetAllDbMeta().Count().Should().Be(0);
+
+ dbFactory.CreateDb(new DbSettings("TestDb", "TestDb"));
+
+ tracker.GetAllDbMeta().Count().Should().Be(1);
+ var firstEntry = tracker.GetAllDbMeta().First();
+ firstEntry.Key.Should().Be("TestDb");
+ }
+}
diff --git a/src/Nethermind/Nethermind.Db.Test/ReadOnlyDbProviderTests.cs b/src/Nethermind/Nethermind.Db.Test/ReadOnlyDbProviderTests.cs
index 5bb30423e2d..7bbeaa18d68 100644
--- a/src/Nethermind/Nethermind.Db.Test/ReadOnlyDbProviderTests.cs
+++ b/src/Nethermind/Nethermind.Db.Test/ReadOnlyDbProviderTests.cs
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
+using NSubstitute;
using NUnit.Framework;
namespace Nethermind.Db.Test
@@ -12,7 +13,7 @@ public class ReadOnlyDbProviderTests
[TestCase(false)]
public void Can_clear(bool localChanges)
{
- ReadOnlyDbProvider dbProvider = new(new DbProvider(), localChanges);
+ ReadOnlyDbProvider dbProvider = new(Substitute.For(), localChanges);
dbProvider.ClearTempChanges();
}
}
diff --git a/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbFactoryTests.cs b/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbFactoryTests.cs
index 276b7251286..09b1d477fbb 100644
--- a/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbFactoryTests.cs
+++ b/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbFactoryTests.cs
@@ -2,7 +2,10 @@
// SPDX-License-Identifier: LGPL-3.0-only
using System.IO.Abstractions;
+using Autofac;
using FluentAssertions;
+using Nethermind.Core;
+using Nethermind.Core.Test.Modules;
using Nethermind.Db.FullPruning;
using Nethermind.Db.Rpc;
using Nethermind.JsonRpc.Client;
@@ -31,9 +34,12 @@ static void ValidateDb(params object[] dbs)
IJsonRpcClient jsonRpcClient = Substitute.For();
IDbFactory rpcDbFactory = new RpcDbFactory(new MemDbFactory(), jsonSerializer, jsonRpcClient, LimboLogs.Instance);
- IDbProvider memDbProvider = new DbProvider();
- StandardDbInitializer standardDbInitializer = new(memDbProvider, rpcDbFactory, Substitute.For());
- standardDbInitializer.InitStandardDbs(true);
+ using IContainer container = new ContainerBuilder()
+ .AddModule(new TestNethermindModule())
+ .AddSingleton(rpcDbFactory)
+ .Build();
+
+ IDbProvider memDbProvider = container.Resolve();
ValidateDb>(
memDbProvider.ReceiptsDb);
diff --git a/src/Nethermind/Nethermind.Db.Test/StandardDbInitializerTests.cs b/src/Nethermind/Nethermind.Db.Test/StandardDbInitializerTests.cs
index 6b927954aae..c47dfff4c42 100644
--- a/src/Nethermind/Nethermind.Db.Test/StandardDbInitializerTests.cs
+++ b/src/Nethermind/Nethermind.Db.Test/StandardDbInitializerTests.cs
@@ -5,10 +5,17 @@
using System.IO;
using System.IO.Abstractions;
using System.Threading.Tasks;
+using Autofac;
using FluentAssertions;
+using Nethermind.Api;
+using Nethermind.Blockchain.Receipts;
+using Nethermind.Blockchain.Synchronization;
+using Nethermind.Core;
+using Nethermind.Core.Test.Db;
using Nethermind.Db.FullPruning;
using Nethermind.Db.Rocks;
using Nethermind.Db.Rocks.Config;
+using Nethermind.Init.Modules;
using Nethermind.Logging;
using NSubstitute;
using NUnit.Framework;
@@ -66,16 +73,31 @@ public async Task InitializerTests_WithPruning()
dbProvider.StateDb.Should().BeOfType();
}
- private async Task InitializeStandardDb(bool useReceipts, bool useMemDb, string path)
+ private Task InitializeStandardDb(bool useReceipts, bool useMemDb, string path)
{
- IDbProvider dbProvider = new DbProvider();
- IDbFactory dbFactory = useMemDb
- ? new MemDbFactory()
- : new RocksDbFactory(new DbConfig(), LimboLogs.Instance, Path.Combine(_folderWithDbs, path));
+ IInitConfig initConfig = new InitConfig()
+ {
+ DiagnosticMode = useMemDb ? DiagnosticMode.MemDb : DiagnosticMode.None,
+ BaseDbPath = path
+ };
- StandardDbInitializer initializer = new(dbProvider, dbFactory, Substitute.For());
- await initializer.InitStandardDbsAsync(useReceipts);
- return dbProvider;
+ IContainer container = new ContainerBuilder()
+ .AddModule(new DbModule(initConfig, new ReceiptConfig()
+ {
+ StoreReceipts = useReceipts
+ }, new SyncConfig()
+ {
+ DownloadReceiptsInFastSync = useReceipts
+ }))
+ .AddModule(new WorldStateModule(initConfig)) // For the full pruning db
+ .AddSingleton(new DbConfig())
+ .AddSingleton(initConfig)
+ .AddSingleton(LimboLogs.Instance)
+ .AddSingleton()
+ .AddSingleton()
+ .Build();
+
+ return Task.FromResult(container.Resolve());
}
private static Type GetReceiptsType(bool useReceipts, Type receiptType = null) => useReceipts ? receiptType ?? typeof(ColumnsDb) : typeof(ReadOnlyColumnsDb);
diff --git a/src/Nethermind/Nethermind.Db/DbModule.cs b/src/Nethermind/Nethermind.Db/DbModule.cs
deleted file mode 100644
index 9405740570a..00000000000
--- a/src/Nethermind/Nethermind.Db/DbModule.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
-// SPDX-License-Identifier: LGPL-3.0-only
-
-using Autofac;
-using Nethermind.Core;
-
-namespace Nethermind.Db;
-
-public class DbModule : Module
-{
- protected override void Load(ContainerBuilder builder)
- {
- base.Load(builder);
- builder
- .AddScoped((dbProvider) => dbProvider.AsReadOnly(false));
-
- // TODO: Have hooks that automatically get these
- string[] dbNames = [
- DbNames.State,
- DbNames.Code,
- DbNames.Metadata,
- DbNames.BlockNumbers,
- DbNames.BadBlocks,
- DbNames.Blocks,
- DbNames.Headers,
- DbNames.BlockInfos,
- DbNames.BadBlocks,
- DbNames.Bloom,
- DbNames.Metadata,
- ];
- foreach (string dbName in dbNames)
- {
- ConfigureDb(builder, dbName);
- }
-
- ConfigureColumnDb(builder, DbNames.Receipts);
- }
-
- private static void ConfigureDb(ContainerBuilder builder, string dbName)
- {
- builder.Register((ctx) =>
- {
- IDbProvider dbProvider = ctx.Resolve();
- IDb db = dbProvider.GetDb(dbName);
- return db;
- })
- .ExternallyOwned()
- .Named(dbName)
- .Named(dbName)
- .Named(dbName)
- .Named(dbName);
-
- builder.Register((ctx) =>
- {
- IDbProvider dbProvider = ctx.Resolve();
- IDb db = dbProvider.GetDb(dbName);
- return db as ITunableDb ?? new NoopTunableDb();
- })
- .ExternallyOwned()
- .Named(dbName);
- }
-
-
- private static void ConfigureColumnDb(ContainerBuilder builder, string dbName)
- {
- builder.Register((ctx) =>
- {
- IDbProvider dbProvider = ctx.Resolve();
- IColumnsDb db = dbProvider.GetColumnDb(dbName);
- return db;
- })
- .ExternallyOwned()
- .As>();
-
- builder.Register((ctx) =>
- {
- IDbProvider dbProvider = ctx.Resolve();
- IColumnsDb db = dbProvider.GetColumnDb(dbName);
- return db as ITunableDb ?? new NoopTunableDb();
- })
- .ExternallyOwned()
- .Named(dbName);
- }
-}
diff --git a/src/Nethermind/Nethermind.Db/DbProvider.cs b/src/Nethermind/Nethermind.Db/DbProvider.cs
index bf7b9ee02e4..4c4583025ea 100644
--- a/src/Nethermind/Nethermind.Db/DbProvider.cs
+++ b/src/Nethermind/Nethermind.Db/DbProvider.cs
@@ -1,94 +1,24 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.IO;
+using Autofac;
namespace Nethermind.Db
{
- public class DbProvider : IDbProvider
+ public class DbProvider(IComponentContext ctx) : IDbProvider
{
- private readonly ConcurrentDictionary _registeredDbs =
- new(StringComparer.InvariantCultureIgnoreCase);
- private readonly ConcurrentDictionary _registeredColumnDbs =
- new(StringComparer.InvariantCultureIgnoreCase);
-
- public IDictionary RegisteredDbs => _registeredDbs;
- public IDictionary RegisteredColumnDbs => _registeredColumnDbs;
-
- public void Dispose()
+ public virtual void Dispose()
{
- foreach (KeyValuePair registeredDb in _registeredDbs)
- {
- registeredDb.Value?.Dispose();
- }
}
public T GetDb(string dbName) where T : class, IDb
{
- if (!_registeredDbs.TryGetValue(dbName, out IDb? found))
- {
- throw new ArgumentException($"{dbName} database has not been registered in {nameof(DbProvider)}.");
- }
-
- if (found is not T result)
- {
- throw new IOException(
- $"An attempt was made to resolve DB {dbName} as {typeof(T)} while its type is {found.GetType()}.");
- }
-
- return result;
- }
-
- public void RegisterDb(string dbName, T db) where T : class, IDb
- {
- if (_registeredDbs.ContainsKey(dbName))
- {
- throw new ArgumentException($"{dbName} has already registered.");
- }
-
- _registeredDbs.TryAdd(dbName, db);
+ return (T)ctx.ResolveKeyed(dbName);
}
public IColumnsDb GetColumnDb(string dbName)
{
- if (!_registeredColumnDbs.TryGetValue(dbName, out object found))
- {
- throw new ArgumentException($"{dbName} database has not been registered in {nameof(DbProvider)}.");
- }
-
- if (found is not IColumnsDb result)
- {
- throw new IOException(
- $"An attempt was made to resolve DB {dbName} as {typeof(T)} while its type is {found.GetType()}.");
- }
-
- return result;
- }
-
- public void RegisterColumnDb(string dbName, IColumnsDb db)
- {
- if (_registeredColumnDbs.ContainsKey(dbName))
- {
- throw new ArgumentException($"{dbName} has already registered.");
- }
-
- _registeredColumnDbs.TryAdd(dbName, db);
- }
-
- public IEnumerable> GetAllDbMeta()
- {
- foreach (KeyValuePair kv in _registeredDbs)
- {
- yield return new KeyValuePair(kv.Key, kv.Value);
- }
-
- foreach (KeyValuePair kv in _registeredColumnDbs)
- {
- yield return new KeyValuePair(kv.Key, (IDbMeta)kv.Value);
- }
+ return ctx.Resolve>();
}
}
}
diff --git a/src/Nethermind/Nethermind.Db/DbTracker.cs b/src/Nethermind/Nethermind.Db/DbTracker.cs
new file mode 100644
index 00000000000..343d51f0d0f
--- /dev/null
+++ b/src/Nethermind/Nethermind.Db/DbTracker.cs
@@ -0,0 +1,46 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Collections.Generic;
+using NonBlocking;
+
+namespace Nethermind.Db;
+
+public class DbTracker
+{
+ private readonly ConcurrentDictionary _createdDbs = new ConcurrentDictionary();
+
+ public void AddDb(string name, IDbMeta dbMeta)
+ {
+ _createdDbs.TryAdd(name, dbMeta);
+ }
+
+ public IEnumerable> GetAllDbMeta()
+ {
+ return _createdDbs;
+ }
+
+ public class DbFactoryInterceptor(DbTracker tracker, IDbFactory baseFactory) : IDbFactory
+ {
+ public IDb CreateDb(DbSettings dbSettings)
+ {
+ IDb db = baseFactory.CreateDb(dbSettings);
+ if (db is IDbMeta dbMeta)
+ {
+ tracker.AddDb(dbSettings.DbName, dbMeta);
+ }
+ return db;
+ }
+
+ public IColumnsDb CreateColumnsDb(DbSettings dbSettings) where T : struct, Enum
+ {
+ IColumnsDb db = baseFactory.CreateColumnsDb(dbSettings);
+ if (db is IDbMeta dbMeta)
+ {
+ tracker.AddDb(dbSettings.DbName, dbMeta);
+ }
+ return db;
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.Db/IDbProvider.cs b/src/Nethermind/Nethermind.Db/IDbProvider.cs
index 7786271bc74..038d70c3842 100644
--- a/src/Nethermind/Nethermind.Db/IDbProvider.cs
+++ b/src/Nethermind/Nethermind.Db/IDbProvider.cs
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: LGPL-3.0-only
using System;
-using System.Collections.Generic;
namespace Nethermind.Db
{
@@ -26,9 +25,5 @@ public interface IDbProvider : IDisposable
T GetDb(string dbName) where T : class, IDb;
IColumnsDb GetColumnDb(string dbName);
-
- void RegisterDb(string dbName, T db) where T : class, IDb;
- void RegisterColumnDb(string dbName, IColumnsDb db);
- IEnumerable> GetAllDbMeta();
}
}
diff --git a/src/Nethermind/Nethermind.Db/Metrics.cs b/src/Nethermind/Nethermind.Db/Metrics.cs
index 8a510db9880..b4889866ab9 100644
--- a/src/Nethermind/Nethermind.Db/Metrics.cs
+++ b/src/Nethermind/Nethermind.Db/Metrics.cs
@@ -16,14 +16,6 @@ namespace Nethermind.Db
{
public static class Metrics
{
- [CounterMetric]
- [Description("Number of Code DB cache reads.")]
- public static long CodeDbCache => _codeDbCache.GetTotalValue();
- private static readonly ZeroContentionCounter _codeDbCache = new();
- [Description("Number of Code DB cache reads on thread.")]
- internal static long ThreadLocalCodeDbCache => _codeDbCache.ThreadLocalValue;
- internal static void IncrementCodeDbCache() => _codeDbCache.Increment();
-
[CounterMetric]
[Description("Number of State Trie cache hits.")]
public static long StateTreeCache => _stateTreeCacheHits.GetTotalValue();
diff --git a/src/Nethermind/Nethermind.Db/ReadOnlyDbProvider.cs b/src/Nethermind/Nethermind.Db/ReadOnlyDbProvider.cs
index 60f10da4bbb..e3546012967 100644
--- a/src/Nethermind/Nethermind.Db/ReadOnlyDbProvider.cs
+++ b/src/Nethermind/Nethermind.Db/ReadOnlyDbProvider.cs
@@ -56,20 +56,5 @@ public IColumnsDb GetColumnDb(string dbName)
.GetColumnDb(dbName)
.CreateReadOnly(_createInMemoryWriteStore));
}
-
- public void RegisterDb(string dbName, T db) where T : class, IDb
- {
- _wrappedProvider.RegisterDb(dbName, db);
- }
-
- public void RegisterColumnDb(string dbName, IColumnsDb db)
- {
- _wrappedProvider.RegisterColumnDb(dbName, db);
- }
-
- public IEnumerable> GetAllDbMeta()
- {
- return _wrappedProvider.GetAllDbMeta();
- }
}
}
diff --git a/src/Nethermind/Nethermind.Db/RocksDbInitializer.cs b/src/Nethermind/Nethermind.Db/RocksDbInitializer.cs
deleted file mode 100644
index 26be4d0ff27..00000000000
--- a/src/Nethermind/Nethermind.Db/RocksDbInitializer.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
-// SPDX-License-Identifier: LGPL-3.0-only
-
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Nethermind.Core.Collections;
-
-namespace Nethermind.Db
-{
- public abstract class RocksDbInitializer
- {
- private readonly IDbProvider _dbProvider;
- protected IDbFactory DbFactory { get; }
-
- private readonly List _registrations = new();
-
- protected RocksDbInitializer(IDbProvider? dbProvider, IDbFactory? dbFactory)
- {
- _dbProvider = dbProvider ?? throw new ArgumentNullException(nameof(dbProvider));
- DbFactory = dbFactory ?? NullDbFactory.Instance;
- }
-
- protected void RegisterCustomDb(string dbName, Func dbFunc)
- {
- void Action()
- {
- IDb db = dbFunc();
- _dbProvider.RegisterDb(dbName, db);
- }
-
- _registrations.Add(Action);
- }
-
- protected void RegisterCustomColumnDb(string dbName, Func> dbFunc)
- {
- void Action()
- {
- IColumnsDb db = dbFunc();
- _dbProvider.RegisterColumnDb(dbName, db);
- }
-
- _registrations.Add(Action);
- }
-
- protected void RegisterDb(DbSettings settings) =>
- AddRegisterAction(settings.DbName, () => CreateDb(settings));
-
- protected void RegisterColumnsDb(DbSettings settings) where T : struct, Enum =>
- AddRegisterAction(settings.DbName, () => CreateColumnDb(settings));
-
- private void AddRegisterAction(string dbName, Func dbCreation) =>
- _registrations.Add(() => _dbProvider.RegisterDb(dbName, dbCreation()));
- private void AddRegisterAction(string dbName, Func> dbCreation) =>
- _registrations.Add(() => _dbProvider.RegisterColumnDb(dbName, dbCreation()));
-
- private IDb CreateDb(DbSettings settings) => DbFactory.CreateDb(settings);
-
- private IColumnsDb CreateColumnDb(DbSettings settings) where T : struct, Enum =>
- DbFactory.CreateColumnsDb(settings);
-
- protected void InitAll()
- {
- foreach (var registration in _registrations)
- {
- registration.Invoke();
- }
- }
-
- protected async Task InitAllAsync()
- {
- using ArrayPoolList allInitializers = new(_registrations.Count);
- foreach (Action registration in _registrations)
- {
- allInitializers.Add(Task.Run(() => registration.Invoke()));
- }
-
- await Task.WhenAll(allInitializers.AsSpan());
- }
-
- protected static string GetTitleDbName(string dbName) => char.ToUpper(dbName[0]) + dbName[1..];
- }
-}
diff --git a/src/Nethermind/Nethermind.Db/StandardDbInitializer.cs b/src/Nethermind/Nethermind.Db/StandardDbInitializer.cs
deleted file mode 100644
index 8a91bd8a4bc..00000000000
--- a/src/Nethermind/Nethermind.Db/StandardDbInitializer.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
-// SPDX-License-Identifier: LGPL-3.0-only
-
-using System.IO.Abstractions;
-using System.Threading;
-using System.Threading.Tasks;
-using Nethermind.Db.FullPruning;
-
-namespace Nethermind.Db
-{
- public class StandardDbInitializer : RocksDbInitializer
- {
- private readonly IFileSystem _fileSystem;
-
- public StandardDbInitializer(
- IDbProvider? dbProvider,
- IDbFactory? rocksDbFactory,
- IFileSystem? fileSystem = null)
- : base(dbProvider, rocksDbFactory)
- {
- _fileSystem = fileSystem ?? new FileSystem();
- }
-
- public void InitStandardDbs(bool useReceiptsDb, bool useBlobsDb = true)
- {
- RegisterAll(useReceiptsDb, useBlobsDb);
- InitAll();
- }
-
- public Task InitStandardDbsAsync(bool useReceiptsDb, bool useBlobsDb = true)
- {
- RegisterAll(useReceiptsDb, useBlobsDb);
- return InitAllAsync();
- }
-
- private void RegisterAll(bool useReceiptsDb, bool useBlobsDb)
- {
- RegisterDb(BuildDbSettings(DbNames.Blocks));
- RegisterDb(BuildDbSettings(DbNames.Headers));
- RegisterDb(BuildDbSettings(DbNames.BlockNumbers));
- RegisterDb(BuildDbSettings(DbNames.BlockInfos));
- RegisterDb(BuildDbSettings(DbNames.BadBlocks));
-
- DbSettings stateDbSettings = BuildDbSettings(DbNames.State);
- RegisterCustomDb(DbNames.State, () => new FullPruningDb(
- stateDbSettings,
- DbFactory is not MemDbFactory
- ? new FullPruningInnerDbFactory(DbFactory, _fileSystem, stateDbSettings.DbPath)
- : DbFactory,
- () => Interlocked.Increment(ref Metrics.StateDbInPruningWrites)));
-
- RegisterDb(BuildDbSettings(DbNames.Code));
- RegisterDb(BuildDbSettings(DbNames.Bloom));
- if (useReceiptsDb)
- {
- RegisterColumnsDb(BuildDbSettings(DbNames.Receipts));
- }
- else
- {
- RegisterCustomColumnDb(DbNames.Receipts, () => new ReadOnlyColumnsDb(new MemColumnsDb(), false));
- }
- RegisterDb(BuildDbSettings(DbNames.Metadata));
- if (useBlobsDb)
- {
- RegisterColumnsDb(BuildDbSettings(DbNames.BlobTransactions));
- }
- }
-
- private static DbSettings BuildDbSettings(string dbName, bool deleteOnStart = false)
- {
- return new(GetTitleDbName(dbName), dbName)
- {
- DeleteOnStart = deleteOnStart
- };
- }
- }
-}
diff --git a/src/Nethermind/Nethermind.Db/TestMemDbProvider.cs b/src/Nethermind/Nethermind.Db/TestMemDbProvider.cs
deleted file mode 100644
index b8276b5a583..00000000000
--- a/src/Nethermind/Nethermind.Db/TestMemDbProvider.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
-// SPDX-License-Identifier: LGPL-3.0-only
-
-
-using System.Threading.Tasks;
-
-namespace Nethermind.Db
-{
- public class TestMemDbProvider
- {
- public static async Task InitAsync()
- {
- IDbProvider memDbProvider = new DbProvider();
- StandardDbInitializer? standardDbInitializer = new StandardDbInitializer(memDbProvider, new MemDbFactory());
- await standardDbInitializer.InitStandardDbsAsync(true);
- return memDbProvider;
- }
-
- public static IDbProvider Init()
- {
- IDbProvider memDbProvider = new DbProvider();
- StandardDbInitializer? standardDbInitializer = new StandardDbInitializer(memDbProvider, new MemDbFactory());
- standardDbInitializer.InitStandardDbs(true);
- return memDbProvider;
- }
- }
-}
diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs
index 139ddfd7e2c..1a7d7d43fc7 100644
--- a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs
+++ b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs
@@ -20,7 +20,7 @@
using Microsoft.Diagnostics.Runtime;
using Nethermind.Evm.Config;
using Microsoft.Diagnostics.Tracing.Parsers;
-using Nethermind.Evm.Tracing.GethStyle;
+using Nethermind.Blockchain.Tracing.GethStyle;
using static System.Runtime.InteropServices.JavaScript.JSType;
using System.Collections.Generic;
using Nethermind.Blockchain;
@@ -31,7 +31,7 @@
using BenchmarkDotNet.Running;
using Nethermind.Specs.Forks;
using Nethermind.Abi;
-using Nethermind.Evm.Tracing.GethStyle.Custom.JavaScript;
+using Nethermind.Blockchain.Tracing.GethStyle.Custom.JavaScript;
using Nethermind.Evm.Test.ILEVM;
using Nethermind.Crypto;
using Nethermind.Evm.Test;
@@ -95,14 +95,16 @@ public LocalSetup(string name, byte[] _bytecode)
bytecode = _bytecode;
- codeInfoRepository = new TestCodeInfoRepository();
ILogManager logmanager = NullLogManager.Instance;
_logger = logmanager.GetClassLogger();
- _virtualMachine = new VirtualMachine(_blockhashProvider, MainnetSpecProvider.Instance, logmanager, vmConfig);
-
+ EthereumCodeInfoRepository _codeInfoRepository = new();
+ codeInfoRepository = new TestCodeInfoRepository();
+ _virtualMachine = new VirtualMachine(_blockhashProvider, MainnetSpecProvider.Instance, LimboLogs.Instance);
+ _virtualMachine.SetBlockExecutionContext(new BlockExecutionContext(_header, _spec));
+ _virtualMachine.SetTxExecutionContext(new TxExecutionContext(Address.Zero, codeInfoRepository, null, 0));
var (address, targetCodeHash) = InsertCode(bytecode);
var driver =
diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs
index 69df78ea3d8..1eecba667b4 100644
--- a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs
+++ b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs
@@ -19,6 +19,7 @@
using Nethermind.Specs.Forks;
using Nethermind.State;
using Nethermind.Trie.Pruning;
+using Nethermind.Blockchain;
namespace Nethermind.Evm.Benchmark;
@@ -76,7 +77,7 @@ public void GlobalSetup()
_stateProvider.Commit(_spec);
Console.WriteLine(MuirGlacier.Instance);
- CodeInfoRepository codeInfoRepository = new();
+ EthereumCodeInfoRepository codeInfoRepository = new();
_virtualMachine = new VirtualMachine(_blockhashProvider, MainnetSpecProvider.Instance, new OneLoggerLogManager(NullLogger.Instance));
_virtualMachine.SetBlockExecutionContext(new BlockExecutionContext(_header, _spec));
_virtualMachine.SetTxExecutionContext(new TxExecutionContext(Address.Zero, codeInfoRepository, null, 0));
diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs
index bddc49f0e2a..0b91cd4607f 100644
--- a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs
+++ b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs
@@ -19,6 +19,7 @@
using Nethermind.Specs.Forks;
using Nethermind.State;
using Nethermind.Trie.Pruning;
+using Nethermind.Blockchain;
namespace Nethermind.Evm.Benchmark
{
@@ -87,7 +88,7 @@ public void GlobalSetup()
_stateProvider.Commit(_spec);
Console.WriteLine(MuirGlacier.Instance);
- CodeInfoRepository codeInfoRepository = new();
+ EthereumCodeInfoRepository codeInfoRepository = new();
_virtualMachine = new VirtualMachine(_blockhashProvider, MainnetSpecProvider.Instance, new OneLoggerLogManager(NullLogger.Instance));
_virtualMachine.SetBlockExecutionContext(new BlockExecutionContext(_header, _spec));
_virtualMachine.SetTxExecutionContext(new TxExecutionContext(Address.Zero, codeInfoRepository, null, 0));
diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/WethBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/WethBenchmarks.cs
index 339627048c4..8d2696df852 100644
--- a/src/Nethermind/Nethermind.Evm.Benchmark/WethBenchmarks.cs
+++ b/src/Nethermind/Nethermind.Evm.Benchmark/WethBenchmarks.cs
@@ -29,6 +29,7 @@
using BenchmarkDotNet.Loggers;
using Nethermind.Evm.CodeAnalysis;
using Nethermind.Trie;
+using Nethermind.Evm.State;
namespace Nethermind.Evm.Benchmark
{
diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/BN254.cs b/src/Nethermind/Nethermind.Evm.Precompiles/BN254.cs
new file mode 100644
index 00000000000..fb4ced5f60f
--- /dev/null
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/BN254.cs
@@ -0,0 +1,211 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Nethermind.MclBindings;
+
+namespace Nethermind.Evm.Precompiles;
+
+using static Mcl;
+
+[SkipLocalsInit]
+internal static unsafe class BN254
+{
+ internal const int PairSize = 192;
+
+ static BN254()
+ {
+ if (mclBn_init(MCL_BN_SNARK1, MCLBN_COMPILED_TIME_VAR) != 0)
+ throw new InvalidOperationException("MCL initialization failed");
+ }
+
+ internal static bool Add(Span input, Span output)
+ {
+ if (input.Length != 128)
+ return false;
+
+ if (!DeserializeG1(input[0..64], out mclBnG1 x))
+ return false;
+
+ if (!DeserializeG1(input[64..128], out mclBnG1 y))
+ return false;
+
+ mclBnG1_add(ref x, x, y); // x += y
+ mclBnG1_normalize(ref x, x);
+
+ return SerializeG1(x, output);
+ }
+
+ internal static bool Mul(Span input, Span output)
+ {
+ if (input.Length != 96)
+ return false;
+
+ if (!DeserializeG1(input[0..64], out mclBnG1 x))
+ return false;
+
+ Span yData = input[64..];
+ yData.Reverse(); // To little-endian
+
+ mclBnFr y = default;
+
+ fixed (byte* ptr = &MemoryMarshal.GetReference(yData))
+ {
+ if (mclBnFr_setLittleEndianMod(ref y, (nint)ptr, 32) == -1 || mclBnFr_isValid(y) == 0)
+ return false;
+ }
+
+ mclBnG1_mul(ref x, x, y); // x *= y
+ mclBnG1_normalize(ref x, x);
+
+ return SerializeG1(x, output);
+ }
+
+ internal static bool CheckPairing(Span input, Span output)
+ {
+ if (input.Length == 0)
+ {
+ output[31] = 1;
+ return true;
+ }
+
+ if (input.Length % PairSize != 0)
+ return false;
+
+ mclBnGT gt = default;
+ Unsafe.SkipInit(out mclBnGT previous);
+ var hasPrevious = false;
+
+ for (int i = 0, count = input.Length; i < count; i += PairSize)
+ {
+ var i64 = i + 64;
+
+ if (!DeserializeG1(input[i..i64], out mclBnG1 g1))
+ return false;
+
+ if (!DeserializeG2(input[i64..(i64 + 128)], out mclBnG2 g2))
+ return false;
+
+ if (mclBnG1_isZero(g1) == 1 || mclBnG2_isZero(g2) == 1)
+ continue;
+
+ mclBn_pairing(ref gt, g1, g2);
+
+ // Skip multiplication for the first pairing as there's no previous result
+ if (hasPrevious)
+ mclBnGT_mul(ref gt, gt, previous); // gt *= previous
+
+ previous = gt;
+ hasPrevious = true;
+ }
+
+ // If gt is zero, then no pairing was computed, and it's considered valid
+ if (mclBnGT_isOne(gt) == 1 || mclBnGT_isZero(gt) == 1)
+ {
+ output[31] = 1;
+ return true;
+ }
+
+ return mclBnGT_isValid(gt) == 1;
+ }
+
+ private static bool DeserializeG1(Span data, out mclBnG1 point)
+ {
+ point = default;
+
+ // Check for all-zero data
+ if (data.IndexOfAnyExcept((byte)0) == -1)
+ return true;
+
+ Span x = data[0..32];
+ x.Reverse(); // To little-endian
+
+ fixed (byte* ptr = &MemoryMarshal.GetReference(x))
+ {
+ if (mclBnFp_deserialize(ref point.x, (nint)ptr, 32) == nuint.Zero)
+ return false;
+ }
+
+ Span y = data[32..64];
+ y.Reverse(); // To little-endian
+
+ fixed (byte* ptr = &MemoryMarshal.GetReference(y))
+ {
+ if (mclBnFp_deserialize(ref point.y, (nint)ptr, 32) == nuint.Zero)
+ return false;
+ }
+
+ mclBnFp_setInt32(ref point.z, 1);
+
+ return mclBnG1_isValid(point) == 1;
+ }
+
+ private static bool DeserializeG2(Span data, out mclBnG2 point)
+ {
+ point = default;
+
+ // Check for all-zero data
+ if (data.IndexOfAnyExcept((byte)0) == -1)
+ return true;
+
+ Span x0 = data[32..64];
+ Span x1 = data[0..32];
+ x0.Reverse(); // To little-endian
+ x1.Reverse(); // To little-endian
+
+ fixed (byte* ptr0 = &MemoryMarshal.GetReference(x0))
+ fixed (byte* ptr1 = &MemoryMarshal.GetReference(x1))
+ {
+ if (mclBnFp_deserialize(ref point.x.d0, (nint)ptr0, 32) == nuint.Zero)
+ return false;
+
+ if (mclBnFp_deserialize(ref point.x.d1, (nint)ptr1, 32) == nuint.Zero)
+ return false;
+ }
+
+ Span y0 = data[96..128];
+ Span y1 = data[64..96];
+ y0.Reverse(); // To little-endian
+ y1.Reverse(); // To little-endian
+
+ fixed (byte* ptr0 = &MemoryMarshal.GetReference(y0))
+ fixed (byte* ptr1 = &MemoryMarshal.GetReference(y1))
+ {
+ if (mclBnFp_deserialize(ref point.y.d0, (nint)ptr0, 32) == nuint.Zero)
+ return false;
+
+ if (mclBnFp_deserialize(ref point.y.d1, (nint)ptr1, 32) == nuint.Zero)
+ return false;
+ }
+
+ mclBnFp_setInt32(ref point.z.d0, 1);
+
+ return mclBnG2_isValid(point) == 1 && mclBnG2_isValidOrder(point) == 1;
+ }
+
+ private static bool SerializeG1(in mclBnG1 point, Span output)
+ {
+ Span x = output[0..32];
+
+ fixed (byte* ptr = &MemoryMarshal.GetReference(x))
+ {
+ if (mclBnFp_getLittleEndian((nint)ptr, 32, point.x) == nuint.Zero)
+ return false;
+ }
+
+ Span y = output[32..64];
+
+ fixed (byte* ptr = &MemoryMarshal.GetReference(y))
+ {
+ if (mclBnFp_getLittleEndian((nint)ptr, 32, point.y) == nuint.Zero)
+ return false;
+ }
+
+ x.Reverse(); // To big-endian
+ y.Reverse(); // To big-endian
+
+ return true;
+ }
+}
diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/BN254AddPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/BN254AddPrecompile.cs
new file mode 100644
index 00000000000..0d7ee731e6d
--- /dev/null
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/BN254AddPrecompile.cs
@@ -0,0 +1,36 @@
+// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using Nethermind.Core;
+using Nethermind.Core.Specs;
+
+namespace Nethermind.Evm.Precompiles;
+
+///
+public class BN254AddPrecompile : IPrecompile
+{
+ public static readonly BN254AddPrecompile Instance = new();
+
+ public static Address Address { get; } = Address.FromNumber(6);
+
+ ///
+ public static string Name => "BN256_ADD";
+
+ ///
+ public long BaseGasCost(IReleaseSpec releaseSpec) => releaseSpec.IsEip1108Enabled ? 150L : 500L;
+
+ public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec) => 0L;
+
+ public (byte[], bool) Run(ReadOnlyMemory inputData, IReleaseSpec releaseSpec)
+ {
+ Metrics.Bn254AddPrecompile++;
+
+ Span input = stackalloc byte[128];
+ Span output = stackalloc byte[64];
+
+ inputData.Span[0..Math.Min(inputData.Length, input.Length)].CopyTo(input);
+
+ return BN254.Add(input, output) ? (output.ToArray(), true) : IPrecompile.Failure;
+ }
+}
diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/BN254MulPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/BN254MulPrecompile.cs
new file mode 100644
index 00000000000..3baddb95bf3
--- /dev/null
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/BN254MulPrecompile.cs
@@ -0,0 +1,36 @@
+// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using Nethermind.Core;
+using Nethermind.Core.Specs;
+
+namespace Nethermind.Evm.Precompiles;
+
+///
+public class BN254MulPrecompile : IPrecompile
+{
+ public static readonly BN254MulPrecompile Instance = new();
+
+ public static Address Address { get; } = Address.FromNumber(7);
+
+ ///
+ public static string Name => "BN256_MUL";
+
+ ///
+ public long BaseGasCost(IReleaseSpec releaseSpec) => releaseSpec.IsEip1108Enabled ? 6_000L : 40_000L;
+
+ public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec) => 0L;
+
+ public (byte[], bool) Run(ReadOnlyMemory inputData, IReleaseSpec releaseSpec)
+ {
+ Metrics.Bn254MulPrecompile++;
+
+ Span input = stackalloc byte[96];
+ Span output = stackalloc byte[64];
+
+ inputData.Span[0..Math.Min(inputData.Length, input.Length)].CopyTo(input);
+
+ return BN254.Mul(input, output) ? (output.ToArray(), true) : IPrecompile.Failure;
+ }
+}
diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/BN254PairingPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/BN254PairingPrecompile.cs
new file mode 100644
index 00000000000..713c280a1e6
--- /dev/null
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/BN254PairingPrecompile.cs
@@ -0,0 +1,50 @@
+// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Buffers;
+using Nethermind.Core;
+using Nethermind.Core.Specs;
+
+namespace Nethermind.Evm.Precompiles;
+
+///
+public class BN254PairingPrecompile : IPrecompile
+{
+ private const int PairingMaxInputSizeGranite = 112_687;
+
+ public static readonly BN254PairingPrecompile Instance = new();
+
+ public static Address Address { get; } = Address.FromNumber(8);
+
+ ///
+ public static string Name => "BN256_PAIRING";
+
+ ///
+ public long BaseGasCost(IReleaseSpec releaseSpec) => releaseSpec.IsEip1108Enabled ? 45_000L : 100_000L;
+
+ public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec) =>
+ (releaseSpec.IsEip1108Enabled ? 34_000L : 80_000L) * (inputData.Length / BN254.PairSize);
+
+ public (byte[], bool) Run(ReadOnlyMemory inputData, IReleaseSpec releaseSpec)
+ {
+ Metrics.Bn254PairingPrecompile++;
+
+ if (releaseSpec.IsOpGraniteEnabled && inputData.Length > PairingMaxInputSizeGranite ||
+ inputData.Length % BN254.PairSize > 0)
+ {
+ return IPrecompile.Failure;
+ }
+
+ var input = ArrayPool.Shared.Rent(inputData.Length);
+ Span output = stackalloc byte[32];
+
+ inputData.CopyTo(input);
+
+ var result = BN254.CheckPairing(input.AsSpan(0, inputData.Length), output);
+
+ ArrayPool.Shared.Return(input);
+
+ return result ? (output.ToArray(), true) : IPrecompile.Failure;
+ }
+}
diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/Blake2FPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Blake2FPrecompile.cs
new file mode 100644
index 00000000000..74762e7ebd5
--- /dev/null
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/Blake2FPrecompile.cs
@@ -0,0 +1,62 @@
+// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using Nethermind.Core;
+using Nethermind.Core.Extensions;
+using Nethermind.Core.Specs;
+using Nethermind.Crypto.Blake2;
+
+namespace Nethermind.Evm.Precompiles;
+
+public class Blake2FPrecompile : IPrecompile
+{
+ private const int RequiredInputLength = 213;
+
+ private readonly Blake2Compression _blake = new();
+
+ public static readonly Blake2FPrecompile Instance = new();
+
+ public static Address Address { get; } = Address.FromNumber(9);
+
+ public static string Name => "BLAKE2F";
+
+ public long BaseGasCost(IReleaseSpec releaseSpec) => 0;
+
+ public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec)
+ {
+ if (inputData.Length != RequiredInputLength)
+ {
+ return 0;
+ }
+
+ byte finalByte = inputData.Span[212];
+ if (finalByte != 0 && finalByte != 1)
+ {
+ return 0;
+ }
+
+ uint rounds = inputData[..4].Span.ReadEthUInt32();
+
+ return rounds;
+ }
+
+ public (byte[], bool) Run(ReadOnlyMemory inputData, IReleaseSpec releaseSpec)
+ {
+ if (inputData.Length != RequiredInputLength)
+ {
+ return IPrecompile.Failure;
+ }
+
+ byte finalByte = inputData.Span[212];
+ if (finalByte != 0 && finalByte != 1)
+ {
+ return IPrecompile.Failure;
+ }
+
+ byte[] result = new byte[64];
+ _blake.Compress(inputData.Span, result);
+
+ return (result, true);
+ }
+}
diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/BlsConst.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/BlsConst.cs
similarity index 98%
rename from src/Nethermind/Nethermind.Evm/Precompiles/Bls/BlsConst.cs
rename to src/Nethermind/Nethermind.Evm.Precompiles/Bls/BlsConst.cs
index 595e6ebcddd..513bfbfe946 100644
--- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/BlsConst.cs
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/BlsConst.cs
@@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
-using System;
using System.Linq;
namespace Nethermind.Evm.Precompiles.Bls;
diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/BlsExtensions.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/BlsExtensions.cs
similarity index 100%
rename from src/Nethermind/Nethermind.Evm/Precompiles/Bls/BlsExtensions.cs
rename to src/Nethermind/Nethermind.Evm.Precompiles/Bls/BlsExtensions.cs
diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/Bls/Discount.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/Discount.cs
new file mode 100644
index 00000000000..4db149d1c9d
--- /dev/null
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/Discount.cs
@@ -0,0 +1,149 @@
+// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+namespace Nethermind.Evm.Precompiles.Bls;
+
+///
+/// https://eips.ethereum.org/EIPS/eip-2537
+///
+internal static class Discount
+{
+ public static int ForG1(int k) => k >= 128 ? _maxDiscountG1 : _discountTable[k].g1;
+ public static int ForG2(int k) => k >= 128 ? _maxDiscountG2 : _discountTable[k].g2;
+
+ private const int _maxDiscountG1 = 519;
+ private const int _maxDiscountG2 = 524;
+
+ private static readonly (int g1, int g2)[] _discountTable =
+ {
+ (0, 0), // 0
+ (1000, 1000), // 1
+ (949, 1000), // 2
+ (848, 923), // 3
+ (797, 884), // 4
+ (764, 855), // 5
+ (750, 832), // 6
+ (738, 812), // 7
+ (728, 796), // 8
+ (719, 782), // 9
+ (712, 770), // 10
+ (705, 759), // 11
+ (698, 749), // 12
+ (692, 740), // 13
+ (687, 732), // 14
+ (682, 724), // 15
+ (677, 717), // 16
+ (673, 711), // 17
+ (669, 704), // 18
+ (665, 699), // 19
+ (661, 693), // 20
+ (658, 688), // 21
+ (654, 683), // 22
+ (651, 679), // 23
+ (648, 674), // 24
+ (645, 670), // 25
+ (642, 666), // 26
+ (640, 663), // 27
+ (637, 659), // 28
+ (635, 655), // 29
+ (632, 652), // 30
+ (630, 649), // 31
+ (627, 646), // 32
+ (625, 643), // 33
+ (623, 640), // 34
+ (621, 637), // 35
+ (619, 634), // 36
+ (617, 632), // 37
+ (615, 629), // 38
+ (613, 627), // 39
+ (611, 624), // 40
+ (609, 622), // 41
+ (608, 620), // 42
+ (606, 618), // 43
+ (604, 615), // 44
+ (603, 613), // 45
+ (601, 611), // 46
+ (599, 609), // 47
+ (598, 607), // 48
+ (596, 606), // 49
+ (595, 604), // 50
+ (593, 602), // 51
+ (592, 600), // 52
+ (591, 598), // 53
+ (589, 597), // 54
+ (588, 595), // 55
+ (586, 593), // 56
+ (585, 592), // 57
+ (584, 590), // 58
+ (582, 589), // 59
+ (581, 587), // 60
+ (580, 586), // 61
+ (579, 584), // 62
+ (577, 583), // 63
+ (576, 582), // 64
+ (575, 580), // 65
+ (574, 579), // 66
+ (573, 578), // 67
+ (572, 576), // 68
+ (570, 575), // 69
+ (569, 574), // 70
+ (568, 573), // 71
+ (567, 571), // 72
+ (566, 570), // 73
+ (565, 569), // 74
+ (564, 568), // 75
+ (563, 567), // 76
+ (562, 566), // 77
+ (561, 565), // 78
+ (560, 563), // 79
+ (559, 562), // 80
+ (558, 561), // 81
+ (557, 560), // 82
+ (556, 559), // 83
+ (555, 558), // 84
+ (554, 557), // 85
+ (553, 556), // 86
+ (552, 555), // 87
+ (551, 554), // 88
+ (550, 553), // 89
+ (549, 552), // 90
+ (548, 552), // 91
+ (547, 551), // 92
+ (547, 550), // 93
+ (546, 549), // 94
+ (545, 548), // 95
+ (544, 547), // 96
+ (543, 546), // 97
+ (542, 545), // 98
+ (541, 545), // 99
+ (540, 544), // 100
+ (540, 543), // 101
+ (539, 542), // 102
+ (538, 541), // 103
+ (537, 541), // 104
+ (536, 540), // 105
+ (536, 539), // 106
+ (535, 538), // 107
+ (534, 537), // 108
+ (533, 537), // 109
+ (532, 536), // 110
+ (532, 535), // 111
+ (531, 535), // 112
+ (530, 534), // 113
+ (529, 533), // 114
+ (528, 532), // 115
+ (528, 532), // 116
+ (527, 531), // 117
+ (526, 530), // 118
+ (525, 530), // 119
+ (525, 529), // 120
+ (524, 528), // 121
+ (523, 528), // 122
+ (522, 527), // 123
+ (522, 526), // 124
+ (521, 526), // 125
+ (520, 525), // 126
+ (520, 524), // 127
+ (519, 524) // 128
+ };
+}
diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1AddPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G1AddPrecompile.cs
similarity index 95%
rename from src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1AddPrecompile.cs
rename to src/Nethermind/Nethermind.Evm.Precompiles/Bls/G1AddPrecompile.cs
index eddb4893252..85ecf7dae0d 100644
--- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1AddPrecompile.cs
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G1AddPrecompile.cs
@@ -5,7 +5,7 @@
using System.Runtime.CompilerServices;
using Nethermind.Core;
using Nethermind.Core.Specs;
-
+using Nethermind.Evm.Precompiles;
using G1 = Nethermind.Crypto.Bls.P1;
namespace Nethermind.Evm.Precompiles.Bls;
@@ -23,6 +23,8 @@ private G1AddPrecompile()
public static Address Address { get; } = Address.FromNumber(0x0b);
+ public static string Name => "BLS12_G1ADD";
+
public long BaseGasCost(IReleaseSpec releaseSpec) => 375L;
public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec) => 0L;
diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MSMPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G1MSMPrecompile.cs
similarity index 98%
rename from src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MSMPrecompile.cs
rename to src/Nethermind/Nethermind.Evm.Precompiles/Bls/G1MSMPrecompile.cs
index 9e5e466a997..80e92ab1cbf 100644
--- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MSMPrecompile.cs
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G1MSMPrecompile.cs
@@ -9,6 +9,7 @@
using G1 = Nethermind.Crypto.Bls.P1;
using System.Runtime.CompilerServices;
+using Nethermind.Evm.Precompiles;
namespace Nethermind.Evm.Precompiles.Bls;
@@ -25,6 +26,8 @@ private G1MSMPrecompile()
public static Address Address { get; } = Address.FromNumber(0x0c);
+ public static string Name => "BLS12_G1MSM";
+
public long BaseGasCost(IReleaseSpec releaseSpec) => 0L;
public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec)
diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2AddPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G2AddPrecompile.cs
similarity index 95%
rename from src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2AddPrecompile.cs
rename to src/Nethermind/Nethermind.Evm.Precompiles/Bls/G2AddPrecompile.cs
index 6e9094f6084..734d8602449 100644
--- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2AddPrecompile.cs
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G2AddPrecompile.cs
@@ -5,7 +5,7 @@
using System.Runtime.CompilerServices;
using Nethermind.Core;
using Nethermind.Core.Specs;
-
+using Nethermind.Evm.Precompiles;
using G2 = Nethermind.Crypto.Bls.P2;
namespace Nethermind.Evm.Precompiles.Bls;
@@ -23,6 +23,8 @@ private G2AddPrecompile()
public static Address Address { get; } = Address.FromNumber(0x0d);
+ public static string Name => "BLS12_G2ADD";
+
public long BaseGasCost(IReleaseSpec releaseSpec) => 600L;
public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec) => 0L;
diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MSMPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G2MSMPrecompile.cs
similarity index 98%
rename from src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MSMPrecompile.cs
rename to src/Nethermind/Nethermind.Evm.Precompiles/Bls/G2MSMPrecompile.cs
index 3ed9ccc8396..8151e8c5f6a 100644
--- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MSMPrecompile.cs
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/G2MSMPrecompile.cs
@@ -9,6 +9,7 @@
using G2 = Nethermind.Crypto.Bls.P2;
using System.Runtime.CompilerServices;
+using Nethermind.Evm.Precompiles;
namespace Nethermind.Evm.Precompiles.Bls;
@@ -25,6 +26,8 @@ private G2MSMPrecompile()
public static Address Address { get; } = Address.FromNumber(0xe);
+ public static string Name => "BLS12_G2MSM";
+
public long BaseGasCost(IReleaseSpec releaseSpec) => 0L;
public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec)
diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapFp2ToG2Precompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/MapFp2ToG2Precompile.cs
similarity index 94%
rename from src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapFp2ToG2Precompile.cs
rename to src/Nethermind/Nethermind.Evm.Precompiles/Bls/MapFp2ToG2Precompile.cs
index d86a2f50c24..cac3f490ff5 100644
--- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapFp2ToG2Precompile.cs
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/MapFp2ToG2Precompile.cs
@@ -5,7 +5,7 @@
using System.Runtime.CompilerServices;
using Nethermind.Core;
using Nethermind.Core.Specs;
-
+using Nethermind.Evm.Precompiles;
using G2 = Nethermind.Crypto.Bls.P2;
namespace Nethermind.Evm.Precompiles.Bls;
@@ -23,6 +23,8 @@ private MapFp2ToG2Precompile()
public static Address Address { get; } = Address.FromNumber(0x11);
+ public static string Name => "BLS12_MAP_FP2_TO_G2";
+
public long BaseGasCost(IReleaseSpec releaseSpec) => 23800L;
public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec) => 0L;
diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapFpToG1Precompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/MapFpToG1Precompile.cs
similarity index 94%
rename from src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapFpToG1Precompile.cs
rename to src/Nethermind/Nethermind.Evm.Precompiles/Bls/MapFpToG1Precompile.cs
index bd1c776f296..f3689b5b98f 100644
--- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapFpToG1Precompile.cs
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/MapFpToG1Precompile.cs
@@ -5,6 +5,7 @@
using System.Runtime.CompilerServices;
using Nethermind.Core;
using Nethermind.Core.Specs;
+using Nethermind.Evm.Precompiles;
using G1 = Nethermind.Crypto.Bls.P1;
namespace Nethermind.Evm.Precompiles.Bls;
@@ -22,6 +23,8 @@ private MapFpToG1Precompile()
public static Address Address { get; } = Address.FromNumber(0x10);
+ public static string Name => "BLS12_MAP_FP_TO_G1";
+
public long BaseGasCost(IReleaseSpec releaseSpec) => 5500L;
public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec) => 0L;
diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/PairingCheckPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/PairingCheckPrecompile.cs
similarity index 96%
rename from src/Nethermind/Nethermind.Evm/Precompiles/Bls/PairingCheckPrecompile.cs
rename to src/Nethermind/Nethermind.Evm.Precompiles/Bls/PairingCheckPrecompile.cs
index 66270d26468..de45b8838a9 100644
--- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/PairingCheckPrecompile.cs
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/Bls/PairingCheckPrecompile.cs
@@ -6,7 +6,7 @@
using Nethermind.Core;
using Nethermind.Core.Collections;
using Nethermind.Core.Specs;
-
+using Nethermind.Evm.Precompiles;
using G1 = Nethermind.Crypto.Bls.P1;
using G2 = Nethermind.Crypto.Bls.P2;
using GT = Nethermind.Crypto.Bls.PT;
@@ -25,6 +25,8 @@ private PairingCheckPrecompile() { }
public static Address Address { get; } = Address.FromNumber(0xf);
+ public static string Name => "BLS12_PAIRING_CHECK";
+
public long BaseGasCost(IReleaseSpec releaseSpec) => 37700L;
public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec) => 32600L * (inputData.Length / PairSize);
diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs b/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs
new file mode 100644
index 00000000000..a828db49404
--- /dev/null
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/EcRecoverPrecompile.cs
@@ -0,0 +1,76 @@
+// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Runtime.CompilerServices;
+using Nethermind.Core;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Extensions;
+using Nethermind.Core.Specs;
+using Nethermind.Crypto;
+using Nethermind.Evm.Precompiles;
+
+namespace Nethermind.Evm.Precompiles;
+
+public class EcRecoverPrecompile : IPrecompile
+{
+ public static readonly EcRecoverPrecompile Instance = new();
+
+ private EcRecoverPrecompile()
+ {
+ }
+
+ public static Address Address { get; } = Address.FromNumber(1);
+
+ public static string Name => "ECREC";
+
+ public long DataGasCost(ReadOnlyMemory inputData, IReleaseSpec releaseSpec) => 0L;
+
+ public long BaseGasCost(IReleaseSpec releaseSpec) => 3000L;
+
+ private readonly byte[] _zero31 = new byte[31];
+
+ public (byte[], bool) Run(ReadOnlyMemory inputData, IReleaseSpec releaseSpec)
+ {
+ Metrics.EcRecoverPrecompile++;
+ return inputData.Length >= 128 ? RunInternal(inputData.Span) : RunInternal(inputData);
+ }
+
+ private (byte[], bool) RunInternal(ReadOnlyMemory inputData)
+ {
+ Span inputDataSpan = stackalloc byte[128];
+ inputData.Span[..Math.Min(128, inputData.Length)]
+ .CopyTo(inputDataSpan[..Math.Min(128, inputData.Length)]);
+
+ return RunInternal(inputDataSpan);
+ }
+
+ private (byte[], bool) RunInternal(ReadOnlySpan inputDataSpan)
+ {
+ ReadOnlySpan vBytes = inputDataSpan.Slice(32, 32);
+
+ // TEST: CALLCODEEcrecoverV_prefixedf0_d0g0v0
+ // TEST: CALLCODEEcrecoverV_prefixedf0_d1g0v0
+ if (!Bytes.AreEqual(_zero31, vBytes[..31]))
+ {
+ return ([], true);
+ }
+
+ byte v = vBytes[31];
+ if (v != 27 && v != 28)
+ {
+ return ([], true);
+ }
+
+ Span publicKey = stackalloc byte[65];
+ if (!EthereumEcdsa.RecoverAddressRaw(inputDataSpan.Slice(64, 64), Signature.GetRecoveryId(v),
+ inputDataSpan[..32], publicKey))
+ {
+ return ([], true);
+ }
+
+ byte[] result = ValueKeccak.Compute(publicKey.Slice(1, 64)).ToByteArray();
+ result.AsSpan(0, 12).Clear();
+ return (result, true);
+ }
+}
diff --git a/src/Nethermind/Nethermind.Evm.Precompiles/Extensions.cs b/src/Nethermind/Nethermind.Evm.Precompiles/Extensions.cs
new file mode 100644
index 00000000000..834de118fe2
--- /dev/null
+++ b/src/Nethermind/Nethermind.Evm.Precompiles/Extensions.cs
@@ -0,0 +1,77 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using Nethermind.Core;
+using Nethermind.Core.Specs;
+using Nethermind.Evm.Precompiles.Bls;
+using System.Collections.Generic;
+
+namespace Nethermind.Evm.Precompiles;
+
+public static class Extensions
+{
+ public static OrderedDictionary