Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
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
41 changes: 26 additions & 15 deletions client/context/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,33 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) {

// Query performs a query for information about the connected node.
func (ctx CLIContext) Query(path string, data cmn.HexBytes) (res []byte, err error) {
return ctx.query(path, data)
resp, err := ctx.query(path, data)
return resp.Value, err
}

// Query information about the connected node with a data payload
func (ctx CLIContext) QueryWithData(path string, data []byte) (res []byte, err error) {
return ctx.query(path, data)
resp, err := ctx.query(path, data)
return resp.Value, err
}

// QueryStore performs a query from a Tendermint node with the provided key and
// store name.
func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (res []byte, err error) {
res, _, err = ctx.queryStore(key, storeName, "key")
return res, err
}

// QueryStoreWithHeight performs a query from a Tendermint node with the provided key and
// store name. Returns the queried data along with the height the query was performed at.
func (ctx CLIContext) QueryStoreWithHeight(key cmn.HexBytes, storeName string) (res []byte, height int64, err error) {
return ctx.queryStore(key, storeName, "key")
}

// QuerySubspace performs a query from a Tendermint node with the provided
// store name and subspace.
func (ctx CLIContext) QuerySubspace(subspace []byte, storeName string) (res []sdk.KVPair, err error) {
resRaw, err := ctx.queryStore(subspace, storeName, "subspace")
resRaw, _, err := ctx.queryStore(subspace, storeName, "subspace")
if err != nil {
return res, err
}
Expand Down Expand Up @@ -126,6 +135,7 @@ func (ctx CLIContext) EnsureAccountExistsFromAddr(addr sdk.AccAddress) error {

// queryAccount queries an account using custom query endpoint of auth module
// returns an error if result is `null` otherwise account data
// returns the height the account was queried at
func (ctx CLIContext) queryAccount(addr sdk.AccAddress) ([]byte, error) {
bz, err := ctx.Codec.MarshalJSON(authtypes.NewQueryAccountParams(addr))
if err != nil {
Expand All @@ -134,20 +144,20 @@ func (ctx CLIContext) queryAccount(addr sdk.AccAddress) ([]byte, error) {

route := fmt.Sprintf("custom/%s/%s", ctx.AccountStore, authtypes.QueryAccount)

res, err := ctx.QueryWithData(route, bz)
resp, err := ctx.query(route, bz)
if err != nil {
return nil, err
}

return res, nil
return resp.Value, nil
}

// query performs a query from a Tendermint node with the provided store name
// and path.
func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, err error) {
func (ctx CLIContext) query(path string, key cmn.HexBytes) (resp abci.ResponseQuery, err error) {
node, err := ctx.GetNode()
if err != nil {
return res, err
return resp, err
}

opts := rpcclient.ABCIQueryOptions{
Expand All @@ -157,25 +167,25 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, err erro

result, err := node.ABCIQueryWithOptions(path, key, opts)
if err != nil {
return res, err
return resp, err
}

resp := result.Response
resp = result.Response
if !resp.IsOK() {
return res, errors.New(resp.Log)
return resp, errors.New(resp.Log)
}

// data from trusted node or subspace query doesn't need verification
if ctx.TrustNode || !isQueryStoreWithProof(path) {
return resp.Value, nil
return resp, nil
}

err = ctx.verifyProof(path, resp)
if err != nil {
return nil, err
return abci.ResponseQuery{}, err
}

return resp.Value, nil
return resp, nil
}

// Verify verifies the consensus proof at given height.
Expand Down Expand Up @@ -233,9 +243,10 @@ func (ctx CLIContext) verifyProof(queryPath string, resp abci.ResponseQuery) err

// queryStore performs a query from a Tendermint node with the provided a store
// name and path.
func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, error) {
func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, int64, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

++

path := fmt.Sprintf("/store/%s/%s", storeName, endPath)
return ctx.query(path, key)
resp, err := ctx.query(path, key)
return resp.Value, resp.Height, err
}

// isQueryStoreWithProof expects a format like /<queryType>/<storeName>/<subpath>
Expand Down
12 changes: 10 additions & 2 deletions x/auth/client/rest/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth/types"
)

// AccountWithQueryHeight wraps the embedded Account
// with the height it was queried at
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// with the height it was queried at
// with the height it was queried at.

type AccountWithQueryHeight struct {
types.Account
Height int64 `json:"height"`
}

// register REST routes
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, storeName string) {
r.HandleFunc(
Expand Down Expand Up @@ -45,7 +52,7 @@ func QueryAccountRequestHandlerFn(
return
}

res, err := cliCtx.QueryStore(types.AddressStoreKey(addr), storeName)
res, height, err := cliCtx.QueryStoreWithHeight(types.AddressStoreKey(addr), storeName)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
Expand All @@ -64,7 +71,8 @@ func QueryAccountRequestHandlerFn(
return
}

rest.PostProcessResponse(w, cliCtx, account)
accountWithHeight := AccountWithQueryHeight{account, height}
rest.PostProcessResponse(w, cliCtx, accountWithHeight)
}
}

Expand Down