diff --git a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs index 810f73ffd2d..8f15d15d8e2 100644 --- a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs +++ b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs @@ -134,6 +134,7 @@ public virtual async Task Execute(CancellationToken cancellationToken) _api.PeerPool, _api.StaticNodesManager, _api.BlockingVerifyTrie!, + _api.WorldStateManager.GlobalStateReader, _api.Enode, initConfig.BaseDbPath, pruningTrigger, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs index 41c68f518c3..da429aec03b 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs @@ -18,6 +18,7 @@ using Nethermind.Network.Config; using Nethermind.Serialization.Json; using Nethermind.Specs.ChainSpecStyle; +using Nethermind.State; using Nethermind.Stats.Model; using Nethermind.Synchronization.FastSync; using NSubstitute; @@ -34,6 +35,7 @@ public class AdminModuleTests private NetworkConfig _networkConfig = null!; private IBlockTree _blockTree = null!; private IBlockingVerifyTrie _blockingVerifyTrie = null!; + private IStateReader _stateReader = null!; private const string _enodeString = "enode://e1b7e0dc09aae610c9dec8a0bee62bab9946cc27ebdd2f9e3571ed6d444628f99e91e43f4a14d42d498217608bb3e1d1bc8ec2aa27d7f7e423413b851bae02bc@127.0.0.1:30303"; private const string _exampleDataDir = "/example/dbdir"; @@ -42,6 +44,7 @@ public void Setup() { _blockTree = Build.A.BlockTree().OfChainLength(5).TestObject; _blockingVerifyTrie = Substitute.For(); + _stateReader = Substitute.For(); _networkConfig = new NetworkConfig(); IPeerPool peerPool = Substitute.For(); ConcurrentDictionary dict = new(); @@ -61,6 +64,7 @@ public void Setup() peerPool, staticNodesManager, _blockingVerifyTrie, + _stateReader, enode, _exampleDataDir, new ManualPruningTrigger(), @@ -117,9 +121,17 @@ public async Task Test_admin_dataDir() [Test] public async Task Test_admin_verifyTrie() { - (await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_verifyTrie")).Should().Contain("Unable to start verify trie"); + (await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_verifyTrie", "latest")).Should().Contain("Unable to start verify trie"); _blockingVerifyTrie.TryStartVerifyTrie(Arg.Any()).Returns(true); - (await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_verifyTrie")).Should().Contain("Starting"); + (await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_verifyTrie", "latest")).Should().Contain("Starting"); + } + + [Test] + public async Task Test_hasStateForBlock() + { + (await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_isStateRootAvailable", "latest")).Should().Contain("false"); + _stateReader.HasStateForRoot(Arg.Any()).Returns(true); + (await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_isStateRootAvailable", "latest")).Should().Contain("true"); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/AdminRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/AdminRpcModule.cs index e2819a1592d..4a6d2e3317d 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/AdminRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/AdminRpcModule.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading.Tasks; using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.FullPruning; using Nethermind.Config; using Nethermind.Core; @@ -12,6 +13,7 @@ using Nethermind.Network; using Nethermind.Network.Config; using Nethermind.Specs.ChainSpecStyle; +using Nethermind.State; using Nethermind.Stats.Model; using Nethermind.Synchronization.FastSync; @@ -28,6 +30,7 @@ public class AdminRpcModule : IAdminRpcModule private readonly string _dataDir; private readonly ManualPruningTrigger _pruningTrigger; private readonly IBlockingVerifyTrie _blockingVerifyTrie; + private readonly IStateReader _stateReader; private NodeInfo _nodeInfo = null!; public AdminRpcModule( @@ -36,6 +39,7 @@ public AdminRpcModule( IPeerPool peerPool, IStaticNodesManager staticNodesManager, IBlockingVerifyTrie blockingVerifyTrie, + IStateReader stateReader, IEnode enode, string dataDir, ManualPruningTrigger pruningTrigger, @@ -48,6 +52,7 @@ public AdminRpcModule( _networkConfig = networkConfig ?? throw new ArgumentNullException(nameof(networkConfig)); _staticNodesManager = staticNodesManager ?? throw new ArgumentNullException(nameof(staticNodesManager)); _blockingVerifyTrie = blockingVerifyTrie ?? throw new ArgumentNullException(nameof(blockingVerifyTrie)); + _stateReader = stateReader ?? throw new ArgumentNullException(nameof(stateReader)); _pruningTrigger = pruningTrigger; _parameters = parameters ?? throw new ArgumentNullException(nameof(parameters)); @@ -139,19 +144,31 @@ public ResultWrapper admin_setSolc() return ResultWrapper.Success(true); } + public ResultWrapper admin_isStateRootAvailable(BlockParameter block) + { + SearchResult headerSearchResult = _blockTree.SearchForHeader(block); + if (headerSearchResult.Object is null) + { + return ResultWrapper.Fail("Unable to find block. Unable to know state root to verify."); + } + + return ResultWrapper.Success(_stateReader.HasStateForBlock(headerSearchResult.Object)); + } + public ResultWrapper admin_prune() { return ResultWrapper.Success(_pruningTrigger.Trigger()); } - public ResultWrapper admin_verifyTrie() + public ResultWrapper admin_verifyTrie(BlockParameter block) { - if (_blockTree.Head is null) + SearchResult headerSearchResult = _blockTree.SearchForHeader(block); + if (headerSearchResult.Object is null) { - return ResultWrapper.Fail("Head is null. Unable to know state root to verify."); + return ResultWrapper.Fail("Unable to find block. Unable to know state root to verify."); } - if (!_blockingVerifyTrie.TryStartVerifyTrie(_blockTree.Head!.Header)) + if (!_blockingVerifyTrie.TryStartVerifyTrie(headerSearchResult.Object)) { return ResultWrapper.Fail("Unable to start verify trie. Verify trie already running."); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/IAdminRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/IAdminRpcModule.cs index a4ab1e9ca30..f9a338e95db 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/IAdminRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/IAdminRpcModule.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading.Tasks; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.FullPruning; namespace Nethermind.JsonRpc.Modules.Admin; @@ -57,20 +58,19 @@ ResultWrapper admin_peers( IsImplemented = true)] ResultWrapper admin_dataDir(); - [JsonRpcMethod(Description = "[DEPRECATED]", IsImplemented = false)] ResultWrapper admin_setSolc(); - [JsonRpcMethod(Description = "Runs full pruning if enabled.", + [JsonRpcMethod(Description = "True if state root for the block is available", EdgeCaseHint = "", ExampleResponse = "\"Starting\"", IsImplemented = true)] - ResultWrapper admin_prune(); + ResultWrapper admin_isStateRootAvailable(BlockParameter block); [JsonRpcMethod(Description = "Runs VerifyTrie.", EdgeCaseHint = "", ExampleResponse = "\"Starting\"", IsImplemented = true)] - ResultWrapper admin_verifyTrie(); + ResultWrapper admin_verifyTrie(BlockParameter block); }