From 83b4c6734f4f4f4bb489e53a64a2bf2a7b347c7e Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 17 Jan 2022 11:59:13 +0300 Subject: [PATCH 1/5] rpc: add support of `getstateroot` to RPC client --- pkg/rpc/client/doc.go | 1 + pkg/rpc/client/rpc.go | 18 +++++++++++++++++ pkg/rpc/client/rpc_test.go | 41 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/pkg/rpc/client/doc.go b/pkg/rpc/client/doc.go index 5ad1eac12..53b5eaaab 100644 --- a/pkg/rpc/client/doc.go +++ b/pkg/rpc/client/doc.go @@ -38,6 +38,7 @@ Supported methods getrawmempool getrawtransaction getstateheight + getstateroot getstorage gettransactionheight getunclaimedgas diff --git a/pkg/rpc/client/rpc.go b/pkg/rpc/client/rpc.go index 2f43dd8e4..ec66ea7f0 100644 --- a/pkg/rpc/client/rpc.go +++ b/pkg/rpc/client/rpc.go @@ -471,6 +471,24 @@ func (c *Client) FindStates(stateroot util.Uint256, historicalContractHash util. return resp, nil } +// GetStateRootByHeight returns state root for the specified height. +func (c *Client) GetStateRootByHeight(height uint32) (*state.MPTRoot, error) { + return c.getStateRoot(request.NewRawParams(height)) +} + +// GetStateRootByBlockHash returns state root for block with specified hash. +func (c *Client) GetStateRootByBlockHash(hash util.Uint256) (*state.MPTRoot, error) { + return c.getStateRoot(request.NewRawParams(hash)) +} + +func (c *Client) getStateRoot(params request.RawParams) (*state.MPTRoot, error) { + var resp = new(state.MPTRoot) + if err := c.performRequest("getstateroot", params, resp); err != nil { + return nil, err + } + return resp, nil +} + // GetStateHeight returns current validated and local node state height. func (c *Client) GetStateHeight() (*result.StateHeight, error) { var ( diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index c4041c353..51c008785 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -769,6 +769,47 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, }, }, + "getstateroot": { + { + name: "positive, by height", + invoke: func(c *Client) (interface{}, error) { + return c.GetStateRootByHeight(5) + }, + serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"version":0,"index":5,"roothash":"0x65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686","witnesses":[]}}`, + result: func(c *Client) interface{} { + h, err := util.Uint256DecodeStringLE("65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686") + if err != nil { + panic(err) + } + return &state.MPTRoot{ + Version: 0, + Index: 5, + Root: h, + Witness: []transaction.Witness{}, + } + }, + }, + { + name: "positive, by hash", + invoke: func(c *Client) (interface{}, error) { + hash, err := util.Uint256DecodeStringLE("86fe1061140b2ea791b0739fb9732abc6e5e47de4927228a1ac41de3d93eb7cb") + if err != nil { + panic(err) + } + return c.GetStateRootByBlockHash(hash) + }, + serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"version":0,"index":5,"roothash":"0x65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686","witnesses":[]}}`, + result: func(c *Client) interface{} { + h, _ := util.Uint256DecodeStringLE("65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686") + return &state.MPTRoot{ + Version: 0, + Index: 5, + Root: h, + Witness: []transaction.Witness{}, + } + }, + }, + }, "getstate": { { name: "positive", From 4c469e6f4960522b6e3a144380375cffeeac016e Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 17 Jan 2022 12:00:56 +0300 Subject: [PATCH 2/5] rpc: update docs of RPC client --- pkg/rpc/client/doc.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/rpc/client/doc.go b/pkg/rpc/client/doc.go index 53b5eaaab..45c23706c 100644 --- a/pkg/rpc/client/doc.go +++ b/pkg/rpc/client/doc.go @@ -18,6 +18,7 @@ TODO: Supported methods calculatenetworkfee + findstates getapplicationlog getbestblockhash getblock @@ -37,6 +38,7 @@ Supported methods getpeers getrawmempool getrawtransaction + getstate getstateheight getstateroot getstorage From edcb6e2eeea3c8239ecdab47276b83ccf056a32f Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 17 Jan 2022 12:23:31 +0300 Subject: [PATCH 3/5] rpc: fix parameters construction error for `findstates` client wrapper --- pkg/rpc/client/rpc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/rpc/client/rpc.go b/pkg/rpc/client/rpc.go index ec66ea7f0..a17e3a19a 100644 --- a/pkg/rpc/client/rpc.go +++ b/pkg/rpc/client/rpc.go @@ -459,7 +459,7 @@ func (c *Client) GetState(stateroot util.Uint256, historicalContractHash util.Ui func (c *Client) FindStates(stateroot util.Uint256, historicalContractHash util.Uint160, historicalPrefix []byte, start []byte, maxCount *int) (result.FindStates, error) { var ( - params = request.NewRawParams(stateroot.StringLE(), historicalContractHash.StringLE(), historicalPrefix, historicalPrefix, start) + params = request.NewRawParams(stateroot.StringLE(), historicalContractHash.StringLE(), historicalPrefix, start) resp result.FindStates ) if maxCount != nil { From e3c0a1635ff1563e83b38641603707b6a24b8279 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 17 Jan 2022 12:24:06 +0300 Subject: [PATCH 4/5] rpc: improve `findstates` errors reporting --- pkg/rpc/server/server.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index 6ea513586..cd5f25763 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -1235,11 +1235,11 @@ func (s *Server) findStates(ps request.Params) (interface{}, *response.Error) { } csHash, err := ps.Value(1).GetUint160FromHex() if err != nil { - return nil, response.WrapErrorWithData(response.ErrInvalidParams, errors.New("invalid contract hash")) + return nil, response.WrapErrorWithData(response.ErrInvalidParams, fmt.Errorf("invalid contract hash: %w", err)) } prefix, err := ps.Value(2).GetBytesBase64() if err != nil { - return nil, response.WrapErrorWithData(response.ErrInvalidParams, errors.New("invalid prefix")) + return nil, response.WrapErrorWithData(response.ErrInvalidParams, fmt.Errorf("invalid prefix: %w", err)) } var ( key []byte @@ -1248,7 +1248,7 @@ func (s *Server) findStates(ps request.Params) (interface{}, *response.Error) { if len(ps) > 3 { key, err = ps.Value(3).GetBytesBase64() if err != nil { - return nil, response.WrapErrorWithData(response.ErrInvalidParams, errors.New("invalid key")) + return nil, response.WrapErrorWithData(response.ErrInvalidParams, fmt.Errorf("invalid key: %w", err)) } if len(key) > 0 { if !bytes.HasPrefix(key, prefix) { @@ -1263,7 +1263,7 @@ func (s *Server) findStates(ps request.Params) (interface{}, *response.Error) { if len(ps) > 4 { count, err = ps.Value(4).GetInt() if err != nil { - return nil, response.WrapErrorWithData(response.ErrInvalidParams, errors.New("invalid count")) + return nil, response.WrapErrorWithData(response.ErrInvalidParams, fmt.Errorf("invalid count: %w", err)) } if count > s.config.MaxFindResultItems { count = s.config.MaxFindResultItems From b98fab6b3837781e56b43da2e7c676681ccf5873 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 18 Jan 2022 14:56:17 +0300 Subject: [PATCH 5/5] rpc: refactor `findstates` client wrapper 1. Use empty `prefix` instead of nil `preifx` in order to avoid RPC server exceptions. 2. Allow to omit `start` parameter` if `maxCount` is not specified. 3. Use empty `start` instead of nil `start` to avoid RPC server exceptions. --- pkg/rpc/client/rpc.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pkg/rpc/client/rpc.go b/pkg/rpc/client/rpc.go index a17e3a19a..086876070 100644 --- a/pkg/rpc/client/rpc.go +++ b/pkg/rpc/client/rpc.go @@ -458,10 +458,19 @@ func (c *Client) GetState(stateroot util.Uint256, historicalContractHash util.Ui // If `maxCount` specified, then maximum number of items to be returned equals to `maxCount`. func (c *Client) FindStates(stateroot util.Uint256, historicalContractHash util.Uint160, historicalPrefix []byte, start []byte, maxCount *int) (result.FindStates, error) { + if historicalPrefix == nil { + historicalPrefix = []byte{} + } var ( - params = request.NewRawParams(stateroot.StringLE(), historicalContractHash.StringLE(), historicalPrefix, start) + params = request.NewRawParams(stateroot.StringLE(), historicalContractHash.StringLE(), historicalPrefix) resp result.FindStates ) + if start == nil && maxCount != nil { + start = []byte{} + } + if start != nil { + params.Values = append(params.Values, start) + } if maxCount != nil { params.Values = append(params.Values, *maxCount) }