From 5a0a36a8c97e59723c7eaa10ebe5e8a8a77ce43c Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Thu, 30 Jan 2020 16:13:42 +0100 Subject: [PATCH] Merge Pr #5585: client and types additions for IBC --- CHANGELOG.md | 6 +++++ client/context/query.go | 51 +++++++++++++++++++++++++++-------------- client/flags/flags.go | 6 +++++ store/types/store.go | 4 ++++ types/coin.go | 4 ++-- types/rest/rest.go | 11 +++++++++ types/store.go | 1 + 7 files changed, 64 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0bbca18522d..ff09e4e9cb67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,12 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (types) [\#5581](https://github.com/cosmos/cosmos-sdk/pull/5581) Add convenience functions {,Must}Bech32ifyAddressBytes. * (staking) [\#5584](https://github.com/cosmos/cosmos-sdk/pull/5584) Add util function `ToTmValidator` that converts a `staking.Validator` type to `*tmtypes.Validator`. +* (client) [\#5585](https://github.com/cosmos/cosmos-sdk/pull/5585) IBC additions: + * Added `prove` flag for commitment proof verification. + * Added `queryABCI` function that returns the full `abci.ResponseQuery` with inclusion merkle proofs. +* (types) [\#5585](https://github.com/cosmos/cosmos-sdk/pull/5585) IBC additions: + * `Coin` denomination max lenght has been increased to 32. + * Added `CapabilityKey` alias for `StoreKey` to match IBC spec. ## [v0.38.0] - 2020-01-23 diff --git a/client/context/query.go b/client/context/query.go index dcf2c92b7f36..b5686f864165 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -49,6 +49,12 @@ func (ctx CLIContext) QueryStore(key tmbytes.HexBytes, storeName string) ([]byte return ctx.queryStore(key, storeName, "key") } +// QueryABCI performs a query to a Tendermint node with the provide RequestQuery. +// It returns the ResultQuery obtained from the query. +func (ctx CLIContext) QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) { + return ctx.queryABCI(req) +} + // QuerySubspace performs a query to a Tendermint node with the provided // store name and subspace. It returns key value pair and height of the query // upon success or an error if the query fails. @@ -72,40 +78,51 @@ func (ctx CLIContext) GetFromName() string { return ctx.FromName } -// query performs a query to a Tendermint node with the provided store name -// and path. It returns the result and height of the query upon success -// or an error if the query fails. In addition, it will verify the returned -// proof if TrustNode is disabled. If proof verification fails or the query -// height is invalid, an error will be returned. -func (ctx CLIContext) query(path string, key tmbytes.HexBytes) (res []byte, height int64, err error) { +func (ctx CLIContext) queryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) { node, err := ctx.GetNode() if err != nil { - return res, height, err + return abci.ResponseQuery{}, err } opts := rpcclient.ABCIQueryOptions{ Height: ctx.Height, - Prove: !ctx.TrustNode, + Prove: req.Prove || !ctx.TrustNode, } - result, err := node.ABCIQueryWithOptions(path, key, opts) + result, err := node.ABCIQueryWithOptions(req.Path, req.Data, opts) if err != nil { - return res, height, err + return abci.ResponseQuery{}, err } - resp := result.Response - if !resp.IsOK() { - return res, resp.Height, errors.New(resp.Log) + if !result.Response.IsOK() { + return abci.ResponseQuery{}, errors.New(result.Response.Log) } // data from trusted node or subspace query doesn't need verification - if ctx.TrustNode || !isQueryStoreWithProof(path) { - return resp.Value, resp.Height, nil + if ctx.TrustNode || !isQueryStoreWithProof(req.Path) { + return result.Response, nil } - err = ctx.verifyProof(path, resp) + err = ctx.verifyProof(req.Path, result.Response) + if err != nil { + return abci.ResponseQuery{}, err + } + + return result.Response, nil +} + +// query performs a query to a Tendermint node with the provided store name +// and path. It returns the result and height of the query upon success +// or an error if the query fails. In addition, it will verify the returned +// proof if TrustNode is disabled. If proof verification fails or the query +// height is invalid, an error will be returned. +func (ctx CLIContext) query(path string, key tmbytes.HexBytes) ([]byte, int64, error) { + resp, err := ctx.queryABCI(abci.RequestQuery{ + Path: path, + Data: key, + }) if err != nil { - return res, resp.Height, err + return nil, 0, err } return resp.Value, resp.Height, nil diff --git a/client/flags/flags.go b/client/flags/flags.go index 2cdaa5f2137f..64dc2f25a34f 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -24,7 +24,9 @@ const ( // DefaultKeyringBackend DefaultKeyringBackend = keys.BackendOS +) +const ( // BroadcastBlock defines a tx broadcasting mode where the client waits for // the tx to be committed in a block. BroadcastBlock = "block" @@ -34,7 +36,10 @@ const ( // BroadcastAsync defines a tx broadcasting mode where the client returns // immediately. BroadcastAsync = "async" +) +// List of CLI flags +const ( FlagHome = tmcli.HomeFlag FlagUseLedger = "ledger" FlagChainID = "chain-id" @@ -59,6 +64,7 @@ const ( FlagRPCWriteTimeout = "write-timeout" FlagOutputDocument = "output-document" // inspired by wget -O FlagSkipConfirmation = "yes" + FlagProve = "prove" FlagKeyringBackend = "keyring-backend" FlagPage = "page" FlagLimit = "limit" diff --git a/store/types/store.go b/store/types/store.go index 377b43909e11..d48585f8fce2 100644 --- a/store/types/store.go +++ b/store/types/store.go @@ -277,6 +277,10 @@ type StoreKey interface { String() string } +// CapabilityKey represent the Cosmos SDK keys for object-capability +// generation in the IBC protocol as defined in https://github.com/cosmos/ics/tree/master/spec/ics-005-port-allocation#data-structures +type CapabilityKey StoreKey + // KVStoreKey is used for accessing substores. // Only the pointer value should ever be used - it functions as a capabilities key. type KVStoreKey struct { diff --git a/types/coin.go b/types/coin.go index 12d82a6e01e9..6a759d569387 100644 --- a/types/coin.go +++ b/types/coin.go @@ -580,8 +580,8 @@ func (coins Coins) Sort() Coins { // Parsing var ( - // Denominations can be 3 ~ 16 characters long. - reDnmString = `[a-z][a-z0-9]{2,15}` + // Denominations can be 3 ~ 32 characters long. + reDnmString = `[a-z][a-z0-9/]{2,31}` reAmt = `[[:digit:]]+` reDecAmt = `[[:digit:]]*\.[[:digit:]]+` reSpc = `[[:space:]]*` diff --git a/types/rest/rest.go b/types/rest/rest.go index 89770c944650..a58a56252553 100644 --- a/types/rest/rest.go +++ b/types/rest/rest.go @@ -375,3 +375,14 @@ func ParseHTTPArgsWithLimit(r *http.Request, defaultLimit int) (tags []string, p func ParseHTTPArgs(r *http.Request) (tags []string, page, limit int, err error) { return ParseHTTPArgsWithLimit(r, DefaultLimit) } + +// ParseQueryParamBool parses the given param to a boolean. It returns false by +// default if the string is not parseable to bool. +func ParseQueryParamBool(r *http.Request, param string) bool { + valueStr := r.FormValue(param) + value := false + if ok, err := strconv.ParseBool(valueStr); err == nil { + value = ok + } + return value +} diff --git a/types/store.go b/types/store.go index ce890f2f6f75..6057526c80e9 100644 --- a/types/store.go +++ b/types/store.go @@ -81,6 +81,7 @@ const ( // nolint - reexport type ( StoreKey = types.StoreKey + CapabilityKey = types.CapabilityKey KVStoreKey = types.KVStoreKey TransientStoreKey = types.TransientStoreKey )