diff --git a/client/context/context.go b/client/context/context.go index 07168ecdf6ca..e683ff2c3701 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -99,7 +99,7 @@ func NewCLIContextWithFrom(from string) CLIContext { return ctx.WithVerifier(verifier) } -// NewCLIContextIBC takes additional arguements +// NewCLIContextIBC takes additional arguments func NewCLIContextIBC(from string, chainID string, nodeURI string) CLIContext { var rpc rpcclient.Client diff --git a/client/context/query.go b/client/context/query.go index 2a01a7577a0c..be664f1c8420 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -129,11 +129,10 @@ func (ctx CLIContext) GetFromName() string { return ctx.FromName } -func (ctx CLIContext) queryABCI(req abci.RequestQuery) (resp abci.ResponseQuery, err error) { - +func (ctx CLIContext) queryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) { node, err := ctx.GetNode() if err != nil { - return resp, err + return abci.ResponseQuery{}, err } // When a client did not provide a query height, manually query for it so it can @@ -141,7 +140,7 @@ func (ctx CLIContext) queryABCI(req abci.RequestQuery) (resp abci.ResponseQuery, if ctx.Height == 0 { status, err := node.Status() if err != nil { - return resp, err + return abci.ResponseQuery{}, err } ctx = ctx.WithHeight(status.SyncInfo.LatestBlockHeight) } @@ -153,26 +152,25 @@ func (ctx CLIContext) queryABCI(req abci.RequestQuery) (resp abci.ResponseQuery, result, err := node.ABCIQueryWithOptions(req.Path, req.Data, opts) if err != nil { - return + return abci.ResponseQuery{}, err } - resp = result.Response - if !resp.IsOK() { - err = errors.New(resp.Log) - return + if !result.Response.IsOK() { + err = errors.New(result.Response.Log) + return abci.ResponseQuery{}, err } // data from trusted node or subspace query doesn't need verification if ctx.TrustNode || !isQueryStoreWithProof(req.Path) { - return resp, nil + return result.Response, nil } - err = ctx.verifyProof(req.Path, resp) + err = ctx.verifyProof(req.Path, result.Response) if err != nil { - return + return abci.ResponseQuery{}, err } - return + return result.Response, nil } // query performs a query to a Tendermint node with the provided store name diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index 6f6a487bbbf6..cc5cb3364c89 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -7,15 +7,17 @@ import ( "strings" "github.com/spf13/cobra" + "github.com/spf13/viper" + abci "github.com/tendermint/tendermint/abci/types" tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/client/utils" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" @@ -44,7 +46,7 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { // GetCmdQueryClientState defines the command to query the state of a client with // a given id as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#query func GetCmdQueryClientState(queryRoute string, cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: "state [client-id]", Short: "Query a client state", Long: strings.TrimSpace( @@ -67,24 +69,33 @@ $ %s query ibc client state [client-id] return err } - res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryClientState), bz) + req := abci.RequestQuery{ + Path: fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryClientState), + Data: bz, + Prove: viper.GetBool(flags.FlagProve), + } + + res, err := cliCtx.QueryABCI(req) if err != nil { return err } var clientState types.State - if err := cdc.UnmarshalJSON(res, &clientState); err != nil { + if err := cdc.UnmarshalJSON(res.Value, &clientState); err != nil { return err } - return cliCtx.PrintOutput(clientState) + clientStateRes := types.NewClientStateResponse(clientID, clientState, res.Proof, res.Height) + return cliCtx.PrintOutput(clientStateRes) }, } + cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") + return cmd } -// GetCmdQueryRoot defines the command to query +// GetCmdQueryRoot defines the command to query a verified commitment root func GetCmdQueryRoot(queryRoute string, cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: "root [client-id] [height]", Short: "Query a verified commitment root", Long: strings.TrimSpace( @@ -112,25 +123,34 @@ $ %s query ibc client root [client-id] [height] return err } - res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryVerifiedRoot), bz) + req := abci.RequestQuery{ + Path: fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryVerifiedRoot), + Data: bz, + Prove: viper.GetBool(flags.FlagProve), + } + + res, err := cliCtx.QueryABCI(req) if err != nil { return err } - var root commitment.RootI - if err := cdc.UnmarshalJSON(res, &root); err != nil { + var root commitment.Root + if err := cdc.UnmarshalJSON(res.Value, &root); err != nil { return err } - return cliCtx.PrintOutput(root) + rootRes := types.NewRootResponse(clientID, height, root, res.Proof, res.Height) + return cliCtx.PrintOutput(rootRes) }, } + cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") + return cmd } // GetCmdQueryConsensusState defines the command to query the consensus state of // the chain as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#query func GetCmdQueryConsensusState(queryRoute string, cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: "consensus-state [client-id]", Short: "Query the latest consensus state of the client", Long: strings.TrimSpace( @@ -148,24 +168,16 @@ $ %s query ibc client consensus-state [client-id] return errors.New("client ID can't be blank") } - bz, err := cdc.MarshalJSON(types.NewQueryClientStateParams(clientID)) + csRes, err := utils.QueryConsensusStateProof(cliCtx, cdc, queryRoute, clientID) if err != nil { return err } - res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryConsensusState), bz) - if err != nil { - return err - } - - var consensusState exported.ConsensusState - if err := cdc.UnmarshalJSON(res, &consensusState); err != nil { - return err - } - - return cliCtx.PrintOutput(consensusState) + return cliCtx.PrintOutput(csRes) }, } + cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") + return cmd } // GetCmdQueryHeader defines the command to query the latest header on the chain diff --git a/x/ibc/02-client/client/utils/utils.go b/x/ibc/02-client/client/utils/utils.go index 5d0786267373..955e06f50e7c 100644 --- a/x/ibc/02-client/client/utils/utils.go +++ b/x/ibc/02-client/client/utils/utils.go @@ -3,23 +3,36 @@ package utils import ( "fmt" + "github.com/spf13/viper" + abci "github.com/tendermint/tendermint/abci/types" tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint" ) // QueryConsensusStateProof queries the store to get the consensus state and a // merkle proof. -func QueryConsensusStateProof(cliCtx client.CLIContext, clientID string) (types.ConsensusStateResponse, error) { +func QueryConsensusStateProof( + cliCtx client.CLIContext, cdc *codec.Codec, + queryRoute, clientID string, +) (types.ConsensusStateResponse, error) { var conStateRes types.ConsensusStateResponse + + bz, err := cdc.MarshalJSON(types.NewQueryClientStateParams(clientID)) + if err != nil { + return conStateRes, err + } + req := abci.RequestQuery{ - Path: "store/ibc/key", - Data: []byte(fmt.Sprintf("clients/%s/consensusState", clientID)), - Prove: true, + Path: fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryClientState), + Data: bz, + Prove: viper.GetBool(flags.FlagProve), } res, err := cliCtx.QueryABCI(req) @@ -28,9 +41,10 @@ func QueryConsensusStateProof(cliCtx client.CLIContext, clientID string) (types. } var cs tendermint.ConsensusState - if err := cliCtx.Codec.UnmarshalBinaryLengthPrefixed(res.Value, &cs); err != nil { + if err := cliCtx.Codec.UnmarshalJSON(res.Value, &cs); err != nil { return conStateRes, err } + return types.NewConsensusStateResponse(clientID, cs, res.Proof, res.Height), nil } diff --git a/x/ibc/02-client/doc.go b/x/ibc/02-client/doc.go index 2b6952ba97eb..cfe3c76c6af7 100644 --- a/x/ibc/02-client/doc.go +++ b/x/ibc/02-client/doc.go @@ -1,5 +1,5 @@ /* -Package client implements the ICS 02 - Client Semenatics specification +Package client implements the ICS 02 - Client Semantics specification https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics. This concrete implementations defines types and method to store and update light clients which tracks on other chain's state. diff --git a/x/ibc/02-client/exported/exported.go b/x/ibc/02-client/exported/exported.go index e7d1ac5c5411..e611b94301fa 100644 --- a/x/ibc/02-client/exported/exported.go +++ b/x/ibc/02-client/exported/exported.go @@ -6,17 +6,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" cmn "github.com/tendermint/tendermint/libs/common" -) -// Blockchain is consensus algorithm which generates valid Headers. It generates -// a unique list of headers starting from a genesis ConsensusState with arbitrary messages. -// This interface is implemented as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#blockchain. -type Blockchain interface { - Genesis() ConsensusState // Consensus state defined in the genesis - Consensus() Header // Header generating function -} + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) // ConsensusState is the state of the consensus process type ConsensusState interface { diff --git a/x/ibc/02-client/keeper/client.go b/x/ibc/02-client/keeper/client.go index b75f8174939a..3ee7a53143bf 100644 --- a/x/ibc/02-client/keeper/client.go +++ b/x/ibc/02-client/keeper/client.go @@ -60,15 +60,6 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H return sdkerrors.Wrap(errors.ErrConsensusStateNotFound(k.codespace), "cannot update client") } - if header.GetHeight() < consensusState.GetHeight() { - return sdkerrors.Wrap( - sdk.ErrInvalidSequence( - fmt.Sprintf("header height < consensus height (%d < %d)", header.GetHeight(), consensusState.GetHeight()), - ), - "cannot update client", - ) - } - consensusState, err := consensusState.CheckValidityAndUpdateState(header) if err != nil { return sdkerrors.Wrap(err, "cannot update client") diff --git a/x/ibc/02-client/keeper/keeper.go b/x/ibc/02-client/keeper/keeper.go index ce0d54e99782..3911c1f98f0e 100644 --- a/x/ibc/02-client/keeper/keeper.go +++ b/x/ibc/02-client/keeper/keeper.go @@ -23,7 +23,6 @@ type Keeper struct { storeKey sdk.StoreKey cdc *codec.Codec codespace sdk.CodespaceType - prefix []byte // prefix bytes for accessing the store } // NewKeeper creates a new NewKeeper instance @@ -32,8 +31,6 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType) storeKey: key, cdc: cdc, codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, errors.DefaultCodespace)), // "ibc/client", - prefix: []byte{}, - // prefix: []byte(types.SubModuleName + "/"), // "client/" } } @@ -44,7 +41,7 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { // GetClientState gets a particular client from the store func (k Keeper) GetClientState(ctx sdk.Context, clientID string) (types.State, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixClient) bz := store.Get(types.KeyClientState(clientID)) if bz == nil { return types.State{}, false @@ -57,14 +54,14 @@ func (k Keeper) GetClientState(ctx sdk.Context, clientID string) (types.State, b // SetClientState sets a particular Client to the store func (k Keeper) SetClientState(ctx sdk.Context, clientState types.State) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixClient) bz := k.cdc.MustMarshalBinaryLengthPrefixed(clientState) - store.Set(types.KeyClientState(clientState.ID()), bz) + store.Set(types.KeyClientState(clientState.ID), bz) } // GetClientType gets the consensus type for a specific client func (k Keeper) GetClientType(ctx sdk.Context, clientID string) (exported.ClientType, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixClient) bz := store.Get(types.KeyClientType(clientID)) if bz == nil { return 0, false @@ -75,13 +72,13 @@ func (k Keeper) GetClientType(ctx sdk.Context, clientID string) (exported.Client // SetClientType sets the specific client consensus type to the provable store func (k Keeper) SetClientType(ctx sdk.Context, clientID string, clientType exported.ClientType) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixClient) store.Set(types.KeyClientType(clientID), []byte{byte(clientType)}) } // GetConsensusState creates a new client state and populates it with a given consensus state func (k Keeper) GetConsensusState(ctx sdk.Context, clientID string) (exported.ConsensusState, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixClient) bz := store.Get(types.KeyConsensusState(clientID)) if bz == nil { return nil, false @@ -94,7 +91,7 @@ func (k Keeper) GetConsensusState(ctx sdk.Context, clientID string) (exported.Co // SetConsensusState sets a ConsensusState to a particular client func (k Keeper) SetConsensusState(ctx sdk.Context, clientID string, consensusState exported.ConsensusState) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixClient) bz := k.cdc.MustMarshalBinaryLengthPrefixed(consensusState) store.Set(types.KeyConsensusState(clientID), bz) } @@ -102,7 +99,7 @@ func (k Keeper) SetConsensusState(ctx sdk.Context, clientID string, consensusSta // GetVerifiedRoot gets a verified commitment Root from a particular height to // a client func (k Keeper) GetVerifiedRoot(ctx sdk.Context, clientID string, height uint64) (commitment.RootI, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixClient) bz := store.Get(types.KeyRoot(clientID, height)) if bz == nil { @@ -117,7 +114,7 @@ func (k Keeper) GetVerifiedRoot(ctx sdk.Context, clientID string, height uint64) // SetVerifiedRoot sets a verified commitment Root from a particular height to // a client func (k Keeper) SetVerifiedRoot(ctx sdk.Context, clientID string, height uint64, root commitment.RootI) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixClient) bz := k.cdc.MustMarshalBinaryLengthPrefixed(root) store.Set(types.KeyRoot(clientID, height), bz) } @@ -151,7 +148,7 @@ func (k Keeper) checkMisbehaviour(ctx sdk.Context, evidence exported.Evidence) e // freeze updates the state of the client in the event of a misbehaviour func (k Keeper) freeze(ctx sdk.Context, clientState types.State) (types.State, error) { if clientState.Frozen { - return types.State{}, sdkerrors.Wrap(errors.ErrClientFrozen(k.codespace, clientState.ID()), "already frozen") + return types.State{}, sdkerrors.Wrap(errors.ErrClientFrozen(k.codespace, clientState.ID), "already frozen") } clientState.Frozen = true diff --git a/x/ibc/02-client/keeper/querier.go b/x/ibc/02-client/keeper/querier.go index 5f56b8d6b01a..8956a72fab2e 100644 --- a/x/ibc/02-client/keeper/querier.go +++ b/x/ibc/02-client/keeper/querier.go @@ -21,7 +21,7 @@ func QuerierClientState(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byt clientState, found := k.GetClientState(ctx, params.ClientID) if !found { - return nil, errors.ErrClientTypeNotFound(k.codespace) + return nil, sdk.ConvertError(errors.ErrClientTypeNotFound(k.codespace)) } bz, err := types.SubModuleCdc.MarshalJSON(clientState) @@ -43,7 +43,7 @@ func QuerierConsensusState(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([] consensusState, found := k.GetConsensusState(ctx, params.ClientID) if !found { - return nil, errors.ErrConsensusStateNotFound(k.codespace) + return nil, sdk.ConvertError(errors.ErrConsensusStateNotFound(k.codespace)) } bz, err := types.SubModuleCdc.MarshalJSON(consensusState) @@ -65,7 +65,7 @@ func QuerierVerifiedRoot(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]by root, found := k.GetVerifiedRoot(ctx, params.ClientID, params.Height) if !found { - return nil, errors.ErrRootNotFound(k.codespace) + return nil, sdk.ConvertError(errors.ErrRootNotFound(k.codespace)) } bz, err := types.SubModuleCdc.MarshalJSON(root) diff --git a/x/ibc/02-client/types/codec.go b/x/ibc/02-client/types/codec.go index 7a141e811a0a..551403e6ad89 100644 --- a/x/ibc/02-client/types/codec.go +++ b/x/ibc/02-client/types/codec.go @@ -11,7 +11,6 @@ var SubModuleCdc = codec.New() // RegisterCodec registers the IBC client interfaces and types func RegisterCodec(cdc *codec.Codec) { - cdc.RegisterInterface((*exported.Blockchain)(nil), nil) cdc.RegisterInterface((*exported.ConsensusState)(nil), nil) cdc.RegisterInterface((*exported.Evidence)(nil), nil) cdc.RegisterInterface((*exported.Header)(nil), nil) diff --git a/x/ibc/02-client/types/errors/errors.go b/x/ibc/02-client/types/errors/errors.go index c133bcfef808..1e9510df6c44 100644 --- a/x/ibc/02-client/types/errors/errors.go +++ b/x/ibc/02-client/types/errors/errors.go @@ -4,70 +4,111 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // client error codes const ( DefaultCodespace sdk.CodespaceType = "client" - CodeClientExists sdk.CodeType = 101 - CodeClientNotFound sdk.CodeType = 102 - CodeClientFrozen sdk.CodeType = 103 - CodeConsensusStateNotFound sdk.CodeType = 104 - CodeInvalidConsensusState sdk.CodeType = 105 - CodeClientTypeNotFound sdk.CodeType = 106 - CodeInvalidClientType sdk.CodeType = 107 - CodeRootNotFound sdk.CodeType = 108 - CodeInvalidHeader sdk.CodeType = 109 - CodeInvalidEvidence sdk.CodeType = 110 + CodeClientExists sdk.CodeType = 200 + CodeClientNotFound sdk.CodeType = 201 + CodeClientFrozen sdk.CodeType = 202 + CodeConsensusStateNotFound sdk.CodeType = 203 + CodeInvalidConsensusState sdk.CodeType = 204 + CodeClientTypeNotFound sdk.CodeType = 205 + CodeInvalidClientType sdk.CodeType = 206 + CodeRootNotFound sdk.CodeType = 207 + CodeInvalidHeader sdk.CodeType = 207 + CodeInvalidEvidence sdk.CodeType = 209 ) // ErrClientExists implements sdk.Error -func ErrClientExists(codespace sdk.CodespaceType, clientID string) sdk.Error { - return sdk.NewError(codespace, CodeClientExists, fmt.Sprintf("client with ID %s already exists", clientID)) +func ErrClientExists(codespace sdk.CodespaceType, clientID string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeClientExists), + fmt.Sprintf("client with ID %s already exists", clientID), + ) } // ErrClientNotFound implements sdk.Error -func ErrClientNotFound(codespace sdk.CodespaceType, clientID string) sdk.Error { - return sdk.NewError(codespace, CodeClientNotFound, fmt.Sprintf("client with ID %s not found", clientID)) +func ErrClientNotFound(codespace sdk.CodespaceType, clientID string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeClientNotFound), + fmt.Sprintf("client with ID %s not found", clientID), + ) } // ErrClientFrozen implements sdk.Error -func ErrClientFrozen(codespace sdk.CodespaceType, clientID string) sdk.Error { - return sdk.NewError(codespace, CodeClientFrozen, fmt.Sprintf("client with ID %s is frozen due to misbehaviour", clientID)) +func ErrClientFrozen(codespace sdk.CodespaceType, clientID string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeClientFrozen), + fmt.Sprintf("client with ID %s is frozen due to misbehaviour", clientID), + ) } // ErrConsensusStateNotFound implements sdk.Error -func ErrConsensusStateNotFound(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeConsensusStateNotFound, "consensus state not found") +func ErrConsensusStateNotFound(codespace sdk.CodespaceType) error { + return sdkerrors.New( + string(codespace), + uint32(CodeConsensusStateNotFound), + "consensus state not found", + ) } // ErrInvalidConsensus implements sdk.Error -func ErrInvalidConsensus(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidConsensusState, "invalid consensus state") +func ErrInvalidConsensus(codespace sdk.CodespaceType) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidConsensusState), + "invalid consensus state", + ) } // ErrClientTypeNotFound implements sdk.Error -func ErrClientTypeNotFound(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeClientTypeNotFound, "client type not found") +func ErrClientTypeNotFound(codespace sdk.CodespaceType) error { + return sdkerrors.New( + string(codespace), + uint32(CodeClientTypeNotFound), + "client type not found", + ) } // ErrInvalidClientType implements sdk.Error -func ErrInvalidClientType(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidClientType, msg) +func ErrInvalidClientType(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidClientType), + msg, + ) } // ErrRootNotFound implements sdk.Error -func ErrRootNotFound(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeRootNotFound, "commitment root not found") +func ErrRootNotFound(codespace sdk.CodespaceType) error { + return sdkerrors.New( + string(codespace), + uint32(CodeRootNotFound), + "commitment root not found", + ) } // ErrInvalidHeader implements sdk.Error -func ErrInvalidHeader(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidHeader, "invalid header") +func ErrInvalidHeader(codespace sdk.CodespaceType) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidHeader), + "invalid header", + ) } // ErrInvalidEvidence implements sdk.Error -func ErrInvalidEvidence(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidEvidence, "invalid evidence: %s", msg) +func ErrInvalidEvidence(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidEvidence), + fmt.Sprintf("invalid evidence: %s", msg), + ) } diff --git a/x/ibc/02-client/types/keys.go b/x/ibc/02-client/types/keys.go index 8d97ca893324..eba16d0c169c 100644 --- a/x/ibc/02-client/types/keys.go +++ b/x/ibc/02-client/types/keys.go @@ -18,6 +18,11 @@ const ( QuerierRoute = SubModuleName ) +// KVStore key prefixes +var ( + KeyPrefixClient = []byte{0x00} +) + // The following paths are the keys to the store as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#path-space // ClientStatePath takes an Identifier and returns a Path under which to store a diff --git a/x/ibc/02-client/types/msgs.go b/x/ibc/02-client/types/msgs.go index 612f7e543e53..f09e126666ff 100644 --- a/x/ibc/02-client/types/msgs.go +++ b/x/ibc/02-client/types/msgs.go @@ -1,8 +1,6 @@ package types import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors" @@ -43,13 +41,13 @@ func (msg MsgCreateClient) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgCreateClient) ValidateBasic() sdk.Error { if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid client ID: %s", err.Error())) + return sdk.ConvertError(err) } if _, err := exported.ClientTypeFromString(msg.ClientType); err != nil { - return errors.ErrInvalidClientType(errors.DefaultCodespace, err.Error()) + return sdk.ConvertError(errors.ErrInvalidClientType(errors.DefaultCodespace, err.Error())) } if msg.ConsensusState == nil { - return errors.ErrInvalidConsensus(errors.DefaultCodespace) + return sdk.ConvertError(errors.ErrInvalidConsensus(errors.DefaultCodespace)) } if msg.Signer.Empty() { return sdk.ErrInvalidAddress("empty address") @@ -98,10 +96,10 @@ func (msg MsgUpdateClient) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgUpdateClient) ValidateBasic() sdk.Error { if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid client ID: %s", err.Error())) + return sdk.ConvertError(err) } if msg.Header == nil { - return errors.ErrInvalidHeader(errors.DefaultCodespace) + return sdk.ConvertError(errors.ErrInvalidHeader(errors.DefaultCodespace)) } if msg.Signer.Empty() { return sdk.ErrInvalidAddress("empty address") @@ -148,13 +146,13 @@ func (msg MsgSubmitMisbehaviour) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgSubmitMisbehaviour) ValidateBasic() sdk.Error { if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid client ID: %s", err.Error())) + return sdk.ConvertError(err) } if msg.Evidence == nil { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, "evidence is nil") + return sdk.ConvertError(errors.ErrInvalidEvidence(errors.DefaultCodespace, "evidence is nil")) } if err := msg.Evidence.ValidateBasic(); err != nil { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, err.Error()) + return sdk.ConvertError(errors.ErrInvalidEvidence(errors.DefaultCodespace, err.Error())) } if msg.Signer.Empty() { return sdk.ErrInvalidAddress("empty address") diff --git a/x/ibc/02-client/types/msgs_test.go b/x/ibc/02-client/types/msgs_test.go index cd416fabdfe8..f7e022ecc89c 100644 --- a/x/ibc/02-client/types/msgs_test.go +++ b/x/ibc/02-client/types/msgs_test.go @@ -5,12 +5,13 @@ import ( "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto/secp256k1" + cmn "github.com/tendermint/tendermint/libs/common" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint" - "github.com/tendermint/tendermint/crypto/secp256k1" - cmn "github.com/tendermint/tendermint/libs/common" ) func TestMsgCreateClientValidateBasic(t *testing.T) { @@ -103,7 +104,7 @@ type mockBadEvidence struct { // Override ValidateBasic func (mbe mockBadEvidence) ValidateBasic() sdk.Error { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, "invalid evidence") + return sdk.ConvertError(errors.ErrInvalidEvidence(errors.DefaultCodespace, "invalid evidence")) } func TestMsgSubmitMisbehaviour(t *testing.T) { diff --git a/x/ibc/02-client/types/querier.go b/x/ibc/02-client/types/querier.go index 7638c0200882..0bf71ebaa6ae 100644 --- a/x/ibc/02-client/types/querier.go +++ b/x/ibc/02-client/types/querier.go @@ -3,9 +3,10 @@ package types import ( "strings" + "github.com/tendermint/tendermint/crypto/merkle" + tmtypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" - "github.com/tendermint/tendermint/crypto/merkle" ) // query routes supported by the IBC client Querier @@ -44,13 +45,34 @@ func NewQueryCommitmentRootParams(id string, height uint64) QueryCommitmentRootP } } +// StateResponse defines the client response for a client state query. +// It includes the commitment proof and the height of the proof. +type StateResponse struct { + ClientState State `json:"client_state" yaml:"client_state"` + Proof commitment.Proof `json:"proof,omitempty" yaml:"proof,omitempty"` + ProofPath commitment.Path `json:"proof_path,omitempty" yaml:"proof_path,omitempty"` + ProofHeight uint64 `json:"proof_height,omitempty" yaml:"proof_height,omitempty"` +} + +// NewClientStateResponse creates a new StateResponse instance. +func NewClientStateResponse( + clientID string, clientState State, proof *merkle.Proof, height int64, +) StateResponse { + return StateResponse{ + ClientState: clientState, + Proof: commitment.Proof{Proof: proof}, + ProofPath: commitment.NewPath(strings.Split(ConsensusStatePath(clientID), "/")), + ProofHeight: uint64(height), + } +} + // ConsensusStateResponse defines the client response for a Consensus state query. // It includes the commitment proof and the height of the proof. type ConsensusStateResponse struct { - ConsensusState tmtypes.ConsensusState - Proof commitment.Proof `json:"proof,omitempty" yaml:"proof,omitempty"` - ProofPath commitment.Path `json:"proof_path,omitempty" yaml:"proof_path,omitempty"` - ProofHeight uint64 `json:"proof_height,omitempty" yaml:"proof_height,omitempty"` + ConsensusState tmtypes.ConsensusState `json:"consensus_state" yaml:"consensus_state"` + Proof commitment.Proof `json:"proof,omitempty" yaml:"proof,omitempty"` + ProofPath commitment.Path `json:"proof_path,omitempty" yaml:"proof_path,omitempty"` + ProofHeight uint64 `json:"proof_height,omitempty" yaml:"proof_height,omitempty"` } // NewConsensusStateResponse creates a new ConsensusStateResponse instance. @@ -64,3 +86,24 @@ func NewConsensusStateResponse( ProofHeight: uint64(height), } } + +// RootResponse defines the client response for a commitment root query. +// It includes the commitment proof and the height of the proof. +type RootResponse struct { + Root commitment.Root `json:"root" yaml:"root"` + Proof commitment.Proof `json:"proof,omitempty" yaml:"proof,omitempty"` + ProofPath commitment.Path `json:"proof_path,omitempty" yaml:"proof_path,omitempty"` + ProofHeight uint64 `json:"proof_height,omitempty" yaml:"proof_height,omitempty"` +} + +// NewRootResponse creates a new RootResponse instance. +func NewRootResponse( + clientID string, height uint64, root commitment.Root, proof *merkle.Proof, proofHeight int64, +) RootResponse { + return RootResponse{ + Root: root, + Proof: commitment.Proof{Proof: proof}, + ProofPath: commitment.NewPath(strings.Split(RootPath(clientID, height), "/")), + ProofHeight: uint64(proofHeight), + } +} diff --git a/x/ibc/02-client/types/state.go b/x/ibc/02-client/types/state.go index 8c60260df0a2..6ae3d0552693 100644 --- a/x/ibc/02-client/types/state.go +++ b/x/ibc/02-client/types/state.go @@ -4,7 +4,7 @@ package types // Any actor holding the Stage can access on and modify that client information. type State struct { // Client ID - id string + ID string `json:"id" yaml:"id"` // Boolean that states if the client is frozen when a misbehaviour proof is // submitted in the event of an equivocation. Frozen bool `json:"frozen" yaml:"frozen"` @@ -13,12 +13,7 @@ type State struct { // NewClientState creates a new ClientState instance func NewClientState(id string) State { return State{ - id: id, + ID: id, Frozen: false, } } - -// ID returns the client identifier -func (s State) ID() string { - return s.id -} diff --git a/x/ibc/02-client/types/tendermint/consensus_state.go b/x/ibc/02-client/types/tendermint/consensus_state.go index 3ad0892a9ea8..f57887045a2f 100644 --- a/x/ibc/02-client/types/tendermint/consensus_state.go +++ b/x/ibc/02-client/types/tendermint/consensus_state.go @@ -2,12 +2,14 @@ package tendermint import ( "bytes" - "errors" + "fmt" lerr "github.com/tendermint/tendermint/lite/errors" tmtypes "github.com/tendermint/tendermint/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" + clienterrors "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -41,7 +43,7 @@ func (cs ConsensusState) GetRoot() commitment.RootI { func (cs ConsensusState) CheckValidityAndUpdateState(header exported.Header) (exported.ConsensusState, error) { tmHeader, ok := header.(Header) if !ok { - return nil, errors.New("header not a valid tendermint header") + return nil, clienterrors.ErrInvalidHeader(clienterrors.DefaultCodespace) } if err := cs.checkValidity(tmHeader); err != nil { @@ -55,6 +57,13 @@ func (cs ConsensusState) CheckValidityAndUpdateState(header exported.Header) (ex // // CONTRACT: assumes header.Height > consensusState.Height func (cs ConsensusState) checkValidity(header Header) error { + if header.GetHeight() < cs.Height { + return sdkerrors.Wrap( + clienterrors.ErrInvalidHeader(clienterrors.DefaultCodespace), + fmt.Sprintf("header height < consensus height (%d < %d)", header.GetHeight(), cs.Height), + ) + } + // check if the hash from the consensus set and header // matches nextHash := cs.NextValidatorSet.Hash() diff --git a/x/ibc/02-client/types/tendermint/misbehaviour.go b/x/ibc/02-client/types/tendermint/misbehaviour.go index 512bb0f72161..1edde8ec1c04 100644 --- a/x/ibc/02-client/types/tendermint/misbehaviour.go +++ b/x/ibc/02-client/types/tendermint/misbehaviour.go @@ -52,20 +52,20 @@ func (ev Evidence) Hash() cmn.HexBytes { // ValidateBasic implements exported.Evidence interface func (ev Evidence) ValidateBasic() sdk.Error { if ev.DuplicateVoteEvidence == nil { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, "duplicate evidence is nil") + return sdk.ConvertError(errors.ErrInvalidEvidence(errors.DefaultCodespace, "duplicate evidence is nil")) } err := ev.DuplicateVoteEvidence.ValidateBasic() if err != nil { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, err.Error()) + return sdk.ConvertError(errors.ErrInvalidEvidence(errors.DefaultCodespace, err.Error())) } if ev.ChainID == "" { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, "chainID is empty") + return sdk.ConvertError(errors.ErrInvalidEvidence(errors.DefaultCodespace, "chainID is empty")) } if ev.ValidatorPower <= 0 { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, fmt.Sprintf("Invalid Validator Power: %d", ev.ValidatorPower)) + return sdk.ConvertError(errors.ErrInvalidEvidence(errors.DefaultCodespace, fmt.Sprintf("Invalid Validator Power: %d", ev.ValidatorPower))) } if ev.TotalPower < ev.ValidatorPower { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, fmt.Sprintf("Invalid Total Power: %d", ev.TotalPower)) + return sdk.ConvertError(errors.ErrInvalidEvidence(errors.DefaultCodespace, fmt.Sprintf("Invalid Total Power: %d", ev.TotalPower))) } return nil } diff --git a/x/ibc/03-connection/alias.go b/x/ibc/03-connection/alias.go index 27757d8163e5..b73456d28dc8 100644 --- a/x/ibc/03-connection/alias.go +++ b/x/ibc/03-connection/alias.go @@ -29,7 +29,6 @@ const ( CodeInvalidVersion = types.CodeInvalidVersion CodeInvalidHeight = types.CodeInvalidHeight CodeInvalidConnectionState = types.CodeInvalidConnectionState - CodeInvalidProof = types.CodeInvalidProof CodeInvalidCounterparty = types.CodeInvalidCounterparty AttributeKeyConnectionID = types.AttributeKeyConnectionID AttributeKeyCounterpartyClientID = types.AttributeKeyCounterpartyClientID @@ -55,10 +54,8 @@ var ( ErrClientConnectionPathsNotFound = types.ErrClientConnectionPathsNotFound ErrConnectionPath = types.ErrConnectionPath ErrInvalidCounterpartyConnection = types.ErrInvalidCounterpartyConnection - ErrInvalidVersion = types.ErrInvalidVersion ErrInvalidHeight = types.ErrInvalidHeight ErrInvalidConnectionState = types.ErrInvalidConnectionState - ErrInvalidConnectionProof = types.ErrInvalidConnectionProof ErrInvalidCounterparty = types.ErrInvalidCounterparty ConnectionPath = types.ConnectionPath ClientConnectionsPath = types.ClientConnectionsPath diff --git a/x/ibc/03-connection/client/cli/query.go b/x/ibc/03-connection/client/cli/query.go index 266ac4bf02d3..f4502807f859 100644 --- a/x/ibc/03-connection/client/cli/query.go +++ b/x/ibc/03-connection/client/cli/query.go @@ -69,10 +69,6 @@ $ %s query ibc connection end [connection-id] return err } - if res.Proof == nil { - return cliCtx.PrintOutput(connection) - } - connRes := types.NewConnectionResponse(connectionID, connection, res.Proof, res.Height) return cliCtx.PrintOutput(connRes) }, @@ -119,10 +115,6 @@ $ %s query ibc connection client [client-id] return err } - if res.Proof == nil { - return cliCtx.PrintOutput(connectionPaths) - } - connPathsRes := types.NewClientConnectionsResponse(clientID, connectionPaths, res.Proof, res.Height) return cliCtx.PrintOutput(connPathsRes) }, diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index cef560ccdd57..b3115069adbc 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -12,6 +12,8 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" @@ -25,7 +27,6 @@ import ( clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" - abci "github.com/tendermint/tendermint/abci/types" ) // Connection Handshake flags @@ -413,7 +414,7 @@ func GetCmdHandshakeState(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - csProof, err := clientutils.QueryConsensusStateProof(ctx1.WithHeight(header.Height-1), clientID1) + csProof, err := clientutils.QueryConsensusStateProof(ctx1.WithHeight(header.Height-1), cdc, clienttypes.QuerierRoute, clientID1) if err != nil { return err } @@ -467,7 +468,7 @@ func GetCmdHandshakeState(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - csProof, err = clientutils.QueryConsensusStateProof(ctx2.WithHeight(header.Height-1), clientID2) + csProof, err = clientutils.QueryConsensusStateProof(ctx2.WithHeight(header.Height-1), cdc, clienttypes.QuerierRoute, clientID2) if err != nil { return err } diff --git a/x/ibc/03-connection/keeper/handshake.go b/x/ibc/03-connection/keeper/handshake.go index 21a005b12c9f..f9288f7d9ae2 100644 --- a/x/ibc/03-connection/keeper/handshake.go +++ b/x/ibc/03-connection/keeper/handshake.go @@ -8,6 +8,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" ) // ConnOpenInit initialises a connection attempt on chain A. @@ -157,7 +158,7 @@ func (k Keeper) ConnOpenAck( } if types.LatestVersion(connection.Versions) != version { - return types.ErrInvalidVersion( + return ibctypes.ErrInvalidVersion( k.codespace, fmt.Sprintf("connection version does't match provided one (%s ≠ %s)", types.LatestVersion(connection.Versions), version), ) diff --git a/x/ibc/03-connection/keeper/handshake_test.go b/x/ibc/03-connection/keeper/handshake_test.go index b8884c56b3ee..e0c0cce29c11 100644 --- a/x/ibc/03-connection/keeper/handshake_test.go +++ b/x/ibc/03-connection/keeper/handshake_test.go @@ -3,11 +3,12 @@ package keeper_test import ( "fmt" + abci "github.com/tendermint/tendermint/abci/types" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" - abci "github.com/tendermint/tendermint/abci/types" ) func (suite *KeeperTestSuite) TestConnOpenInit() { diff --git a/x/ibc/03-connection/keeper/keeper.go b/x/ibc/03-connection/keeper/keeper.go index 1488c6c03ec7..337e6dd66a88 100644 --- a/x/ibc/03-connection/keeper/keeper.go +++ b/x/ibc/03-connection/keeper/keeper.go @@ -16,22 +16,18 @@ import ( // Keeper defines the IBC connection keeper type Keeper struct { - storeKey sdk.StoreKey - cdc *codec.Codec - codespace sdk.CodespaceType - prefix []byte // prefix bytes for accessing the store - + storeKey sdk.StoreKey + cdc *codec.Codec + codespace sdk.CodespaceType clientKeeper types.ClientKeeper } // NewKeeper creates a new IBC connection Keeper instance func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType, ck types.ClientKeeper) Keeper { return Keeper{ - storeKey: key, - cdc: cdc, - codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/connection", - prefix: []byte{}, - // prefix: []byte(types.SubModuleName + "/"), // "connection/" + storeKey: key, + cdc: cdc, + codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/connection", clientKeeper: ck, } } @@ -49,7 +45,7 @@ func (k Keeper) GetCommitmentPrefix() commitment.PrefixI { // GetConnection returns a connection with a particular identifier func (k Keeper) GetConnection(ctx sdk.Context, connectionID string) (types.ConnectionEnd, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixConnection) bz := store.Get(types.KeyConnection(connectionID)) if bz == nil { return types.ConnectionEnd{}, false @@ -62,7 +58,7 @@ func (k Keeper) GetConnection(ctx sdk.Context, connectionID string) (types.Conne // SetConnection sets a connection to the store func (k Keeper) SetConnection(ctx sdk.Context, connectionID string, connection types.ConnectionEnd) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixConnection) bz := k.cdc.MustMarshalBinaryLengthPrefixed(connection) store.Set(types.KeyConnection(connectionID), bz) } @@ -70,7 +66,7 @@ func (k Keeper) SetConnection(ctx sdk.Context, connectionID string, connection t // GetClientConnectionPaths returns all the connection paths stored under a // particular client func (k Keeper) GetClientConnectionPaths(ctx sdk.Context, clientID string) ([]string, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixConnection) bz := store.Get(types.KeyClientConnections(clientID)) if bz == nil { return nil, false @@ -83,7 +79,7 @@ func (k Keeper) GetClientConnectionPaths(ctx sdk.Context, clientID string) ([]st // SetClientConnectionPaths sets the connections paths for client func (k Keeper) SetClientConnectionPaths(ctx sdk.Context, clientID string, paths []string) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixConnection) bz := k.cdc.MustMarshalBinaryLengthPrefixed(paths) store.Set(types.KeyClientConnections(clientID), bz) } @@ -92,7 +88,7 @@ func (k Keeper) SetClientConnectionPaths(ctx sdk.Context, clientID string, paths // connections associated with a client. // // CONTRACT: client must already exist -func (k Keeper) addConnectionToClient(ctx sdk.Context, clientID, connectionID string) sdk.Error { +func (k Keeper) addConnectionToClient(ctx sdk.Context, clientID, connectionID string) error { conns, found := k.GetClientConnectionPaths(ctx, clientID) if !found { conns = []string{} @@ -107,7 +103,8 @@ func (k Keeper) addConnectionToClient(ctx sdk.Context, clientID, connectionID st // set of connections associated with a client. // // CONTRACT: client must already exist -func (k Keeper) removeConnectionFromClient(ctx sdk.Context, clientID, connectionID string) sdk.Error { +// nolint: unused +func (k Keeper) removeConnectionFromClient(ctx sdk.Context, clientID, connectionID string) error { conns, found := k.GetClientConnectionPaths(ctx, clientID) if !found { return types.ErrClientConnectionPathsNotFound(k.codespace, clientID) diff --git a/x/ibc/03-connection/keeper/keeper_test.go b/x/ibc/03-connection/keeper/keeper_test.go index 9c086f647d06..bf6dfe0d7839 100644 --- a/x/ibc/03-connection/keeper/keeper_test.go +++ b/x/ibc/03-connection/keeper/keeper_test.go @@ -3,14 +3,15 @@ package keeper_test import ( "testing" + "github.com/stretchr/testify/suite" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" - "github.com/stretchr/testify/suite" - abci "github.com/tendermint/tendermint/abci/types" ) const ( diff --git a/x/ibc/03-connection/keeper/querier.go b/x/ibc/03-connection/keeper/querier.go index 85bb02559e78..8802ec7443fe 100644 --- a/x/ibc/03-connection/keeper/querier.go +++ b/x/ibc/03-connection/keeper/querier.go @@ -20,7 +20,7 @@ func QuerierConnection(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte connection, found := k.GetConnection(ctx, params.ConnectionID) if !found { - return nil, types.ErrConnectionNotFound(k.codespace, params.ConnectionID) + return nil, sdk.ConvertError(types.ErrConnectionNotFound(k.codespace, params.ConnectionID)) } bz, err := types.SubModuleCdc.MarshalJSON(connection) @@ -42,7 +42,7 @@ func QuerierClientConnections(ctx sdk.Context, req abci.RequestQuery, k Keeper) clientConnectionPaths, found := k.GetClientConnectionPaths(ctx, params.ClientID) if !found { - return nil, types.ErrClientConnectionPathsNotFound(k.codespace, params.ClientID) + return nil, sdk.ConvertError(types.ErrClientConnectionPathsNotFound(k.codespace, params.ClientID)) } bz, err := types.SubModuleCdc.MarshalJSON(clientConnectionPaths) diff --git a/x/ibc/03-connection/types/connection.go b/x/ibc/03-connection/types/connection.go index 07eb0a25c6ac..23ec6ca5709b 100644 --- a/x/ibc/03-connection/types/connection.go +++ b/x/ibc/03-connection/types/connection.go @@ -4,7 +4,7 @@ import ( "encoding/json" "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" ) @@ -55,12 +55,12 @@ func NewCounterparty(clientID, connectionID string, prefix commitment.PrefixI) C } // ValidateBasic performs a basic validation check of the identifiers and prefix -func (c Counterparty) ValidateBasic() sdk.Error { +func (c Counterparty) ValidateBasic() error { if err := host.DefaultConnectionIdentifierValidator(c.ConnectionID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid counterparty connection ID: %s", err.Error())) + return sdkerrors.Wrap(err, "invalid counterparty connection ID") } if err := host.DefaultClientIdentifierValidator(c.ClientID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid counterparty client ID: %s", err.Error())) + return sdkerrors.Wrap(err, "invalid counterparty client ID") } if c.Prefix == nil || len(c.Prefix.Bytes()) == 0 { return ErrInvalidCounterparty(DefaultCodespace, "invalid counterparty prefix") diff --git a/x/ibc/03-connection/types/errors.go b/x/ibc/03-connection/types/errors.go index b2a2cbe2ad5f..d62e14a49218 100644 --- a/x/ibc/03-connection/types/errors.go +++ b/x/ibc/03-connection/types/errors.go @@ -4,70 +4,92 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // connection error codes const ( DefaultCodespace sdk.CodespaceType = SubModuleName - CodeConnectionExists sdk.CodeType = 101 - CodeConnectionNotFound sdk.CodeType = 102 - CodeClientConnectionPathsNotFound sdk.CodeType = 103 - CodeConnectionPath sdk.CodeType = 104 - CodeInvalidCounterpartyConnection sdk.CodeType = 105 - CodeInvalidVersion sdk.CodeType = 106 - CodeInvalidHeight sdk.CodeType = 107 - CodeInvalidConnectionState sdk.CodeType = 108 - CodeInvalidProof sdk.CodeType = 109 - CodeInvalidCounterparty sdk.CodeType = 110 + CodeConnectionExists sdk.CodeType = 210 + CodeConnectionNotFound sdk.CodeType = 211 + CodeClientConnectionPathsNotFound sdk.CodeType = 212 + CodeConnectionPath sdk.CodeType = 213 + CodeInvalidCounterpartyConnection sdk.CodeType = 214 + CodeInvalidVersion sdk.CodeType = 215 + CodeInvalidHeight sdk.CodeType = 216 + CodeInvalidConnectionState sdk.CodeType = 217 + CodeInvalidCounterparty sdk.CodeType = 218 ) // ErrConnectionExists implements sdk.Error -func ErrConnectionExists(codespace sdk.CodespaceType, connectionID string) sdk.Error { - return sdk.NewError(codespace, CodeConnectionExists, fmt.Sprintf("connection with ID %s already exists", connectionID)) +func ErrConnectionExists(codespace sdk.CodespaceType, connectionID string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeConnectionExists), + fmt.Sprintf("connection with ID %s already exists", connectionID), + ) } // ErrConnectionNotFound implements sdk.Error -func ErrConnectionNotFound(codespace sdk.CodespaceType, connectionID string) sdk.Error { - return sdk.NewError(codespace, CodeConnectionNotFound, fmt.Sprintf("connection with ID %s not found", connectionID)) +func ErrConnectionNotFound(codespace sdk.CodespaceType, connectionID string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeConnectionNotFound), + fmt.Sprintf("connection with ID %s not found", connectionID), + ) } // ErrClientConnectionPathsNotFound implements sdk.Error -func ErrClientConnectionPathsNotFound(codespace sdk.CodespaceType, clientID string) sdk.Error { - return sdk.NewError(codespace, CodeClientConnectionPathsNotFound, fmt.Sprintf("client connection paths not found for ID %s", clientID)) +func ErrClientConnectionPathsNotFound(codespace sdk.CodespaceType, clientID string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeClientConnectionPathsNotFound), + fmt.Sprintf("client connection paths not found for ID %s", clientID), + ) } // ErrConnectionPath implements sdk.Error -func ErrConnectionPath(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeConnectionPath, "connection path is not associated to the client") +func ErrConnectionPath(codespace sdk.CodespaceType) error { + return sdkerrors.New( + string(codespace), + uint32(CodeConnectionPath), + "connection path is not associated to the client", + ) } // ErrInvalidCounterpartyConnection implements sdk.Error -func ErrInvalidCounterpartyConnection(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidCounterpartyConnection, "couldn't verify connection membership on counterparty's client") -} - -// ErrInvalidVersion implements sdk.Error -func ErrInvalidVersion(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidVersion, msg) +func ErrInvalidCounterpartyConnection(codespace sdk.CodespaceType) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidCounterpartyConnection), + "couldn't verify connection membership on counterparty's client", + ) } // ErrInvalidHeight implements sdk.Error -func ErrInvalidHeight(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidHeight, msg) +func ErrInvalidHeight(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidHeight), + msg, + ) } // ErrInvalidConnectionState implements sdk.Error -func ErrInvalidConnectionState(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidConnectionState, msg) -} - -// ErrInvalidConnectionProof implements sdk.Error -func ErrInvalidConnectionProof(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidProof, msg) +func ErrInvalidConnectionState(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidConnectionState), + msg, + ) } // ErrInvalidCounterparty implements sdk.Error -func ErrInvalidCounterparty(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidCounterparty, msg) +func ErrInvalidCounterparty(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidCounterparty), + msg, + ) } diff --git a/x/ibc/03-connection/types/keys.go b/x/ibc/03-connection/types/keys.go index 7dd82ae80a2e..40eda70e340f 100644 --- a/x/ibc/03-connection/types/keys.go +++ b/x/ibc/03-connection/types/keys.go @@ -18,6 +18,11 @@ const ( QuerierRoute = SubModuleName ) +// KVStore key prefixes +var ( + KeyPrefixConnection = []byte{0x00} +) + // The following paths are the keys to the store as defined in https://github.com/cosmos/ics/tree/master/spec/ics-003-connection-semantics#store-paths // ConnectionPath defines the path under which connection paths are stored diff --git a/x/ibc/03-connection/types/msgs.go b/x/ibc/03-connection/types/msgs.go index 10ede21b1124..e302badac9c4 100644 --- a/x/ibc/03-connection/types/msgs.go +++ b/x/ibc/03-connection/types/msgs.go @@ -1,10 +1,10 @@ package types import ( - "fmt" "strings" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" @@ -49,15 +49,15 @@ func (msg MsgConnectionOpenInit) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgConnectionOpenInit) ValidateBasic() sdk.Error { if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid connection ID: %s", err.Error())) + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid connection ID")) } if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid client ID: %s", err.Error())) + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid client ID")) } if msg.Signer.Empty() { return sdk.ErrInvalidAddress("missing signer address") } - return msg.Counterparty.ValidateBasic() + return sdk.ConvertError(msg.Counterparty.ValidateBasic()) } // GetSignBytes implements sdk.Msg @@ -120,35 +120,35 @@ func (msg MsgConnectionOpenTry) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgConnectionOpenTry) ValidateBasic() sdk.Error { if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid connection ID: %s", err.Error())) + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid connection ID")) } if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid client ID: %s", err.Error())) + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid client ID")) } if len(msg.CounterpartyVersions) == 0 { - return ErrInvalidVersion(DefaultCodespace, "missing counterparty versions") + return sdk.ConvertError(ibctypes.ErrInvalidVersion(DefaultCodespace, "missing counterparty versions")) } for _, version := range msg.CounterpartyVersions { if strings.TrimSpace(version) == "" { - return ErrInvalidVersion(DefaultCodespace, "version can't be blank") + return sdk.ConvertError(ibctypes.ErrInvalidVersion(DefaultCodespace, "version can't be blank")) } } if msg.ProofInit == nil { - return ErrInvalidConnectionProof(DefaultCodespace, "proof init cannot be nil") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof init cannot be nil")) } if msg.ProofConsensus == nil { - return ErrInvalidConnectionProof(DefaultCodespace, "proof consensus cannot be nil") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof consensus cannot be nil")) } if msg.ProofHeight == 0 { - return ErrInvalidHeight(DefaultCodespace, "proof height must be > 0") + return sdk.ConvertError(ErrInvalidHeight(DefaultCodespace, "proof height must be > 0")) } if msg.ConsensusHeight == 0 { - return ErrInvalidHeight(DefaultCodespace, "consensus height must be > 0") + return sdk.ConvertError(ErrInvalidHeight(DefaultCodespace, "consensus height must be > 0")) } if msg.Signer.Empty() { return sdk.ErrInvalidAddress("missing signer address") } - return msg.Counterparty.ValidateBasic() + return sdk.ConvertError(msg.Counterparty.ValidateBasic()) } // GetSignBytes implements sdk.Msg @@ -205,22 +205,22 @@ func (msg MsgConnectionOpenAck) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgConnectionOpenAck) ValidateBasic() sdk.Error { if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid connection ID: %s", err.Error())) + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid connection ID")) } if strings.TrimSpace(msg.Version) == "" { - return ErrInvalidVersion(DefaultCodespace, "version can't be blank") + return sdk.ConvertError(ibctypes.ErrInvalidVersion(DefaultCodespace, "version can't be blank")) } if msg.ProofTry == nil { - return ErrInvalidConnectionProof(DefaultCodespace, "proof try cannot be nil") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof try cannot be nil")) } if msg.ProofConsensus == nil { - return ErrInvalidConnectionProof(DefaultCodespace, "proof consensus cannot be nil") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof consensus cannot be nil")) } if msg.ProofHeight == 0 { - return ErrInvalidHeight(DefaultCodespace, "proof height must be > 0") + return sdk.ConvertError(ErrInvalidHeight(DefaultCodespace, "proof height must be > 0")) } if msg.ConsensusHeight == 0 { - return ErrInvalidHeight(DefaultCodespace, "consensus height must be > 0") + return sdk.ConvertError(ErrInvalidHeight(DefaultCodespace, "consensus height must be > 0")) } if msg.Signer.Empty() { return sdk.ErrInvalidAddress("missing signer address") @@ -274,15 +274,14 @@ func (msg MsgConnectionOpenConfirm) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgConnectionOpenConfirm) ValidateBasic() sdk.Error { if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid connection ID: %s", err.Error())) + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid connection ID")) } if msg.ProofAck == nil { - return ErrInvalidConnectionProof(DefaultCodespace, "proof ack cannot be nil") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof ack cannot be nil")) } if msg.ProofHeight == 0 { - return ErrInvalidHeight(DefaultCodespace, "proof height must be > 0") + return sdk.ConvertError(ErrInvalidHeight(DefaultCodespace, "proof height must be > 0")) } - if msg.Signer.Empty() { return sdk.ErrInvalidAddress("missing signer address") } diff --git a/x/ibc/03-connection/types/msgs_test.go b/x/ibc/03-connection/types/msgs_test.go index 7c94f3036936..87fbae8b7276 100644 --- a/x/ibc/03-connection/types/msgs_test.go +++ b/x/ibc/03-connection/types/msgs_test.go @@ -4,9 +4,10 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + sdk "github.com/cosmos/cosmos-sdk/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" - "github.com/stretchr/testify/require" ) func TestNewMsgConnectionOpenInit(t *testing.T) { diff --git a/x/ibc/03-connection/types/querier.go b/x/ibc/03-connection/types/querier.go index 6fbb151342f4..c254bebd6b4c 100644 --- a/x/ibc/03-connection/types/querier.go +++ b/x/ibc/03-connection/types/querier.go @@ -3,8 +3,9 @@ package types import ( "strings" - commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/tendermint/tendermint/crypto/merkle" + + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) // query routes supported by the IBC connection Querier diff --git a/x/ibc/04-channel/alias.go b/x/ibc/04-channel/alias.go index 25f73b478565..8ce587180679 100644 --- a/x/ibc/04-channel/alias.go +++ b/x/ibc/04-channel/alias.go @@ -36,7 +36,6 @@ const ( CodePacketTimeout = types.CodePacketTimeout CodeInvalidChannel = types.CodeInvalidChannel CodeInvalidChannelState = types.CodeInvalidChannelState - CodeInvalidChannelProof = types.CodeInvalidChannelProof AttributeKeySenderPort = types.AttributeKeySenderPort AttributeKeyReceiverPort = types.AttributeKeyReceiverPort AttributeKeyChannelID = types.AttributeKeyChannelID @@ -66,7 +65,6 @@ var ( ErrPacketTimeout = types.ErrPacketTimeout ErrInvalidChannel = types.ErrInvalidChannel ErrInvalidChannelState = types.ErrInvalidChannelState - ErrInvalidChannelProof = types.ErrInvalidChannelProof ChannelPath = types.ChannelPath ChannelCapabilityPath = types.ChannelCapabilityPath NextSequenceSendPath = types.NextSequenceSendPath diff --git a/x/ibc/04-channel/client/cli/tx.go b/x/ibc/04-channel/client/cli/tx.go index 265ec880d73a..fea92f900ee9 100644 --- a/x/ibc/04-channel/client/cli/tx.go +++ b/x/ibc/04-channel/client/cli/tx.go @@ -11,6 +11,8 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" @@ -24,7 +26,6 @@ import ( clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" - abci "github.com/tendermint/tendermint/abci/types" ) const ( diff --git a/x/ibc/04-channel/exported/exported.go b/x/ibc/04-channel/exported/exported.go index 8fb84f7c1c01..6fd31751fef6 100644 --- a/x/ibc/04-channel/exported/exported.go +++ b/x/ibc/04-channel/exported/exported.go @@ -1,9 +1,6 @@ package exported -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - +// PacketI defines the standard interface for IBC packets type PacketI interface { GetSequence() uint64 GetTimeoutHeight() uint64 @@ -12,5 +9,5 @@ type PacketI interface { GetDestPort() string GetDestChannel() string GetData() []byte - ValidateBasic() sdk.Error + ValidateBasic() error } diff --git a/x/ibc/04-channel/keeper/handshake_test.go b/x/ibc/04-channel/keeper/handshake_test.go index 5a8ce10ceb4a..fde534b0f26d 100644 --- a/x/ibc/04-channel/keeper/handshake_test.go +++ b/x/ibc/04-channel/keeper/handshake_test.go @@ -3,6 +3,8 @@ package keeper_test import ( "fmt" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" clienttypestm "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint" @@ -10,7 +12,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" - abci "github.com/tendermint/tendermint/abci/types" ) func (suite *KeeperTestSuite) createClient() { diff --git a/x/ibc/04-channel/keeper/keeper.go b/x/ibc/04-channel/keeper/keeper.go index dc6bbd3fb021..0de7cc329288 100644 --- a/x/ibc/04-channel/keeper/keeper.go +++ b/x/ibc/04-channel/keeper/keeper.go @@ -15,11 +15,9 @@ import ( // Keeper defines the IBC channel keeper type Keeper struct { - storeKey sdk.StoreKey - cdc *codec.Codec - codespace sdk.CodespaceType - prefix []byte // prefix bytes for accessing the store - + storeKey sdk.StoreKey + cdc *codec.Codec + codespace sdk.CodespaceType clientKeeper types.ClientKeeper connectionKeeper types.ConnectionKeeper portKeeper types.PortKeeper @@ -32,11 +30,9 @@ func NewKeeper( portKeeper types.PortKeeper, ) Keeper { return Keeper{ - storeKey: key, - cdc: cdc, - codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/channel", - prefix: []byte{}, - // prefix: []byte(types.SubModuleName + "/"), // "channel/" + storeKey: key, + cdc: cdc, + codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/channel", clientKeeper: clientKeeper, connectionKeeper: connectionKeeper, portKeeper: portKeeper, @@ -50,7 +46,7 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { // GetChannel returns a channel with a particular identifier binded to a specific port func (k Keeper) GetChannel(ctx sdk.Context, portID, channelID string) (types.Channel, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) bz := store.Get(types.KeyChannel(portID, channelID)) if bz == nil { return types.Channel{}, false @@ -63,14 +59,14 @@ func (k Keeper) GetChannel(ctx sdk.Context, portID, channelID string) (types.Cha // SetChannel sets a channel to the store func (k Keeper) SetChannel(ctx sdk.Context, portID, channelID string, channel types.Channel) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) bz := k.cdc.MustMarshalBinaryLengthPrefixed(channel) store.Set(types.KeyChannel(portID, channelID), bz) } // GetChannelCapability gets a channel's capability key from the store func (k Keeper) GetChannelCapability(ctx sdk.Context, portID, channelID string) (string, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) bz := store.Get(types.KeyChannelCapabilityPath(portID, channelID)) if bz == nil { return "", false @@ -81,13 +77,13 @@ func (k Keeper) GetChannelCapability(ctx sdk.Context, portID, channelID string) // SetChannelCapability sets a channel's capability key to the store func (k Keeper) SetChannelCapability(ctx sdk.Context, portID, channelID string, key string) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) store.Set(types.KeyChannelCapabilityPath(portID, channelID), []byte(key)) } // GetNextSequenceSend gets a channel's next send sequence from the store func (k Keeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) bz := store.Get(types.KeyNextSequenceSend(portID, channelID)) if bz == nil { return 0, false @@ -98,14 +94,14 @@ func (k Keeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) ( // SetNextSequenceSend sets a channel's next send sequence to the store func (k Keeper) SetNextSequenceSend(ctx sdk.Context, portID, channelID string, sequence uint64) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) bz := sdk.Uint64ToBigEndian(sequence) store.Set(types.KeyNextSequenceSend(portID, channelID), bz) } // GetNextSequenceRecv gets a channel's next receive sequence from the store func (k Keeper) GetNextSequenceRecv(ctx sdk.Context, portID, channelID string) (uint64, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) bz := store.Get(types.KeyNextSequenceRecv(portID, channelID)) if bz == nil { return 0, false @@ -116,38 +112,38 @@ func (k Keeper) GetNextSequenceRecv(ctx sdk.Context, portID, channelID string) ( // SetNextSequenceRecv sets a channel's next receive sequence to the store func (k Keeper) SetNextSequenceRecv(ctx sdk.Context, portID, channelID string, sequence uint64) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) bz := sdk.Uint64ToBigEndian(sequence) store.Set(types.KeyNextSequenceRecv(portID, channelID), bz) } // GetPacketCommitment gets the packet commitment hash from the store func (k Keeper) GetPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64) []byte { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) bz := store.Get(types.KeyPacketCommitment(portID, channelID, sequence)) return bz } // SetPacketCommitment sets the packet commitment hash to the store func (k Keeper) SetPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64, commitmentHash []byte) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) store.Set(types.KeyPacketCommitment(portID, channelID, sequence), commitmentHash) } func (k Keeper) deletePacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) store.Delete(types.KeyPacketCommitment(portID, channelID, sequence)) } // SetPacketAcknowledgement sets the packet ack hash to the store func (k Keeper) SetPacketAcknowledgement(ctx sdk.Context, portID, channelID string, sequence uint64, ackHash []byte) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) store.Set(types.KeyPacketAcknowledgement(portID, channelID, sequence), ackHash) } // GetPacketAcknowledgement gets the packet ack hash from the store func (k Keeper) GetPacketAcknowledgement(ctx sdk.Context, portID, channelID string, sequence uint64) ([]byte, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), k.prefix) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChannel) bz := store.Get(types.KeyPacketAcknowledgement(portID, channelID, sequence)) if bz == nil { return nil, false diff --git a/x/ibc/04-channel/keeper/keeper_test.go b/x/ibc/04-channel/keeper/keeper_test.go index f05cc56db841..299b0ab9c5e5 100644 --- a/x/ibc/04-channel/keeper/keeper_test.go +++ b/x/ibc/04-channel/keeper/keeper_test.go @@ -3,13 +3,14 @@ package keeper_test import ( "testing" + "github.com/stretchr/testify/suite" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" - "github.com/stretchr/testify/suite" - abci "github.com/tendermint/tendermint/abci/types" ) // define constants used for testing diff --git a/x/ibc/04-channel/keeper/querier.go b/x/ibc/04-channel/keeper/querier.go index 3618c5f29fd4..3bf671d1e0fb 100644 --- a/x/ibc/04-channel/keeper/querier.go +++ b/x/ibc/04-channel/keeper/querier.go @@ -20,7 +20,7 @@ func QuerierChannel(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, s channel, found := k.GetChannel(ctx, params.PortID, params.ChannelID) if !found { - return nil, types.ErrChannelNotFound(k.codespace, params.PortID, params.ChannelID) + return nil, sdk.ConvertError(types.ErrChannelNotFound(k.codespace, params.PortID, params.ChannelID)) } bz, err := types.SubModuleCdc.MarshalJSON(channel) diff --git a/x/ibc/04-channel/types/channel.go b/x/ibc/04-channel/types/channel.go index 98bbb9b44f1e..d14c42ad6e2c 100644 --- a/x/ibc/04-channel/types/channel.go +++ b/x/ibc/04-channel/types/channel.go @@ -5,8 +5,7 @@ import ( "fmt" "strings" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/errors" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" ) @@ -33,7 +32,7 @@ func NewChannel( } // ValidateBasic performs a basic validation of the channel fields -func (ch Channel) ValidateBasic() sdk.Error { +func (ch Channel) ValidateBasic() error { if ch.State.String() == "" { return ErrInvalidChannelState( DefaultCodespace, @@ -50,7 +49,7 @@ func (ch Channel) ValidateBasic() sdk.Error { return ErrInvalidChannel(DefaultCodespace, "IBC v1 only supports one connection hop") } if err := host.DefaultConnectionIdentifierValidator(ch.ConnectionHops[0]); err != nil { - return ErrInvalidChannel(DefaultCodespace, errors.Wrap(err, "invalid connection hop ID").Error()) + return sdkerrors.Wrap(err, "invalid connection hop ID") } if strings.TrimSpace(ch.Version) == "" { return ErrInvalidChannel(DefaultCodespace, "channel version can't be blank") @@ -73,12 +72,12 @@ func NewCounterparty(portID, channelID string) Counterparty { } // ValidateBasic performs a basic validation check of the identifiers -func (c Counterparty) ValidateBasic() sdk.Error { +func (c Counterparty) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(c.PortID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid counterparty connection ID: %s", err.Error())) + return sdkerrors.Wrap(err, "invalid counterparty connection ID") } if err := host.DefaultChannelIdentifierValidator(c.ChannelID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid counterparty client ID: %s", err.Error())) + return sdkerrors.Wrap(err, "invalid counterparty client ID") } return nil } diff --git a/x/ibc/04-channel/types/errors.go b/x/ibc/04-channel/types/errors.go index 37d3925b513e..318c78017d34 100644 --- a/x/ibc/04-channel/types/errors.go +++ b/x/ibc/04-channel/types/errors.go @@ -4,70 +4,101 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // channel error codes const ( DefaultCodespace sdk.CodespaceType = SubModuleName - CodeChannelExists sdk.CodeType = 101 - CodeChannelNotFound sdk.CodeType = 102 - CodeInvalidCounterpartyChannel sdk.CodeType = 103 - CodeChannelCapabilityNotFound sdk.CodeType = 104 - CodeInvalidPacket sdk.CodeType = 105 - CodeSequenceNotFound sdk.CodeType = 106 - CodePacketTimeout sdk.CodeType = 107 - CodeInvalidChannel sdk.CodeType = 108 - CodeInvalidChannelState sdk.CodeType = 109 - CodeInvalidChannelProof sdk.CodeType = 110 + CodeChannelExists sdk.CodeType = 219 + CodeChannelNotFound sdk.CodeType = 220 + CodeInvalidCounterpartyChannel sdk.CodeType = 221 + CodeChannelCapabilityNotFound sdk.CodeType = 222 + CodeInvalidPacket sdk.CodeType = 223 + CodeSequenceNotFound sdk.CodeType = 224 + CodePacketTimeout sdk.CodeType = 225 + CodeInvalidChannel sdk.CodeType = 226 + CodeInvalidChannelState sdk.CodeType = 227 ) // ErrChannelExists implements sdk.Error -func ErrChannelExists(codespace sdk.CodespaceType, channelID string) sdk.Error { - return sdk.NewError(codespace, CodeChannelExists, fmt.Sprintf("channel with ID %s already exists", channelID)) +func ErrChannelExists(codespace sdk.CodespaceType, channelID string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeChannelExists), + fmt.Sprintf("channel with ID %s already exists", channelID), + ) } // ErrChannelNotFound implements sdk.Error -func ErrChannelNotFound(codespace sdk.CodespaceType, portID, channelID string) sdk.Error { - return sdk.NewError(codespace, CodeChannelNotFound, fmt.Sprintf("channel with ID %s on port %s not found", channelID, portID)) +func ErrChannelNotFound(codespace sdk.CodespaceType, portID, channelID string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeChannelNotFound), + fmt.Sprintf("channel with ID %s on port %s not found", channelID, portID), + ) } // ErrInvalidCounterpartyChannel implements sdk.Error -func ErrInvalidCounterpartyChannel(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidCounterpartyChannel, msg) +func ErrInvalidCounterpartyChannel(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidCounterpartyChannel), + msg, + ) } // ErrChannelCapabilityNotFound implements sdk.Error -func ErrChannelCapabilityNotFound(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeChannelCapabilityNotFound, "channel capability key not found") +func ErrChannelCapabilityNotFound(codespace sdk.CodespaceType) error { + return sdkerrors.New( + string(codespace), + uint32(CodeChannelCapabilityNotFound), + "channel capability key not found", + ) } // ErrInvalidPacket implements sdk.Error -func ErrInvalidPacket(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidPacket, msg) +func ErrInvalidPacket(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidPacket), + msg, + ) } // ErrSequenceNotFound implements sdk.Error -func ErrSequenceNotFound(codespace sdk.CodespaceType, seqType string) sdk.Error { - return sdk.NewError(codespace, CodeSequenceNotFound, fmt.Sprintf("next %s sequence counter not found", seqType)) +func ErrSequenceNotFound(codespace sdk.CodespaceType, seqType string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeSequenceNotFound), + fmt.Sprintf("next %s sequence counter not found", seqType), + ) } // ErrPacketTimeout implements sdk.Error -func ErrPacketTimeout(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodePacketTimeout, "packet timeout") +func ErrPacketTimeout(codespace sdk.CodespaceType) error { + return sdkerrors.New( + string(codespace), + uint32(CodePacketTimeout), + "packet timeout", + ) } // ErrInvalidChannel implements sdk.Error -func ErrInvalidChannel(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidChannel, msg) +func ErrInvalidChannel(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidChannel), + msg, + ) } // ErrInvalidChannelState implements sdk.Error -func ErrInvalidChannelState(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidChannelState, msg) -} - -// ErrInvalidChannelProof implements sdk.Error -func ErrInvalidChannelProof(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidChannelProof, msg) +func ErrInvalidChannelState(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidChannelState), + msg, + ) } diff --git a/x/ibc/04-channel/types/keys.go b/x/ibc/04-channel/types/keys.go index f308640b2e32..7849b37f90e1 100644 --- a/x/ibc/04-channel/types/keys.go +++ b/x/ibc/04-channel/types/keys.go @@ -18,6 +18,11 @@ const ( QuerierRoute = SubModuleName ) +// KVStore key prefixes +var ( + KeyPrefixChannel = []byte{0x00} +) + // ChannelPath defines the path under which channels are stored func ChannelPath(portID, channelID string) string { return fmt.Sprintf("ports/%s/channels/%s", portID, channelID) diff --git a/x/ibc/04-channel/types/msgs.go b/x/ibc/04-channel/types/msgs.go index a6d7d856e34f..6f69c5d6ea86 100644 --- a/x/ibc/04-channel/types/msgs.go +++ b/x/ibc/04-channel/types/msgs.go @@ -1,10 +1,10 @@ package types import ( - "fmt" "strings" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" @@ -46,14 +46,14 @@ func (msg MsgChannelOpenInit) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelOpenInit) ValidateBasic() sdk.Error { - if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid port ID: %s", err.Error())) + if err := host.DefaultConnectionIdentifierValidator(msg.PortID); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) } - if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid channel ID: %s", err.Error())) + if err := host.DefaultClientIdentifierValidator(msg.ChannelID); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) } // Signer can be empty - return msg.Channel.ValidateBasic() + return sdk.ConvertError(msg.Channel.ValidateBasic()) } // GetSignBytes implements sdk.Msg @@ -109,23 +109,23 @@ func (msg MsgChannelOpenTry) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelOpenTry) ValidateBasic() sdk.Error { - if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid port ID: %s", err.Error())) + if err := host.DefaultConnectionIdentifierValidator(msg.PortID); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) } - if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid channel ID: %s", err.Error())) + if err := host.DefaultClientIdentifierValidator(msg.ChannelID); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) } if strings.TrimSpace(msg.CounterpartyVersion) == "" { - return ErrInvalidCounterpartyChannel(DefaultCodespace, "counterparty version cannot be blank") + return sdk.ConvertError(ErrInvalidCounterpartyChannel(DefaultCodespace, "counterparty version cannot be blank")) } if msg.ProofInit == nil { - return ErrInvalidChannelProof(DefaultCodespace, "cannot submit an empty proof") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "cannot submit an empty proof")) } if msg.ProofHeight == 0 { - return ErrInvalidChannelProof(DefaultCodespace, "proof height must be > 0") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof height must be > 0")) } // Signer can be empty - return msg.Channel.ValidateBasic() + return sdk.ConvertError(msg.Channel.ValidateBasic()) } // GetSignBytes implements sdk.Msg @@ -176,20 +176,20 @@ func (msg MsgChannelOpenAck) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelOpenAck) ValidateBasic() sdk.Error { - if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid port ID: %s", err.Error())) + if err := host.DefaultConnectionIdentifierValidator(msg.PortID); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) } - if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid channel ID: %s", err.Error())) + if err := host.DefaultClientIdentifierValidator(msg.ChannelID); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) } if strings.TrimSpace(msg.CounterpartyVersion) == "" { - return ErrInvalidCounterpartyChannel(DefaultCodespace, "counterparty version cannot be blank") + return sdk.ConvertError(ErrInvalidCounterpartyChannel(DefaultCodespace, "counterparty version cannot be blank")) } if msg.ProofTry == nil { - return ErrInvalidChannelProof(DefaultCodespace, "cannot submit an empty proof") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "cannot submit an empty proof")) } if msg.ProofHeight == 0 { - return ErrInvalidChannelProof(DefaultCodespace, "proof height must be > 0") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof height must be > 0")) } // Signer can be empty return nil @@ -241,17 +241,17 @@ func (msg MsgChannelOpenConfirm) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelOpenConfirm) ValidateBasic() sdk.Error { - if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid port ID: %s", err.Error())) + if err := host.DefaultConnectionIdentifierValidator(msg.PortID); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) } - if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid channel ID: %s", err.Error())) + if err := host.DefaultClientIdentifierValidator(msg.ChannelID); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) } if msg.ProofAck == nil { - return ErrInvalidChannelProof(DefaultCodespace, "cannot submit an empty proof") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "cannot submit an empty proof")) } if msg.ProofHeight == 0 { - return ErrInvalidChannelProof(DefaultCodespace, "proof height must be > 0") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof height must be > 0")) } // Signer can be empty return nil @@ -296,11 +296,11 @@ func (msg MsgChannelCloseInit) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelCloseInit) ValidateBasic() sdk.Error { - if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid port ID: %s", err.Error())) + if err := host.DefaultConnectionIdentifierValidator(msg.PortID); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) } - if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid channel ID: %s", err.Error())) + if err := host.DefaultClientIdentifierValidator(msg.ChannelID); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) } // Signer can be empty return nil @@ -353,16 +353,16 @@ func (msg MsgChannelCloseConfirm) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelCloseConfirm) ValidateBasic() sdk.Error { if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid port ID: %s", err.Error())) + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) } if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid channel ID: %s", err.Error())) + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) } if msg.ProofInit == nil { - return ErrInvalidChannelProof(DefaultCodespace, "cannot submit an empty proof") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "cannot submit an empty proof")) } if msg.ProofHeight == 0 { - return ErrInvalidChannelProof(DefaultCodespace, "proof height must be > 0") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof height must be > 0")) } // Signer can be empty return nil diff --git a/x/ibc/04-channel/types/msgs_test.go b/x/ibc/04-channel/types/msgs_test.go index c57a35af74ad..3754ea4efa1a 100644 --- a/x/ibc/04-channel/types/msgs_test.go +++ b/x/ibc/04-channel/types/msgs_test.go @@ -3,9 +3,10 @@ package types import ( "testing" + "github.com/stretchr/testify/require" + sdk "github.com/cosmos/cosmos-sdk/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" - "github.com/stretchr/testify/require" ) // define constants used for testing @@ -38,21 +39,21 @@ var ( // TestMsgChannelOpenInit tests ValidateBasic for MsgChannelOpenInit func TestMsgChannelOpenInit(t *testing.T) { testMsgs := []MsgChannelOpenInit{ - NewMsgChannelOpenInit("testport", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // valid msg - NewMsgChannelOpenInit(invalidShortPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // too short port id - NewMsgChannelOpenInit(invalidLongPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // too long port id - NewMsgChannelOpenInit(invalidPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // port id contains non-alpha - NewMsgChannelOpenInit("testport", invalidShortChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // too short channel id - NewMsgChannelOpenInit("testport", invalidLongChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // too long channel id - NewMsgChannelOpenInit("testport", invalidChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // channel id contains non-alpha - NewMsgChannelOpenInit("testport", "testchannel", "1.0", Order(3), connHops, "testcpport", "testcpchannel", addr), // invalid channel order - NewMsgChannelOpenInit("testport", "testchannel", "1.0", ORDERED, invalidConnHops, "testcpport", "testcpchannel", addr), // connection hops more than 1 - NewMsgChannelOpenInit("testport", "testchannel", "1.0", UNORDERED, invalidShortConnHops, "testcpport", "testcpchannel", addr), // too short connection id - NewMsgChannelOpenInit("testport", "testchannel", "1.0", UNORDERED, invalidLongConnHops, "testcpport", "testcpchannel", addr), // too long connection id - NewMsgChannelOpenInit("testport", "testchannel", "1.0", UNORDERED, []string{invalidConnection}, "testcpport", "testcpchannel", addr), // connection id contains non-alpha - NewMsgChannelOpenInit("testport", "testchannel", "", UNORDERED, connHops, "testcpport", "testcpchannel", addr), // empty channel version - NewMsgChannelOpenInit("testport", "testchannel", "1.0", UNORDERED, connHops, invalidPort, "testcpchannel", addr), // invalid counterparty port id - NewMsgChannelOpenInit("testport", "testchannel", "1.0", UNORDERED, connHops, "testcpport", invalidChannel, addr), // invalid counterparty channel id + NewMsgChannelOpenInit("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // valid msg + NewMsgChannelOpenInit(invalidShortPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // too short port id + NewMsgChannelOpenInit(invalidLongPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // too long port id + NewMsgChannelOpenInit(invalidPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // port id contains non-alpha + NewMsgChannelOpenInit("testportid", invalidShortChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // too short channel id + NewMsgChannelOpenInit("testportid", invalidLongChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // too long channel id + NewMsgChannelOpenInit("testportid", invalidChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // channel id contains non-alpha + NewMsgChannelOpenInit("testportid", "testchannel", "1.0", Order(3), connHops, "testcpport", "testcpchannel", addr), // invalid channel order + NewMsgChannelOpenInit("testportid", "testchannel", "1.0", ORDERED, invalidConnHops, "testcpport", "testcpchannel", addr), // connection hops more than 1 + NewMsgChannelOpenInit("testportid", "testchannel", "1.0", UNORDERED, invalidShortConnHops, "testcpport", "testcpchannel", addr), // too short connection id + NewMsgChannelOpenInit("testportid", "testchannel", "1.0", UNORDERED, invalidLongConnHops, "testcpport", "testcpchannel", addr), // too long connection id + NewMsgChannelOpenInit("testportid", "testchannel", "1.0", UNORDERED, []string{invalidConnection}, "testcpport", "testcpchannel", addr), // connection id contains non-alpha + NewMsgChannelOpenInit("testportid", "testchannel", "", UNORDERED, connHops, "testcpport", "testcpchannel", addr), // empty channel version + NewMsgChannelOpenInit("testportid", "testchannel", "1.0", UNORDERED, connHops, invalidPort, "testcpchannel", addr), // invalid counterparty port id + NewMsgChannelOpenInit("testportid", "testchannel", "1.0", UNORDERED, connHops, "testcpport", invalidChannel, addr), // invalid counterparty channel id } testCases := []struct { @@ -90,24 +91,24 @@ func TestMsgChannelOpenInit(t *testing.T) { // TestMsgChannelOpenTry tests ValidateBasic for MsgChannelOpenTry func TestMsgChannelOpenTry(t *testing.T) { testMsgs := []MsgChannelOpenTry{ - NewMsgChannelOpenTry("testport", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // valid msg - NewMsgChannelOpenTry(invalidShortPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too short port id - NewMsgChannelOpenTry(invalidLongPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too long port id - NewMsgChannelOpenTry(invalidPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // port id contains non-alpha - NewMsgChannelOpenTry("testport", invalidShortChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too short channel id - NewMsgChannelOpenTry("testport", invalidLongChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too long channel id - NewMsgChannelOpenTry("testport", invalidChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // channel id contains non-alpha - NewMsgChannelOpenTry("testport", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "", proof, 1, addr), // empty counterparty version - NewMsgChannelOpenTry("testport", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", nil, 1, addr), // empty proof - NewMsgChannelOpenTry("testport", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 0, addr), // proof height is zero - NewMsgChannelOpenTry("testport", "testchannel", "1.0", Order(4), connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // invalid channel order - NewMsgChannelOpenTry("testport", "testchannel", "1.0", UNORDERED, invalidConnHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // connection hops more than 1 - NewMsgChannelOpenTry("testport", "testchannel", "1.0", UNORDERED, invalidShortConnHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too short connection id - NewMsgChannelOpenTry("testport", "testchannel", "1.0", UNORDERED, invalidLongConnHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too long connection id - NewMsgChannelOpenTry("testport", "testchannel", "1.0", UNORDERED, []string{invalidConnection}, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // connection id contains non-alpha - NewMsgChannelOpenTry("testport", "testchannel", "", UNORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // empty channel version - NewMsgChannelOpenTry("testport", "testchannel", "1.0", UNORDERED, connHops, invalidPort, "testcpchannel", "1.0", proof, 1, addr), // invalid counterparty port id - NewMsgChannelOpenTry("testport", "testchannel", "1.0", UNORDERED, connHops, "testcpport", invalidChannel, "1.0", proof, 1, addr), // invalid counterparty channel id + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // valid msg + NewMsgChannelOpenTry(invalidShortPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too short port id + NewMsgChannelOpenTry(invalidLongPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too long port id + NewMsgChannelOpenTry(invalidPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // port id contains non-alpha + NewMsgChannelOpenTry("testportid", invalidShortChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too short channel id + NewMsgChannelOpenTry("testportid", invalidLongChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too long channel id + NewMsgChannelOpenTry("testportid", invalidChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // channel id contains non-alpha + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "", proof, 1, addr), // empty counterparty version + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", nil, 1, addr), // empty proof + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 0, addr), // proof height is zero + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", Order(4), connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // invalid channel order + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, invalidConnHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // connection hops more than 1 + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, invalidShortConnHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too short connection id + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, invalidLongConnHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too long connection id + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, []string{invalidConnection}, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // connection id contains non-alpha + NewMsgChannelOpenTry("testportid", "testchannel", "", UNORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // empty channel version + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, connHops, invalidPort, "testcpchannel", "1.0", proof, 1, addr), // invalid counterparty port id + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, connHops, "testcpport", invalidChannel, "1.0", proof, 1, addr), // invalid counterparty channel id } testCases := []struct { @@ -148,16 +149,16 @@ func TestMsgChannelOpenTry(t *testing.T) { // TestMsgChannelOpenAck tests ValidateBasic for MsgChannelOpenAck func TestMsgChannelOpenAck(t *testing.T) { testMsgs := []MsgChannelOpenAck{ - NewMsgChannelOpenAck("testport", "testchannel", "1.0", proof, 1, addr), // valid msg - NewMsgChannelOpenAck(invalidShortPort, "testchannel", "1.0", proof, 1, addr), // too short port id - NewMsgChannelOpenAck(invalidLongPort, "testchannel", "1.0", proof, 1, addr), // too long port id - NewMsgChannelOpenAck(invalidPort, "testchannel", "1.0", proof, 1, addr), // port id contains non-alpha - NewMsgChannelOpenAck("testport", invalidShortChannel, "1.0", proof, 1, addr), // too short channel id - NewMsgChannelOpenAck("testport", invalidLongChannel, "1.0", proof, 1, addr), // too long channel id - NewMsgChannelOpenAck("testport", invalidChannel, "1.0", proof, 1, addr), // channel id contains non-alpha - NewMsgChannelOpenAck("testport", "testchannel", "", proof, 1, addr), // empty counterparty version - NewMsgChannelOpenAck("testport", "testchannel", "1.0", nil, 1, addr), // empty proof - NewMsgChannelOpenAck("testport", "testchannel", "1.0", proof, 0, addr), // proof height is zero + NewMsgChannelOpenAck("testportid", "testchannel", "1.0", proof, 1, addr), // valid msg + NewMsgChannelOpenAck(invalidShortPort, "testchannel", "1.0", proof, 1, addr), // too short port id + NewMsgChannelOpenAck(invalidLongPort, "testchannel", "1.0", proof, 1, addr), // too long port id + NewMsgChannelOpenAck(invalidPort, "testchannel", "1.0", proof, 1, addr), // port id contains non-alpha + NewMsgChannelOpenAck("testportid", invalidShortChannel, "1.0", proof, 1, addr), // too short channel id + NewMsgChannelOpenAck("testportid", invalidLongChannel, "1.0", proof, 1, addr), // too long channel id + NewMsgChannelOpenAck("testportid", invalidChannel, "1.0", proof, 1, addr), // channel id contains non-alpha + NewMsgChannelOpenAck("testportid", "testchannel", "", proof, 1, addr), // empty counterparty version + NewMsgChannelOpenAck("testportid", "testchannel", "1.0", nil, 1, addr), // empty proof + NewMsgChannelOpenAck("testportid", "testchannel", "1.0", proof, 0, addr), // proof height is zero } testCases := []struct { @@ -190,15 +191,15 @@ func TestMsgChannelOpenAck(t *testing.T) { // TestMsgChannelOpenConfirm tests ValidateBasic for MsgChannelOpenConfirm func TestMsgChannelOpenConfirm(t *testing.T) { testMsgs := []MsgChannelOpenConfirm{ - NewMsgChannelOpenConfirm("testport", "testchannel", proof, 1, addr), // valid msg - NewMsgChannelOpenConfirm(invalidShortPort, "testchannel", proof, 1, addr), // too short port id - NewMsgChannelOpenConfirm(invalidLongPort, "testchannel", proof, 1, addr), // too long port id - NewMsgChannelOpenConfirm(invalidPort, "testchannel", proof, 1, addr), // port id contains non-alpha - NewMsgChannelOpenConfirm("testport", invalidShortChannel, proof, 1, addr), // too short channel id - NewMsgChannelOpenConfirm("testport", invalidLongChannel, proof, 1, addr), // too long channel id - NewMsgChannelOpenConfirm("testport", invalidChannel, proof, 1, addr), // channel id contains non-alpha - NewMsgChannelOpenConfirm("testport", "testchannel", nil, 1, addr), // empty proof - NewMsgChannelOpenConfirm("testport", "testchannel", proof, 0, addr), // proof height is zero + NewMsgChannelOpenConfirm("testportid", "testchannel", proof, 1, addr), // valid msg + NewMsgChannelOpenConfirm(invalidShortPort, "testchannel", proof, 1, addr), // too short port id + NewMsgChannelOpenConfirm(invalidLongPort, "testchannel", proof, 1, addr), // too long port id + NewMsgChannelOpenConfirm(invalidPort, "testchannel", proof, 1, addr), // port id contains non-alpha + NewMsgChannelOpenConfirm("testportid", invalidShortChannel, proof, 1, addr), // too short channel id + NewMsgChannelOpenConfirm("testportid", invalidLongChannel, proof, 1, addr), // too long channel id + NewMsgChannelOpenConfirm("testportid", invalidChannel, proof, 1, addr), // channel id contains non-alpha + NewMsgChannelOpenConfirm("testportid", "testchannel", nil, 1, addr), // empty proof + NewMsgChannelOpenConfirm("testportid", "testchannel", proof, 0, addr), // proof height is zero } testCases := []struct { @@ -230,13 +231,13 @@ func TestMsgChannelOpenConfirm(t *testing.T) { // TestMsgChannelCloseInit tests ValidateBasic for MsgChannelCloseInit func TestMsgChannelCloseInit(t *testing.T) { testMsgs := []MsgChannelCloseInit{ - NewMsgChannelCloseInit("testport", "testchannel", addr), // valid msg - NewMsgChannelCloseInit(invalidShortPort, "testchannel", addr), // too short port id - NewMsgChannelCloseInit(invalidLongPort, "testchannel", addr), // too long port id - NewMsgChannelCloseInit(invalidPort, "testchannel", addr), // port id contains non-alpha - NewMsgChannelCloseInit("testport", invalidShortChannel, addr), // too short channel id - NewMsgChannelCloseInit("testport", invalidLongChannel, addr), // too long channel id - NewMsgChannelCloseInit("testport", invalidChannel, addr), // channel id contains non-alpha + NewMsgChannelCloseInit("testportid", "testchannel", addr), // valid msg + NewMsgChannelCloseInit(invalidShortPort, "testchannel", addr), // too short port id + NewMsgChannelCloseInit(invalidLongPort, "testchannel", addr), // too long port id + NewMsgChannelCloseInit(invalidPort, "testchannel", addr), // port id contains non-alpha + NewMsgChannelCloseInit("testportid", invalidShortChannel, addr), // too short channel id + NewMsgChannelCloseInit("testportid", invalidLongChannel, addr), // too long channel id + NewMsgChannelCloseInit("testportid", invalidChannel, addr), // channel id contains non-alpha } testCases := []struct { @@ -266,15 +267,15 @@ func TestMsgChannelCloseInit(t *testing.T) { // TestMsgChannelCloseConfirm tests ValidateBasic for MsgChannelCloseConfirm func TestMsgChannelCloseConfirm(t *testing.T) { testMsgs := []MsgChannelCloseConfirm{ - NewMsgChannelCloseConfirm("testport", "testchannel", proof, 1, addr), // valid msg - NewMsgChannelCloseConfirm(invalidShortPort, "testchannel", proof, 1, addr), // too short port id - NewMsgChannelCloseConfirm(invalidLongPort, "testchannel", proof, 1, addr), // too long port id - NewMsgChannelCloseConfirm(invalidPort, "testchannel", proof, 1, addr), // port id contains non-alpha - NewMsgChannelCloseConfirm("testport", invalidShortChannel, proof, 1, addr), // too short channel id - NewMsgChannelCloseConfirm("testport", invalidLongChannel, proof, 1, addr), // too long channel id - NewMsgChannelCloseConfirm("testport", invalidChannel, proof, 1, addr), // channel id contains non-alpha - NewMsgChannelCloseConfirm("testport", "testchannel", nil, 1, addr), // empty proof - NewMsgChannelCloseConfirm("testport", "testchannel", proof, 0, addr), // proof height is zero + NewMsgChannelCloseConfirm("testportid", "testchannel", proof, 1, addr), // valid msg + NewMsgChannelCloseConfirm(invalidShortPort, "testchannel", proof, 1, addr), // too short port id + NewMsgChannelCloseConfirm(invalidLongPort, "testchannel", proof, 1, addr), // too long port id + NewMsgChannelCloseConfirm(invalidPort, "testchannel", proof, 1, addr), // port id contains non-alpha + NewMsgChannelCloseConfirm("testportid", invalidShortChannel, proof, 1, addr), // too short channel id + NewMsgChannelCloseConfirm("testportid", invalidLongChannel, proof, 1, addr), // too long channel id + NewMsgChannelCloseConfirm("testportid", invalidChannel, proof, 1, addr), // channel id contains non-alpha + NewMsgChannelCloseConfirm("testportid", "testchannel", nil, 1, addr), // empty proof + NewMsgChannelCloseConfirm("testportid", "testchannel", proof, 0, addr), // proof height is zero } testCases := []struct { diff --git a/x/ibc/04-channel/types/packet.go b/x/ibc/04-channel/types/packet.go index 8d170cc62a9d..8cfadf458487 100644 --- a/x/ibc/04-channel/types/packet.go +++ b/x/ibc/04-channel/types/packet.go @@ -3,7 +3,6 @@ package types import ( "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" ) @@ -37,29 +36,29 @@ func NewPacket( } } -// Sequence implements PacketI interface +// GetSequence implements PacketI interface func (p Packet) GetSequence() uint64 { return p.Sequence } -// TimeoutHeight implements PacketI interface +// GetTimeoutHeight implements PacketI interface func (p Packet) GetTimeoutHeight() uint64 { return p.Timeout } -// SourcePort implements PacketI interface +// GetSourcePort implements PacketI interface func (p Packet) GetSourcePort() string { return p.SourcePort } -// SourceChannel implements PacketI interface +// GetSourceChannel implements PacketI interface func (p Packet) GetSourceChannel() string { return p.SourceChannel } -// DestPort implements PacketI interface +// GetDestPort implements PacketI interface func (p Packet) GetDestPort() string { return p.DestinationPort } -// DestChannel implements PacketI interface +// GetDestChannel implements PacketI interface func (p Packet) GetDestChannel() string { return p.DestinationChannel } -// Data implements PacketI interface +// GetData implements PacketI interface func (p Packet) GetData() []byte { return p.Data } // ValidateBasic implements PacketI interface -func (p Packet) ValidateBasic() sdk.Error { +func (p Packet) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(p.SourcePort); err != nil { return ErrInvalidPacket(DefaultCodespace, fmt.Sprintf("invalid source port ID: %s", err.Error())) } @@ -104,5 +103,5 @@ func NewOpaquePacket(sequence, timeout uint64, sourcePort, sourceChannel, return OpaquePacket{&Packet} } -// Data implements PacketI interface +// GetData implements PacketI interface func (op OpaquePacket) GetData() []byte { return nil } diff --git a/x/ibc/05-port/alias.go b/x/ibc/05-port/alias.go index a74c7fe61537..de0907a93212 100644 --- a/x/ibc/05-port/alias.go +++ b/x/ibc/05-port/alias.go @@ -12,26 +12,22 @@ import ( ) const ( - DefaultCodespace = types.DefaultCodespace - CodePortExists = types.CodePortExists - CodePortNotFound = types.CodePortNotFound - CodePortNotAuthenticated = types.CodePortNotAuthenticated - CodeInvalidPortID = types.CodeInvalidPortID - SubModuleName = types.SubModuleName - StoreKey = types.StoreKey - RouterKey = types.RouterKey - QuerierRoute = types.QuerierRoute + DefaultCodespace = types.DefaultCodespace + CodePortExists = types.CodePortExists + CodePortNotFound = types.CodePortNotFound + SubModuleName = types.SubModuleName + StoreKey = types.StoreKey + RouterKey = types.RouterKey + QuerierRoute = types.QuerierRoute ) var ( // functions aliases - NewKeeper = keeper.NewKeeper - ErrPortExists = types.ErrPortExists - ErrPortNotFound = types.ErrPortNotFound - ErrPortNotAuthenticated = types.ErrPortNotAuthenticated - ErrInvalidPortID = types.ErrInvalidPortID - PortPath = types.PortPath - KeyPort = types.KeyPort + NewKeeper = keeper.NewKeeper + ErrPortExists = types.ErrPortExists + ErrPortNotFound = types.ErrPortNotFound + PortPath = types.PortPath + KeyPort = types.KeyPort ) type ( diff --git a/x/ibc/05-port/keeper/keeper.go b/x/ibc/05-port/keeper/keeper.go index cdb48010237f..54e5e1ad13de 100644 --- a/x/ibc/05-port/keeper/keeper.go +++ b/x/ibc/05-port/keeper/keeper.go @@ -14,9 +14,7 @@ type Keeper struct { storeKey sdk.StoreKey cdc *codec.Codec codespace sdk.CodespaceType - prefix []byte // prefix bytes for accessing the store - ports map[string]string - bound []string + ports map[string]bool } // NewKeeper creates a new IBC connection Keeper instance @@ -25,22 +23,13 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType) storeKey: key, cdc: cdc, codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/port", - prefix: []byte{}, - // prefix: []byte(types.SubModuleName + "/"), // "port/" - ports: make(map[string]string), // map of capability key names to port ids + ports: make(map[string]bool), // map of capability key names to port ids } } -// GetPorts returns the list of bound ports. -// (these ports still must have been bound statically) -func (k Keeper) GetPorts() []string { - return k.bound -} - -// GetPort retrieves a given port ID from keeper map -func (k Keeper) GetPort(ck sdk.CapabilityKey) (string, bool) { - portID, found := k.ports[ck.Name()] - return portID, found +// isBounded checks a given port ID is already bounded. +func (k Keeper) isBounded(portID string) bool { + return k.ports[portID] } // BindPort binds to a port and returns the associated capability. @@ -52,15 +41,13 @@ func (k Keeper) BindPort(portID string) sdk.CapabilityKey { panic(err.Error()) } - for _, b := range k.bound { - if b == portID { - panic(fmt.Sprintf("port %s is already bound", portID)) - } + if k.isBounded(portID) { + panic(fmt.Sprintf("port %s is already bound", portID)) } key := sdk.NewKVStoreKey(portID) - k.ports[key.Name()] = portID - k.bound = append(k.bound, portID) + k.ports[key.Name()] = true // NOTE: key name and value always match + return key } @@ -73,5 +60,5 @@ func (k Keeper) Authenticate(key sdk.CapabilityKey, portID string) bool { panic(err.Error()) } - return k.ports[key.Name()] == portID + return k.ports[key.Name()] } diff --git a/x/ibc/05-port/types/errors.go b/x/ibc/05-port/types/errors.go index 20031c826107..d15b07bf0791 100644 --- a/x/ibc/05-port/types/errors.go +++ b/x/ibc/05-port/types/errors.go @@ -4,34 +4,41 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // port error codes const ( DefaultCodespace sdk.CodespaceType = SubModuleName - CodePortExists sdk.CodeType = 101 - CodePortNotFound sdk.CodeType = 102 - CodePortNotAuthenticated sdk.CodeType = 103 - CodeInvalidPortID sdk.CodeType = 104 + CodePortExists sdk.CodeType = 228 + CodePortNotFound sdk.CodeType = 229 + CodeInvalidPort sdk.CodeType = 230 ) // ErrPortExists implements sdk.Error -func ErrPortExists(codespace sdk.CodespaceType, portID string) sdk.Error { - return sdk.NewError(codespace, CodePortExists, fmt.Sprintf("port with ID %s is already binded", portID)) +func ErrPortExists(codespace sdk.CodespaceType, portID string) error { + return sdkerrors.New( + string(codespace), + uint32(CodePortExists), + fmt.Sprintf("port with ID %s is already binded", portID), + ) } // ErrPortNotFound implements sdk.Error -func ErrPortNotFound(codespace sdk.CodespaceType, portID string) sdk.Error { - return sdk.NewError(codespace, CodePortNotFound, fmt.Sprintf("port with ID %s not found", portID)) +func ErrPortNotFound(codespace sdk.CodespaceType, portID string) error { + return sdkerrors.New( + string(codespace), + uint32(CodePortNotFound), + fmt.Sprintf("port with ID %s not found", portID), + ) } -// ErrPortNotAuthenticated implements sdk.Error -func ErrPortNotAuthenticated(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodePortNotAuthenticated, "port failed authentication") -} - -// ErrInvalidPortID implements sdk.Error -func ErrInvalidPortID(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidPortID, "invalid port ID") +// ErrInvalidPort implements sdk.Error +func ErrInvalidPort(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodePortNotFound), + msg, + ) } diff --git a/x/ibc/20-transfer/alias.go b/x/ibc/20-transfer/alias.go index 66028740581e..ab75c9dab2d2 100644 --- a/x/ibc/20-transfer/alias.go +++ b/x/ibc/20-transfer/alias.go @@ -12,36 +12,23 @@ import ( ) const ( - DefaultPacketTimeout = keeper.DefaultPacketTimeout - DefaultCodespace = types.DefaultCodespace - CodeInvalidAddress = types.CodeInvalidAddress - CodeErrSendPacket = types.CodeErrSendPacket - CodeInvalidPacketData = types.CodeInvalidPacketData - CodeInvalidChannelOrder = types.CodeInvalidChannelOrder - CodeInvalidPort = types.CodeInvalidPort - CodeInvalidVersion = types.CodeInvalidVersion - AttributeKeyReceiver = types.AttributeKeyReceiver - SubModuleName = types.SubModuleName - StoreKey = types.StoreKey - RouterKey = types.RouterKey - QuerierRoute = types.QuerierRoute - BoundPortID = types.BoundPortID + DefaultPacketTimeout = keeper.DefaultPacketTimeout + DefaultCodespace = types.DefaultCodespace + AttributeKeyReceiver = types.AttributeKeyReceiver + SubModuleName = types.SubModuleName + StoreKey = types.StoreKey + RouterKey = types.RouterKey + QuerierRoute = types.QuerierRoute ) var ( // functions aliases - NewKeeper = keeper.NewKeeper - RegisterCodec = types.RegisterCodec - ErrInvalidAddress = types.ErrInvalidAddress - ErrSendPacket = types.ErrSendPacket - ErrInvalidPacketData = types.ErrInvalidPacketData - ErrInvalidChannelOrder = types.ErrInvalidChannelOrder - ErrInvalidPort = types.ErrInvalidPort - ErrInvalidVersion = types.ErrInvalidVersion - GetEscrowAddress = types.GetEscrowAddress - GetDenomPrefix = types.GetDenomPrefix - GetModuleAccountName = types.GetModuleAccountName - NewMsgTransfer = types.NewMsgTransfer + NewKeeper = keeper.NewKeeper + RegisterCodec = types.RegisterCodec + GetEscrowAddress = types.GetEscrowAddress + GetDenomPrefix = types.GetDenomPrefix + GetModuleAccountName = types.GetModuleAccountName + NewMsgTransfer = types.NewMsgTransfer // variable aliases ModuleCdc = types.ModuleCdc diff --git a/x/ibc/20-transfer/client/cli/query.go b/x/ibc/20-transfer/client/cli/query.go index 4be0103385ee..6aad7157e228 100644 --- a/x/ibc/20-transfer/client/cli/query.go +++ b/x/ibc/20-transfer/client/cli/query.go @@ -7,12 +7,13 @@ import ( "github.com/spf13/cobra" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/version" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" - abci "github.com/tendermint/tendermint/abci/types" ) // GetQueryCmd returns the query commands for IBC fungible token transfer diff --git a/x/ibc/20-transfer/keeper/callbacks.go b/x/ibc/20-transfer/keeper/callbacks.go index 8594783e6456..444e966b97c8 100644 --- a/x/ibc/20-transfer/keeper/callbacks.go +++ b/x/ibc/20-transfer/keeper/callbacks.go @@ -5,8 +5,11 @@ import ( "strings" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" + porttypes "github.com/cosmos/cosmos-sdk/x/ibc/05-port/types" "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer/types" + ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" ) // nolint: unused @@ -20,15 +23,19 @@ func (k Keeper) onChanOpenInit( version string, ) error { if order != channeltypes.UNORDERED { - return types.ErrInvalidChannelOrder(k.codespace, order.String()) + return channeltypes.ErrInvalidChannel(k.codespace, "channel must be UNORDERED") } - if counterparty.PortID != types.BoundPortID { - return types.ErrInvalidPort(k.codespace, portID) + // NOTE: here the capability key name defines the port ID of the counterparty + if counterparty.PortID != k.boundedCapability.Name() { + return porttypes.ErrInvalidPort( + k.codespace, + fmt.Sprintf("counterparty port ID doesn't match the capability key (%s ≠ %s)", portID, k.boundedCapability.Name()), + ) } if strings.TrimSpace(version) != "" { - return types.ErrInvalidVersion(k.codespace, fmt.Sprintf("invalid version: %s", version)) + return ibctypes.ErrInvalidVersion(k.codespace, "version cannot be blank") } // NOTE: as the escrow address is generated from both the port and channel IDs @@ -48,19 +55,23 @@ func (k Keeper) onChanOpenTry( counterpartyVersion string, ) error { if order != channeltypes.UNORDERED { - return types.ErrInvalidChannelOrder(k.codespace, order.String()) + return channeltypes.ErrInvalidChannel(k.codespace, "channel must be UNORDERED") } - if counterparty.PortID != types.BoundPortID { - return types.ErrInvalidPort(k.codespace, portID) + // NOTE: here the capability key name defines the port ID of the counterparty + if counterparty.PortID != k.boundedCapability.Name() { + return porttypes.ErrInvalidPort( + k.codespace, + fmt.Sprintf("counterparty port ID doesn't match the capability key (%s ≠ %s)", portID, k.boundedCapability.Name()), + ) } if strings.TrimSpace(version) != "" { - return types.ErrInvalidVersion(k.codespace, fmt.Sprintf("invalid version: %s", version)) + return ibctypes.ErrInvalidVersion(k.codespace, "version cannot be blank") } if strings.TrimSpace(counterpartyVersion) != "" { - return types.ErrInvalidVersion(k.codespace, fmt.Sprintf("invalid counterparty version: %s", version)) + return ibctypes.ErrInvalidVersion(k.codespace, "counterparty version cannot be blank") } // NOTE: as the escrow address is generated from both the port and channel IDs @@ -76,7 +87,7 @@ func (k Keeper) onChanOpenAck( version string, ) error { if strings.TrimSpace(version) != "" { - return types.ErrInvalidVersion(k.codespace, fmt.Sprintf("invalid version: %s", version)) + return ibctypes.ErrInvalidVersion(k.codespace, "version cannot be blank") } return nil @@ -122,7 +133,7 @@ func (k Keeper) onRecvPacket( err := data.UnmarshalJSON(packet.GetData()) if err != nil { - return types.ErrInvalidPacketData(k.codespace) + return sdkerrors.Wrap(err, "invalid packet data") } return k.ReceiveTransfer( @@ -150,7 +161,7 @@ func (k Keeper) onTimeoutPacket( err := data.UnmarshalJSON(packet.GetData()) if err != nil { - return types.ErrInvalidPacketData(k.codespace) + return sdkerrors.Wrap(err, "invalid packet data") } // check the denom prefix diff --git a/x/ibc/20-transfer/keeper/keeper.go b/x/ibc/20-transfer/keeper/keeper.go index 95576d4609f3..c42786f42741 100644 --- a/x/ibc/20-transfer/keeper/keeper.go +++ b/x/ibc/20-transfer/keeper/keeper.go @@ -22,7 +22,9 @@ type Keeper struct { storeKey sdk.StoreKey cdc *codec.Codec codespace sdk.CodespaceType - prefix []byte // prefix bytes for accessing the store + + // Capability key and port to which ICS20 is binded. Used for packet relaying. + boundedCapability sdk.CapabilityKey clientKeeper types.ClientKeeper connectionKeeper types.ConnectionKeeper @@ -34,9 +36,9 @@ type Keeper struct { // NewKeeper creates a new IBC transfer Keeper instance func NewKeeper( cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType, - clientKeeper types.ClientKeeper, connnectionKeeper types.ConnectionKeeper, - channelKeeper types.ChannelKeeper, bankKeeper types.BankKeeper, - supplyKeeper types.SupplyKeeper, + capKey sdk.CapabilityKey, clientKeeper types.ClientKeeper, + connnectionKeeper types.ConnectionKeeper, channelKeeper types.ChannelKeeper, + bankKeeper types.BankKeeper, supplyKeeper types.SupplyKeeper, ) Keeper { // ensure ibc transfer module account is set @@ -45,15 +47,15 @@ func NewKeeper( } return Keeper{ - storeKey: key, - cdc: cdc, - codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/transfer", - prefix: []byte(types.SubModuleName + "/"), // "transfer/" - clientKeeper: clientKeeper, - connectionKeeper: connnectionKeeper, - channelKeeper: channelKeeper, - bankKeeper: bankKeeper, - supplyKeeper: supplyKeeper, + storeKey: key, + cdc: cdc, + codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/transfer", + boundedCapability: capKey, + clientKeeper: clientKeeper, + connectionKeeper: connnectionKeeper, + channelKeeper: channelKeeper, + bankKeeper: bankKeeper, + supplyKeeper: supplyKeeper, } } diff --git a/x/ibc/20-transfer/keeper/relay.go b/x/ibc/20-transfer/keeper/relay.go index d87a589bbd80..dae2180dc44f 100644 --- a/x/ibc/20-transfer/keeper/relay.go +++ b/x/ibc/20-transfer/keeper/relay.go @@ -5,6 +5,7 @@ import ( "strings" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer/types" @@ -61,7 +62,7 @@ func (k Keeper) ReceivePacket(ctx sdk.Context, packet channelexported.PacketI, p var data types.PacketData err = data.UnmarshalJSON(packet.GetData()) if err != nil { - return sdk.NewError(types.DefaultCodespace, types.CodeInvalidPacketData, "invalid packet data") + return sdkerrors.Wrap(err, "invalid packet data") } return k.ReceiveTransfer(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetDestPort(), packet.GetDestChannel(), data) @@ -173,7 +174,7 @@ func (k Keeper) createOutgoingPacket( // TODO: This should be binary-marshaled and hashed (for the commitment in the store). packetDataBz, err := packetData.MarshalJSON() if err != nil { - return sdk.NewError(sdk.CodespaceType(types.DefaultCodespace), types.CodeInvalidPacketData, "invalid packet data") + return sdkerrors.Wrap(err, "invalid packet data") } packet := channeltypes.NewPacket( @@ -186,8 +187,5 @@ func (k Keeper) createOutgoingPacket( packetDataBz, ) - // TODO: Remove this, capability keys are never generated when sending packets. Not sure why this is here. - key := sdk.NewKVStoreKey(types.BoundPortID) - - return k.channelKeeper.SendPacket(ctx, packet, key) + return k.channelKeeper.SendPacket(ctx, packet, k.boundedCapability) } diff --git a/x/ibc/20-transfer/types/errors.go b/x/ibc/20-transfer/types/errors.go deleted file mode 100644 index 51f95d560a01..000000000000 --- a/x/ibc/20-transfer/types/errors.go +++ /dev/null @@ -1,51 +0,0 @@ -package types - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// transfer error codes -const ( - DefaultCodespace sdk.CodespaceType = SubModuleName - - CodeInvalidAddress sdk.CodeType = 101 - CodeErrSendPacket sdk.CodeType = 102 - CodeInvalidPacketData sdk.CodeType = 103 - CodeInvalidChannelOrder sdk.CodeType = 104 - CodeInvalidPort sdk.CodeType = 105 - CodeInvalidVersion sdk.CodeType = 106 - CodeProofMissing sdk.CodeType = 107 - CodeInvalidHeight sdk.CodeType = 108 -) - -// ErrInvalidAddress implements sdk.Error -func ErrInvalidAddress(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidAddress, msg) -} - -// ErrSendPacket implements sdk.Error -func ErrSendPacket(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeErrSendPacket, "failed to send packet") -} - -// ErrInvalidPacketData implements sdk.Error -func ErrInvalidPacketData(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidPacketData, "invalid packet data") -} - -// ErrInvalidChannelOrder implements sdk.Error -func ErrInvalidChannelOrder(codespace sdk.CodespaceType, order string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidChannelOrder, fmt.Sprintf("invalid channel order: %s", order)) -} - -// ErrInvalidPort implements sdk.Error -func ErrInvalidPort(codespace sdk.CodespaceType, portID string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidPort, fmt.Sprintf("invalid port ID: %s", portID)) -} - -// ErrInvalidVersion implements sdk.Error -func ErrInvalidVersion(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidVersion, msg) -} diff --git a/x/ibc/20-transfer/types/keys.go b/x/ibc/20-transfer/types/keys.go index 09b54dcadea5..469456bbd946 100644 --- a/x/ibc/20-transfer/types/keys.go +++ b/x/ibc/20-transfer/types/keys.go @@ -22,8 +22,8 @@ const ( // QuerierRoute is the querier route for IBC transfer QuerierRoute = SubModuleName - // BoundPortID defines the name of the capability key - BoundPortID = "bank" + // DefaultCodespace is the default error codespace for the ibc transfers + DefaultCodespace sdk.CodespaceType = SubModuleName ) // GetEscrowAddress returns the escrow address for the specified channel diff --git a/x/ibc/20-transfer/types/msgs.go b/x/ibc/20-transfer/types/msgs.go index 506676e66d7e..d0e7d9fbbe72 100644 --- a/x/ibc/20-transfer/types/msgs.go +++ b/x/ibc/20-transfer/types/msgs.go @@ -1,13 +1,12 @@ package types import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" - + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types" channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" ) @@ -46,11 +45,11 @@ func (MsgTransfer) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgTransfer) ValidateBasic() sdk.Error { - if err := host.DefaultPortIdentifierValidator(msg.SourcePort); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid port ID: %s", err.Error())) + if err := host.DefaultConnectionIdentifierValidator(msg.SourcePort); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid source port ID")) } - if err := host.DefaultPortIdentifierValidator(msg.SourceChannel); err != nil { - return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid channel ID: %s", err.Error())) + if err := host.DefaultClientIdentifierValidator(msg.SourceChannel); err != nil { + return sdk.ConvertError(sdkerrors.Wrap(err, "invalid source channel ID")) } if !msg.Amount.IsValid() { return sdk.ErrInvalidCoins("transfer amount is invalid") @@ -106,25 +105,25 @@ func (MsgRecvPacket) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgRecvPacket) ValidateBasic() sdk.Error { - if msg.Height < 1 { - return sdk.NewError(DefaultCodespace, CodeInvalidHeight, "invalid height") + if msg.Height == 0 { + return sdk.ConvertError(connectiontypes.ErrInvalidHeight(DefaultCodespace, "height must be > 0")) } - if msg.Proofs == nil { - return sdk.NewError(DefaultCodespace, CodeProofMissing, "proof missing") + if msg.Proofs == nil || len(msg.Proofs) == 0 { + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "missing proofs")) } for _, proof := range msg.Proofs { if proof.Proof == nil { - return sdk.NewError(DefaultCodespace, CodeProofMissing, "proof missing") + return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "cannot submit an empty proof")) } } if msg.Signer.Empty() { - return sdk.NewError(DefaultCodespace, CodeInvalidAddress, "invalid signer") + return sdk.ErrInvalidAddress("missing signer address") } - return msg.Packet.ValidateBasic() + return sdk.ConvertError(msg.Packet.ValidateBasic()) } // GetSignBytes implements sdk.Msg diff --git a/x/ibc/23-commitment/merkle.go b/x/ibc/23-commitment/merkle.go index ab428eeaf737..3c41559f4b4f 100644 --- a/x/ibc/23-commitment/merkle.go +++ b/x/ibc/23-commitment/merkle.go @@ -2,6 +2,7 @@ package commitment import ( "errors" + "net/url" "github.com/tendermint/tendermint/crypto/merkle" @@ -90,9 +91,13 @@ func (Path) GetCommitmentType() Type { return Merkle } -// String implements fmt.Stringer +// String implements fmt.Stringer. It returns unescaped path of the URL string. func (p Path) String() string { - return p.KeyPath.String() + path, err := url.PathUnescape(p.KeyPath.String()) + if err != nil { + panic(err) + } + return path } // ApplyPrefix constructs a new commitment path from the arguments. It interprets diff --git a/x/ibc/24-host/errors.go b/x/ibc/24-host/errors.go index e6a526e6d0f8..0ff6ad59d896 100644 --- a/x/ibc/24-host/errors.go +++ b/x/ibc/24-host/errors.go @@ -1,22 +1,47 @@ package host import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// IBCCodeSpace is the codespace for all errors defined in the ibc module -const IBCCodeSpace = "ibc" +// SubModuleName defines the ICS 24 host +const SubModuleName = "host" + +// Error codes specific to the ibc host submodule +const ( + DefaultCodespace sdk.CodespaceType = SubModuleName -var ( - // ErrInvalidID is returned if identifier string is invalid - ErrInvalidID = sdkerrors.Register(IBCCodeSpace, 1, "invalid identifier") + CodeInvalidID sdk.CodeType = 231 + CodeInvalidPath sdk.CodeType = 232 + CodeInvalidPacket sdk.CodeType = 233 +) - // ErrInvalidPath is returned if path string is invalid - ErrInvalidPath = sdkerrors.Register(IBCCodeSpace, 2, "invalid path") +// ErrInvalidID returns a typed ABCI error for an invalid identifier +func ErrInvalidID(codespace sdk.CodespaceType, id string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidID), + fmt.Sprintf("invalid identifier '%s'", id), + ) +} - // ErrInvalidEvidence is returned if evidence is invalid - ErrInvalidEvidence = sdkerrors.Register(IBCCodeSpace, 3, "invalid evidence") +// ErrInvalidPath returns a typed ABCI error for an invalid path +func ErrInvalidPath(codespace sdk.CodespaceType, path string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidPath), + fmt.Sprintf("invalid path '%s'", path), + ) +} - // ErrInvalidPacket is returned if packets embedded in msg are invalid - ErrInvalidPacket = sdkerrors.Register(IBCCodeSpace, 4, "invalid packet extracted from msg") -) +// ErrInvalidPacket returns a typed ABCI error for an invalid identifier +func ErrInvalidPacket(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidPacket), + fmt.Sprintf("invalid packet: '%s'", msg), + ) +} diff --git a/x/ibc/24-host/validate.go b/x/ibc/24-host/validate.go index 6632d27c25c1..8c20c0065282 100644 --- a/x/ibc/24-host/validate.go +++ b/x/ibc/24-host/validate.go @@ -25,15 +25,15 @@ type ValidateFn func(string) error func defaultIdentifierValidator(id string, min, max int) error { // valid id MUST NOT contain "/" separator if strings.Contains(id, "/") { - return sdkerrors.Wrap(ErrInvalidID, "identifier cannot contain separator: /") + return sdkerrors.Wrap(ErrInvalidID(DefaultCodespace, id), "identifier cannot contain separator: /") } // valid id must be between 10 and 20 characters if len(id) < min || len(id) > max { - return sdkerrors.Wrapf(ErrInvalidID, "identifier has invalid length: %d, must be between %d-%d characters", len(id), min, max) + return sdkerrors.Wrapf(ErrInvalidID(DefaultCodespace, id), "identifier has invalid length: %d, must be between %d-%d characters", len(id), min, max) } // valid id must contain only lower alphabetic characters if !isAlphaLower(id) { - return sdkerrors.Wrap(ErrInvalidID, "identifier must contain only lowercase alphabetic characters") + return sdkerrors.Wrap(ErrInvalidID(DefaultCodespace, id), "identifier must contain only lowercase alphabetic characters") } return nil } @@ -76,7 +76,7 @@ func NewPathValidator(idValidator ValidateFn) ValidateFn { // Each path element must either be valid identifier or alphanumeric err := idValidator(p) if err != nil && !isAlphaNumeric(p) { - return sdkerrors.Wrapf(ErrInvalidPath, "path contains invalid identifier or non-alphanumeric path element: %s", p) + return sdkerrors.Wrapf(ErrInvalidPath(DefaultCodespace, path), "path contains invalid identifier or non-alphanumeric path element: %s", p) } } return nil @@ -91,7 +91,7 @@ func DefaultPathValidator(path string) error { for _, p := range pathArr { // Each path element must either be alphanumeric if !isAlphaNumeric(p) { - return sdkerrors.Wrapf(ErrInvalidPath, "invalid path element containing non-alphanumeric characters: %s", p) + return sdkerrors.Wrapf(ErrInvalidPath(DefaultCodespace, path), "invalid path element containing non-alphanumeric characters: %s", p) } } return nil diff --git a/x/ibc/keeper/keeper.go b/x/ibc/keeper/keeper.go index 2145416efb55..2c28b5c9dd51 100644 --- a/x/ibc/keeper/keeper.go +++ b/x/ibc/keeper/keeper.go @@ -3,6 +3,7 @@ package keeper import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" @@ -28,7 +29,13 @@ func NewKeeper( connectionKeeper := connection.NewKeeper(cdc, key, codespace, clientKeeper) portKeeper := port.NewKeeper(cdc, key, codespace) channelKeeper := channel.NewKeeper(cdc, key, codespace, clientKeeper, connectionKeeper, portKeeper) - transferKeeper := transfer.NewKeeper(cdc, key, codespace, clientKeeper, connectionKeeper, channelKeeper, bk, sk) + + // TODO: move out of IBC keeper. Blocked on ADR15 + capKey := portKeeper.BindPort(bank.ModuleName) + transferKeeper := transfer.NewKeeper( + cdc, key, codespace, capKey, + clientKeeper, connectionKeeper, channelKeeper, bk, sk, + ) return Keeper{ ClientKeeper: clientKeeper, diff --git a/x/ibc/keeper/querier_test.go b/x/ibc/keeper/querier_test.go index 62e37faac203..81abe9ffadb1 100644 --- a/x/ibc/keeper/querier_test.go +++ b/x/ibc/keeper/querier_test.go @@ -13,7 +13,7 @@ import ( ) // TestNewQuerier tests that the querier paths are correct. -// NOTE: the actuall testing functionallity are located on each ICS querier test. +// NOTE: the actuall testing functionality are located on each ICS querier test. func (suite *KeeperTestSuite) TestNewQuerier() { query := abci.RequestQuery{ diff --git a/x/ibc/types/errors.go b/x/ibc/types/errors.go new file mode 100644 index 000000000000..086851321b6a --- /dev/null +++ b/x/ibc/types/errors.go @@ -0,0 +1,33 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// common IBC error codes +const ( + // DefaultCodespace of the IBC module + DefaultCodespace sdk.CodespaceType = ModuleName + + CodeInvalidProof sdk.CodeType = 234 + CodeInvalidVersion sdk.CodeType = 235 +) + +// ErrInvalidProof implements sdk.Error +func ErrInvalidProof(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidProof), + msg, + ) +} + +// ErrInvalidVersion implements sdk.Error +func ErrInvalidVersion(codespace sdk.CodespaceType, msg string) error { + return sdkerrors.New( + string(codespace), + uint32(CodeInvalidVersion), + msg, + ) +} diff --git a/x/ibc/types/types.go b/x/ibc/types/types.go index bce43911994f..6722e5f3a426 100644 --- a/x/ibc/types/types.go +++ b/x/ibc/types/types.go @@ -1,9 +1,5 @@ package types -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - const ( // ModuleName is the name of the IBC module ModuleName = "ibc" @@ -16,7 +12,4 @@ const ( // RouterKey is the msg router key for the IBC module RouterKey string = ModuleName - - // DefaultCodespace of the IBC module - DefaultCodespace sdk.CodespaceType = ModuleName ) diff --git a/x/ibc/version/version.go b/x/ibc/version/version.go deleted file mode 100644 index a7d3275fae5b..000000000000 --- a/x/ibc/version/version.go +++ /dev/null @@ -1,13 +0,0 @@ -package version - -import "strconv" - -const Version int64 = 1 - -func DefaultPrefix() []byte { - return Prefix(Version) -} - -func Prefix(version int64) []byte { - return []byte("v" + strconv.FormatInt(version, 10) + "/") -}