Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return account queries with height #4536

Merged
merged 4 commits into from
Jun 13, 2019
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) {
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
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)
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
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) {
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
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")
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
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
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
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
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
// 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) {
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
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
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
}

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
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
// 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
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
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