Merge pull request #2328 from nspcc-dev/rpc/getstateroot-client

rpc: add `getstateroot` to RPC client
This commit is contained in:
Roman Khimov 2022-01-18 18:13:27 +03:00 committed by GitHub
commit 0afe8826ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 5 deletions

View file

@ -18,6 +18,7 @@ TODO:
Supported methods Supported methods
calculatenetworkfee calculatenetworkfee
findstates
getapplicationlog getapplicationlog
getbestblockhash getbestblockhash
getblock getblock
@ -37,7 +38,9 @@ Supported methods
getpeers getpeers
getrawmempool getrawmempool
getrawtransaction getrawtransaction
getstate
getstateheight getstateheight
getstateroot
getstorage getstorage
gettransactionheight gettransactionheight
getunclaimedgas getunclaimedgas

View file

@ -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`. // 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, func (c *Client) FindStates(stateroot util.Uint256, historicalContractHash util.Uint160, historicalPrefix []byte,
start []byte, maxCount *int) (result.FindStates, error) { start []byte, maxCount *int) (result.FindStates, error) {
if historicalPrefix == nil {
historicalPrefix = []byte{}
}
var ( var (
params = request.NewRawParams(stateroot.StringLE(), historicalContractHash.StringLE(), historicalPrefix, historicalPrefix, start) params = request.NewRawParams(stateroot.StringLE(), historicalContractHash.StringLE(), historicalPrefix)
resp result.FindStates resp result.FindStates
) )
if start == nil && maxCount != nil {
start = []byte{}
}
if start != nil {
params.Values = append(params.Values, start)
}
if maxCount != nil { if maxCount != nil {
params.Values = append(params.Values, *maxCount) params.Values = append(params.Values, *maxCount)
} }
@ -471,6 +480,24 @@ func (c *Client) FindStates(stateroot util.Uint256, historicalContractHash util.
return resp, nil 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. // GetStateHeight returns current validated and local node state height.
func (c *Client) GetStateHeight() (*result.StateHeight, error) { func (c *Client) GetStateHeight() (*result.StateHeight, error) {
var ( var (

View file

@ -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": { "getstate": {
{ {
name: "positive", name: "positive",

View file

@ -1235,11 +1235,11 @@ func (s *Server) findStates(ps request.Params) (interface{}, *response.Error) {
} }
csHash, err := ps.Value(1).GetUint160FromHex() csHash, err := ps.Value(1).GetUint160FromHex()
if err != nil { 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() prefix, err := ps.Value(2).GetBytesBase64()
if err != nil { 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 ( var (
key []byte key []byte
@ -1248,7 +1248,7 @@ func (s *Server) findStates(ps request.Params) (interface{}, *response.Error) {
if len(ps) > 3 { if len(ps) > 3 {
key, err = ps.Value(3).GetBytesBase64() key, err = ps.Value(3).GetBytesBase64()
if err != nil { 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 len(key) > 0 {
if !bytes.HasPrefix(key, prefix) { if !bytes.HasPrefix(key, prefix) {
@ -1263,7 +1263,7 @@ func (s *Server) findStates(ps request.Params) (interface{}, *response.Error) {
if len(ps) > 4 { if len(ps) > 4 {
count, err = ps.Value(4).GetInt() count, err = ps.Value(4).GetInt()
if err != nil { 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 { if count > s.config.MaxFindResultItems {
count = s.config.MaxFindResultItems count = s.config.MaxFindResultItems