From 0e0e35e4692dfc0852c7bf11d448a8ea9d7a8a0b Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Fri, 8 Dec 2023 20:41:55 +0800 Subject: [PATCH] Refactor/state cleanup (#6260) * Separate statedb initialization from blockchain initialization * Minor cleanup * World state factory * Don't take db provider or trie store * Use state reader instead of trie store for full state finder * Unify and use property * Boundary watcher * Dont need this anymore * Minor comment * Reducing change * Missed a setter * Some tests * Fix build * Fix build * Addressing comment * Minor comment adjustment * Fix startup block tree fixer missed --- ...sts.TestAccountAbstractionRpcBlockchain.cs | 5 +- .../AccountAbstractionPlugin.cs | 3 +- .../Nethermind.Api/IApiWithBlockchain.cs | 3 +- .../Nethermind.Api/NethermindApi.cs | 8 +- .../AuRaContractGasLimitOverrideTests.cs | 3 +- .../Contract/TxPriorityContractTests.cs | 2 +- .../Transactions/TxCertifierFilterTests.cs | 5 +- .../Transactions/TxPermissionFilterTest.cs | 5 +- .../Visitors/StartupTreeFixerTests.cs | 13 +- .../TrieStoreBoundaryWatcher.cs | 7 +- .../Visitors/StartupBlockTreeFixer.cs | 9 +- .../InitializeBlockchainAuRa.cs | 14 +- .../LoadGenesisBlockAuRa.cs | 15 +- .../StartBlockProducerAuRa.cs | 13 +- .../CliquePlugin.cs | 6 +- .../NethDevPlugin.cs | 5 +- .../Processing/OneTimeProcessor.cs | 10 +- .../Processing/ReadOnlyChainProcessingEnv.cs | 3 +- .../Processing/ReadOnlyTxProcessingEnv.cs | 19 +- .../ReadOnlyTxProcessingEnvFactory.cs | 17 +- .../Producers/BlockProducerEnvFactory.cs | 20 +- .../Blockchain/TestBlockchain.cs | 8 +- .../BlockchainBridgeTests.cs | 19 +- .../Nethermind.Init/InitializeStateDb.cs | 237 ++++++++++++++++++ .../Steps/InitializeBlockProducer.cs | 4 +- .../Steps/InitializeBlockchain.cs | 206 +-------------- .../Steps/InitializeNetwork.cs | 2 +- .../Nethermind.Init/Steps/LoadGenesisBlock.cs | 16 +- .../Steps/RegisterRpcModules.cs | 9 +- .../Nethermind.Init/Steps/ReviewBlockTree.cs | 2 +- .../EthModuleBenchmarks.cs | 5 +- .../Modules/Proof/ProofRpcModuleTests.cs | 10 +- .../Modules/TestRpcBlockchain.cs | 3 +- .../Modules/TraceRpcModuleTests.cs | 4 +- .../Modules/DebugModule/DebugModuleFactory.cs | 11 +- .../Modules/Proof/ProofModuleFactory.cs | 14 +- .../Modules/Trace/TraceModuleFactory.cs | 13 +- .../AuRaMergeEngineModuleTests.cs | 5 +- .../AuRaMergeBlockProducerEnvFactory.cs | 11 +- .../Nethermind.Merge.AuRa/AuRaMergePlugin.cs | 3 +- .../InitializeBlockchainAuRaMerge.cs | 12 +- .../EngineModuleTests.Setup.cs | 3 +- .../EngineModuleTests.Synchronization.cs | 2 +- .../MergePluginTests.cs | 3 +- .../MergePlugin.BlockProducer.cs | 1 - .../Nethermind.Merge.Plugin/MergePlugin.cs | 6 +- .../Synchronization/MergeSynchronizer.cs | 5 +- .../MevRpcModuleTests.TestMevRpcBlockchain.cs | 6 +- .../Nethermind.Mev/Execution/TracerFactory.cs | 14 +- src/Nethermind/Nethermind.Mev/MevPlugin.cs | 3 +- .../InitializeBlockProducerOptimism.cs | 5 +- .../InitializeBlockchainOptimism.cs | 1 - .../OptimismBlockProducerEnvFactory.cs | 12 +- .../Nethermind.Optimism/OptimismPlugin.cs | 4 +- .../Ethereum/ContextWithMocks.cs | 11 +- .../WorldStateManagerTests.cs | 66 +++++ .../Nethermind.State/IWorldStateManager.cs | 21 ++ .../ReadOnlyWorldStateManager.cs | 52 ++++ .../Nethermind.State/StateProvider.cs | 5 + .../Nethermind.State/StateReader.cs | 4 +- .../Nethermind.State/WorldStateManager.cs | 34 +++ .../OldStyleFullSynchronizerTests.cs | 6 +- .../SyncProgressResolverTests.cs | 47 ++-- .../SyncThreadTests.cs | 2 +- .../SynchronizerTests.cs | 9 +- .../ParallelSync/FullStateFinder.cs | 20 +- .../Synchronizer.cs | 12 +- 67 files changed, 669 insertions(+), 464 deletions(-) create mode 100644 src/Nethermind/Nethermind.Init/InitializeStateDb.cs create mode 100644 src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs create mode 100644 src/Nethermind/Nethermind.State/IWorldStateManager.cs create mode 100644 src/Nethermind/Nethermind.State/ReadOnlyWorldStateManager.cs create mode 100644 src/Nethermind/Nethermind.State/WorldStateManager.cs diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs index f14e0ae0e5c..556fdf6efbb 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs @@ -99,9 +99,8 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT SpecProvider.UpdateMergeTransitionInfo(1, 0); BlockProducerEnvFactory blockProducerEnvFactory = new BlockProducerEnvFactory( - DbProvider, + WorldStateManager, BlockTree, - ReadOnlyTrieStore, SpecProvider, BlockValidator, NoBlockRewards.Instance, @@ -212,7 +211,7 @@ protected override BlockProcessor CreateBlockProcessor() UserOperationSimulator[entryPoint] = new( UserOperationTxBuilder[entryPoint], ReadOnlyState, - new ReadOnlyTxProcessingEnvFactory(DbProvider, ReadOnlyTrieStore, BlockTree, SpecProvider, LogManager), + new ReadOnlyTxProcessingEnvFactory(WorldStateManager, BlockTree, SpecProvider, LogManager), EntryPointContractAbi, entryPoint!, WhitelistedPayamsters, diff --git a/src/Nethermind/Nethermind.AccountAbstraction/AccountAbstractionPlugin.cs b/src/Nethermind/Nethermind.AccountAbstraction/AccountAbstractionPlugin.cs index df23fac7e6b..6d7f1145b67 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction/AccountAbstractionPlugin.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction/AccountAbstractionPlugin.cs @@ -121,8 +121,7 @@ private UserOperationSimulator UserOperationSimulator(Address entryPoint) var (getFromApi, _) = _nethermindApi!.ForProducer; ReadOnlyTxProcessingEnvFactory readOnlyTxProcessingEnvFactory = new( - getFromApi.DbProvider, - getFromApi.ReadOnlyTrieStore, + getFromApi.WorldStateManager!, getFromApi.BlockTree, getFromApi.SpecProvider, getFromApi.LogManager); diff --git a/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs b/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs index 5bbf5f7886d..97ebb787cf2 100644 --- a/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs +++ b/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs @@ -43,7 +43,6 @@ public interface IApiWithBlockchain : IApiWithStores, IBlockchainBridgeFactory IUnclesValidator? UnclesValidator { get; set; } IHeaderValidator? HeaderValidator { get; set; } IManualBlockProductionTrigger ManualBlockProductionTrigger { get; } - IReadOnlyTrieStore? ReadOnlyTrieStore { get; set; } IRewardCalculatorSource? RewardCalculatorSource { get; set; } /// /// PoS switcher for The Merge @@ -59,9 +58,9 @@ public interface IApiWithBlockchain : IApiWithStores, IBlockchainBridgeFactory /// DO NOT USE OUTSIDE OF PROCESSING BLOCK CONTEXT! /// IWorldState? WorldState { get; set; } - IKeyValueStoreWithBatching? MainStateDbWithCache { get; set; } IReadOnlyStateProvider? ChainHeadStateProvider { get; set; } IStateReader? StateReader { get; set; } + IWorldStateManager? WorldStateManager { get; set; } ITransactionProcessor? TransactionProcessor { get; set; } ITrieStore? TrieStore { get; set; } ITxSender? TxSender { get; set; } diff --git a/src/Nethermind/Nethermind.Api/NethermindApi.cs b/src/Nethermind/Nethermind.Api/NethermindApi.cs index d83305c6cb8..3574e6bbb92 100644 --- a/src/Nethermind/Nethermind.Api/NethermindApi.cs +++ b/src/Nethermind/Nethermind.Api/NethermindApi.cs @@ -70,17 +70,13 @@ public NethermindApi(IConfigProvider configProvider, IJsonSerializer jsonSeriali DisposeStack.Push(CryptoRandom); } - private IReadOnlyDbProvider? _readOnlyDbProvider; - public IBlockchainBridge CreateBlockchainBridge() { ReadOnlyBlockTree readOnlyTree = BlockTree!.AsReadOnly(); - LazyInitializer.EnsureInitialized(ref _readOnlyDbProvider, () => new ReadOnlyDbProvider(DbProvider, false)); // TODO: reuse the same trie cache here ReadOnlyTxProcessingEnv readOnlyTxProcessingEnv = new( - _readOnlyDbProvider, - ReadOnlyTrieStore, + WorldStateManager!, readOnlyTree, SpecProvider, LogManager); @@ -191,13 +187,13 @@ public ISealEngine SealEngine public ISyncServer? SyncServer { get; set; } public IWorldState? WorldState { get; set; } public IReadOnlyStateProvider? ChainHeadStateProvider { get; set; } + public IWorldStateManager? WorldStateManager { get; set; } public IStateReader? StateReader { get; set; } public IStaticNodesManager? StaticNodesManager { get; set; } public ITimestamper Timestamper { get; } = Core.Timestamper.Default; public ITimerFactory TimerFactory { get; } = Core.Timers.TimerFactory.Default; public ITransactionProcessor? TransactionProcessor { get; set; } public ITrieStore? TrieStore { get; set; } - public IReadOnlyTrieStore? ReadOnlyTrieStore { get; set; } public ITxSender? TxSender { get; set; } public INonceManager? NonceManager { get; set; } public ITxPool? TxPool { get; set; } diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/AuRaContractGasLimitOverrideTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/AuRaContractGasLimitOverrideTests.cs index c5f1a04d732..aa52e803a15 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/AuRaContractGasLimitOverrideTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/AuRaContractGasLimitOverrideTests.cs @@ -83,8 +83,7 @@ protected override BlockProcessor CreateBlockProcessor() KeyValuePair blockGasLimitContractTransition = ChainSpec.AuRa.BlockGasLimitContractTransitions.First(); BlockGasLimitContract gasLimitContract = new(AbiEncoder.Instance, blockGasLimitContractTransition.Value, blockGasLimitContractTransition.Key, new ReadOnlyTxProcessingEnv( - DbProvider, - new TrieStore(DbProvider.StateDb, LimboLogs.Instance).AsReadOnly(), + WorldStateManager, BlockTree, SpecProvider, LimboLogs.Instance)); GasLimitOverrideCache = new AuRaContractGasLimitOverride.Cache(); diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/TxPriorityContractTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/TxPriorityContractTests.cs index 3e0fc34aa08..276671dab2a 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/TxPriorityContractTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/TxPriorityContractTests.cs @@ -254,7 +254,7 @@ protected override TxPoolTxSource CreateTxPoolTxSource() TxPoolTxSource txPoolTxSource = base.CreateTxPoolTxSource(); TxPriorityContract = new TxPriorityContract(AbiEncoder.Instance, TestItem.AddressA, - new ReadOnlyTxProcessingEnv(DbProvider, TrieStore.AsReadOnly(), BlockTree, SpecProvider, LimboLogs.Instance)); + new ReadOnlyTxProcessingEnv(WorldStateManager, BlockTree, SpecProvider, LimboLogs.Instance)); Priorities = new DictionaryContractDataStore( new TxPriorityContract.DestinationSortedListContractDataStoreCollection(), diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs index 887961a3c6d..0e6d4c5bde4 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs @@ -137,9 +137,8 @@ protected override BlockProcessor CreateBlockProcessor() { AbiEncoder abiEncoder = AbiEncoder.Instance; ReadOnlyTransactionProcessorSource = new ReadOnlyTxProcessingEnv( - DbProvider, - new TrieStore(DbProvider.StateDb, LimboLogs.Instance).AsReadOnly(), - BlockTree, SpecProvider, + WorldStateManager, + BlockTree, SpecProvider, LimboLogs.Instance); RegisterContract = new RegisterContract(abiEncoder, ChainSpec.Parameters.Registrar, ReadOnlyTransactionProcessorSource); CertifierContract = new CertifierContract( diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs index 27a9fd4e8c2..6c9553f5b19 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs @@ -276,14 +276,13 @@ protected override BlockProcessor CreateBlockProcessor() IReadOnlyTrieStore trieStore = new TrieStore(DbProvider.StateDb, LimboLogs.Instance).AsReadOnly(); IReadOnlyTxProcessorSource txProcessorSource = new ReadOnlyTxProcessingEnv( - DbProvider, - trieStore, + WorldStateManager, BlockTree, SpecProvider, LimboLogs.Instance); VersionedTransactionPermissionContract transactionPermissionContract = new(AbiEncoder.Instance, _contractAddress, 1, - new ReadOnlyTxProcessingEnv(DbProvider, trieStore, BlockTree, SpecProvider, LimboLogs.Instance), TransactionPermissionContractVersions, LimboLogs.Instance, SpecProvider); + new ReadOnlyTxProcessingEnv(WorldStateManager, BlockTree, SpecProvider, LimboLogs.Instance), TransactionPermissionContractVersions, LimboLogs.Instance, SpecProvider); TxPermissionFilterCache = new PermissionBasedTxFilter.Cache(); PermissionBasedTxFilter = new PermissionBasedTxFilter(transactionPermissionContract, TxPermissionFilterCache, LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs index 695a8c96a35..a6cc779152e 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs @@ -15,6 +15,8 @@ using Nethermind.State.Repositories; using Nethermind.Db.Blooms; using Nethermind.JsonRpc.Test.Modules; +using Nethermind.State; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Blockchain.Test.Visitors @@ -72,7 +74,7 @@ public async Task Deletes_everything_after_the_missing_level() .WithDatabaseFrom(builder) .TestObject; - StartupBlockTreeFixer fixer = new(new SyncConfig(), tree, new MemDb(), LimboNoErrorLogger.Instance); + StartupBlockTreeFixer fixer = new(new SyncConfig(), tree, Substitute.For(), LimboNoErrorLogger.Instance); await tree.Accept(fixer, CancellationToken.None); Assert.Null(blockInfosDb.Get(3), "level 3"); @@ -110,7 +112,7 @@ public async Task Suggesting_blocks_works_correctly_after_processor_restart(int testRpc.BlockchainProcessor = newBlockchainProcessor; // fixing after restart - StartupBlockTreeFixer fixer = new(new SyncConfig(), tree, testRpc.DbProvider.StateDb, LimboNoErrorLogger.Instance, 5); + StartupBlockTreeFixer fixer = new(new SyncConfig(), tree, testRpc.StateReader, LimboNoErrorLogger.Instance, 5); await tree.Accept(fixer, CancellationToken.None); // waiting for N new heads @@ -144,8 +146,7 @@ public async Task Fixer_should_not_suggest_block_without_state(int suggestedBloc testRpc.BlockchainProcessor = newBlockchainProcessor; // we create a new empty db for stateDb so we shouldn't suggest new blocks - MemDb stateDb = new(); - IBlockTreeVisitor fixer = new StartupBlockTreeFixer(new SyncConfig(), tree, stateDb, LimboNoErrorLogger.Instance, 5); + IBlockTreeVisitor fixer = new StartupBlockTreeFixer(new SyncConfig(), tree, Substitute.For(), LimboNoErrorLogger.Instance, 5); BlockVisitOutcome result = await fixer.VisitBlock(tree.Head!, CancellationToken.None); Assert.That(result, Is.EqualTo(BlockVisitOutcome.None)); @@ -166,7 +167,7 @@ public async Task Fixer_should_not_suggest_block_with_null_block() newBlockchainProcessor.Start(); testRpc.BlockchainProcessor = newBlockchainProcessor; - IBlockTreeVisitor fixer = new StartupBlockTreeFixer(new SyncConfig(), tree, testRpc.DbProvider.StateDb, LimboNoErrorLogger.Instance, 5); + IBlockTreeVisitor fixer = new StartupBlockTreeFixer(new SyncConfig(), tree, testRpc.StateReader, LimboNoErrorLogger.Instance, 5); BlockVisitOutcome result = await fixer.VisitBlock(null!, CancellationToken.None); Assert.That(result, Is.EqualTo(BlockVisitOutcome.None)); @@ -213,7 +214,7 @@ public async Task When_head_block_is_followed_by_a_block_bodies_gap_it_should_de tree.UpdateMainChain(block2); - StartupBlockTreeFixer fixer = new(new SyncConfig(), tree, new MemDb(), LimboNoErrorLogger.Instance); + StartupBlockTreeFixer fixer = new(new SyncConfig(), tree, Substitute.For(), LimboNoErrorLogger.Instance); await tree.Accept(fixer, CancellationToken.None); Assert.Null(blockInfosDb.Get(3), "level 3"); diff --git a/src/Nethermind/Nethermind.Blockchain/TrieStoreBoundaryWatcher.cs b/src/Nethermind/Nethermind.Blockchain/TrieStoreBoundaryWatcher.cs index 8aebd45a381..c1c76a317d5 100644 --- a/src/Nethermind/Nethermind.Blockchain/TrieStoreBoundaryWatcher.cs +++ b/src/Nethermind/Nethermind.Blockchain/TrieStoreBoundaryWatcher.cs @@ -4,20 +4,21 @@ using System; using Nethermind.Blockchain.Find; using Nethermind.Logging; +using Nethermind.State; using Nethermind.Trie.Pruning; namespace Nethermind.Blockchain { /// - /// Watches state persistence in with and saves it in . + /// Watches state persistence in with and saves it in . /// public class TrieStoreBoundaryWatcher : IDisposable { - private readonly ITrieStore _trieStore; + private readonly IWorldStateManager _trieStore; private readonly IBlockTree _blockTree; private readonly ILogger _logger; - public TrieStoreBoundaryWatcher(ITrieStore trieStore, IBlockTree blockTree, ILogManager logManager) + public TrieStoreBoundaryWatcher(IWorldStateManager trieStore, IBlockTree blockTree, ILogManager logManager) { _trieStore = trieStore; _blockTree = blockTree; diff --git a/src/Nethermind/Nethermind.Blockchain/Visitors/StartupBlockTreeFixer.cs b/src/Nethermind/Nethermind.Blockchain/Visitors/StartupBlockTreeFixer.cs index ba61002020f..2dc9658cb99 100644 --- a/src/Nethermind/Nethermind.Blockchain/Visitors/StartupBlockTreeFixer.cs +++ b/src/Nethermind/Nethermind.Blockchain/Visitors/StartupBlockTreeFixer.cs @@ -12,6 +12,7 @@ using Nethermind.Core.Crypto; using Nethermind.Db; using Nethermind.Logging; +using Nethermind.State; namespace Nethermind.Blockchain.Visitors { @@ -19,7 +20,7 @@ public class StartupBlockTreeFixer : IBlockTreeVisitor { public const int DefaultBatchSize = 4000; private readonly IBlockTree _blockTree; - private readonly IDb _stateDb; + private readonly IStateReader _stateReader; private readonly ILogger _logger; private long _startNumber; private long _blocksToLoad; @@ -42,12 +43,12 @@ public class StartupBlockTreeFixer : IBlockTreeVisitor public StartupBlockTreeFixer( ISyncConfig syncConfig, IBlockTree blockTree, - IDb stateDb, + IStateReader stateReader, ILogger logger, long batchSize = DefaultBatchSize) { _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); - _stateDb = stateDb; + _stateReader = stateReader; _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _batchSize = batchSize; @@ -242,7 +243,7 @@ private bool CanSuggestBlocks(Block block) { BlockHeader? parentHeader = _blockTree.FindParentHeader(block.Header, BlockTreeLookupOptions.TotalDifficultyNotNeeded); if (parentHeader is null || parentHeader.StateRoot is null || - _stateDb.Get(parentHeader.StateRoot) is null) + !_stateReader.HasStateForRoot(parentHeader.StateRoot)) return false; } else diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs index f23c2acfce7..a229f242635 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs @@ -25,6 +25,7 @@ using Nethermind.Evm.TransactionProcessing; using Nethermind.Init.Steps; using Nethermind.Logging; +using Nethermind.State; using Nethermind.TxPool; using Nethermind.TxPool.Comparison; @@ -53,7 +54,6 @@ protected override BlockProcessor CreateBlockProcessor() if (_api.RewardCalculatorSource is null) throw new StepDependencyException(nameof(_api.RewardCalculatorSource)); if (_api.TransactionProcessor is null) throw new StepDependencyException(nameof(_api.TransactionProcessor)); if (_api.DbProvider is null) throw new StepDependencyException(nameof(_api.DbProvider)); - if (_api.WorldState is null) throw new StepDependencyException(nameof(_api.WorldState)); if (_api.TxPool is null) throw new StepDependencyException(nameof(_api.TxPool)); if (_api.ReceiptStorage is null) throw new StepDependencyException(nameof(_api.ReceiptStorage)); if (_api.BlockTree is null) throw new StepDependencyException(nameof(_api.BlockTree)); @@ -87,12 +87,14 @@ protected override BlockProcessor CreateBlockProcessor() protected virtual BlockProcessor NewBlockProcessor(AuRaNethermindApi api, ITxFilter txFilter, ContractRewriter contractRewriter) { + IWorldState worldState = _api.WorldState!; + return new AuRaBlockProcessor( _api.SpecProvider, _api.BlockValidator, _api.RewardCalculatorSource.Get(_api.TransactionProcessor), - new BlockProcessor.BlockValidationTransactionsExecutor(_api.TransactionProcessor, _api.WorldState), - _api.WorldState, + new BlockProcessor.BlockValidationTransactionsExecutor(_api.TransactionProcessor, worldState), + worldState, _api.ReceiptStorage, _api.LogManager, _api.BlockTree, @@ -104,7 +106,7 @@ protected virtual BlockProcessor NewBlockProcessor(AuRaNethermindApi api, ITxFil } protected ReadOnlyTxProcessingEnv CreateReadOnlyTransactionProcessorSource() => - new ReadOnlyTxProcessingEnv(_api.DbProvider, _api.ReadOnlyTrieStore, _api.BlockTree, _api.SpecProvider, _api.LogManager); + new ReadOnlyTxProcessingEnv(_api.WorldStateManager!, _api.BlockTree, _api.SpecProvider, _api.LogManager); protected override IHealthHintService CreateHealthHintService() => new AuraHealthHintService(_auRaStepCalculator, _api.ValidatorStore); @@ -129,8 +131,10 @@ private IAuRaValidator CreateAuRaValidator(IBlockProcessor processor, IReadOnlyT _api.LogManager, chainSpecAuRa.TwoThirdsMajorityTransition); + IWorldState worldState = _api.WorldState!; + IAuRaValidator validator = new AuRaValidatorFactory(_api.AbiEncoder, - _api.WorldState, + worldState, _api.TransactionProcessor, _api.BlockTree, readOnlyTxProcessorSource, diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/LoadGenesisBlockAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/LoadGenesisBlockAuRa.cs index 06890d4fefc..4a27419705b 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/LoadGenesisBlockAuRa.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/LoadGenesisBlockAuRa.cs @@ -6,6 +6,7 @@ using Nethermind.Init.Steps; using Nethermind.Int256; using Nethermind.Specs.Forks; +using Nethermind.State; namespace Nethermind.Consensus.AuRa.InitializationSteps { @@ -18,23 +19,21 @@ public LoadGenesisBlockAuRa(AuRaNethermindApi api) : base(api) _api = api; } - protected override void Load() + protected override void Load(IWorldState worldState) { - CreateSystemAccounts(); - base.Load(); + CreateSystemAccounts(worldState); + base.Load(worldState); } - private void CreateSystemAccounts() + private void CreateSystemAccounts(IWorldState worldState) { if (_api.ChainSpec is null) throw new StepDependencyException(nameof(_api.ChainSpec)); bool hasConstructorAllocation = _api.ChainSpec.Allocations.Values.Any(a => a.Constructor is not null); if (hasConstructorAllocation) { - if (_api.WorldState is null) throw new StepDependencyException(nameof(_api.WorldState)); - - _api.WorldState.CreateAccount(Address.Zero, UInt256.Zero); - _api.WorldState.Commit(Homestead.Instance); + worldState.CreateAccount(Address.Zero, UInt256.Zero); + worldState.Commit(Homestead.Instance); } } } diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs index c8bd56c76e6..b419ed44f3a 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs @@ -171,7 +171,7 @@ internal TxPoolTxSource CreateTxPoolTxSource(ReadOnlyTxProcessingEnv processingE { // We need special one for TxPriority as its following Head separately with events and we want rules from Head, not produced block IReadOnlyTxProcessorSource readOnlyTxProcessorSourceForTxPriority = - new ReadOnlyTxProcessingEnv(_api.DbProvider, _api.ReadOnlyTrieStore, _api.BlockTree, _api.SpecProvider, _api.LogManager); + new ReadOnlyTxProcessingEnv(_api.WorldStateManager!, _api.BlockTree, _api.SpecProvider, _api.LogManager); (_txPriorityContract, _localDataSource) = TxAuRaFilterBuilders.CreateTxPrioritySources(_auraConfig, _api, readOnlyTxProcessorSourceForTxPriority); @@ -228,18 +228,17 @@ internal TxPoolTxSource CreateTxPoolTxSource(ReadOnlyTxProcessingEnv processingE // TODO: Use BlockProducerEnvFactory private BlockProducerEnv GetProducerChain(ITxSource? additionalTxSource) { - ReadOnlyTxProcessingEnv CreateReadonlyTxProcessingEnv(ReadOnlyDbProvider dbProvider, ReadOnlyBlockTree blockTree) + ReadOnlyTxProcessingEnv CreateReadonlyTxProcessingEnv(ReadOnlyBlockTree blockTree) { - return new(dbProvider, _api.ReadOnlyTrieStore, blockTree, _api.SpecProvider, _api.LogManager); + return new(_api.WorldStateManager!, blockTree, _api.SpecProvider, _api.LogManager); } BlockProducerEnv Create() { - ReadOnlyDbProvider dbProvider = _api.DbProvider.AsReadOnly(false); ReadOnlyBlockTree readOnlyBlockTree = _api.BlockTree.AsReadOnly(); - ReadOnlyTxProcessingEnv txProcessingEnv = CreateReadonlyTxProcessingEnv(dbProvider, readOnlyBlockTree); - ReadOnlyTxProcessingEnv constantContractsProcessingEnv = CreateReadonlyTxProcessingEnv(dbProvider, readOnlyBlockTree); + ReadOnlyTxProcessingEnv txProcessingEnv = CreateReadonlyTxProcessingEnv(readOnlyBlockTree); + ReadOnlyTxProcessingEnv constantContractsProcessingEnv = CreateReadonlyTxProcessingEnv(readOnlyBlockTree); BlockProcessor blockProcessor = CreateBlockProcessor(txProcessingEnv, constantContractsProcessingEnv); IBlockchainProcessor blockchainProcessor = @@ -252,7 +251,7 @@ BlockProducerEnv Create() BlockchainProcessor.Options.NoReceipts); OneTimeChainProcessor chainProcessor = new( - dbProvider, + txProcessingEnv.StateProvider, blockchainProcessor); return new BlockProducerEnv() diff --git a/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs b/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs index 4180bd2a69a..e83e633064d 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs @@ -90,13 +90,11 @@ public Task InitBlockProducer(IBlockProductionTrigger? blockProd _snapshotManager!, getFromApi.LogManager); - ReadOnlyDbProvider readOnlyDbProvider = getFromApi.DbProvider!.AsReadOnly(false); ReadOnlyBlockTree readOnlyBlockTree = getFromApi.BlockTree!.AsReadOnly(); ITransactionComparerProvider transactionComparerProvider = getFromApi.TransactionComparerProvider; ReadOnlyTxProcessingEnv producerEnv = new( - readOnlyDbProvider, - getFromApi.ReadOnlyTrieStore, + _nethermindApi.WorldStateManager!, readOnlyBlockTree, getFromApi.SpecProvider, getFromApi.LogManager); @@ -121,7 +119,7 @@ public Task InitBlockProducer(IBlockProductionTrigger? blockProd BlockchainProcessor.Options.NoReceipts); OneTimeChainProcessor chainProcessor = new( - readOnlyDbProvider, + producerEnv.StateProvider, producerChainProcessor); ITxFilterPipeline txFilterPipeline = diff --git a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs index 60fa34be699..7220b3c2bba 100644 --- a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs @@ -45,7 +45,6 @@ public Task InitBlockProducer(IBlockProductionTrigger? blockProd var (getFromApi, _) = _nethermindApi!.ForProducer; - ReadOnlyDbProvider readOnlyDbProvider = getFromApi.DbProvider.AsReadOnly(false); ReadOnlyBlockTree readOnlyBlockTree = getFromApi.BlockTree.AsReadOnly(); ITxFilterPipeline txFilterPipeline = new TxFilterPipelineBuilder(_nethermindApi.LogManager) @@ -64,10 +63,8 @@ public Task InitBlockProducer(IBlockProductionTrigger? blockProd ILogger logger = getFromApi.LogManager.GetClassLogger(); if (logger.IsInfo) logger.Info("Starting Neth Dev block producer & sealer"); - ReadOnlyTxProcessingEnv producerEnv = new( - readOnlyDbProvider, - getFromApi.ReadOnlyTrieStore, + _nethermindApi.WorldStateManager!, readOnlyBlockTree, getFromApi.SpecProvider, getFromApi.LogManager); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs index dba8eecce74..b2d0b8c14a8 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs @@ -6,6 +6,7 @@ using Nethermind.Core; using Nethermind.Db; using Nethermind.Evm.Tracing; +using Nethermind.State; namespace Nethermind.Consensus.Processing { @@ -14,13 +15,13 @@ public class OneTimeChainProcessor : IBlockchainProcessor public ITracerBag Tracers => _processor.Tracers; private readonly IBlockchainProcessor _processor; - private readonly IReadOnlyDbProvider _readOnlyDbProvider; + private readonly IWorldState _worldState; private object _lock = new(); - public OneTimeChainProcessor(IReadOnlyDbProvider readOnlyDbProvider, IBlockchainProcessor processor) + public OneTimeChainProcessor(IWorldState worldState, IBlockchainProcessor processor) { - _readOnlyDbProvider = readOnlyDbProvider ?? throw new ArgumentNullException(nameof(readOnlyDbProvider)); + _worldState = worldState ?? throw new ArgumentNullException(nameof(worldState)); _processor = processor ?? throw new ArgumentNullException(nameof(processor)); } @@ -45,7 +46,7 @@ public Task StopAsync(bool processRemainingBlocks = false) } finally { - _readOnlyDbProvider.ClearTempChanges(); + _worldState.Reset(); } return result; @@ -66,7 +67,6 @@ public bool IsProcessingBlocks(ulong? maxProcessingInterval) public void Dispose() { _processor?.Dispose(); - _readOnlyDbProvider?.Dispose(); } } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs index 65baaa7ea3e..6fff1bc71d9 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs @@ -31,7 +31,6 @@ public ReadOnlyChainProcessingEnv( IBlockPreprocessorStep recoveryStep, IRewardCalculator rewardCalculator, IReceiptStorage receiptStorage, - IReadOnlyDbProvider dbProvider, ISpecProvider specProvider, ILogManager logManager, IBlockProcessor.IBlockTransactionsExecutor? blockTransactionsExecutor = null) @@ -53,7 +52,7 @@ public ReadOnlyChainProcessingEnv( _blockProcessingQueue = new BlockchainProcessor(_txEnv.BlockTree, BlockProcessor, recoveryStep, _txEnv.StateReader, logManager, BlockchainProcessor.Options.NoReceipts); BlockProcessingQueue = _blockProcessingQueue; - ChainProcessor = new OneTimeChainProcessor(dbProvider, _blockProcessingQueue); + ChainProcessor = new OneTimeChainProcessor(txEnv.StateProvider, _blockProcessingQueue); } public void Dispose() diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs index 8cadba155b6..66d1e91cd4e 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs @@ -5,12 +5,10 @@ using Nethermind.Blockchain; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; -using Nethermind.Db; using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; using Nethermind.State; -using Nethermind.Trie.Pruning; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -22,34 +20,29 @@ public class ReadOnlyTxProcessingEnv : IReadOnlyTxProcessorSource public IWorldState StateProvider { get; } public ITransactionProcessor TransactionProcessor { get; set; } public IBlockTree BlockTree { get; } - public IReadOnlyDbProvider DbProvider { get; } public IBlockhashProvider BlockhashProvider { get; } public IVirtualMachine Machine { get; } public ReadOnlyTxProcessingEnv( - IDbProvider? dbProvider, - IReadOnlyTrieStore? trieStore, + IWorldStateManager worldStateManager, IBlockTree? blockTree, ISpecProvider? specProvider, ILogManager? logManager) - : this(dbProvider?.AsReadOnly(false), trieStore, blockTree?.AsReadOnly(), specProvider, logManager) + : this(worldStateManager, blockTree?.AsReadOnly(), specProvider, logManager) { } public ReadOnlyTxProcessingEnv( - IReadOnlyDbProvider? readOnlyDbProvider, - IReadOnlyTrieStore? readOnlyTrieStore, + IWorldStateManager worldStateManager, IReadOnlyBlockTree? readOnlyBlockTree, ISpecProvider? specProvider, ILogManager? logManager) { if (specProvider is null) throw new ArgumentNullException(nameof(specProvider)); + if (worldStateManager is null) throw new ArgumentNullException(nameof(worldStateManager)); - DbProvider = readOnlyDbProvider ?? throw new ArgumentNullException(nameof(readOnlyDbProvider)); - ReadOnlyDb codeDb = readOnlyDbProvider.CodeDb.AsReadOnly(true); - - StateReader = new StateReader(readOnlyTrieStore, codeDb, logManager); - StateProvider = new WorldState(readOnlyTrieStore, codeDb, logManager); + StateReader = worldStateManager.GlobalStateReader; + StateProvider = worldStateManager.CreateResettableWorldState(); BlockTree = readOnlyBlockTree ?? throw new ArgumentNullException(nameof(readOnlyBlockTree)); BlockhashProvider = new BlockhashProvider(BlockTree, logManager); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnvFactory.cs index 0f5612dd38d..1408e3c547e 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnvFactory.cs @@ -5,41 +5,38 @@ using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Logging; +using Nethermind.State; using Nethermind.Trie.Pruning; namespace Nethermind.Consensus.Processing; public class ReadOnlyTxProcessingEnvFactory { - private readonly IReadOnlyDbProvider? _readOnlyDbProvider; - private readonly IReadOnlyTrieStore? _readOnlyTrieStore; + private readonly IWorldStateManager _worldStateManager; private readonly IReadOnlyBlockTree? _readOnlyBlockTree; private readonly ISpecProvider? _specProvider; private readonly ILogManager? _logManager; public ReadOnlyTxProcessingEnvFactory( - IDbProvider? dbProvider, - IReadOnlyTrieStore? trieStore, + IWorldStateManager worldStateManager, IBlockTree? blockTree, ISpecProvider? specProvider, ILogManager? logManager) - : this(dbProvider?.AsReadOnly(false), trieStore, blockTree?.AsReadOnly(), specProvider, logManager) + : this(worldStateManager, blockTree?.AsReadOnly(), specProvider, logManager) { } public ReadOnlyTxProcessingEnvFactory( - IReadOnlyDbProvider? readOnlyDbProvider, - IReadOnlyTrieStore? readOnlyTrieStore, + IWorldStateManager worldStateManager, IReadOnlyBlockTree? readOnlyBlockTree, ISpecProvider? specProvider, ILogManager? logManager) { - _readOnlyDbProvider = readOnlyDbProvider; - _readOnlyTrieStore = readOnlyTrieStore; + _worldStateManager = worldStateManager; _readOnlyBlockTree = readOnlyBlockTree; _specProvider = specProvider; _logManager = logManager; } - public ReadOnlyTxProcessingEnv Create() => new(_readOnlyDbProvider, _readOnlyTrieStore, _readOnlyBlockTree, _specProvider, _logManager); + public ReadOnlyTxProcessingEnv Create() => new(_worldStateManager, _readOnlyBlockTree, _specProvider, _logManager); } diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs index 3d88b53ba6a..05d36c9a321 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs @@ -12,18 +12,17 @@ using Nethermind.Consensus.Withdrawals; using Nethermind.Core.Specs; using Nethermind.Db; +using Nethermind.Evm.Tracing.GethStyle.JavaScript; using Nethermind.Logging; using Nethermind.State; -using Nethermind.Trie.Pruning; using Nethermind.TxPool; namespace Nethermind.Consensus.Producers { public class BlockProducerEnvFactory : IBlockProducerEnvFactory { - protected readonly IDbProvider _dbProvider; + protected readonly IWorldStateManager _worldStateManager; protected readonly IBlockTree _blockTree; - protected readonly IReadOnlyTrieStore _readOnlyTrieStore; protected readonly ISpecProvider _specProvider; protected readonly IBlockValidator _blockValidator; protected readonly IRewardCalculatorSource _rewardCalculatorSource; @@ -37,9 +36,8 @@ public class BlockProducerEnvFactory : IBlockProducerEnvFactory public IBlockTransactionsExecutorFactory TransactionsExecutorFactory { get; set; } public BlockProducerEnvFactory( - IDbProvider dbProvider, + IWorldStateManager worldStateManager, IBlockTree blockTree, - IReadOnlyTrieStore readOnlyTrieStore, ISpecProvider specProvider, IBlockValidator blockValidator, IRewardCalculatorSource rewardCalculatorSource, @@ -50,9 +48,8 @@ public BlockProducerEnvFactory( IBlocksConfig blocksConfig, ILogManager logManager) { - _dbProvider = dbProvider; + _worldStateManager = worldStateManager; _blockTree = blockTree; - _readOnlyTrieStore = readOnlyTrieStore; _specProvider = specProvider; _blockValidator = blockValidator; _rewardCalculatorSource = rewardCalculatorSource; @@ -68,11 +65,10 @@ public BlockProducerEnvFactory( public virtual BlockProducerEnv Create(ITxSource? additionalTxSource = null) { - ReadOnlyDbProvider readOnlyDbProvider = _dbProvider.AsReadOnly(false); ReadOnlyBlockTree readOnlyBlockTree = _blockTree.AsReadOnly(); ReadOnlyTxProcessingEnv txProcessingEnv = - CreateReadonlyTxProcessingEnv(readOnlyDbProvider, readOnlyBlockTree); + CreateReadonlyTxProcessingEnv(_worldStateManager, readOnlyBlockTree); BlockProcessor blockProcessor = CreateBlockProcessor(txProcessingEnv, @@ -93,7 +89,7 @@ public virtual BlockProducerEnv Create(ITxSource? additionalTxSource = null) BlockchainProcessor.Options.NoReceipts); OneTimeChainProcessor chainProcessor = new( - readOnlyDbProvider, + txProcessingEnv.StateProvider, blockchainProcessor); return new BlockProducerEnv @@ -106,8 +102,8 @@ public virtual BlockProducerEnv Create(ITxSource? additionalTxSource = null) }; } - protected virtual ReadOnlyTxProcessingEnv CreateReadonlyTxProcessingEnv(ReadOnlyDbProvider readOnlyDbProvider, ReadOnlyBlockTree readOnlyBlockTree) => - new(readOnlyDbProvider, _readOnlyTrieStore, readOnlyBlockTree, _specProvider, _logManager); + protected virtual ReadOnlyTxProcessingEnv CreateReadonlyTxProcessingEnv(IWorldStateManager worldStateManager, ReadOnlyBlockTree readOnlyBlockTree) => + new(worldStateManager, readOnlyBlockTree, _specProvider, _logManager); protected virtual ITxSource CreateTxSourceForProducer( ITxSource? additionalTxSource, diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 829c74fab84..1163effe3da 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -35,6 +35,7 @@ using Nethermind.State.Repositories; using Nethermind.Trie.Pruning; using Nethermind.TxPool; +using NSubstitute; using BlockTree = Nethermind.Blockchain.BlockTree; namespace Nethermind.Core.Test.Blockchain; @@ -49,6 +50,7 @@ public class TestBlockchain : IDisposable public IReceiptStorage ReceiptStorage { get; set; } = null!; public ITxPool TxPool { get; set; } = null!; public IDb CodeDb => DbProvider.CodeDb; + public IWorldStateManager WorldStateManager { get; set; } = null!; public IBlockProcessor BlockProcessor { get; set; } = null!; public IBeaconBlockRootHandler BeaconBlockRootHandler { get; set; } = null!; public IBlockchainProcessor BlockchainProcessor { get; set; } = null!; @@ -139,6 +141,7 @@ protected virtual async Task Build(ISpecProvider? specProvider = State.CommitTree(0); ReadOnlyTrieStore = TrieStore.AsReadOnly(StateDb); + WorldStateManager = new WorldStateManager(State, TrieStore, DbProvider, LimboLogs.Instance); StateReader = new StateReader(ReadOnlyTrieStore, CodeDb, LogManager); BlockTree = Builders.Build.A.BlockTree() @@ -155,7 +158,7 @@ protected virtual async Task Build(ISpecProvider? specProvider = NonceManager = new NonceManager(chainHeadInfoProvider.AccountStateProvider); - _trieStoreWatcher = new TrieStoreBoundaryWatcher(TrieStore, BlockTree, LogManager); + _trieStoreWatcher = new TrieStoreBoundaryWatcher(WorldStateManager, BlockTree, LogManager); ReceiptStorage = new InMemoryReceiptStorage(); VirtualMachine virtualMachine = new(new BlockhashProvider(BlockTree, LogManager), SpecProvider, LogManager); @@ -247,9 +250,8 @@ protected virtual IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolTx BlocksConfig blocksConfig = new(); BlockProducerEnvFactory blockProducerEnvFactory = new( - DbProvider, + WorldStateManager, BlockTree, - ReadOnlyTrieStore, SpecProvider, BlockValidator, NoBlockRewards.Instance, diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index 5726f173f9c..ec3713b966b 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -29,6 +29,7 @@ using NUnit.Framework; using Nethermind.Config; using Nethermind.Evm; +using Nethermind.State; namespace Nethermind.Facade.Test { @@ -60,9 +61,14 @@ public async Task SetUp() _ethereumEcdsa = Substitute.For(); _specProvider = MainnetSpecProvider.Instance; + ReadOnlyDbProvider dbProvider = new ReadOnlyDbProvider(_dbProvider, false); + IReadOnlyTrieStore trieStore = new TrieStore(_dbProvider.StateDb, LimboLogs.Instance).AsReadOnly(); + + IWorldStateManager readOnlyWorldStateManager = + new ReadOnlyWorldStateManager(dbProvider, trieStore, LimboLogs.Instance); + ReadOnlyTxProcessingEnv processingEnv = new( - new ReadOnlyDbProvider(_dbProvider, false), - new TrieStore(_dbProvider.StateDb, LimboLogs.Instance).AsReadOnly(), + readOnlyWorldStateManager, new ReadOnlyBlockTree(_blockTree), _specProvider, LimboLogs.Instance); @@ -204,9 +210,14 @@ public void Call_uses_valid_beneficiary() [TestCase(0)] public void Bridge_head_is_correct(long headNumber) { + ReadOnlyDbProvider dbProvider = new ReadOnlyDbProvider(_dbProvider, false); + IReadOnlyTrieStore trieStore = new TrieStore(_dbProvider.StateDb, LimboLogs.Instance).AsReadOnly(); + + IWorldStateManager readOnlyWorldStateManager = + new ReadOnlyWorldStateManager(dbProvider, trieStore, LimboLogs.Instance); + ReadOnlyTxProcessingEnv processingEnv = new( - new ReadOnlyDbProvider(_dbProvider, false), - new TrieStore(_dbProvider.StateDb, LimboLogs.Instance).AsReadOnly(), + readOnlyWorldStateManager, new ReadOnlyBlockTree(_blockTree), _specProvider, LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.Init/InitializeStateDb.cs b/src/Nethermind/Nethermind.Init/InitializeStateDb.cs new file mode 100644 index 00000000000..a82b57becc2 --- /dev/null +++ b/src/Nethermind/Nethermind.Init/InitializeStateDb.cs @@ -0,0 +1,237 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.IO.Abstractions; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Nethermind.Api; +using Nethermind.Blockchain; +using Nethermind.Blockchain.FullPruning; +using Nethermind.Blockchain.Synchronization; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; +using Nethermind.Db; +using Nethermind.Db.FullPruning; +using Nethermind.Init.Steps; +using Nethermind.JsonRpc.Converters; +using Nethermind.JsonRpc.Modules.DebugModule; +using Nethermind.JsonRpc.Modules.Trace; +using Nethermind.Logging; +using Nethermind.Serialization.Json; +using Nethermind.State; +using Nethermind.State.Witnesses; +using Nethermind.Synchronization.Trie; +using Nethermind.Synchronization.Witness; +using Nethermind.Trie; +using Nethermind.Trie.Pruning; + +namespace Nethermind.Init; + +[RunnerStepDependencies(typeof(InitializePlugins), typeof(InitializeBlockTree), typeof(SetupKeyStore))] +public class InitializeStateDb : IStep +{ + private readonly INethermindApi _api; + private ILogger? _logger; + + public InitializeStateDb(INethermindApi api) + { + _api = api; + } + + public Task Execute(CancellationToken cancellationToken) + { + InitBlockTraceDumper(); + + (IApiWithStores getApi, IApiWithBlockchain setApi) = _api.ForBlockchain; + + if (getApi.ChainSpec is null) throw new StepDependencyException(nameof(getApi.ChainSpec)); + if (getApi.DbProvider is null) throw new StepDependencyException(nameof(getApi.DbProvider)); + if (getApi.SpecProvider is null) throw new StepDependencyException(nameof(getApi.SpecProvider)); + if (getApi.BlockTree is null) throw new StepDependencyException(nameof(getApi.BlockTree)); + + _logger = getApi.LogManager.GetClassLogger(); + ISyncConfig syncConfig = getApi.Config(); + IPruningConfig pruningConfig = getApi.Config(); + IInitConfig initConfig = getApi.Config(); + + if (syncConfig.DownloadReceiptsInFastSync && !syncConfig.DownloadBodiesInFastSync) + { + if (_logger.IsWarn) _logger.Warn($"{nameof(syncConfig.DownloadReceiptsInFastSync)} is selected but {nameof(syncConfig.DownloadBodiesInFastSync)} - enabling bodies to support receipts download."); + syncConfig.DownloadBodiesInFastSync = true; + } + + IWitnessCollector witnessCollector; + if (syncConfig.WitnessProtocolEnabled) + { + WitnessCollector witnessCollectorImpl = new(getApi.DbProvider.WitnessDb, _api.LogManager); + witnessCollector = setApi.WitnessCollector = witnessCollectorImpl; + setApi.WitnessRepository = witnessCollectorImpl.WithPruning(getApi.BlockTree!, getApi.LogManager); + } + else + { + witnessCollector = setApi.WitnessCollector = NullWitnessCollector.Instance; + setApi.WitnessRepository = NullWitnessCollector.Instance; + } + + CachingStore cachedStateDb = getApi.DbProvider.StateDb + .Cached(Trie.MemoryAllowance.TrieNodeCacheCount); + IKeyValueStore codeDb = getApi.DbProvider.CodeDb + .WitnessedBy(witnessCollector); + + IKeyValueStoreWithBatching stateWitnessedBy = cachedStateDb.WitnessedBy(witnessCollector); + IPersistenceStrategy persistenceStrategy; + IPruningStrategy pruningStrategy; + if (pruningConfig.Mode.IsMemory()) + { + persistenceStrategy = Persist.IfBlockOlderThan(pruningConfig.PersistenceInterval); // TODO: this should be based on time + if (pruningConfig.Mode.IsFull()) + { + PruningTriggerPersistenceStrategy triggerPersistenceStrategy = new((IFullPruningDb)getApi.DbProvider!.StateDb, getApi.BlockTree!, getApi.LogManager); + getApi.DisposeStack.Push(triggerPersistenceStrategy); + persistenceStrategy = persistenceStrategy.Or(triggerPersistenceStrategy); + } + + pruningStrategy = Prune.WhenCacheReaches(pruningConfig.CacheMb.MB()); // TODO: memory hint should define this + } + else + { + pruningStrategy = No.Pruning; + persistenceStrategy = Persist.EveryBlock; + } + + TrieStore trieStore = syncConfig.TrieHealing + ? new HealingTrieStore( + stateWitnessedBy, + pruningStrategy, + persistenceStrategy, + getApi.LogManager) + : new TrieStore( + stateWitnessedBy, + pruningStrategy, + persistenceStrategy, + getApi.LogManager); + + // TODO: Needed by node serving. Probably should use `StateReader` instead. + setApi.TrieStore = trieStore; + + IWorldState worldState = syncConfig.TrieHealing + ? new HealingWorldState( + trieStore, + codeDb, + getApi.LogManager) + : new WorldState( + trieStore, + codeDb, + getApi.LogManager); + + if (pruningConfig.Mode.IsFull()) + { + IFullPruningDb fullPruningDb = (IFullPruningDb)getApi.DbProvider!.StateDb; + fullPruningDb.PruningStarted += (_, args) => + { + cachedStateDb.PersistCache(args.Context); + trieStore.PersistCache(args.Context, args.Context.CancellationTokenSource.Token); + }; + } + + // This is probably the point where a different state implementation would switch. + IWorldStateManager stateManager = setApi.WorldStateManager = new WorldStateManager( + worldState, + trieStore, + getApi.DbProvider, + getApi.LogManager); + + // TODO: Don't forget this + TrieStoreBoundaryWatcher trieStoreBoundaryWatcher = new(stateManager, _api.BlockTree!, _api.LogManager); + getApi.DisposeStack.Push(trieStoreBoundaryWatcher); + getApi.DisposeStack.Push(trieStore); + + setApi.WorldState = stateManager.GlobalWorldState; + setApi.StateReader = stateManager.GlobalStateReader; + setApi.ChainHeadStateProvider = new ChainHeadReadOnlyStateProvider(getApi.BlockTree, stateManager.GlobalStateReader); + + worldState.StateRoot = getApi.BlockTree!.Head?.StateRoot ?? Keccak.EmptyTreeHash; + + if (_api.Config().DiagnosticMode == DiagnosticMode.VerifyTrie) + { + Task.Run(() => + { + try + { + _logger!.Info("Collecting trie stats and verifying that no nodes are missing..."); + IWorldState diagStateProvider = stateManager.GlobalWorldState; + diagStateProvider.StateRoot = getApi.BlockTree!.Head?.StateRoot ?? Keccak.EmptyTreeHash; + TrieStats stats = diagStateProvider.CollectStats(getApi.DbProvider.CodeDb, _api.LogManager); + _logger.Info($"Starting from {getApi.BlockTree.Head?.Number} {getApi.BlockTree.Head?.StateRoot}{Environment.NewLine}" + stats); + } + catch (Exception ex) + { + _logger!.Error(ex.ToString()); + } + }); + } + + // Init state if we need system calls before actual processing starts + if (getApi.BlockTree!.Head?.StateRoot is not null) + { + worldState.StateRoot = getApi.BlockTree.Head.StateRoot; + } + + InitializeFullPruning(pruningConfig, initConfig, _api, stateManager.GlobalStateReader); + + return Task.CompletedTask; + } + + private static void InitBlockTraceDumper() + { + BlockTraceDumper.Converters.AddRange(EthereumJsonSerializer.CommonConverters); + BlockTraceDumper.Converters.AddRange(DebugModuleFactory.Converters); + BlockTraceDumper.Converters.AddRange(TraceModuleFactory.Converters); + BlockTraceDumper.Converters.Add(new TxReceiptConverter()); + } + + private static void InitializeFullPruning( + IPruningConfig pruningConfig, + IInitConfig initConfig, + INethermindApi api, + IStateReader stateReader) + { + IPruningTrigger? CreateAutomaticTrigger(string dbPath) + { + long threshold = pruningConfig.FullPruningThresholdMb.MB(); + + switch (pruningConfig.FullPruningTrigger) + { + case FullPruningTrigger.StateDbSize: + return new PathSizePruningTrigger(dbPath, threshold, api.TimerFactory, api.FileSystem); + case FullPruningTrigger.VolumeFreeSpace: + return new DiskFreeSpacePruningTrigger(dbPath, threshold, api.TimerFactory, api.FileSystem); + default: + return null; + } + } + + if (pruningConfig.Mode.IsFull()) + { + IDb stateDb = api.DbProvider!.StateDb; + if (stateDb is IFullPruningDb fullPruningDb) + { + string pruningDbPath = fullPruningDb.GetPath(initConfig.BaseDbPath); + IPruningTrigger? pruningTrigger = CreateAutomaticTrigger(pruningDbPath); + if (pruningTrigger is not null) + { + api.PruningTrigger.Add(pruningTrigger); + } + + IDriveInfo? drive = api.FileSystem.GetDriveInfos(pruningDbPath).FirstOrDefault(); + FullPruner pruner = new(fullPruningDb, api.PruningTrigger, pruningConfig, api.BlockTree!, + stateReader, api.ProcessExit!, ChainSizes.CreateChainSizeInfo(api.ChainSpec.ChainId), + drive, api.LogManager); + api.DisposeStack.Push(pruner); + } + } + } +} diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockProducer.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockProducer.cs index badde6e2f42..0fa117e656e 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockProducer.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockProducer.cs @@ -32,9 +32,9 @@ public async Task Execute(CancellationToken _) protected virtual async Task BuildProducer() { - _api.BlockProducerEnvFactory = new BlockProducerEnvFactory(_api.DbProvider!, + _api.BlockProducerEnvFactory = new BlockProducerEnvFactory( + _api.WorldStateManager!, _api.BlockTree!, - _api.ReadOnlyTrieStore!, _api.SpecProvider!, _api.BlockValidator!, _api.RewardCalculatorSource!, diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index 1aacf5203e6..798b19e6b91 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -44,11 +44,10 @@ namespace Nethermind.Init.Steps { - [RunnerStepDependencies(typeof(InitializePlugins), typeof(InitializeBlockTree), typeof(SetupKeyStore))] + [RunnerStepDependencies(typeof(InitializeStateDb), typeof(InitializePlugins), typeof(InitializeBlockTree), typeof(SetupKeyStore))] public class InitializeBlockchain : IStep { private readonly INethermindApi _api; - private ILogger? _logger; // ReSharper disable once MemberCanBeProtected.Global public InitializeBlockchain(INethermindApi api) @@ -64,146 +63,14 @@ public async Task Execute(CancellationToken _) [Todo(Improve.Refactor, "Use chain spec for all chain configuration")] protected virtual Task InitBlockchain() { - InitBlockTraceDumper(); - (IApiWithStores getApi, IApiWithBlockchain setApi) = _api.ForBlockchain; + setApi.TransactionComparerProvider = new TransactionComparerProvider(getApi.SpecProvider!, getApi.BlockTree!.AsReadOnly()); + setApi.TxValidator = new TxValidator(_api.SpecProvider!.ChainId); - if (getApi.ChainSpec is null) throw new StepDependencyException(nameof(getApi.ChainSpec)); - if (getApi.DbProvider is null) throw new StepDependencyException(nameof(getApi.DbProvider)); - if (getApi.SpecProvider is null) throw new StepDependencyException(nameof(getApi.SpecProvider)); - if (getApi.BlockTree is null) throw new StepDependencyException(nameof(getApi.BlockTree)); - - _logger = getApi.LogManager.GetClassLogger(); IInitConfig initConfig = getApi.Config(); - ISyncConfig syncConfig = getApi.Config(); - IPruningConfig pruningConfig = getApi.Config(); IBlocksConfig blocksConfig = getApi.Config(); - IMiningConfig miningConfig = getApi.Config(); - - if (syncConfig.DownloadReceiptsInFastSync && !syncConfig.DownloadBodiesInFastSync) - { - if (_logger.IsWarn) _logger.Warn($"{nameof(syncConfig.DownloadReceiptsInFastSync)} is selected but {nameof(syncConfig.DownloadBodiesInFastSync)} - enabling bodies to support receipts download."); - syncConfig.DownloadBodiesInFastSync = true; - } - - IWitnessCollector witnessCollector; - if (syncConfig.WitnessProtocolEnabled) - { - WitnessCollector witnessCollectorImpl = new(getApi.DbProvider.WitnessDb, _api.LogManager); - witnessCollector = setApi.WitnessCollector = witnessCollectorImpl; - setApi.WitnessRepository = witnessCollectorImpl.WithPruning(getApi.BlockTree!, getApi.LogManager); - } - else - { - witnessCollector = setApi.WitnessCollector = NullWitnessCollector.Instance; - setApi.WitnessRepository = NullWitnessCollector.Instance; - } - - CachingStore cachedStateDb = getApi.DbProvider.StateDb - .Cached(Trie.MemoryAllowance.TrieNodeCacheCount); - setApi.MainStateDbWithCache = cachedStateDb; - IKeyValueStore codeDb = getApi.DbProvider.CodeDb - .WitnessedBy(witnessCollector); - - IKeyValueStoreWithBatching stateWitnessedBy = setApi.MainStateDbWithCache.WitnessedBy(witnessCollector); - IPersistenceStrategy persistenceStrategy; - IPruningStrategy pruningStrategy; - if (pruningConfig.Mode.IsMemory()) - { - persistenceStrategy = Persist.IfBlockOlderThan(pruningConfig.PersistenceInterval); // TODO: this should be based on time - if (pruningConfig.Mode.IsFull()) - { - PruningTriggerPersistenceStrategy triggerPersistenceStrategy = new((IFullPruningDb)getApi.DbProvider!.StateDb, getApi.BlockTree!, getApi.LogManager); - getApi.DisposeStack.Push(triggerPersistenceStrategy); - persistenceStrategy = persistenceStrategy.Or(triggerPersistenceStrategy); - } - - pruningStrategy = Prune.WhenCacheReaches(pruningConfig.CacheMb.MB()); // TODO: memory hint should define this - } - else - { - pruningStrategy = No.Pruning; - persistenceStrategy = Persist.EveryBlock; - } - - TrieStore trieStore = syncConfig.TrieHealing - ? new HealingTrieStore( - stateWitnessedBy, - pruningStrategy, - persistenceStrategy, - getApi.LogManager) - : new TrieStore( - stateWitnessedBy, - pruningStrategy, - persistenceStrategy, - getApi.LogManager); - setApi.TrieStore = trieStore; - - IWorldState worldState = setApi.WorldState = syncConfig.TrieHealing - ? new HealingWorldState( - trieStore, - codeDb, - getApi.LogManager) - : new WorldState( - trieStore, - codeDb, - getApi.LogManager); - - if (pruningConfig.Mode.IsFull()) - { - IFullPruningDb fullPruningDb = (IFullPruningDb)getApi.DbProvider!.StateDb; - fullPruningDb.PruningStarted += (_, args) => - { - cachedStateDb.PersistCache(args.Context); - trieStore.PersistCache(args.Context, args.Context.CancellationTokenSource.Token); - }; - } - - TrieStoreBoundaryWatcher trieStoreBoundaryWatcher = new(trieStore, _api.BlockTree!, _api.LogManager); - getApi.DisposeStack.Push(trieStoreBoundaryWatcher); - getApi.DisposeStack.Push(trieStore); - - ITrieStore readOnlyTrieStore = setApi.ReadOnlyTrieStore = trieStore.AsReadOnly(cachedStateDb); - - ReadOnlyDbProvider readOnly = new(getApi.DbProvider, false); - - IStateReader stateReader = setApi.StateReader = new StateReader(readOnlyTrieStore, readOnly.GetDb(DbNames.Code), getApi.LogManager); - - setApi.TransactionComparerProvider = new TransactionComparerProvider(getApi.SpecProvider!, getApi.BlockTree.AsReadOnly()); - setApi.ChainHeadStateProvider = new ChainHeadReadOnlyStateProvider(getApi.BlockTree, stateReader); - - worldState.StateRoot = getApi.BlockTree!.Head?.StateRoot ?? Keccak.EmptyTreeHash; - - if (_api.Config().DiagnosticMode == DiagnosticMode.VerifyTrie) - { - Task.Run(() => - { - try - { - _logger!.Info("Collecting trie stats and verifying that no nodes are missing..."); - TrieStore noPruningStore = new(stateWitnessedBy, No.Pruning, Persist.EveryBlock, getApi.LogManager); - IWorldState diagStateProvider = new WorldState(noPruningStore, codeDb, getApi.LogManager) - { - StateRoot = getApi.BlockTree!.Head?.StateRoot ?? Keccak.EmptyTreeHash - }; - TrieStats stats = diagStateProvider.CollectStats(getApi.DbProvider.CodeDb, _api.LogManager); - _logger.Info($"Starting from {getApi.BlockTree.Head?.Number} {getApi.BlockTree.Head?.StateRoot}{Environment.NewLine}" + stats); - } - catch (Exception ex) - { - _logger!.Error(ex.ToString()); - } - }); - } - - // Init state if we need system calls before actual processing starts - if (getApi.BlockTree!.Head?.StateRoot is not null) - { - worldState.StateRoot = getApi.BlockTree.Head.StateRoot; - } - - setApi.TxValidator = new TxValidator(_api.SpecProvider!.ChainId); + IStateReader stateReader = setApi.StateReader!; ITxPool txPool = _api.TxPool = CreateTxPool(); ReceiptCanonicalityMonitor receiptCanonicalityMonitor = new(getApi.BlockTree, getApi.ReceiptStorage, _api.LogManager); @@ -223,10 +90,10 @@ protected virtual Task InitBlockchain() setApi.BlockValidator = CreateBlockValidator(); IChainHeadInfoProvider chainHeadInfoProvider = - new ChainHeadInfoProvider(getApi.SpecProvider, getApi.BlockTree, stateReader); + new ChainHeadInfoProvider(getApi.SpecProvider!, getApi.BlockTree!, stateReader); // TODO: can take the tx sender from plugin here maybe - ITxSigner txSigner = new WalletTxSigner(getApi.Wallet, getApi.SpecProvider.ChainId); + ITxSigner txSigner = new WalletTxSigner(getApi.Wallet, getApi.SpecProvider!.ChainId); TxSealer nonceReservingTxSealer = new(txSigner, getApi.Timestamper); INonceManager nonceManager = new NonceManager(chainHeadInfoProvider.AccountStateProvider); @@ -234,7 +101,7 @@ protected virtual Task InitBlockchain() setApi.TxSender = new TxPoolSender(txPool, nonceReservingTxSealer, nonceManager, getApi.EthereumEcdsa!); setApi.TxPoolInfoProvider = new TxPoolInfoProvider(chainHeadInfoProvider.AccountStateProvider, txPool); - setApi.GasPriceOracle = new GasPriceOracle(getApi.BlockTree, getApi.SpecProvider, _api.LogManager, blocksConfig.MinGasPrice); + setApi.GasPriceOracle = new GasPriceOracle(getApi.BlockTree!, getApi.SpecProvider, _api.LogManager, blocksConfig.MinGasPrice); IBlockProcessor mainBlockProcessor = setApi.MainBlockProcessor = CreateBlockProcessor(); BlockchainProcessor blockchainProcessor = new( @@ -260,8 +127,6 @@ protected virtual Task InitBlockchain() setApi.HealthHintService = CreateHealthHintService(); setApi.BlockProductionPolicy = CreateBlockProductionPolicy(); - InitializeFullPruning(pruningConfig, initConfig, _api, stateReader); - return Task.CompletedTask; } @@ -286,7 +151,6 @@ protected virtual IUnclesValidator CreateUnclesValidator() protected virtual ITransactionProcessor CreateTransactionProcessor() { if (_api.SpecProvider is null) throw new StepDependencyException(nameof(_api.SpecProvider)); - if (_api.WorldState is null) throw new StepDependencyException(nameof(_api.WorldState)); VirtualMachine virtualMachine = CreateVirtualMachine(); @@ -312,56 +176,6 @@ protected virtual VirtualMachine CreateVirtualMachine() _api.LogManager); } - private static void InitializeFullPruning( - IPruningConfig pruningConfig, - IInitConfig initConfig, - INethermindApi api, - IStateReader stateReader) - { - IPruningTrigger? CreateAutomaticTrigger(string dbPath) - { - long threshold = pruningConfig.FullPruningThresholdMb.MB(); - - switch (pruningConfig.FullPruningTrigger) - { - case FullPruningTrigger.StateDbSize: - return new PathSizePruningTrigger(dbPath, threshold, api.TimerFactory, api.FileSystem); - case FullPruningTrigger.VolumeFreeSpace: - return new DiskFreeSpacePruningTrigger(dbPath, threshold, api.TimerFactory, api.FileSystem); - default: - return null; - } - } - - if (pruningConfig.Mode.IsFull()) - { - IDb stateDb = api.DbProvider!.StateDb; - if (stateDb is IFullPruningDb fullPruningDb) - { - string pruningDbPath = fullPruningDb.GetPath(initConfig.BaseDbPath); - IPruningTrigger? pruningTrigger = CreateAutomaticTrigger(pruningDbPath); - if (pruningTrigger is not null) - { - api.PruningTrigger.Add(pruningTrigger); - } - - IDriveInfo? drive = api.FileSystem.GetDriveInfos(pruningDbPath).FirstOrDefault(); - FullPruner pruner = new(fullPruningDb, api.PruningTrigger, pruningConfig, api.BlockTree!, - stateReader, api.ProcessExit!, ChainSizes.CreateChainSizeInfo(api.ChainSpec.ChainId), - drive, api.LogManager); - api.DisposeStack.Push(pruner); - } - } - } - - private static void InitBlockTraceDumper() - { - BlockTraceDumper.Converters.AddRange(EthereumJsonSerializer.CommonConverters); - BlockTraceDumper.Converters.AddRange(DebugModuleFactory.Converters); - BlockTraceDumper.Converters.AddRange(TraceModuleFactory.Converters); - BlockTraceDumper.Converters.Add(new TxReceiptConverter()); - } - protected virtual IHealthHintService CreateHealthHintService() => new HealthHintService(_api.ChainSpec!); @@ -394,12 +208,14 @@ protected virtual BlockProcessor CreateBlockProcessor() if (_api.RewardCalculatorSource is null) throw new StepDependencyException(nameof(_api.RewardCalculatorSource)); if (_api.TransactionProcessor is null) throw new StepDependencyException(nameof(_api.TransactionProcessor)); + IWorldState worldState = _api.WorldState!; + return new BlockProcessor( _api.SpecProvider, _api.BlockValidator, _api.RewardCalculatorSource.Get(_api.TransactionProcessor!), - new BlockProcessor.BlockValidationTransactionsExecutor(_api.TransactionProcessor, _api.WorldState!), - _api.WorldState, + new BlockProcessor.BlockValidationTransactionsExecutor(_api.TransactionProcessor, worldState), + worldState, _api.ReceiptStorage, _api.WitnessCollector, _api.LogManager); diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs index 7b0e7e7a60c..8c6977c05db 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs @@ -152,9 +152,9 @@ private async Task Initialize(CancellationToken cancellationToken) blockDownloaderFactory, _api.Pivot, _api.ProcessExit!, - _api.ReadOnlyTrieStore!, _api.BetterPeerStrategy, _api.ChainSpec, + _api.StateReader!, _api.LogManager); } diff --git a/src/Nethermind/Nethermind.Init/Steps/LoadGenesisBlock.cs b/src/Nethermind/Nethermind.Init/Steps/LoadGenesisBlock.cs index 7752c47a248..a87d9f01663 100644 --- a/src/Nethermind/Nethermind.Init/Steps/LoadGenesisBlock.cs +++ b/src/Nethermind/Nethermind.Init/Steps/LoadGenesisBlock.cs @@ -38,13 +38,15 @@ public async Task Execute(CancellationToken _) throw new StepDependencyException(); } + IWorldState worldState = _api.WorldState!; + // if we already have a database with blocks then we do not need to load genesis from spec if (_api.BlockTree.Genesis is null) { - Load(); + Load(worldState); } - ValidateGenesisHash(expectedGenesisHash); + ValidateGenesisHash(expectedGenesisHash, worldState); if (!_initConfig.ProcessingEnabled) { @@ -53,11 +55,10 @@ public async Task Execute(CancellationToken _) } } - protected virtual void Load() + protected virtual void Load(IWorldState worldState) { if (_api.ChainSpec is null) throw new StepDependencyException(nameof(_api.ChainSpec)); if (_api.BlockTree is null) throw new StepDependencyException(nameof(_api.BlockTree)); - if (_api.WorldState is null) throw new StepDependencyException(nameof(_api.WorldState)); if (_api.SpecProvider is null) throw new StepDependencyException(nameof(_api.SpecProvider)); if (_api.DbProvider is null) throw new StepDependencyException(nameof(_api.DbProvider)); if (_api.TransactionProcessor is null) throw new StepDependencyException(nameof(_api.TransactionProcessor)); @@ -65,7 +66,7 @@ protected virtual void Load() Block genesis = new GenesisLoader( _api.ChainSpec, _api.SpecProvider, - _api.WorldState, + worldState, _api.TransactionProcessor) .Load(); @@ -92,15 +93,14 @@ void GenesisProcessed(object? sender, BlockEventArgs args) /// If is null then it means that we do not care about the genesis hash (e.g. in some quick testing of private chains)/> /// /// - private void ValidateGenesisHash(Hash256? expectedGenesisHash) + private void ValidateGenesisHash(Hash256? expectedGenesisHash, IWorldState worldState) { - if (_api.WorldState is null) throw new StepDependencyException(nameof(_api.WorldState)); if (_api.BlockTree is null) throw new StepDependencyException(nameof(_api.BlockTree)); BlockHeader genesis = _api.BlockTree.Genesis ?? throw new NullReferenceException("Genesis block is null"); if (expectedGenesisHash is not null && genesis.Hash != expectedGenesisHash) { - if (_logger.IsWarn) _logger.Warn(_api.WorldState.DumpState()); + if (_logger.IsWarn) _logger.Warn(worldState.DumpState()); if (_logger.IsWarn) _logger.Warn(genesis.ToString(BlockHeader.Format.Full)); if (_logger.IsError) _logger.Error($"Unexpected genesis hash, expected {expectedGenesisHash}, but was {genesis.Hash}"); } diff --git a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs index 0eb289dd245..b4aaab22365 100644 --- a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs +++ b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs @@ -61,6 +61,7 @@ public virtual async Task Execute(CancellationToken cancellationToken) if (_api.SyncModeSelector is null) throw new StepDependencyException(nameof(_api.SyncModeSelector)); if (_api.TxSender is null) throw new StepDependencyException(nameof(_api.TxSender)); if (_api.StateReader is null) throw new StepDependencyException(nameof(_api.StateReader)); + if (_api.WorldStateManager is null) throw new StepDependencyException(nameof(_api.WorldStateManager)); if (_api.PeerManager is null) throw new StepDependencyException(nameof(_api.PeerManager)); if (jsonRpcConfig.Enabled) @@ -88,7 +89,6 @@ public virtual async Task Execute(CancellationToken cancellationToken) if (_api.ReceiptStorage is null) throw new StepDependencyException(nameof(_api.ReceiptStorage)); if (_api.GasPriceOracle is null) throw new StepDependencyException(nameof(_api.GasPriceOracle)); if (_api.EthSyncingInfo is null) throw new StepDependencyException(nameof(_api.EthSyncingInfo)); - if (_api.ReadOnlyTrieStore is null) throw new StepDependencyException(nameof(_api.ReadOnlyTrieStore)); EthModuleFactory ethModuleFactory = new( @@ -116,10 +116,11 @@ public virtual async Task Execute(CancellationToken cancellationToken) if (_api.PeerPool is null) throw new StepDependencyException(nameof(_api.PeerPool)); if (_api.WitnessRepository is null) throw new StepDependencyException(nameof(_api.WitnessRepository)); - ProofModuleFactory proofModuleFactory = new(_api.DbProvider, _api.BlockTree, _api.ReadOnlyTrieStore, _api.BlockPreprocessor, _api.ReceiptFinder, _api.SpecProvider, _api.LogManager); + ProofModuleFactory proofModuleFactory = new(_api.WorldStateManager, _api.BlockTree, _api.BlockPreprocessor, _api.ReceiptFinder, _api.SpecProvider, _api.LogManager); rpcModuleProvider.RegisterBounded(proofModuleFactory, 2, rpcConfig.Timeout); DebugModuleFactory debugModuleFactory = new( + _api.WorldStateManager, _api.DbProvider, _api.BlockTree, rpcConfig, @@ -128,7 +129,6 @@ public virtual async Task Execute(CancellationToken cancellationToken) _api.RewardCalculatorSource, _api.ReceiptStorage, new ReceiptMigration(_api), - _api.ReadOnlyTrieStore, _api.ConfigProvider, _api.SpecProvider, _api.SyncModeSelector, @@ -137,9 +137,8 @@ public virtual async Task Execute(CancellationToken cancellationToken) rpcModuleProvider.RegisterBoundedByCpuCount(debugModuleFactory, rpcConfig.Timeout); TraceModuleFactory traceModuleFactory = new( - _api.DbProvider, + _api.WorldStateManager, _api.BlockTree, - _api.ReadOnlyTrieStore, rpcConfig, _api.BlockPreprocessor, _api.RewardCalculatorSource, diff --git a/src/Nethermind/Nethermind.Init/Steps/ReviewBlockTree.cs b/src/Nethermind/Nethermind.Init/Steps/ReviewBlockTree.cs index f5ca3f245cc..b9dd8fb4797 100644 --- a/src/Nethermind/Nethermind.Init/Steps/ReviewBlockTree.cs +++ b/src/Nethermind/Nethermind.Init/Steps/ReviewBlockTree.cs @@ -59,7 +59,7 @@ await _api.BlockTree.Accept(loader, cancellationToken).ContinueWith(t => } else { - StartupBlockTreeFixer fixer = new(syncConfig, _api.BlockTree, _api.DbProvider!.StateDb, _logger!); + StartupBlockTreeFixer fixer = new(syncConfig, _api.BlockTree, _api.WorldStateManager!.GlobalStateReader, _logger!); await _api.BlockTree.Accept(fixer, cancellationToken).ContinueWith(t => { if (t.IsFaulted) diff --git a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs index 4300f11f7f8..c846f9c8169 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs @@ -63,6 +63,8 @@ public void GlobalSetup() stateProvider.Commit(spec); stateProvider.CommitTree(0); + WorldStateManager stateManager = new WorldStateManager(stateProvider, trieStore, dbProvider, LimboLogs.Instance); + StateReader stateReader = new(trieStore, codeDb, LimboLogs.Instance); ChainLevelInfoRepository chainLevelInfoRepository = new(blockInfoDb); @@ -120,8 +122,7 @@ TransactionProcessor transactionProcessor BlockchainBridge bridge = new( new ReadOnlyTxProcessingEnv( - new ReadOnlyDbProvider(dbProvider, false), - trieStore.AsReadOnly(), + stateManager, new ReadOnlyBlockTree(blockTree), specProvider, LimboLogs.Instance), diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs index 2c791359a4d..aabb92d9c02 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs @@ -44,6 +44,7 @@ public class ProofRpcModuleTests private IBlockTree _blockTree = null!; private IDbProvider _dbProvider = null!; private TestSpecProvider _specProvider = null!; + private ReadOnlyWorldStateManager _readOnlyWorldStateManager = null!; public ProofRpcModuleTests(bool createSystemAccount, bool useNonZeroGasPrice) { @@ -59,10 +60,12 @@ public async Task Setup() _blockTree = Build.A.BlockTree(_specProvider).WithTransactions(receiptStorage).OfChainLength(10).TestObject; _dbProvider = await TestMemDbProvider.InitAsync(); + ITrieStore trieStore = new TrieStore(_dbProvider.StateDb, LimboLogs.Instance); + _readOnlyWorldStateManager = new ReadOnlyWorldStateManager(_dbProvider, trieStore.AsReadOnly(), LimboLogs.Instance); + ProofModuleFactory moduleFactory = new( - _dbProvider, + _readOnlyWorldStateManager, _blockTree, - new TrieStore(_dbProvider.StateDb, LimboLogs.Instance).AsReadOnly(), new CompositeBlockPreprocessorStep(new RecoverSignatures(new EthereumEcdsa(TestBlockchainIds.ChainId, LimboLogs.Instance), NullTxPool.Instance, _specProvider, LimboLogs.Instance)), receiptStorage, _specProvider, @@ -205,9 +208,8 @@ public async Task Get_receipt_when_block_has_few_receipts(bool withHeader, strin _receiptFinder.FindBlockHash(Arg.Any()).Returns(_blockTree.FindBlock(1)!.Hash); ProofModuleFactory moduleFactory = new ProofModuleFactory( - _dbProvider, + _readOnlyWorldStateManager, _blockTree, - new TrieStore(_dbProvider.StateDb, LimboLogs.Instance).AsReadOnly(), new CompositeBlockPreprocessorStep(new RecoverSignatures(new EthereumEcdsa(TestBlockchainIds.ChainId, LimboLogs.Instance), NullTxPool.Instance, _specProvider, LimboLogs.Instance)), _receiptFinder, _specProvider, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs index 7bbe956ae36..753dcd8ec13 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs @@ -123,8 +123,7 @@ protected override async Task Build(ISpecProvider? specProvider IFilterManager filterManager = new FilterManager(filterStore, BlockProcessor, TxPool, LimboLogs.Instance); ReadOnlyTxProcessingEnv processingEnv = new( - new ReadOnlyDbProvider(DbProvider, false), - new TrieStore(DbProvider.StateDb, LimboLogs.Instance).AsReadOnly(), + WorldStateManager, new ReadOnlyBlockTree(BlockTree), SpecProvider, LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index d7ccdf1b973..e7c13817945 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -46,12 +46,11 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) await Blockchain.AddFunds(TestItem.AddressA, 1000.Ether()); await Blockchain.AddFunds(TestItem.AddressB, 1000.Ether()); await Blockchain.AddFunds(TestItem.AddressC, 1000.Ether()); - ReadOnlyDbProvider? dbProvider = Blockchain.DbProvider.AsReadOnly(false); ReceiptsRecovery receiptsRecovery = new(Blockchain.EthereumEcdsa, Blockchain.SpecProvider); IReceiptFinder receiptFinder = new FullInfoReceiptFinder(Blockchain.ReceiptStorage, receiptsRecovery, Blockchain.BlockFinder); ReadOnlyTxProcessingEnv txProcessingEnv = - new(dbProvider, Blockchain.ReadOnlyTrieStore, Blockchain.BlockTree.AsReadOnly(), Blockchain.SpecProvider, Blockchain.LogManager); + new(Blockchain.WorldStateManager, Blockchain.BlockTree.AsReadOnly(), Blockchain.SpecProvider, Blockchain.LogManager); RewardCalculator rewardCalculatorSource = new(Blockchain.SpecProvider); IRewardCalculator rewardCalculator = rewardCalculatorSource.Get(txProcessingEnv.TransactionProcessor); @@ -65,7 +64,6 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) Blockchain.BlockPreprocessorStep, rewardCalculator, Blockchain.ReceiptStorage, - dbProvider, Blockchain.SpecProvider, Blockchain.LogManager, transactionsExecutor); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs index f9385b8d86c..92f25eeea44 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs @@ -16,6 +16,7 @@ using Nethermind.Evm.Tracing.GethStyle.JavaScript; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; +using Nethermind.State; using Nethermind.Synchronization.ParallelSync; using Nethermind.Trie.Pruning; using Newtonsoft.Json; @@ -24,12 +25,12 @@ namespace Nethermind.JsonRpc.Modules.DebugModule; public class DebugModuleFactory : ModuleFactoryBase { + private readonly IWorldStateManager _worldStateManager; private readonly IJsonRpcConfig _jsonRpcConfig; private readonly IBlockValidator _blockValidator; private readonly IRewardCalculatorSource _rewardCalculatorSource; private readonly IReceiptStorage _receiptStorage; private readonly IReceiptsMigration _receiptsMigration; - private readonly IReadOnlyTrieStore _trieStore; private readonly IConfigProvider _configProvider; private readonly ISpecProvider _specProvider; private readonly ILogManager _logManager; @@ -41,6 +42,7 @@ public class DebugModuleFactory : ModuleFactoryBase private ILogger _logger; public DebugModuleFactory( + IWorldStateManager worldStateManager, IDbProvider dbProvider, IBlockTree blockTree, IJsonRpcConfig jsonRpcConfig, @@ -49,13 +51,13 @@ public DebugModuleFactory( IRewardCalculatorSource rewardCalculator, IReceiptStorage receiptStorage, IReceiptsMigration receiptsMigration, - IReadOnlyTrieStore trieStore, IConfigProvider configProvider, ISpecProvider specProvider, ISyncModeSelector syncModeSelector, IFileSystem fileSystem, ILogManager logManager) { + _worldStateManager = worldStateManager; _dbProvider = dbProvider.AsReadOnly(false); _blockTree = blockTree.AsReadOnly(); _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); @@ -64,7 +66,6 @@ public DebugModuleFactory( _rewardCalculatorSource = rewardCalculator ?? throw new ArgumentNullException(nameof(rewardCalculator)); _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); _receiptsMigration = receiptsMigration ?? throw new ArgumentNullException(nameof(receiptsMigration)); - _trieStore = (trieStore ?? throw new ArgumentNullException(nameof(trieStore))); _configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); @@ -76,8 +77,7 @@ public DebugModuleFactory( public override IDebugRpcModule Create() { ReadOnlyTxProcessingEnv txEnv = new( - _dbProvider, - _trieStore, + _worldStateManager, _blockTree, _specProvider, _logManager); @@ -90,7 +90,6 @@ public override IDebugRpcModule Create() _recoveryStep, _rewardCalculatorSource.Get(txEnv.TransactionProcessor), _receiptStorage, - _dbProvider, _specProvider, _logManager, transactionsExecutor); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs index 39693f5b682..590f23df523 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs @@ -13,6 +13,7 @@ using Nethermind.Db; using Nethermind.JsonRpc.Data; using Nethermind.Logging; +using Nethermind.State; using Nethermind.Trie.Pruning; using Newtonsoft.Json; @@ -25,34 +26,31 @@ public class ProofModuleFactory : ModuleFactoryBase private readonly ISpecProvider _specProvider; private readonly ILogManager _logManager; private readonly IReadOnlyBlockTree _blockTree; - private readonly ReadOnlyDbProvider _dbProvider; - private readonly IReadOnlyTrieStore _trieStore; + private readonly IWorldStateManager _worldStateManager; public ProofModuleFactory( - IDbProvider dbProvider, + IWorldStateManager worldStateManager, IBlockTree blockTree, - IReadOnlyTrieStore trieStore, IBlockPreprocessorStep recoveryStep, IReceiptFinder receiptFinder, ISpecProvider specProvider, ILogManager logManager) { + _worldStateManager = worldStateManager ?? throw new ArgumentNullException(nameof(worldStateManager)); _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); _recoveryStep = recoveryStep ?? throw new ArgumentNullException(nameof(recoveryStep)); _receiptFinder = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); - _dbProvider = dbProvider.AsReadOnly(false); _blockTree = blockTree.AsReadOnly(); - _trieStore = trieStore; } public override IProofRpcModule Create() { ReadOnlyTxProcessingEnv txProcessingEnv = new( - _dbProvider, _trieStore, _blockTree, _specProvider, _logManager); + _worldStateManager, _blockTree, _specProvider, _logManager); ReadOnlyChainProcessingEnv chainProcessingEnv = new( - txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _dbProvider, _specProvider, _logManager); + txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _specProvider, _logManager); Tracer tracer = new( txProcessingEnv.StateProvider, diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs index 5c6bbc599a7..814bcca829c 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs @@ -13,6 +13,7 @@ using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Logging; +using Nethermind.State; using Nethermind.Trie.Pruning; using Newtonsoft.Json; @@ -20,9 +21,8 @@ namespace Nethermind.JsonRpc.Modules.Trace { public class TraceModuleFactory : ModuleFactoryBase { - private readonly ReadOnlyDbProvider _dbProvider; + private readonly IWorldStateManager _worldStateManager; private readonly IReadOnlyBlockTree _blockTree; - private readonly IReadOnlyTrieStore _trieNodeResolver; private readonly IJsonRpcConfig _jsonRpcConfig; private readonly IReceiptStorage _receiptStorage; private readonly ISpecProvider _specProvider; @@ -32,9 +32,8 @@ public class TraceModuleFactory : ModuleFactoryBase private readonly IPoSSwitcher _poSSwitcher; public TraceModuleFactory( - IDbProvider dbProvider, + IWorldStateManager worldStateManager, IBlockTree blockTree, - IReadOnlyTrieStore trieNodeResolver, IJsonRpcConfig jsonRpcConfig, IBlockPreprocessorStep recoveryStep, IRewardCalculatorSource rewardCalculatorSource, @@ -43,9 +42,8 @@ public TraceModuleFactory( IPoSSwitcher poSSwitcher, ILogManager logManager) { - _dbProvider = dbProvider.AsReadOnly(false); + _worldStateManager = worldStateManager; _blockTree = blockTree.AsReadOnly(); - _trieNodeResolver = trieNodeResolver; _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); _recoveryStep = recoveryStep ?? throw new ArgumentNullException(nameof(recoveryStep)); _rewardCalculatorSource = rewardCalculatorSource ?? throw new ArgumentNullException(nameof(rewardCalculatorSource)); @@ -59,7 +57,7 @@ public TraceModuleFactory( public override ITraceRpcModule Create() { ReadOnlyTxProcessingEnv txProcessingEnv = - new(_dbProvider, _trieNodeResolver, _blockTree, _specProvider, _logManager); + new(_worldStateManager, _blockTree, _specProvider, _logManager); IRewardCalculator rewardCalculator = new MergeRpcRewardCalculator(_rewardCalculatorSource.Get(txProcessingEnv.TransactionProcessor), @@ -75,7 +73,6 @@ public override ITraceRpcModule Create() _recoveryStep, rewardCalculator, _receiptStorage, - _dbProvider, _specProvider, _logManager, transactionsExecutor); diff --git a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs index d0a268e94c5..bcce08fd888 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs @@ -110,7 +110,7 @@ protected override IBlockProcessor CreateBlockProcessor() { BlockTree = BlockTree, DbProvider = DbProvider, - ReadOnlyTrieStore = ReadOnlyTrieStore, + WorldStateManager = WorldStateManager, SpecProvider = SpecProvider, TransactionComparerProvider = TransactionComparerProvider, TxPool = TxPool @@ -157,9 +157,8 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT _api!, new AuRaConfig(), new DisposableStack(), - DbProvider, + WorldStateManager, BlockTree, - ReadOnlyTrieStore, SpecProvider, BlockValidator, NoBlockRewards.Instance, diff --git a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs index b8e311bd306..163f28bf719 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs @@ -13,10 +13,9 @@ using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Specs; -using Nethermind.Db; using Nethermind.Logging; using Nethermind.Merge.AuRa.Withdrawals; -using Nethermind.Trie.Pruning; +using Nethermind.State; using Nethermind.TxPool; namespace Nethermind.Merge.AuRa; @@ -31,9 +30,8 @@ public AuRaMergeBlockProducerEnvFactory( AuRaNethermindApi auraApi, IAuraConfig auraConfig, DisposableStack disposeStack, - IDbProvider dbProvider, + IWorldStateManager worldStateManager, IBlockTree blockTree, - IReadOnlyTrieStore readOnlyTrieStore, ISpecProvider specProvider, IBlockValidator blockValidator, IRewardCalculatorSource rewardCalculatorSource, @@ -43,9 +41,8 @@ public AuRaMergeBlockProducerEnvFactory( ITransactionComparerProvider transactionComparerProvider, IBlocksConfig blocksConfig, ILogManager logManager) : base( - dbProvider, + worldStateManager, blockTree, - readOnlyTrieStore, specProvider, blockValidator, rewardCalculatorSource, @@ -97,7 +94,7 @@ protected override TxPoolTxSource CreateTxPoolTxSource( ILogManager logManager) { ReadOnlyTxProcessingEnv constantContractsProcessingEnv = CreateReadonlyTxProcessingEnv( - _dbProvider.AsReadOnly(false), + _worldStateManager, _blockTree.AsReadOnly()); return new StartBlockProducerAuRa(_auraApi) diff --git a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs index 0c7f3c666b2..e38a2d21256 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs @@ -50,9 +50,8 @@ public override Task InitBlockProducer(IConsensusPlugin consensu (AuRaNethermindApi)_api, _api.Config(), _api.DisposeStack, - _api.DbProvider!, + _api.WorldStateManager!, _api.BlockTree!, - _api.ReadOnlyTrieStore!, _api.SpecProvider!, _api.BlockValidator!, _api.RewardCalculatorSource!, diff --git a/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs b/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs index 7bdf6ee9311..cfecb0722b6 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs @@ -5,8 +5,10 @@ using Nethermind.Consensus.AuRa.InitializationSteps; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Transactions; +using Nethermind.Evm.TransactionProcessing; using Nethermind.Init.Steps; using Nethermind.Merge.AuRa.Withdrawals; +using Nethermind.State; namespace Nethermind.Merge.AuRa.InitializationSteps { @@ -21,19 +23,21 @@ public InitializeBlockchainAuRaMerge(AuRaNethermindApi api) : base(api) protected override BlockProcessor NewBlockProcessor(AuRaNethermindApi api, ITxFilter txFilter, ContractRewriter contractRewriter) { - var withdrawalContractFactory = new WithdrawalContractFactory(_api.ChainSpec!.AuRa, _api.AbiEncoder); + WithdrawalContractFactory withdrawalContractFactory = new WithdrawalContractFactory(_api.ChainSpec!.AuRa, _api.AbiEncoder); + IWorldState worldState = _api.WorldState!; + ITransactionProcessor transactionProcessor = _api.TransactionProcessor!; return new AuRaMergeBlockProcessor( _api.SpecProvider!, _api.BlockValidator!, _api.RewardCalculatorSource!.Get(_api.TransactionProcessor!), - new BlockProcessor.BlockValidationTransactionsExecutor(_api.TransactionProcessor!, _api.WorldState!), - _api.WorldState!, + new BlockProcessor.BlockValidationTransactionsExecutor(transactionProcessor!, worldState), + worldState, _api.ReceiptStorage!, _api.LogManager, _api.BlockTree!, new AuraWithdrawalProcessor( - withdrawalContractFactory.Create(_api.TransactionProcessor!), _api.LogManager), + withdrawalContractFactory.Create(transactionProcessor!), _api.LogManager), txFilter, GetGasLimitCalculator(), contractRewriter diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index 27147005e13..982c5a1741b 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -188,9 +188,8 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT targetAdjustedGasLimitCalculator); BlockProducerEnvFactory blockProducerEnvFactory = new( - DbProvider, + WorldStateManager!, BlockTree, - ReadOnlyTrieStore, SpecProvider, BlockValidator, NoBlockRewards.Instance, diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs index 1f05dbed6f1..335b0707324 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs @@ -934,7 +934,7 @@ private MultiSyncModeSelector CreateMultiSyncModeSelector(MergeTestBlockchain ch SyncProgressResolver syncProgressResolver = new( chain.BlockTree, - new FullStateFinder(chain.BlockTree, chain.DbProvider.StateDb, chain.TrieStore), + new FullStateFinder(chain.BlockTree, chain.StateReader), new SyncConfig(), Substitute.For>(), Substitute.For>(), diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs index 98e6cf1254e..33cc6895c78 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs @@ -45,9 +45,8 @@ public void Setup() _context.BlockProcessingQueue?.IsEmpty.Returns(true); _context.MemDbFactory = new MemDbFactory(); _context.BlockProducerEnvFactory = new BlockProducerEnvFactory( - _context.DbProvider!, + _context.WorldStateManager!, _context.BlockTree!, - _context.ReadOnlyTrieStore!, _context.SpecProvider!, _context.BlockValidator!, _context.RewardCalculatorSource!, diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.BlockProducer.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.BlockProducer.cs index a8436b8813f..dd36585b986 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.BlockProducer.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.BlockProducer.cs @@ -35,7 +35,6 @@ public virtual async Task InitBlockProducer(IConsensusPlugin con if (_api.ReceiptStorage is null) throw new ArgumentNullException(nameof(_api.ReceiptStorage)); if (_api.TxPool is null) throw new ArgumentNullException(nameof(_api.TxPool)); if (_api.DbProvider is null) throw new ArgumentNullException(nameof(_api.DbProvider)); - if (_api.ReadOnlyTrieStore is null) throw new ArgumentNullException(nameof(_api.ReadOnlyTrieStore)); if (_api.BlockchainProcessor is null) throw new ArgumentNullException(nameof(_api.BlockchainProcessor)); if (_api.HeaderValidator is null) throw new ArgumentNullException(nameof(_api.HeaderValidator)); if (_mergeBlockProductionPolicy is null) throw new ArgumentNullException(nameof(_mergeBlockProductionPolicy)); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs index 3af26b08cef..a8f65248086 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs @@ -257,7 +257,6 @@ public Task InitRpcModules() { if (_api.BlockTree is null) throw new ArgumentNullException(nameof(_api.BlockTree)); if (_api.BlockchainProcessor is null) throw new ArgumentNullException(nameof(_api.BlockchainProcessor)); - if (_api.WorldState is null) throw new ArgumentNullException(nameof(_api.WorldState)); if (_api.HeaderValidator is null) throw new ArgumentNullException(nameof(_api.HeaderValidator)); if (_api.EthSyncingInfo is null) throw new ArgumentNullException(nameof(_api.EthSyncingInfo)); if (_api.Sealer is null) throw new ArgumentNullException(nameof(_api.Sealer)); @@ -372,6 +371,7 @@ public Task InitSynchronization() if (_api.NodeStatsManager is null) throw new ArgumentNullException(nameof(_api.NodeStatsManager)); if (_api.HeaderValidator is null) throw new ArgumentNullException(nameof(_api.HeaderValidator)); if (_api.PeerDifficultyRefreshPool is null) throw new ArgumentNullException(nameof(_api.PeerDifficultyRefreshPool)); + if (_api.StateReader is null) throw new ArgumentNullException(nameof(_api.StateReader)); // ToDo strange place for validators initialization PeerRefresher peerRefresher = new(_api.PeerDifficultyRefreshPool, _api.TimerFactory, _api.LogManager); @@ -416,7 +416,7 @@ public Task InitSynchronization() _api.SealValidator!, _syncConfig, _api.BetterPeerStrategy!, - new FullStateFinder(_api.BlockTree, _api.DbProvider.StateDb, _api.TrieStore!.AsReadOnly()), + new FullStateFinder(_api.BlockTree, _api.StateReader), _api.LogManager); MergeSynchronizer synchronizer = new MergeSynchronizer( @@ -433,10 +433,10 @@ public Task InitSynchronization() _mergeConfig, _invalidChainTracker, _api.ProcessExit!, - _api.ReadOnlyTrieStore!, _api.BetterPeerStrategy, _api.ChainSpec, _beaconSync, + _api.StateReader, _api.LogManager ); _api.Synchronizer = synchronizer; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeSynchronizer.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeSynchronizer.cs index ea6142ce3ba..2be83e23cd7 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeSynchronizer.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeSynchronizer.cs @@ -11,6 +11,7 @@ using Nethermind.Logging; using Nethermind.Merge.Plugin.InvalidChainTracker; using Nethermind.Specs.ChainSpecStyle; +using Nethermind.State; using Nethermind.Stats; using Nethermind.Synchronization; using Nethermind.Synchronization.Blocks; @@ -51,10 +52,10 @@ public MergeSynchronizer( IMergeConfig mergeConfig, IInvalidChainTracker invalidChainTracker, IProcessExitSource exitSource, - IReadOnlyTrieStore readOnlyTrieStore, IBetterPeerStrategy betterPeerStrategy, ChainSpec chainSpec, IBeaconSyncStrategy beaconSync, + IStateReader stateReader, ILogManager logManager) : base( dbProvider, @@ -67,9 +68,9 @@ public MergeSynchronizer( blockDownloaderFactory, pivot, exitSource, - readOnlyTrieStore, betterPeerStrategy, chainSpec, + stateReader, logManager) { _invalidChainTracker = invalidChainTracker; diff --git a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs index 9198ecf4c71..6824ebb1800 100644 --- a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs @@ -92,9 +92,8 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT SpecProvider.UpdateMergeTransitionInfo(1, 0); BlockProducerEnvFactory blockProducerEnvFactory = new( - DbProvider, + WorldStateManager, BlockTree, - ReadOnlyTrieStore, SpecProvider, BlockValidator, NoBlockRewards.Instance, @@ -205,9 +204,8 @@ protected override BlockProcessor CreateBlockProcessor() LogManager); _tracerFactory = new TracerFactory( - DbProvider, BlockTree, - ReadOnlyTrieStore, + WorldStateManager, BlockPreprocessorStep, SpecProvider, LogManager, diff --git a/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs b/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs index d09f9f9955c..7fd9f25a611 100644 --- a/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs +++ b/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs @@ -11,6 +11,7 @@ using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Logging; +using Nethermind.State; using Nethermind.Trie.Pruning; namespace Nethermind.Mev.Execution @@ -22,13 +23,11 @@ public class TracerFactory : ITracerFactory private readonly ILogManager _logManager; private readonly ProcessingOptions _processingOptions; private readonly IReadOnlyBlockTree _blockTree; - private readonly ReadOnlyDbProvider _dbProvider; - private readonly IReadOnlyTrieStore _trieStore; + private readonly IWorldStateManager _worldStateManager; public TracerFactory( - IDbProvider dbProvider, IBlockTree blockTree, - IReadOnlyTrieStore trieStore, + IWorldStateManager worldStateManager, IBlockPreprocessorStep recoveryStep, ISpecProvider specProvider, ILogManager logManager, @@ -38,18 +37,17 @@ public TracerFactory( _processingOptions = processingOptions; _recoveryStep = recoveryStep ?? throw new ArgumentNullException(nameof(recoveryStep)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); - _dbProvider = dbProvider.AsReadOnly(false); + _worldStateManager = worldStateManager ?? throw new ArgumentNullException(nameof(worldStateManager)); _blockTree = blockTree.AsReadOnly(); - _trieStore = trieStore; } public ITracer Create() { ReadOnlyTxProcessingEnv txProcessingEnv = new( - _dbProvider, _trieStore, _blockTree, _specProvider, _logManager); + _worldStateManager, _blockTree, _specProvider, _logManager); ReadOnlyChainProcessingEnv chainProcessingEnv = new( - txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _dbProvider, _specProvider, _logManager); + txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _specProvider, _logManager); return CreateTracer(txProcessingEnv, chainProcessingEnv); } diff --git a/src/Nethermind/Nethermind.Mev/MevPlugin.cs b/src/Nethermind/Nethermind.Mev/MevPlugin.cs index 96aaf787dd3..7a8b4bd2618 100644 --- a/src/Nethermind/Nethermind.Mev/MevPlugin.cs +++ b/src/Nethermind/Nethermind.Mev/MevPlugin.cs @@ -90,9 +90,8 @@ private ITracerFactory TracerFactory var (getFromApi, _) = _nethermindApi!.ForProducer; _tracerFactory = new TracerFactory( - getFromApi.DbProvider!, getFromApi.BlockTree!, - getFromApi.ReadOnlyTrieStore!, + getFromApi.WorldStateManager!, getFromApi.BlockPreprocessor!, getFromApi.SpecProvider!, getFromApi.LogManager!, diff --git a/src/Nethermind/Nethermind.Optimism/InitializeBlockProducerOptimism.cs b/src/Nethermind/Nethermind.Optimism/InitializeBlockProducerOptimism.cs index e7b01097df8..3de030e80ce 100644 --- a/src/Nethermind/Nethermind.Optimism/InitializeBlockProducerOptimism.cs +++ b/src/Nethermind/Nethermind.Optimism/InitializeBlockProducerOptimism.cs @@ -23,7 +23,6 @@ protected override Task BuildProducer() { if (_api.DbProvider is null) throw new StepDependencyException(nameof(_api.DbProvider)); if (_api.BlockTree is null) throw new StepDependencyException(nameof(_api.BlockTree)); - if (_api.ReadOnlyTrieStore is null) throw new StepDependencyException(nameof(_api.ReadOnlyTrieStore)); if (_api.SpecProvider is null) throw new StepDependencyException(nameof(_api.SpecProvider)); if (_api.RewardCalculatorSource is null) throw new StepDependencyException(nameof(_api.RewardCalculatorSource)); if (_api.ReceiptStorage is null) throw new StepDependencyException(nameof(_api.ReceiptStorage)); @@ -32,12 +31,12 @@ protected override Task BuildProducer() if (_api.BlockValidator is null) throw new StepDependencyException(nameof(_api.BlockValidator)); if (_api.SpecHelper is null) throw new StepDependencyException(nameof(_api.SpecHelper)); if (_api.L1CostHelper is null) throw new StepDependencyException(nameof(_api.L1CostHelper)); + if (_api.WorldStateManager is null) throw new StepDependencyException(nameof(_api.WorldStateManager)); _api.BlockProducerEnvFactory = new OptimismBlockProducerEnvFactory( + _api.WorldStateManager, _api.ChainSpec, - _api.DbProvider, _api.BlockTree, - _api.ReadOnlyTrieStore, _api.SpecProvider, _api.BlockValidator, _api.RewardCalculatorSource, diff --git a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs index fbf648b45aa..6920765a0dc 100644 --- a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs +++ b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs @@ -40,7 +40,6 @@ protected override Task InitBlockchain() protected override ITransactionProcessor CreateTransactionProcessor() { if (_api.SpecProvider is null) throw new StepDependencyException(nameof(_api.SpecProvider)); - if (_api.WorldState is null) throw new StepDependencyException(nameof(_api.WorldState)); if (_api.SpecHelper is null) throw new StepDependencyException(nameof(_api.SpecHelper)); if (_api.L1CostHelper is null) throw new StepDependencyException(nameof(_api.L1CostHelper)); diff --git a/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs index 3ae5600db5b..7393e7fdfa8 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs @@ -16,6 +16,7 @@ using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; using Nethermind.Specs.ChainSpecStyle; +using Nethermind.State; using Nethermind.Trie.Pruning; using Nethermind.TxPool; @@ -28,10 +29,9 @@ public class OptimismBlockProducerEnvFactory : BlockProducerEnvFactory private readonly OPL1CostHelper _l1CostHelper; public OptimismBlockProducerEnvFactory( + IWorldStateManager worldStateManager, ChainSpec chainSpec, - IDbProvider dbProvider, IBlockTree blockTree, - IReadOnlyTrieStore readOnlyTrieStore, ISpecProvider specProvider, IBlockValidator blockValidator, IRewardCalculatorSource rewardCalculatorSource, @@ -42,8 +42,8 @@ public OptimismBlockProducerEnvFactory( IBlocksConfig blocksConfig, OPSpecHelper specHelper, OPL1CostHelper l1CostHelper, - ILogManager logManager) : base(dbProvider, - blockTree, readOnlyTrieStore, specProvider, blockValidator, + ILogManager logManager) : base(worldStateManager, + blockTree, specProvider, blockValidator, rewardCalculatorSource, receiptStorage, blockPreprocessorStep, txPool, transactionComparerProvider, blocksConfig, logManager) { @@ -53,10 +53,10 @@ public OptimismBlockProducerEnvFactory( TransactionsExecutorFactory = new OptimismTransactionsExecutorFactory(specProvider, logManager); } - protected override ReadOnlyTxProcessingEnv CreateReadonlyTxProcessingEnv(ReadOnlyDbProvider readOnlyDbProvider, + protected override ReadOnlyTxProcessingEnv CreateReadonlyTxProcessingEnv(IWorldStateManager worldStateManager, ReadOnlyBlockTree readOnlyBlockTree) { - ReadOnlyTxProcessingEnv result = new(readOnlyDbProvider, _readOnlyTrieStore, + ReadOnlyTxProcessingEnv result = new(worldStateManager, readOnlyBlockTree, _specProvider, _logManager); result.TransactionProcessor = new OptimismTransactionProcessor(_specProvider, result.StateProvider, result.Machine, _logManager, _l1CostHelper, _specHelper); diff --git a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs index a8acd8974d5..d95345a7fbb 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs @@ -148,7 +148,7 @@ public Task InitSynchronization() _api.SealValidator!, _syncConfig, _api.BetterPeerStrategy!, - new FullStateFinder(_api.BlockTree, _api.DbProvider.StateDb, _api.TrieStore!.AsReadOnly()), + new FullStateFinder(_api.BlockTree, _api.StateReader!), _api.LogManager); _api.Synchronizer = new MergeSynchronizer( @@ -165,10 +165,10 @@ public Task InitSynchronization() _mergeConfig, _invalidChainTracker, _api.ProcessExit!, - _api.ReadOnlyTrieStore!, _api.BetterPeerStrategy, _api.ChainSpec, _beaconSync, + _api.StateReader!, _api.LogManager ); diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs index a4e48cec847..0550a49d49f 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs @@ -49,8 +49,10 @@ namespace Nethermind.Runner.Test.Ethereum { public static class Build { - public static NethermindApi ContextWithMocks() => - new(Substitute.For(), Substitute.For(), LimboLogs.Instance, new ChainSpec()) + public static NethermindApi ContextWithMocks() + { + var api = new NethermindApi(Substitute.For(), Substitute.For(), LimboLogs.Instance, + new ChainSpec()) { Enode = Substitute.For(), TxPool = Substitute.For(), @@ -104,7 +106,6 @@ public static NethermindApi ContextWithMocks() => WebSocketsManager = Substitute.For(), ChainLevelInfoRepository = Substitute.For(), TrieStore = Substitute.For(), - ReadOnlyTrieStore = Substitute.For(), BlockProducerEnvFactory = Substitute.For(), TransactionComparerProvider = Substitute.For(), GasPriceOracle = Substitute.For(), @@ -118,5 +119,9 @@ public static NethermindApi ContextWithMocks() => ReceiptMonitor = Substitute.For(), WitnessRepository = Substitute.For() }; + + api.WorldStateManager = new ReadOnlyWorldStateManager(api.DbProvider, Substitute.For(), LimboLogs.Instance); + return api; + } } } diff --git a/src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs b/src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs new file mode 100644 index 00000000000..754cad26b66 --- /dev/null +++ b/src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using FluentAssertions; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Db; +using Nethermind.Logging; +using Nethermind.Specs; +using Nethermind.State; +using Nethermind.Trie.Pruning; +using NSubstitute; +using NUnit.Framework; + +namespace Nethermind.Store.Test; + +public class WorldStateManagerTests +{ + [Test] + public void ShouldProxyGlobalWorldState() + { + IWorldState worldState = Substitute.For(); + ITrieStore trieStore = Substitute.For(); + IDbProvider dbProvider = TestMemDbProvider.Init(); + WorldStateManager worldStateManager = new WorldStateManager(worldState, trieStore, dbProvider, LimboLogs.Instance); + + worldStateManager.GlobalWorldState.Should().Be(worldState); + } + + [Test] + public void ShouldProxyReorgBoundaryEvent() + { + IWorldState worldState = Substitute.For(); + ITrieStore trieStore = Substitute.For(); + IDbProvider dbProvider = TestMemDbProvider.Init(); + WorldStateManager worldStateManager = new WorldStateManager(worldState, trieStore, dbProvider, LimboLogs.Instance); + + bool gotEvent = false; + worldStateManager.ReorgBoundaryReached += (sender, reached) => gotEvent = true; + trieStore.ReorgBoundaryReached += Raise.EventWith(new ReorgBoundaryReached(1)); + + gotEvent.Should().BeTrue(); + } + + [Test] + public void ShouldCreateTemporaryWorldState_AndCanReset() + { + IWorldState worldState = Substitute.For(); + ITrieStore trieStore = Substitute.For(); + IDbProvider dbProvider = TestMemDbProvider.Init(); + WorldStateManager worldStateManager = new WorldStateManager(worldState, trieStore, dbProvider, LimboLogs.Instance); + + IWorldState tempWorldState = worldStateManager.CreateResettableWorldState(); + IStateReader stateReader = worldStateManager.GlobalStateReader; + + byte[] code = new byte[] { 1 }; + Hash256 codeHash = Keccak.Compute(code); + tempWorldState.CreateAccount(Address.Zero, 0, 0); + tempWorldState.InsertCode(Address.Zero, code, MainnetSpecProvider.Instance.GenesisSpec); + + stateReader.GetCode(codeHash).Should().NotBeNull(); + tempWorldState.Reset(); + stateReader.GetCode(codeHash).Should().BeNull(); + } +} diff --git a/src/Nethermind/Nethermind.State/IWorldStateManager.cs b/src/Nethermind/Nethermind.State/IWorldStateManager.cs new file mode 100644 index 00000000000..26a01d09f67 --- /dev/null +++ b/src/Nethermind/Nethermind.State/IWorldStateManager.cs @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Trie.Pruning; + +namespace Nethermind.State; + +public interface IWorldStateManager +{ + IWorldState GlobalWorldState { get; } + IStateReader GlobalStateReader { get; } + + /// + /// Used by read only tasks that need to execute blocks. + /// + /// + IWorldState CreateResettableWorldState(); + + event EventHandler? ReorgBoundaryReached; +} diff --git a/src/Nethermind/Nethermind.State/ReadOnlyWorldStateManager.cs b/src/Nethermind/Nethermind.State/ReadOnlyWorldStateManager.cs new file mode 100644 index 00000000000..d2a9b5ebce1 --- /dev/null +++ b/src/Nethermind/Nethermind.State/ReadOnlyWorldStateManager.cs @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Core; +using Nethermind.Db; +using Nethermind.Logging; +using Nethermind.Trie.Pruning; + +namespace Nethermind.State; + +/// +/// Mainly to make it easier for test +/// +public class ReadOnlyWorldStateManager : IWorldStateManager +{ + private IReadOnlyDbProvider _readOnlyDbProvider; + private IReadOnlyTrieStore? _readOnlyTrieStore; + private ILogManager _logManager; + private readonly IDbProvider _dbProvider; + private readonly ReadOnlyDb _codeDb; + + public ReadOnlyWorldStateManager( + IDbProvider dbProvider, + IReadOnlyTrieStore? readOnlyTrieStore, + ILogManager logManager + ) + { + _readOnlyTrieStore = readOnlyTrieStore; + _dbProvider = dbProvider; + _logManager = logManager; + + _readOnlyDbProvider = _dbProvider.AsReadOnly(false); + _codeDb = _readOnlyDbProvider.GetDb(DbNames.Code).AsReadOnly(true); + GlobalStateReader = new StateReader(_readOnlyTrieStore, _codeDb, _logManager); + } + + public virtual IWorldState GlobalWorldState => throw new InvalidOperationException("global world state not supported"); + + public IStateReader GlobalStateReader { get; } + + public IWorldState CreateResettableWorldState() + { + return new WorldState(_readOnlyTrieStore, _codeDb, _logManager); + } + + public virtual event EventHandler? ReorgBoundaryReached + { + add => throw new InvalidOperationException("Unsupported operation"); + remove => throw new InvalidOperationException("Unsupported operation"); + } +} diff --git a/src/Nethermind/Nethermind.State/StateProvider.cs b/src/Nethermind/Nethermind.State/StateProvider.cs index f24e6ca45a3..ac0b6c7334d 100644 --- a/src/Nethermind/Nethermind.State/StateProvider.cs +++ b/src/Nethermind/Nethermind.State/StateProvider.cs @@ -801,6 +801,11 @@ public void Reset() _currentPosition = Resettable.EmptyPosition; Array.Clear(_changes, 0, _changes.Length); _needsStateRootUpdate = false; + + if (_codeDb is IReadOnlyDb readOnlyDb) + { + readOnlyDb.ClearTempChanges(); + } } public void CommitTree(long blockNumber) diff --git a/src/Nethermind/Nethermind.State/StateReader.cs b/src/Nethermind/Nethermind.State/StateReader.cs index 1fb7463f0c9..c6544eb0bef 100644 --- a/src/Nethermind/Nethermind.State/StateReader.cs +++ b/src/Nethermind/Nethermind.State/StateReader.cs @@ -15,12 +15,12 @@ namespace Nethermind.State { public class StateReader : IStateReader { - private readonly IDb _codeDb; + private readonly IKeyValueStore _codeDb; private readonly ILogger _logger; private readonly StateTree _state; private readonly StorageTree _storage; - public StateReader(ITrieStore? trieStore, IDb? codeDb, ILogManager? logManager) + public StateReader(ITrieStore? trieStore, IKeyValueStore? codeDb, ILogManager? logManager) { _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _codeDb = codeDb ?? throw new ArgumentNullException(nameof(codeDb)); diff --git a/src/Nethermind/Nethermind.State/WorldStateManager.cs b/src/Nethermind/Nethermind.State/WorldStateManager.cs new file mode 100644 index 00000000000..cfb570a8daa --- /dev/null +++ b/src/Nethermind/Nethermind.State/WorldStateManager.cs @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Db; +using Nethermind.Logging; +using Nethermind.Trie.Pruning; + +namespace Nethermind.State; + +public class WorldStateManager : ReadOnlyWorldStateManager +{ + private readonly IWorldState _worldState; + private readonly ITrieStore _trieStore; + + public WorldStateManager( + IWorldState worldState, + ITrieStore trieStore, + IDbProvider dbProvider, + ILogManager logManager + ) : base(dbProvider, trieStore.AsReadOnly(), logManager) + { + _worldState = worldState; + _trieStore = trieStore; + } + + public override IWorldState GlobalWorldState => _worldState; + + public override event EventHandler? ReorgBoundaryReached + { + add => _trieStore.ReorgBoundaryReached += value; + remove => _trieStore.ReorgBoundaryReached -= value; + } +} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs index 04bacae7669..2d99f6b3d99 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs @@ -20,6 +20,7 @@ using Nethermind.Logging; using Nethermind.Specs; using Nethermind.Specs.ChainSpecStyle; +using Nethermind.State; using Nethermind.State.Witnesses; using Nethermind.Stats; using Nethermind.Synchronization.Blocks; @@ -65,6 +66,9 @@ public async Task Setup() Always.Valid, new TotalDifficultyBetterPeerStrategy(LimboLogs.Instance), LimboLogs.Instance); + + IStateReader stateReader = new StateReader(trieStore, _codeDb, LimboLogs.Instance); + _synchronizer = new Synchronizer( dbProvider, MainnetSpecProvider.Instance, @@ -76,9 +80,9 @@ public async Task Setup() blockDownloaderFactory, pivot, Substitute.For(), - trieStore.AsReadOnly(), bestPeerStrategy, new ChainSpec(), + stateReader, LimboLogs.Instance); _syncServer = new SyncServer( trieStore.AsKeyValueStore(), diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs index 3fa95df3df1..2a82088423e 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs @@ -8,6 +8,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Db; using Nethermind.Logging; +using Nethermind.State; using Nethermind.Synchronization.FastBlocks; using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.SnapSync; @@ -26,13 +27,13 @@ public class SyncProgressResolverTests public void Header_block_is_0_when_no_header_was_suggested() { IBlockTree blockTree = Substitute.For(); - IDb stateDb = new MemDb(); + IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { PivotNumber = "1", }; - SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateDb, NullTrieNodeResolver.Instance, false, syncConfig, LimboLogs.Instance); + SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); blockTree.BestSuggestedHeader.ReturnsNull(); Assert.That(syncProgressResolver.FindBestHeader(), Is.EqualTo(0)); } @@ -41,13 +42,13 @@ public void Header_block_is_0_when_no_header_was_suggested() public void Best_block_is_0_when_no_block_was_suggested() { IBlockTree blockTree = Substitute.For(); - IDb stateDb = new MemDb(); + IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { PivotNumber = "1", }; - SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateDb, NullTrieNodeResolver.Instance, false, syncConfig, LimboLogs.Instance); + SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); blockTree.BestSuggestedBody.ReturnsNull(); Assert.That(syncProgressResolver.FindBestFullBlock(), Is.EqualTo(0)); } @@ -56,17 +57,17 @@ public void Best_block_is_0_when_no_block_was_suggested() public void Best_state_is_head_when_there_are_no_suggested_blocks() { IBlockTree blockTree = Substitute.For(); - IDb stateDb = new MemDb(); + IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { PivotNumber = "1", }; - SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateDb, NullTrieNodeResolver.Instance, false, syncConfig, LimboLogs.Instance); + SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); Block head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; blockTree.Head.Returns(head); blockTree.BestSuggestedHeader.Returns(head.Header); - stateDb[head.StateRoot!.Bytes] = new byte[] { 1 }; + stateReader.HasStateForRoot(head.StateRoot!).Returns(true); Assert.That(syncProgressResolver.FindBestFullState(), Is.EqualTo(head.Number)); } @@ -74,21 +75,21 @@ public void Best_state_is_head_when_there_are_no_suggested_blocks() public void Best_state_is_suggested_if_there_is_suggested_block_with_state() { IBlockTree blockTree = Substitute.For(); - IDb stateDb = new MemDb(); + IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { PivotNumber = "1", }; - SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateDb, NullTrieNodeResolver.Instance, false, syncConfig, LimboLogs.Instance); + SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); Block head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; BlockHeader suggested = Build.A.BlockHeader.WithNumber(6).WithStateRoot(TestItem.KeccakB).TestObject; blockTree.Head.Returns(head); blockTree.BestSuggestedHeader.Returns(suggested); blockTree.FindHeader(Arg.Any(), BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(head.Header); - stateDb[head.StateRoot!.Bytes] = new byte[] { 1 }; - stateDb[suggested.StateRoot!.Bytes] = new byte[] { 1 }; + stateReader.HasStateForRoot(head.StateRoot!).Returns(true); + stateReader.HasStateForRoot(suggested.StateRoot!).Returns(true); Assert.That(syncProgressResolver.FindBestFullState(), Is.EqualTo(suggested.Number)); } @@ -96,20 +97,20 @@ public void Best_state_is_suggested_if_there_is_suggested_block_with_state() public void Best_state_is_head_if_there_is_suggested_block_without_state() { IBlockTree blockTree = Substitute.For(); - IDb stateDb = new MemDb(); + IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { PivotNumber = "1", }; - SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateDb, NullTrieNodeResolver.Instance, false, syncConfig, LimboLogs.Instance); + SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); Block head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; BlockHeader suggested = Build.A.BlockHeader.WithNumber(6).WithStateRoot(TestItem.KeccakB).TestObject; blockTree.Head.Returns(head); blockTree.BestSuggestedHeader.Returns(suggested); blockTree.FindHeader(Arg.Any(), BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(head.Header); - stateDb[head.StateRoot!.Bytes] = new byte[] { 1 }; - stateDb[suggested.StateRoot!.Bytes] = null; + stateReader.HasStateForRoot(head.StateRoot!).Returns(true); + stateReader.HasStateForRoot(suggested.StateRoot!).Returns(false); Assert.That(syncProgressResolver.FindBestFullState(), Is.EqualTo(head.Number)); } @@ -117,14 +118,14 @@ public void Best_state_is_head_if_there_is_suggested_block_without_state() public void Is_fast_block_finished_returns_true_when_no_fast_block_sync_is_used() { IBlockTree blockTree = Substitute.For(); - IDb stateDb = new MemDb(); + IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { FastBlocks = false, PivotNumber = "1", }; - SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateDb, NullTrieNodeResolver.Instance, false, syncConfig, LimboLogs.Instance); + SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); Assert.True(syncProgressResolver.IsFastBlocksHeadersFinished()); Assert.True(syncProgressResolver.IsFastBlocksBodiesFinished()); Assert.True(syncProgressResolver.IsFastBlocksReceiptsFinished()); @@ -134,7 +135,7 @@ public void Is_fast_block_finished_returns_true_when_no_fast_block_sync_is_used( public void Is_fast_block_bodies_finished_returns_false_when_blocks_not_downloaded() { IBlockTree blockTree = Substitute.For(); - IDb stateDb = new MemDb(); + IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { FastBlocks = true, @@ -147,7 +148,7 @@ public void Is_fast_block_bodies_finished_returns_false_when_blocks_not_download blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); blockTree.LowestInsertedBodyNumber.Returns(2); - SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateDb, NullTrieNodeResolver.Instance, false, syncConfig, LimboLogs.Instance); + SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); Assert.False(syncProgressResolver.IsFastBlocksBodiesFinished()); } @@ -155,7 +156,7 @@ public void Is_fast_block_bodies_finished_returns_false_when_blocks_not_download public void Is_fast_block_receipts_finished_returns_true_when_receipts_not_downloaded_and_we_do_not_want_to_download_receipts() { IBlockTree blockTree = Substitute.For(); - IDb stateDb = new MemDb(); + IStateReader stateReader = Substitute.For(); SyncConfig syncConfig = new() { FastBlocks = true, @@ -167,19 +168,19 @@ public void Is_fast_block_receipts_finished_returns_true_when_receipts_not_downl blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); blockTree.LowestInsertedBodyNumber.Returns(1); - SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateDb, NullTrieNodeResolver.Instance, true, syncConfig, LimboLogs.Instance); + SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, true, syncConfig, LimboLogs.Instance); Assert.True(syncProgressResolver.IsFastBlocksReceiptsFinished()); } - private SyncProgressResolver CreateProgressResolver(IBlockTree blockTree, IDb stateDb, NullTrieNodeResolver nodeResolver, bool isReceiptFinished, SyncConfig syncConfig, LimboLogs limboLogs) + private SyncProgressResolver CreateProgressResolver(IBlockTree blockTree, IStateReader stateReader, bool isReceiptFinished, SyncConfig syncConfig, LimboLogs limboLogs) { ISyncFeed receiptFeed = Substitute.For>(); receiptFeed.IsFinished.Returns(isReceiptFinished); return new SyncProgressResolver( blockTree, - new FullStateFinder(blockTree, stateDb, nodeResolver), + new FullStateFinder(blockTree, stateReader), syncConfig, Substitute.For>(), Substitute.For>(), diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs index f14ef9cd2d5..4753b1bbcda 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs @@ -360,9 +360,9 @@ private SyncTestContext CreateSyncManager(int index) blockDownloaderFactory, pivot, Substitute.For(), - trieStore.AsReadOnly(), bestPeerStrategy, new ChainSpec(), + stateReader, logManager); ISyncModeSelector selector = synchronizer.SyncModeSelector; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs index f739e907743..f5b04a53354 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs @@ -32,6 +32,7 @@ using Nethermind.Merge.Plugin.Synchronization; using Nethermind.Merge.Plugin.Test; using Nethermind.Specs.ChainSpecStyle; +using Nethermind.State; using Nethermind.State.Witnesses; using Nethermind.Synchronization.Blocks; using Nethermind.Synchronization.ParallelSync; @@ -332,7 +333,9 @@ ISyncConfig GetSyncConfig() => ? new MergeBetterPeerStrategy(totalDifficultyBetterPeerStrategy, poSSwitcher, beaconPivot, LimboLogs.Instance) : totalDifficultyBetterPeerStrategy; - FullStateFinder fullStateFinder = new FullStateFinder(BlockTree, stateDb, trieStore); + StateReader reader = new StateReader(trieStore, codeDb, LimboLogs.Instance); + + FullStateFinder fullStateFinder = new FullStateFinder(BlockTree, reader); SyncPeerPool = new SyncPeerPool(BlockTree, stats, bestPeerStrategy, _logManager, 25); Pivot pivot = new(syncConfig); @@ -365,10 +368,10 @@ ISyncConfig GetSyncConfig() => mergeConfig, invalidChainTracker, Substitute.For(), - trieStore.AsReadOnly(), bestPeerStrategy, new ChainSpec(), No.BeaconSync, + reader, _logManager); } else @@ -391,9 +394,9 @@ ISyncConfig GetSyncConfig() => blockDownloaderFactory, pivot, Substitute.For(), - trieStore.AsReadOnly(), bestPeerStrategy, new ChainSpec(), + reader, _logManager); } diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/FullStateFinder.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/FullStateFinder.cs index b885071f9f9..4b89d37cdad 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/FullStateFinder.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/FullStateFinder.cs @@ -7,6 +7,7 @@ using Nethermind.Core.Crypto; using Nethermind.Db; using Nethermind.Logging; +using Nethermind.State; using Nethermind.Trie; using Nethermind.Trie.Pruning; @@ -18,18 +19,15 @@ public class FullStateFinder : IFullStateFinder // then we will never have to look 128 back again // note that we will be doing that every second or so private const int MaxLookupBack = 128; - private readonly IDb _stateDb; - private readonly ITrieNodeResolver _trieNodeResolver; + private readonly IStateReader _stateReader; private readonly IBlockTree _blockTree; public FullStateFinder( IBlockTree blockTree, - IDb stateDb, - ITrieNodeResolver trieNodeResolver) + IStateReader stateReader) { _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); - _stateDb = stateDb ?? throw new ArgumentNullException(nameof(stateDb)); - _trieNodeResolver = trieNodeResolver ?? throw new ArgumentNullException(nameof(trieNodeResolver)); + _stateReader = stateReader ?? throw new ArgumentNullException(nameof(stateReader)); } private bool IsFullySynced(Hash256 stateRoot) @@ -39,15 +37,7 @@ private bool IsFullySynced(Hash256 stateRoot) return true; } - TrieNode trieNode = _trieNodeResolver.FindCachedOrUnknown(stateRoot); - bool stateRootIsInMemory = trieNode.NodeType != NodeType.Unknown; - // We check whether one of below happened: - // 1) the block has been processed but not yet persisted (pruning) OR - // 2) the block has been persisted and removed from cache already OR - // 3) the full block state has been synced in the state nodes sync (fast sync) - // In 2) and 3) the state root will be saved in the database. - // In fast sync we never save the state root unless all the descendant nodes have been stored in the DB. - return stateRootIsInMemory || _stateDb.Get(stateRoot) is not null; + return _stateReader.HasStateForRoot(stateRoot); } public long FindBestFullState() diff --git a/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs b/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs index 33361381b43..d74a06f8fff 100644 --- a/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs +++ b/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs @@ -14,6 +14,7 @@ using Nethermind.Db; using Nethermind.Logging; using Nethermind.Specs.ChainSpecStyle; +using Nethermind.State; using Nethermind.Stats; using Nethermind.Stats.Model; using Nethermind.Synchronization.Blocks; @@ -76,7 +77,7 @@ public class Synchronizer : ISynchronizer private ISyncProgressResolver? _syncProgressResolver; public ISyncProgressResolver SyncProgressResolver => _syncProgressResolver ??= new SyncProgressResolver( _blockTree, - new FullStateFinder(_blockTree, _dbProvider.StateDb, _readOnlyTrieStore), + new FullStateFinder(_blockTree, _stateReader), _syncConfig, HeadersSyncFeed, BodiesSyncFeed, @@ -84,10 +85,9 @@ public class Synchronizer : ISynchronizer SnapSyncFeed, _logManager); - private readonly IReadOnlyTrieStore _readOnlyTrieStore; - - protected ISyncModeSelector? _syncModeSelector; + private readonly IStateReader _stateReader; + public virtual ISyncModeSelector SyncModeSelector => _syncModeSelector ??= new MultiSyncModeSelector( SyncProgressResolver, _syncPeerPool!, @@ -108,9 +108,9 @@ public Synchronizer( IBlockDownloaderFactory blockDownloaderFactory, IPivot pivot, IProcessExitSource processExitSource, - IReadOnlyTrieStore readOnlyTrieStore, IBetterPeerStrategy betterPeerStrategy, ChainSpec chainSpec, + IStateReader stateReader, ILogManager logManager) { _dbProvider = dbProvider ?? throw new ArgumentNullException(nameof(dbProvider)); @@ -127,7 +127,7 @@ public Synchronizer( _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); _betterPeerStrategy = betterPeerStrategy ?? throw new ArgumentNullException(nameof(betterPeerStrategy)); _chainSpec = chainSpec ?? throw new ArgumentNullException(nameof(chainSpec)); - _readOnlyTrieStore = readOnlyTrieStore ?? throw new ArgumentNullException(nameof(readOnlyTrieStore)); + _stateReader = stateReader ?? throw new ArgumentNullException(nameof(_stateReader)); _syncReport = new SyncReport(_syncPeerPool!, nodeStatsManager!, _syncConfig, _pivot, logManager);