Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions neo.sln
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.Plugins.RestServer.Test
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestServer", "src\Plugins\RestServer\RestServer.csproj", "{4865C487-C1A1-4E36-698D-1EC4CCF08FDB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.Plugins.StateService.Tests", "tests\Neo.Plugins.StateService.Tests\Neo.Plugins.StateService.Tests.csproj", "{229C7877-C0FA-4399-A0DB-96E714A59481}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -271,6 +273,10 @@ Global
{4865C487-C1A1-4E36-698D-1EC4CCF08FDB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4865C487-C1A1-4E36-698D-1EC4CCF08FDB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4865C487-C1A1-4E36-698D-1EC4CCF08FDB}.Release|Any CPU.Build.0 = Release|Any CPU
{229C7877-C0FA-4399-A0DB-96E714A59481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{229C7877-C0FA-4399-A0DB-96E714A59481}.Debug|Any CPU.Build.0 = Debug|Any CPU
{229C7877-C0FA-4399-A0DB-96E714A59481}.Release|Any CPU.ActiveCfg = Release|Any CPU
{229C7877-C0FA-4399-A0DB-96E714A59481}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -319,6 +325,7 @@ Global
{8C7A7070-08E3-435A-A909-9541B5C66E8C} = {EDE05FA8-8E73-4924-BC63-DD117127EEE1}
{A7FE2B30-11F8-E88D-D5BF-AF1B11EFEC8E} = {7F257712-D033-47FF-B439-9D4320D06599}
{4865C487-C1A1-4E36-698D-1EC4CCF08FDB} = {C2DC830A-327A-42A7-807D-295216D30DBB}
{229C7877-C0FA-4399-A0DB-96E714A59481} = {7F257712-D033-47FF-B439-9D4320D06599}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BCBA19D9-F868-4C6D-8061-A2B91E06E3EC}
Expand Down
87 changes: 35 additions & 52 deletions src/Plugins/StateService/StatePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ private void OnGetStateHeight()
[ConsoleCommand("get proof", Category = "StateService", Description = "Get proof of key and contract hash")]
private void OnGetProof(UInt256 rootHash, UInt160 scriptHash, string key)
{
if (_system is null || _system.Settings.Network != StateServiceSettings.Default.Network) throw new InvalidOperationException("Network doesn't match");
if (_system is null || _system.Settings.Network != StateServiceSettings.Default.Network)
throw new InvalidOperationException("Network doesn't match");

try
{
ConsoleHelper.Info("Proof: ", GetProof(rootHash, scriptHash, Convert.FromBase64String(key)));
Expand All @@ -186,8 +188,7 @@ private void OnVerifyProof(UInt256 rootHash, string proof)
{
try
{
ConsoleHelper.Info("Verify Result: ",
VerifyProof(rootHash, Convert.FromBase64String(proof)));
ConsoleHelper.Info("Verify Result: ", VerifyProof(rootHash, Convert.FromBase64String(proof)));
}
catch (RpcException e)
{
Expand All @@ -196,9 +197,8 @@ private void OnVerifyProof(UInt256 rootHash, string proof)
}

[RpcMethod]
public JToken GetStateRoot(JArray _params)
public JToken GetStateRoot(uint index)
{
var index = Result.Ok_Or(() => uint.Parse(_params[0].AsString()), RpcError.InvalidParams.WithData($"Invalid state root index: {_params[0]}"));
using var snapshot = StateStore.Singleton.GetSnapshot();
var stateRoot = snapshot.GetStateRoot(index).NotNull_Or(RpcError.UnknownStateRoot);
return stateRoot.ToJson();
Expand Down Expand Up @@ -233,7 +233,7 @@ private string GetProof(Trie trie, StorageKey skey)

private string GetProof(UInt256 rootHash, UInt160 scriptHash, byte[] key)
{
(!StateServiceSettings.Default.FullState && StateStore.Singleton.CurrentLocalRootHash != rootHash).False_Or(RpcError.UnsupportedState);
CheckRootHash(rootHash);

using var store = StateStore.Singleton.GetStoreSnapshot();
var trie = new Trie(store, rootHash);
Expand All @@ -242,12 +242,10 @@ private string GetProof(UInt256 rootHash, UInt160 scriptHash, byte[] key)
}

[RpcMethod]
public JToken GetProof(JArray _params)
public JToken GetProof(UInt256 rootHash, UInt160 scriptHash, string key)
{
var rootHash = Result.Ok_Or(() => UInt256.Parse(_params[0].AsString()), RpcError.InvalidParams.WithData($"Invalid root hash: {_params[0]}"));
var scriptHash = Result.Ok_Or(() => UInt160.Parse(_params[1].AsString()), RpcError.InvalidParams.WithData($"Invalid script hash: {_params[1]}"));
var key = Result.Ok_Or(() => Convert.FromBase64String(_params[2].AsString()), RpcError.InvalidParams.WithData($"Invalid key: {_params[2]}"));
return GetProof(rootHash, scriptHash, key);
var keyBytes = Result.Ok_Or(() => Convert.FromBase64String(key), RpcError.InvalidParams.WithData($"Invalid key: {key}"));
return GetProof(rootHash, scriptHash, keyBytes);
}

private string VerifyProof(UInt256 rootHash, byte[] proof)
Expand All @@ -269,15 +267,15 @@ private string VerifyProof(UInt256 rootHash, byte[] proof)
}

[RpcMethod]
public JToken VerifyProof(JArray _params)
public JToken VerifyProof(UInt256 rootHash, string proof)
{
var rootHash = Result.Ok_Or(() => UInt256.Parse(_params[0].AsString()), RpcError.InvalidParams.WithData($"Invalid root hash: {_params[0]}"));
var proofBytes = Result.Ok_Or(() => Convert.FromBase64String(_params[1].AsString()), RpcError.InvalidParams.WithData($"Invalid proof: {_params[1]}"));
var proofBytes = Result.Ok_Or(
() => Convert.FromBase64String(proof), RpcError.InvalidParams.WithData($"Invalid proof: {proof}"));
return VerifyProof(rootHash, proofBytes);
}

[RpcMethod]
public JToken GetStateHeight(JArray _params)
public JToken GetStateHeight()
{
return new JObject()
{
Expand All @@ -289,50 +287,39 @@ public JToken GetStateHeight(JArray _params)
private ContractState GetHistoricalContractState(Trie trie, UInt160 scriptHash)
{
const byte prefix = 8;
StorageKey skey = new KeyBuilder(NativeContract.ContractManagement.Id, prefix).Add(scriptHash);
return trie.TryGetValue(skey.ToArray(), out var value) ? value.AsSerializable<StorageItem>().GetInteroperable<ContractState>() : null;
var skey = new KeyBuilder(NativeContract.ContractManagement.Id, prefix).Add(scriptHash);
return trie.TryGetValue(skey.ToArray(), out var value)
? value.AsSerializable<StorageItem>().GetInteroperable<ContractState>()
: null;
}

private StorageKey ParseStorageKey(byte[] data)
{
return new()
{
Id = BinaryPrimitives.ReadInt32LittleEndian(data),
Key = data.AsMemory(sizeof(int)),
};
return new() { Id = BinaryPrimitives.ReadInt32LittleEndian(data), Key = data.AsMemory(sizeof(int)) };
}

[RpcMethod]
public JToken FindStates(JArray _params)
private void CheckRootHash(UInt256 rootHash)
{
var rootHash = Result.Ok_Or(() => UInt256.Parse(_params[0].AsString()), RpcError.InvalidParams.WithData($"Invalid root hash: {_params[0]}"));
(!StateServiceSettings.Default.FullState && StateStore.Singleton.CurrentLocalRootHash != rootHash).False_Or(RpcError.UnsupportedState);
var fullState = StateServiceSettings.Default.FullState;
var current = StateStore.Singleton.CurrentLocalRootHash;
(!fullState && current != rootHash)
.False_Or(RpcError.UnsupportedState.WithData($"fullState:{fullState},current:{current},rootHash:{rootHash}"));
}

var scriptHash = Result.Ok_Or(() => UInt160.Parse(_params[1].AsString()), RpcError.InvalidParams.WithData($"Invalid script hash: {_params[1]}"));
var prefix = Result.Ok_Or(() => Convert.FromBase64String(_params[2].AsString()), RpcError.InvalidParams.WithData($"Invalid prefix: {_params[2]}"));
var key = Array.Empty<byte>();
if (3 < _params.Count)
key = Result.Ok_Or(() => Convert.FromBase64String(_params[3].AsString()), RpcError.InvalidParams.WithData($"Invalid key: {_params[3]}"));
[RpcMethod]
public JToken FindStates(UInt256 rootHash, UInt160 scriptHash, byte[] prefix, byte[] key = null, int count = 0)
{
CheckRootHash(rootHash);

int count = StateServiceSettings.Default.MaxFindResultItems;
if (4 < _params.Count)
count = Result.Ok_Or(() => int.Parse(_params[4].AsString()), RpcError.InvalidParams.WithData($"Invalid count: {_params[4]}"));
if (StateServiceSettings.Default.MaxFindResultItems < count)
count = StateServiceSettings.Default.MaxFindResultItems;
key ??= [];
count = count <= 0 ? StateServiceSettings.Default.MaxFindResultItems : count;
count = Math.Min(count, StateServiceSettings.Default.MaxFindResultItems);
Comment on lines +315 to +316
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the first statement. count = Math.Min(...) is enough to be compatible with the old implementation.

Copy link
Contributor Author

@Wi1l-B0t Wi1l-B0t Aug 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the count not set, the value is 0 and it should set to StateServiceSettings.Default.MaxFindResultItems


using var store = StateStore.Singleton.GetStoreSnapshot();
var trie = new Trie(store, rootHash);
var contract = GetHistoricalContractState(trie, scriptHash).NotNull_Or(RpcError.UnknownContract);
var pkey = new StorageKey()
{
Id = contract.Id,
Key = prefix,
};
var fkey = new StorageKey()
{
Id = pkey.Id,
Key = key,
};
var pkey = new StorageKey() { Id = contract.Id, Key = prefix };
var fkey = new StorageKey() { Id = pkey.Id, Key = key };

var json = new JObject();
var jarr = new JArray();
Expand Down Expand Up @@ -364,16 +351,12 @@ public JToken FindStates(JArray _params)
}

[RpcMethod]
public JToken GetState(JArray _params)
public JToken GetState(UInt256 rootHash, UInt160 scriptHash, byte[] key)
{
var rootHash = Result.Ok_Or(() => UInt256.Parse(_params[0].AsString()), RpcError.InvalidParams.WithData($"Invalid root hash: {_params[0]}"));
(!StateServiceSettings.Default.FullState && StateStore.Singleton.CurrentLocalRootHash != rootHash).False_Or(RpcError.UnsupportedState);
CheckRootHash(rootHash);

var scriptHash = Result.Ok_Or(() => UInt160.Parse(_params[1].AsString()), RpcError.InvalidParams.WithData($"Invalid script hash: {_params[1]}"));
var key = Result.Ok_Or(() => Convert.FromBase64String(_params[2].AsString()), RpcError.InvalidParams.WithData($"Invalid key: {_params[2]}"));
using var store = StateStore.Singleton.GetStoreSnapshot();
var trie = new Trie(store, rootHash);

var contract = GetHistoricalContractState(trie, scriptHash).NotNull_Or(RpcError.UnknownContract);
var skey = new StorageKey()
{
Expand Down
4 changes: 4 additions & 0 deletions src/Plugins/StateService/StateService.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@
</None>
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="$(PackageId).Tests" />
</ItemGroup>

</Project>
1 change: 0 additions & 1 deletion tests/Neo.Plugins.SignClient.Tests/UT_SignClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
using Google.Protobuf;
using Grpc.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Neo.Cryptography;
using Neo.Cryptography.ECC;
Expand Down
1 change: 0 additions & 1 deletion tests/Neo.Plugins.SignClient.Tests/UT_Vsock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
// modifications are permitted.

using Microsoft.Extensions.Configuration;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Neo.Plugins.SignClient.Tests
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MSTest" Version="$(MSTestVersion)" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Plugins\StateService\StateService.csproj" />
<ProjectReference Include="..\..\tests\Neo.UnitTests\Neo.UnitTests.csproj" />
</ItemGroup>

</Project>
Loading
Loading