diff --git a/src/RpcServer/RpcServer.Blockchain.cs b/src/RpcServer/RpcServer.Blockchain.cs
index c09514107..9cc1abaaf 100644
--- a/src/RpcServer/RpcServer.Blockchain.cs
+++ b/src/RpcServer/RpcServer.Blockchain.cs
@@ -197,6 +197,56 @@ protected virtual JToken GetStorage(JArray _params)
return Convert.ToBase64String(item.Value.Span);
}
+ [RpcMethod]
+ protected virtual JToken FindStorage(JArray _params)
+ {
+ using var snapshot = system.GetSnapshot();
+ if (!int.TryParse(_params[0].AsString(), out int id))
+ {
+ UInt160 hash = UInt160.Parse(_params[0].AsString());
+ ContractState contract = NativeContract.ContractManagement.GetContract(snapshot, hash);
+ if (contract is null) throw new RpcException(-100, "Unknown contract");
+ id = contract.Id;
+ }
+
+ byte[] prefix = Convert.FromBase64String(_params[1].AsString());
+ byte[] prefix_key = StorageKey.CreateSearchPrefix(id, prefix);
+
+ if (!int.TryParse(_params[2].AsString(), out int start))
+ {
+ start = 0;
+ }
+
+ JObject json = new();
+ JArray jarr = new();
+ int pageSize = settings.FindStoragePageSize;
+ int i = 0;
+
+ using (var iter = snapshot.Find(prefix_key).Skip(count: start).GetEnumerator())
+ {
+ var hasMore = false;
+ while (iter.MoveNext())
+ {
+ if (i == pageSize)
+ {
+ hasMore = true;
+ break;
+ }
+
+ JObject j = new();
+ j["key"] = Convert.ToBase64String(iter.Current.Key.Key.Span);
+ j["value"] = Convert.ToBase64String(iter.Current.Value.Value.Span);
+ jarr.Add(j);
+ i++;
+ }
+ json["truncated"] = hasMore;
+ }
+
+ json["next"] = start + i;
+ json["results"] = jarr;
+ return json;
+ }
+
[RpcMethod]
protected virtual JToken GetTransactionHeight(JArray _params)
{
diff --git a/src/RpcServer/RpcServer.csproj b/src/RpcServer/RpcServer.csproj
index 600eec6c3..77a4c158e 100644
--- a/src/RpcServer/RpcServer.csproj
+++ b/src/RpcServer/RpcServer.csproj
@@ -4,5 +4,5 @@
Neo.Plugins.RpcServer
Neo.Plugins
-
+
diff --git a/src/RpcServer/Settings.cs b/src/RpcServer/Settings.cs
index 8bf8d0c95..6d5b1202a 100644
--- a/src/RpcServer/Settings.cs
+++ b/src/RpcServer/Settings.cs
@@ -45,6 +45,7 @@ public record RpcServerSettings
public string[] DisabledMethods { get; init; }
public bool SessionEnabled { get; init; }
public TimeSpan SessionExpirationTime { get; init; }
+ public int FindStoragePageSize { get; init; }
public static RpcServerSettings Default { get; } = new RpcServerSettings
{
@@ -60,7 +61,8 @@ public record RpcServerSettings
DisabledMethods = Array.Empty(),
MaxConcurrentConnections = 40,
SessionEnabled = false,
- SessionExpirationTime = TimeSpan.FromSeconds(60)
+ SessionExpirationTime = TimeSpan.FromSeconds(60),
+ FindStoragePageSize = 50
};
public static RpcServerSettings Load(IConfigurationSection section) => new()
@@ -80,7 +82,8 @@ public record RpcServerSettings
DisabledMethods = section.GetSection("DisabledMethods").GetChildren().Select(p => p.Get()).ToArray(),
MaxConcurrentConnections = section.GetValue("MaxConcurrentConnections", Default.MaxConcurrentConnections),
SessionEnabled = section.GetValue("SessionEnabled", Default.SessionEnabled),
- SessionExpirationTime = TimeSpan.FromSeconds(section.GetValue("SessionExpirationTime", (int)Default.SessionExpirationTime.TotalSeconds))
+ SessionExpirationTime = TimeSpan.FromSeconds(section.GetValue("SessionExpirationTime", (int)Default.SessionExpirationTime.TotalSeconds)),
+ FindStoragePageSize = section.GetValue("FindStoragePageSize", Default.FindStoragePageSize)
};
}
}
diff --git a/src/RpcServer/config.json b/src/RpcServer/config.json
index 89bc7f578..cfb60752f 100644
--- a/src/RpcServer/config.json
+++ b/src/RpcServer/config.json
@@ -17,7 +17,8 @@
"MaxStackSize": 65535,
"DisabledMethods": [ "openwallet" ],
"SessionEnabled": false,
- "SessionExpirationTime": 60
+ "SessionExpirationTime": 60,
+ "FindStoragePageSize": 50
}
]
}