From 428241256bee808532804ee9afbde98bdf522f67 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Tue, 5 Nov 2019 18:04:49 +0100 Subject: [PATCH] ICS 05 implementation (#5193) * fix lint * fix lint * add handler/msgs/client * rm relay * finalize rebase on 23 root/path sep * fix lint, fix syntax * fix querying * extract out context withstore * fix 02-client test * fix 23-commitment test * add query in progress * rm freebase, reformat query * add cli/handler/msg in progress * add cli/msg/handler * add CLIQuery, fix tests * fix golangci * add docs in progre * add comments * add comments * Apply suggestions from code review Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * add comments in progress * add comments * fix comment * add comments in progress * recover IntEncoding scheme for integer * add uint tests, don't use codec in custom types * finalize merge * add godoc * add godoc in progress * reformat test * rm XXX * add godoc * modify store * add query * update query.go * update query.go * cli refactor in progress * cli refactor in progress * add Query to boolean.go * fix key * fix cli / merkle test * godoc cleanup * godoc cleanup * godoc cleanup * godoc cleanup * godoc cleanup * fix test * fix client * merge from ics04 branch * merge from ics04 branch * merge from ics04 branch * merge from ics04 branch * fix lint * Apply suggestions from code review Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * applying review in progress * apply review - make querier interface * fix dependency * fix dependency * revise querier interface to work both on cli & store * revise querier interface to work both on cli & store * reflect downstream change * fix cli * reflect downstream changes * rm commented lines * address review in progress * address review, rm cleanup/closing * rename Path -> Prefix * Store accessor upstream changes (#5119) * Store accessor upstream changes (#5119) * add comments, reformat merkle querier * rm merkle/utils * ICS 23 upstream changes (#5120) * ICS 23 upstream changes (#5120) * update Value * update test * fix * ICS 02 upstream changes (#5122) * ICS 02 upstream changes (#5122) * ICS 03 upstream changes (#5123) * ICS 03 upstream changes (#5123) * cleanup types and submodule * more cleanup and godocs * remove counterPartyManager/State and cleanup * implement SubmitMisbehaviour and refactor * errors * events * fix test * refactors * WIP refactor ICS03 * remove Mapping * remove store accessors * proposed refactor * remove store accessors from ICS02 * refactor queriers, handler and clean keeper * logger and tx long description * ineffassign * Apply suggestions from code review Co-Authored-By: Jack Zampolin * Apply suggestions from code review Co-Authored-By: Jack Zampolin * remove store accessors * refactor handshake to update it to the latest ICS03 spec * update handler and msgs * add verification functions * update verification * ICS02 module.go * top level x/ibc structure * update connection queries * update connection tx * remove extra files * update expected client keeper and export verification funcs * ICS 05 Implementation * release port and godocs * Update x/ibc/02-client/client/cli/query.go Co-Authored-By: Jack Zampolin * Update x/ibc/02-client/types/tendermint/consensus_state.go Co-Authored-By: Jack Zampolin * address some of the review comments * resolve some TODOs and address comments from review * update connection versioning * minor error updates * update errors and add port Keeper to ibc Keeper * minor UX improvements * rename pkg * fixes * refactor ICS23 * cleanup types * ICS 5 updates (#5222) * Validate port identifiers * Refactor to static bind * Add comments * Add 'GetPorts' query function * rename pkg and fix import * implement batch verification * gosimple suggestion * various fixes; remove legacy tests; remove commitment path query * alias * minor updates from ICS23 * renaming * update verification and rename root funcs * move querier to x/ibc * update query.go to use 'custom/...' query path * add tests * ICS 24 Implementation (#5229) * add validation functions * validate path in ics-23 * address @fede comments * move errors into host package * flatten ICS23 structure * fix ApplyPrefix * updates from ICS23 and ICS24 * msg.ValidateBasic and ADR09 evidence interface * complete types testing * delete empty test file * remove ibc errors from core error package * custom JSON marshaling; msg.ValidateBasic; renaming of variables * minor update * custom JSON marshaling * use host validation for port ids * start batch-verify tests * minor changes on commitment types * R4R - Store consensus state correctly (#5242) * store consensus state correctly * fix client example * update alias * update alias * update alias and keeper.GetPort() * use testsuite * Integrate Evidence Implementation into ICS-02 (#5258) * implement evidence in ics-02 * fix build errors and import cycles * address fede comments * remove unnecessary pubkey and fix init * add tests * finish tendermint tests * complete merge * Add tests for msgs * upstream changes * fix * upstream changes * fix cons state * context changes * fix cli tx * upstream changes * upstream changes --- store/types/store.go | 4 ++ types/store.go | 1 + x/ibc/05-port/alias.go | 39 +++++++++++++++++ x/ibc/05-port/keeper/keeper.go | 77 ++++++++++++++++++++++++++++++++++ x/ibc/05-port/types/errors.go | 37 ++++++++++++++++ x/ibc/05-port/types/keys.go | 31 ++++++++++++++ x/ibc/keeper/keeper.go | 4 ++ 7 files changed, 193 insertions(+) create mode 100644 x/ibc/05-port/alias.go create mode 100644 x/ibc/05-port/keeper/keeper.go create mode 100644 x/ibc/05-port/types/errors.go create mode 100644 x/ibc/05-port/types/keys.go diff --git a/store/types/store.go b/store/types/store.go index 5b5e64742552..bd8a3d58c85a 100644 --- a/store/types/store.go +++ b/store/types/store.go @@ -277,6 +277,10 @@ type StoreKey interface { String() string } +// CapabilityKey represent the Cosmos SDK keys for object-capability +// generation in the IBC protocol as defined in https://github.com/cosmos/ics/tree/master/spec/ics-005-port-allocation#data-structures +type CapabilityKey StoreKey + // KVStoreKey is used for accessing substores. // Only the pointer value should ever be used - it functions as a capabilities key. type KVStoreKey struct { diff --git a/types/store.go b/types/store.go index c34b6d437d09..db18b127b69d 100644 --- a/types/store.go +++ b/types/store.go @@ -69,6 +69,7 @@ const ( // nolint - reexport type ( StoreKey = types.StoreKey + CapabilityKey = types.CapabilityKey KVStoreKey = types.KVStoreKey TransientStoreKey = types.TransientStoreKey ) diff --git a/x/ibc/05-port/alias.go b/x/ibc/05-port/alias.go new file mode 100644 index 000000000000..a74c7fe61537 --- /dev/null +++ b/x/ibc/05-port/alias.go @@ -0,0 +1,39 @@ +package port + +// nolint +// autogenerated code using github.com/rigelrozanski/multitool +// aliases generated for the following subdirectories: +// ALIASGEN: github.com/cosmos/cosmos-sdk/x/ibc/05-port/keeper +// ALIASGEN: github.com/cosmos/cosmos-sdk/x/ibc/05-port/types + +import ( + "github.com/cosmos/cosmos-sdk/x/ibc/05-port/keeper" + "github.com/cosmos/cosmos-sdk/x/ibc/05-port/types" +) + +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 +) + +var ( + // functions aliases + NewKeeper = keeper.NewKeeper + ErrPortExists = types.ErrPortExists + ErrPortNotFound = types.ErrPortNotFound + ErrPortNotAuthenticated = types.ErrPortNotAuthenticated + ErrInvalidPortID = types.ErrInvalidPortID + PortPath = types.PortPath + KeyPort = types.KeyPort +) + +type ( + Keeper = keeper.Keeper +) diff --git a/x/ibc/05-port/keeper/keeper.go b/x/ibc/05-port/keeper/keeper.go new file mode 100644 index 000000000000..5a7a9fb05bae --- /dev/null +++ b/x/ibc/05-port/keeper/keeper.go @@ -0,0 +1,77 @@ +package keeper + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/ibc/05-port/types" + host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" +) + +// 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 + ports map[sdk.CapabilityKey]string + bound []string +} + +// NewKeeper creates a new IBC connection Keeper instance +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType) Keeper { + return Keeper{ + 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[sdk.CapabilityKey]string), // map of capabilities 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] + return portID, found +} + +// BindPort binds to a port and returns the associated capability. +// Ports must be bound statically when the chain starts in `app.go`. +// The capability must then be passed to a module which will need to pass +// it as an extra parameter when calling functions on the IBC module. +func (k Keeper) BindPort(portID string) sdk.CapabilityKey { + if err := host.DefaultPortIdentifierValidator(portID); err != nil { + panic(err.Error()) + } + + for _, b := range k.bound { + if b == portID { + panic(fmt.Sprintf("port %s is already bound", portID)) + } + } + + key := sdk.NewKVStoreKey(portID) + k.ports[key] = portID + k.bound = append(k.bound, portID) + return key +} + +// Authenticate authenticates a capability key against a port ID +// by checking if the memory address of the capability was previously +// generated and bound to the port (provided as a parameter) which the capability +// is being authenticated against. +func (k Keeper) Authenticate(key sdk.CapabilityKey, portID string) bool { + if err := host.DefaultPortIdentifierValidator(portID); err != nil { + panic(err.Error()) + } + + return k.ports[key] == portID +} diff --git a/x/ibc/05-port/types/errors.go b/x/ibc/05-port/types/errors.go new file mode 100644 index 000000000000..20031c826107 --- /dev/null +++ b/x/ibc/05-port/types/errors.go @@ -0,0 +1,37 @@ +package types + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// port error codes +const ( + DefaultCodespace sdk.CodespaceType = SubModuleName + + CodePortExists sdk.CodeType = 101 + CodePortNotFound sdk.CodeType = 102 + CodePortNotAuthenticated sdk.CodeType = 103 + CodeInvalidPortID sdk.CodeType = 104 +) + +// 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)) +} + +// 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)) +} + +// 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") +} diff --git a/x/ibc/05-port/types/keys.go b/x/ibc/05-port/types/keys.go new file mode 100644 index 000000000000..b1250e0e4463 --- /dev/null +++ b/x/ibc/05-port/types/keys.go @@ -0,0 +1,31 @@ +package types + +import ( + "fmt" +) + +const ( + // SubModuleName defines the IBC port name + SubModuleName = "port" + + // StoreKey is the store key string for IBC ports + StoreKey = SubModuleName + + // RouterKey is the message route for IBC ports + RouterKey = SubModuleName + + // QuerierRoute is the querier route for IBC ports + QuerierRoute = SubModuleName +) + +// The following paths are the keys to the store as defined in https://github.com/cosmos/ics/tree/master/spec/ics-005-port-allocation#store-paths + +// PortPath defines the path under which ports paths are stored +func PortPath(portID string) string { + return fmt.Sprintf("ports/%s", portID) +} + +// KeyPort returns the store key for a particular port +func KeyPort(portID string) []byte { + return []byte(PortPath(portID)) +} diff --git a/x/ibc/keeper/keeper.go b/x/ibc/keeper/keeper.go index dafe8892d167..c9708a6e79a1 100644 --- a/x/ibc/keeper/keeper.go +++ b/x/ibc/keeper/keeper.go @@ -5,21 +5,25 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + port "github.com/cosmos/cosmos-sdk/x/ibc/05-port" ) // Keeper defines each ICS keeper for IBC type Keeper struct { ClientKeeper client.Keeper ConnectionKeeper connection.Keeper + PortKeeper port.Keeper } // NewKeeper creates a new ibc Keeper func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType) Keeper { clientKeeper := client.NewKeeper(cdc, key, codespace) connectionKeeper := connection.NewKeeper(cdc, key, codespace, clientKeeper) + portKeeper := port.NewKeeper(cdc, key, codespace) return Keeper{ ClientKeeper: clientKeeper, ConnectionKeeper: connectionKeeper, + PortKeeper: portKeeper, } }