forked from TrueCloudLab/neoneo-go
rpcsrv, rpcclient: support getstoragehistoric
call
Make it similar to `findstoragehistoric`. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
parent
97d523ceed
commit
1fb0c96e2c
5 changed files with 180 additions and 0 deletions
|
@ -559,6 +559,26 @@ func (c *Client) getStorage(params []any) ([]byte, error) {
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
// GetStorageByIDHistoric returns the historical stored value according to the
|
||||
// contract ID and, stored key and specified stateroot.
|
||||
func (c *Client) GetStorageByIDHistoric(root util.Uint256, id int32, key []byte) ([]byte, error) {
|
||||
return c.getStorageHistoric([]any{root.StringLE(), id, key})
|
||||
}
|
||||
|
||||
// GetStorageByHashHistoric returns the historical stored value according to the
|
||||
// contract script hash, the stored key and specified stateroot.
|
||||
func (c *Client) GetStorageByHashHistoric(root util.Uint256, hash util.Uint160, key []byte) ([]byte, error) {
|
||||
return c.getStorageHistoric([]any{root.StringLE(), hash.StringLE(), key})
|
||||
}
|
||||
|
||||
func (c *Client) getStorageHistoric(params []any) ([]byte, error) {
|
||||
var resp []byte
|
||||
if err := c.performRequest("getstoragehistoric", params, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// FindStorageByHash returns contract storage items by the given contract hash and prefix.
|
||||
// If `start` index is specified, items starting from `start` index are being returned
|
||||
// (including item located at the start index).
|
||||
|
|
|
@ -1040,6 +1040,50 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
},
|
||||
},
|
||||
},
|
||||
"getstoragehistoric": {
|
||||
{
|
||||
name: "by hash, positive",
|
||||
invoke: func(c *Client) (any, error) {
|
||||
root, _ := util.Uint256DecodeStringLE("252e9d73d49c95c7618d40650da504e05183a1b2eed0685e42c360413c329170")
|
||||
hash, err := util.Uint160DecodeStringLE("03febccf81ac85e3d795bc5cbd4e84e907812aa3")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
key, err := hex.DecodeString("5065746572")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c.GetStorageByHashHistoric(root, hash, key)
|
||||
},
|
||||
serverResponse: `{"jsonrpc":"2.0","id":1,"result":"TGlu"}`,
|
||||
result: func(c *Client) any {
|
||||
value, err := hex.DecodeString("4c696e")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return value
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "by ID, positive",
|
||||
invoke: func(c *Client) (any, error) {
|
||||
root, _ := util.Uint256DecodeStringLE("252e9d73d49c95c7618d40650da504e05183a1b2eed0685e42c360413c329170")
|
||||
key, err := hex.DecodeString("5065746572")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c.GetStorageByIDHistoric(root, -1, key)
|
||||
},
|
||||
serverResponse: `{"jsonrpc":"2.0","id":1,"result":"TGlu"}`,
|
||||
result: func(c *Client) any {
|
||||
value, err := hex.DecodeString("4c696e")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return value
|
||||
},
|
||||
},
|
||||
},
|
||||
"gettransactionheight": {
|
||||
{
|
||||
name: "positive",
|
||||
|
|
|
@ -2690,3 +2690,36 @@ func TestClient_FindStorageHistoric(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, result.FindStorage{}, actual)
|
||||
}
|
||||
|
||||
func TestClient_GetStorageHistoric(t *testing.T) {
|
||||
chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t)
|
||||
defer chain.Close()
|
||||
defer rpcSrv.Shutdown()
|
||||
|
||||
c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, c.Init())
|
||||
|
||||
root, err := util.Uint256DecodeStringLE(block20StateRootLE)
|
||||
require.NoError(t, err)
|
||||
h, err := util.Uint160DecodeStringLE(testContractHash)
|
||||
require.NoError(t, err)
|
||||
key := []byte("aa10")
|
||||
expected := []byte("v2")
|
||||
|
||||
// By hash.
|
||||
actual, err := c.GetStorageByHashHistoric(root, h, key)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, actual)
|
||||
|
||||
// By ID.
|
||||
actual, err = c.GetStorageByIDHistoric(root, 1, key) // Rubles contract
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, actual)
|
||||
|
||||
// Missing item.
|
||||
earlyRoot, err := chain.GetStateRoot(15) // there's no `aa10` value in Rubles contract by the moment of block #15
|
||||
require.NoError(t, err)
|
||||
_, err = c.GetStorageByHashHistoric(earlyRoot.Root, h, key)
|
||||
require.ErrorIs(t, neorpc.ErrUnknownStorageItem, err)
|
||||
}
|
||||
|
|
|
@ -229,6 +229,7 @@ var rpcHandlers = map[string]func(*Server, params.Params) (any, *neorpc.Error){
|
|||
"getstateheight": (*Server).getStateHeight,
|
||||
"getstateroot": (*Server).getStateRoot,
|
||||
"getstorage": (*Server).getStorage,
|
||||
"getstoragehistoric": (*Server).getStorageHistoric,
|
||||
"gettransactionheight": (*Server).getTransactionHeight,
|
||||
"getunclaimedgas": (*Server).getUnclaimedGas,
|
||||
"getnextblockvalidators": (*Server).getNextBlockValidators,
|
||||
|
@ -1855,6 +1856,36 @@ func (s *Server) getStorage(ps params.Params) (any, *neorpc.Error) {
|
|||
return []byte(item), nil
|
||||
}
|
||||
|
||||
func (s *Server) getStorageHistoric(ps params.Params) (any, *neorpc.Error) {
|
||||
root, respErr := s.getStateRootFromParam(ps.Value(0))
|
||||
if respErr != nil {
|
||||
return nil, respErr
|
||||
}
|
||||
if len(ps) < 2 {
|
||||
return nil, neorpc.ErrInvalidParams
|
||||
}
|
||||
|
||||
id, rErr := s.contractIDFromParam(ps.Value(1), root)
|
||||
if rErr != nil {
|
||||
return nil, rErr
|
||||
}
|
||||
key, err := ps.Value(2).GetBytesBase64()
|
||||
if err != nil {
|
||||
return nil, neorpc.ErrInvalidParams
|
||||
}
|
||||
pKey := makeStorageKey(id, key)
|
||||
|
||||
v, err := s.chain.GetStateModule().GetState(root, pKey)
|
||||
if err != nil && !errors.Is(err, mpt.ErrNotFound) {
|
||||
return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get state item: %s", err))
|
||||
}
|
||||
if v == nil {
|
||||
return "", neorpc.ErrUnknownStorageItem
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (s *Server) getrawtransaction(reqParams params.Params) (any, *neorpc.Error) {
|
||||
txHash, err := reqParams.Value(0).GetUint256()
|
||||
if err != nil {
|
||||
|
|
|
@ -659,6 +659,58 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
errCode: neorpc.InvalidParamsCode,
|
||||
},
|
||||
},
|
||||
"getstoragehistoric": {
|
||||
{
|
||||
name: "positive",
|
||||
params: fmt.Sprintf(`["%s", "%s", "%s"]`, block20StateRootLE, testContractHash, base64.StdEncoding.EncodeToString([]byte("aa10"))),
|
||||
result: func(e *executor) any {
|
||||
v := base64.StdEncoding.EncodeToString([]byte("v2"))
|
||||
return &v
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "missing key",
|
||||
params: fmt.Sprintf(`["%s", "%s", "dGU="]`, block20StateRootLE, testContractHash),
|
||||
fail: true,
|
||||
errCode: neorpc.ErrUnknownStorageItemCode,
|
||||
},
|
||||
{
|
||||
name: "no params",
|
||||
params: `[]`,
|
||||
fail: true,
|
||||
errCode: neorpc.InvalidParamsCode,
|
||||
},
|
||||
{
|
||||
name: "no second parameter",
|
||||
params: fmt.Sprintf(`["%s"]`, block20StateRootLE),
|
||||
fail: true,
|
||||
errCode: neorpc.InvalidParamsCode,
|
||||
},
|
||||
{
|
||||
name: "no third parameter",
|
||||
params: fmt.Sprintf(`["%s", "%s"]`, block20StateRootLE, testContractHash),
|
||||
fail: true,
|
||||
errCode: neorpc.InvalidParamsCode,
|
||||
},
|
||||
{
|
||||
name: "invalid stateroot",
|
||||
params: `["notahex"]`,
|
||||
fail: true,
|
||||
errCode: neorpc.InvalidParamsCode,
|
||||
},
|
||||
{
|
||||
name: "invalid hash",
|
||||
params: fmt.Sprintf(`["%s", "notahex"]`, block20StateRootLE),
|
||||
fail: true,
|
||||
errCode: neorpc.InvalidParamsCode,
|
||||
},
|
||||
{
|
||||
name: "invalid key",
|
||||
params: fmt.Sprintf(`["%s", "%s", "notabase64$"]`, block20StateRootLE, testContractHash),
|
||||
fail: true,
|
||||
errCode: neorpc.InvalidParamsCode,
|
||||
},
|
||||
},
|
||||
"findstorage": {
|
||||
{
|
||||
name: "not truncated",
|
||||
|
|
Loading…
Reference in a new issue