diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 6acecc932fe..ba11c556e9e 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -352,29 +352,24 @@ module.exports = { path: "/ibc/light-clients/overview.html", }, { - title: "ClientState", + title: "Client State interface", directory: false, path: "/ibc/light-clients/client-state.html", }, { - title: "ConsensusState", + title: "Consensus State interface", directory: false, path: "/ibc/light-clients/consensus-state.html", }, { - title: "Setup", - directory: false, - path: "/ibc/light-clients/setup.html", - }, - { - title: "Updates Handling", + title: "Handling Updates and Misbehaviour", directory: false, - path: "/ibc/light-clients/update.html", + path: "/ibc/light-clients/updates-and-misbehaviour.html", }, { - title: "Misbehaviour Handling", + title: "Handling Upgrades", directory: false, - path: "/ibc/light-clients/misbehaviour.html", + path: "/ibc/light-clients/upgrades.html", }, { title: "Existence/Non-Existence Proofs", @@ -382,19 +377,19 @@ module.exports = { path: "/ibc/light-clients/proofs.html", }, { - title: "Upgrades Handling", + title: "Handling Proposals", directory: false, - path: "/ibc/light-clients/upgrade.html", + path: "/ibc/light-clients/proposals.html", }, { - title: "Proposal Handling", + title: "Handling Genesis", directory: false, - path: "/ibc/light-clients/proposal.html", + path: "/ibc/light-clients/genesis.html", }, { - title: "Genesis Handling", + title: "Setup", directory: false, - path: "/ibc/light-clients/genesis.html", + path: "/ibc/light-clients/setup.html", }, ] }, diff --git a/docs/architecture/adr-001-coin-source-tracing.md b/docs/architecture/adr-001-coin-source-tracing.md index 4aeb59aecab..94a9c86de63 100644 --- a/docs/architecture/adr-001-coin-source-tracing.md +++ b/docs/architecture/adr-001-coin-source-tracing.md @@ -114,7 +114,7 @@ trace the token back to the originating chain, as specified on ICS20. The new proposed format will be the following: -```golang +```go ibcDenom = "ibc/" + hash(trace path + "/" + base denom) ``` @@ -133,7 +133,7 @@ message DenomTrace { The `IBCDenom` function constructs the `Coin` denomination used when creating the ICS20 fungible token packet data: -```golang +```go // Hash returns the hex bytes of the SHA256 hash of the DenomTrace fields using the following formula: // // hash = sha256(tracePath + "/" + baseDenom) @@ -157,7 +157,7 @@ In order to retrieve the trace information from an IBC denomination, a lookup ta added to the `ibc-transfer` module. These values need to also be persisted between upgrades, meaning that a new `[]DenomTrace` `GenesisState` field state needs to be added to the module: -```golang +```go // GetDenomTrace retrieves the full identifiers trace and base denomination from the store. func (k Keeper) GetDenomTrace(ctx Context, denomTraceHash []byte) (DenomTrace, bool) { store := ctx.KVStore(k.storeKey) @@ -188,14 +188,14 @@ func (k Keeper) SetDenomTrace(ctx Context, denomTrace DenomTrace) { The `MsgTransfer` will validate that the `Coin` denomination from the `Token` field contains a valid hash, if the trace info is provided, or that the base denominations matches: -```golang +```go func (msg MsgTransfer) ValidateBasic() error { // ... return ValidateIBCDenom(msg.Token.Denom) } ``` -```golang +```go // ValidateIBCDenom validates that the given denomination is either: // // - A valid base denomination (eg: 'uatom') @@ -226,7 +226,7 @@ The denomination trace info only needs to be updated when token is received: - Receiver is **source** chain: The receiver created the token and must have the trace lookup already stored (if necessary _ie_ native token case wouldn't need a lookup). - Receiver is **not source** chain: Store the received info. For example, during step 1, when chain `B` receives `transfer/channelToA/denom`. -```golang +```go // SendTransfer // ... @@ -245,7 +245,7 @@ if types.SenderChainIsSource(sourcePort, sourceChannel, fullDenomPath) { //... ``` -```golang +```go // DenomPathFromHash returns the full denomination path prefix from an ibc denom with a hash // component. func (k Keeper) DenomPathFromHash(ctx sdk.Context, denom string) (string, error) { @@ -266,7 +266,7 @@ func (k Keeper) DenomPathFromHash(ctx sdk.Context, denom string) (string, error) ``` -```golang +```go // OnRecvPacket // ... @@ -322,7 +322,7 @@ return k.bankKeeper.SendCoinsFromModuleToAccount( ) ``` -```golang +```go func NewDenomTraceFromRawDenom(denom string) DenomTrace{ denomSplit := strings.Split(denom, "/") trace := "" diff --git a/docs/dev/go-style-guide.md b/docs/dev/go-style-guide.md index f481c4bcd32..c45d677e603 100644 --- a/docs/dev/go-style-guide.md +++ b/docs/dev/go-style-guide.md @@ -71,7 +71,7 @@ Perhaps more key for code readability than good commenting is having the right s - Use [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports). - Separate imports into blocks: one for the standard lib, one for external libs and one for application libs. For example: - ```golang + ```go import ( // standard library imports "fmt" @@ -105,7 +105,7 @@ Perhaps more key for code readability than good commenting is having the right s - Panic is appropriate when an internal invariant of a system is broken, while all other cases (in particular, incorrect or invalid usage) should return errors. - Error messages should be formatted as following: - ```golang + ```go sdkerrors.Wrapf( , "expected %s, got %s", diff --git a/docs/ibc/integration.md b/docs/ibc/integration.md index 61c2510588f..1e735df438c 100644 --- a/docs/ibc/integration.md +++ b/docs/ibc/integration.md @@ -16,7 +16,7 @@ Integrating the IBC module to your SDK-based application is straighforward. The - Add required modules to the `module.BasicManager` - Define additional `Keeper` fields for the new modules on the `App` type -- Add the module's `StoreKeys` and initialize their `Keepers` +- Add the module's `StoreKey`s and initialize their `Keeper`s - Set up corresponding routers and routes for the `ibc` module - Add the modules to the module `Manager` - Add modules to `Begin/EndBlockers` and `InitGenesis` @@ -28,10 +28,10 @@ The first step is to add the following modules to the `BasicManager`: `x/capabil and `x/ibc-transfer`. After that, we need to grant `Minter` and `Burner` permissions to the `ibc-transfer` `ModuleAccount` to mint and burn relayed tokens. -### Integrating Light Clients +### Integrating light clients > Note that from v7 onwards, all light clients have to be explicitly registered in a chain's app.go and follow the steps listed below. - This is in contrast to earlier versions of ibc-go when 07-tendermint and 06-solomachine were added out of the box. + This is in contrast to earlier versions of ibc-go when `07-tendermint` and `06-solomachine` were added out of the box. All light clients must be registered with `module.BasicManager` in a chain's app.go file. @@ -40,9 +40,9 @@ The following code example shows how to register the existing `ibctm.AppModuleBa ```diff import ( - ... -+ ibctm "github.com/cosmos/ibc-go/v6/modules/light-clients/07-tendermint" - ... + ... ++ ibctm "github.com/cosmos/ibc-go/v6/modules/light-clients/07-tendermint" + ... ) // app.go @@ -55,7 +55,7 @@ var ( transfer.AppModuleBasic{}, // i.e ibc-transfer module // register light clients on IBC -+ ibctm.AppModuleBasic{}, ++ ibctm.AppModuleBasic{}, ) // module account permissions @@ -63,6 +63,7 @@ var ( // other module accounts permissions // ... ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + } ) ``` diff --git a/docs/ibc/light-clients/client-state.md b/docs/ibc/light-clients/client-state.md index 9ecfe891323..bd74762e562 100644 --- a/docs/ibc/light-clients/client-state.md +++ b/docs/ibc/light-clients/client-state.md @@ -4,7 +4,7 @@ order: 2 # Implementing the `ClientState` interface -Learn how to implement the [`ClientState`](https://github.com/cosmos/ibc-go/blob/v6.0.0/modules/core/exported/client.go#L40) interface. +Learn how to implement the [`ClientState`](https://github.com/cosmos/ibc-go/blob/v6.0.0/modules/core/exported/client.go#L40) interface. This list of methods described here does not include all methods of the interface. Some methods are explained in detail in the relevant sections of the guide. ## `ClientType` method @@ -18,27 +18,27 @@ The format is created as follows: `ClientType-{N}` where `{N}` is the unique glo ## `Validate` method `Validate` should validate every client state field and should return an error if any value is invalid. The light client -implementer is in charge of determining which checks are required. See the [tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/v6.0.0/modules/light-clients/07-tendermint/types/client_state.go#L101) as a reference. +implementer is in charge of determining which checks are required. See the [Tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/v6.0.0/modules/light-clients/07-tendermint/types/client_state.go#L101) as a reference. ## `Status` method `Status` must return the status of the client. - An `Active` status indicates that clients are allowed to process packets. -- A `Frozen` status indicates that a client is not allowed to be used. -- An `Expired` status indicates that a client is not allowed to be used. +- A `Frozen` status indicates that misbehaviour was detected in the counterparty chain and the client is not allowed to be used. +- An `Expired` status indicates that a client is not allowed to be used because it was not updated for longer than the trusting period. - An `Unknown` status indicates that there was an error in determining the status of a client. -All possible Status types can be found [here](https://github.com/cosmos/ibc-go/blob/v6.0.0/modules/core/exported/client.go#L26-L36). +All possible `Status` types can be found [here](https://github.com/cosmos/ibc-go/blob/v6.0.0/modules/core/exported/client.go#L26-L36). -This field is returned by the gRPC [QueryClientStatusResponse](https://github.com/cosmos/ibc-go/blob/v6.0.0/modules/core/02-client/types/query.pb.go#L665) endpoint. +This field is returned in the response of the gRPC [`ibc.core.client.v1.Query/ClientStatus`](https://github.com/cosmos/ibc-go/blob/v6.0.0/modules/core/02-client/types/query.pb.go#L665) endpoint. ## `ZeroCustomFields` method `ZeroCustomFields` should return a copy of the light client with all client customizable fields with their zero value. It should not mutate the fields of the light client. This method is used when [scheduling upgrades](https://github.com/cosmos/ibc-go/blob/v6.0.0/modules/core/02-client/keeper/proposal.go#L89). Upgrades are used to upgrade chain specific fields. -In the tendermint case, this may be the chainID or the unbonding period. -For more information about client upgrades see [the developer guide](../upgrades/developer-guide.md). +In the tendermint case, this may be the chain ID or the unbonding period. +For more information about client upgrades see the [Handling upgrades](./upgrades.md) section. ## `GetTimestampAtHeight` method @@ -54,22 +54,22 @@ Clients may also store any necessary client-specific metadata. ## `VerifyMembership` method -`VerifyMembership` must verify the existence of a value at a given CommitmentPath at the specified height. For more information about membership proofs -see [the proof docs](./proofs.md). +`VerifyMembership` must verify the existence of a value at a given commitment path at the specified height. For more information about membership proofs +see the [Existence and non-existence proofs section](./proofs.md). ## `VerifyNonMembership` method -`VerifyNonMembership` must verify the absence of a value at a given CommitmentPath at a specified height. For more information about non membership proofs -see [the proof docs](./proofs.md). +`VerifyNonMembership` must verify the absence of a value at a given commitment path at a specified height. For more information about non-membership proofs +see the [Existence and non-existence proofs section](./proofs.md). ## `VerifyClientMessage` method -VerifyClientMessage must verify a ClientMessage. A ClientMessage could be a Header, Misbehaviour, or batch update. -It must handle each type of ClientMessage appropriately. Calls to CheckForMisbehaviour, UpdateState, and UpdateStateOnMisbehaviour -will assume that the content of the ClientMessage has been verified and can be trusted. An error should be returned +`VerifyClientMessage` must verify a `ClientMessage`. A `ClientMessage` could be a `Header`, `Misbehaviour`, or batch update. +It must handle each type of `ClientMessage` appropriately. Calls to `CheckForMisbehaviour`, `UpdateState`, and `UpdateStateOnMisbehaviour` +will assume that the content of the `ClientMessage` has been verified and can be trusted. An error should be returned if the ClientMessage fails to verify. ## `CheckForMisbehaviour` method -Checks for evidence of a misbehaviour in Header or Misbehaviour type. It assumes the ClientMessage +Checks for evidence of a misbehaviour in `Header` or `Misbehaviour` type. It assumes the `ClientMessage` has already been verified. diff --git a/docs/ibc/light-clients/consensus-state.md b/docs/ibc/light-clients/consensus-state.md index ebde1e8cbbe..51ce29eac62 100644 --- a/docs/ibc/light-clients/consensus-state.md +++ b/docs/ibc/light-clients/consensus-state.md @@ -4,7 +4,9 @@ order: 3 # Implementing the `ConsensusState` interface -A `ConsensusState` is the snapshot of the counterparty chain that an IBC client uses to verify proofs (e.g. a block). The further development of multiple types of IBC light clients and the difficulties presented by this generalization problem (see [ADR-006](https://github.com/cosmos/ibc-go/blob/main/docs/architecture/adr-006-02-client-refactor.md) for more information about this historical context) led to the design decision of each client keeping track of and set its own `ClientState` and `ConsensusState`, as well as the simplification of client `ConsensusState` updates through the generalized `ClientMessage` interface. +A `ConsensusState` is the snapshot of the counterparty chain, that an IBC client uses to verify proofs (e.g. a block). + +The further development of multiple types of IBC light clients and the difficulties presented by this generalization problem (see [ADR-006](https://github.com/cosmos/ibc-go/blob/main/docs/architecture/adr-006-02-client-refactor.md) for more information about this historical context) led to the design decision of each client keeping track of and set its own `ClientState` and `ConsensusState`, as well as the simplification of client `ConsensusState` updates through the generalized `ClientMessage` interface. The below [`ConsensusState`](https://github.com/cosmos/ibc-go/blob/main/modules/core/exported/client.go#L134) interface is a generalized interface for the types of information a `ConsensusState` could contain. For a reference `ConsensusState` implementation, please see the [Tendermint light client `ConsensusState`](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/07-tendermint/consensus_state.go). diff --git a/docs/ibc/light-clients/genesis.md b/docs/ibc/light-clients/genesis.md index 8b5d697cc9e..9947b8094b3 100644 --- a/docs/ibc/light-clients/genesis.md +++ b/docs/ibc/light-clients/genesis.md @@ -1,18 +1,18 @@ -# Genesis Metadata +# Genesis metadata Learn how to implement the `ExportMetadata` interface {synopsis} -## Pre-requisite Readings +## Pre-requisite readings - [Cosmos SDK module genesis](https://docs.cosmos.network/v0.47/building-modules/genesis) {prereq} `ClientState` instances are provided their own isolated and namespaced client store upon initialisation. `ClientState` implementations may choose to store any amount of arbitrary metadata in order to verify counterparty consensus state and perform light client updates correctly. -The `ExportMetadata` method of the `ClientState` interface provides light client modules with the ability to persist metadata in genesis exports. +The `ExportMetadata` method of the [`ClientState` interface](https://github.com/cosmos/ibc-go/blob/e650be91614ced7be687c30eb42714787a3bbc59/modules/core/exported/client.go) provides light client modules with the ability to persist metadata in genesis exports. ```go ExportMetadata(clientStore sdk.KVStore) []GenesisMetadata @@ -29,7 +29,8 @@ type GenesisMetadata interface { } ``` -This allows `ClientState` instances to retrieve and export any number of key-value pairs which are maintained within the store in their raw `[]byte` form. +This allows `ClientState` instances to retrieve and export any number of key-value pairs which are maintained within the store in their raw `[]byte` form. + When a chain is started with a `genesis.json` file which contains `ClientState` metadata (for example, when performing manual upgrades using an exported `genesis.json`) the `02-client` submodule of core IBC will handle setting the key-value pairs within their respective client stores. [See `02-client` `InitGenesis`](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/core/02-client/genesis.go#L18-L22). -Please refer to the [`07-tendermint` implementation](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/genesis.go#L12) as an example. +Please refer to the [Tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/genesis.go#L12) for an example. diff --git a/docs/ibc/light-clients/overview.md b/docs/ibc/light-clients/overview.md index c8505603d21..9eae03f7a43 100644 --- a/docs/ibc/light-clients/overview.md +++ b/docs/ibc/light-clients/overview.md @@ -14,7 +14,7 @@ Learn how to build IBC light client modules and fulfill the interfaces required IBC uses light clients in order to provide trust-minimized interoperability between sovereign blockchains. Light clients operate under a strict set of rules which provide security guarantees for state updates and facilitate the ability to verify the state of a remote blockchain using merkle proofs. -The following aims to provide a high level IBC light client module developer guide. Access to IBC light clients are gated by the core IBC `MsgServer` which utilizes the abstractions set by the `02-client` submodule to call into a light client module. A light client module developer is only required to implement a set interfaces as defined in the `core/modules/exported` package of ibc-go. +The following aims to provide a high level IBC light client module developer guide. Access to IBC light clients are gated by the core IBC `MsgServer` which utilizes the abstractions set by the `02-client` submodule to call into a light client module. A light client module developer is only required to implement a set interfaces as defined in the `modules/core/exported` package of ibc-go. A light client module developer should be concerned with three main interfaces: @@ -26,9 +26,9 @@ Throughout this guide the `07-tendermint` light client module may be referred to ## Concepts and vocabulary -### ClientState +### `ClientState` -ClientState is a term used to define the data structure which encapsulates opaque light client state. The `ClientState` contains all the information needed to verify a `ClientMessage` and perform membership and non-membership proof verification of counterparty state. This includes properties that refer to the remote state machine, the light client type and the specific light client instance. +`ClientState` is a term used to define the data structure which encapsulates opaque light client state. The `ClientState` contains all the information needed to verify a `ClientMessage` and perform membership and non-membership proof verification of counterparty state. This includes properties that refer to the remote state machine, the light client type and the specific light client instance. For example: @@ -40,25 +40,25 @@ For example: The `ClientState` type maintained within the light client module *must* implement the [`ClientState`](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/modules/core/exported/client.go#L36) interface defined in `core/modules/exported/client.go`. The methods which make up this interface are detailed at a more granular level in the [ClientState section of this guide](./client-state.md). -Please refer to the `07-tendermint` light client module's [`ClientState` defintion](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L18) containing information such as chain ID, status, latest height, unbonding period and proof specifications. +Please refer to the `07-tendermint` light client module's [`ClientState` definition](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L18) containing information such as chain ID, status, latest height, unbonding period and proof specifications. -### ConsensusState +### `ConsensusState` -ConsensusState is a term used to define the data structure which encapsulates consensus data at a particular point in time, i.e. a unique height or sequence number of a state machine. There must exist a single trusted `ConsensusState` for each height. `ConsensusState` generally contains a trusted root, validator set information and timestamp. +`ConsensusState` is a term used to define the data structure which encapsulates consensus data at a particular point in time, i.e. a unique height or sequence number of a state machine. There must exist a single trusted `ConsensusState` for each height. `ConsensusState` generally contains a trusted root, validator set information and timestamp. For example, the `ConsensusState` of the `07-tendermint` light client module defines a trusted root which is used by the `ClientState` to perform verification of membership and non-membership commitment proofs, as well as the next validator set hash used for verifying headers can be trusted in client updates. -The `ConsensusState` type maintained within the light client module *must* implement the [`ConsensusState`](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/modules/core/exported/client.go#L134) interface defined in `core/modules/exported/client.go`. -The methods which make up this interface are detailed at a more granular level in the [ConsensusState section of this guide](./consensus-state.md). +The `ConsensusState` type maintained within the light client module *must* implement the [`ConsensusState`](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/modules/core/exported/client.go#L134) interface defined in `modules/core/exported/client.go`. +The methods which make up this interface are detailed at a more granular level in the [`ConsensusState` section of this guide](./consensus-state.md). -### Height +### `Height` -Height defines a monotonically increasing sequence number which provides ordering of consensus state data persisted through client updates. -IBC light client module developers are expected to use the [concrete type](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/proto/ibc/core/client/v1/client.proto#L89) provided by the `02-client` submodule. This implements the expectations required by the `Height` interface defined in `core/modules/exported/client.go`. +`Height` defines a monotonically increasing sequence number which provides ordering of consensus state data persisted through client updates. +IBC light client module developers are expected to use the [concrete type](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/proto/ibc/core/client/v1/client.proto#L89) provided by the `02-client` submodule. This implements the expectations required by the [`Height`](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/core/exported/client.go#L157) interface defined in `modules/core/exported/client.go`. -### ClientMessage +### `ClientMessage` -ClientMessage refers to the interface type [`ClientMessage`](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/modules/core/exported/client.go#L148) used for performing updates to a `ClientState` stored on chain. +`ClientMessage` refers to the interface type [`ClientMessage`](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/modules/core/exported/client.go#L148) used for performing updates to a `ClientState` stored on chain. This may be any concrete type which produces a change in state to the IBC client when verified. The following are considered as valid update scenarios: @@ -67,4 +67,4 @@ The following are considered as valid update scenarios: - A batch of block headers which when verified inserts `N` `ConsensusState` instances for `N` unique heights. - Evidence of misbehaviour provided by two conflicting block headers. -Learn more in the [handling client updates](./update.md) and [handling misbehaviour](./updates-and-misbehaviour.md) sections. +Learn more in the [Handling update and misbehaviour](./updates-and-misbehaviour.md) section. diff --git a/docs/ibc/light-clients/proofs.md b/docs/ibc/light-clients/proofs.md index 585511d9aee..91ddc2c03fd 100644 --- a/docs/ibc/light-clients/proofs.md +++ b/docs/ibc/light-clients/proofs.md @@ -1,35 +1,62 @@ -# Existence and Non-Existence Proofs +# Existence and non-existence proofs -IBC uses merkle proofs in order to verify the state of a remote counterparty state machine given a trusted root, and [ICS23](https://github.com/cosmos/ics23/tree/master/go) is a general approach for verifying merkle trees which is used in `ibc-go`. +IBC uses merkle proofs in order to verify the state of a remote counterparty state machine given a trusted root, and [ICS-23](https://github.com/cosmos/ics23/tree/master/go) is a general approach for verifying merkle trees which is used in ibc-go. -Currently, all Cosmos SDK modules contain their own stores, which maintain the state of the application module in an IAVL (immutable AVL) binary merkle tree format. Specifically with regard to IBC, core IBC maintains its own IAVL store, and IBC apps (e.g. transfer) maintain their own dedicated stores. The Cosmos SDK multistore therefore creates a simple merkle tree of all of these IAVL trees, and from each of these individual IAVL tree root hashes derives a root hash for the application state tree as a whole (the apphash). +Currently, all Cosmos SDK modules contain their own stores, which maintain the state of the application module in an IAVL (immutable AVL) binary merkle tree format. Specifically with regard to IBC, core IBC maintains its own IAVL store, and IBC apps (e.g. transfer) maintain their own dedicated stores. The Cosmos SDK multistore therefore creates a simple merkle tree of all of these IAVL trees, and from each of these individual IAVL tree root hashes it derives a root hash for the application state tree as a whole (the `AppHash`). -For the purposes of `ibc-go`, there are two types of proofs which are important: existence and non-existence proofs, terms which have been used interchangeably with membership and non-membership proofs. For the purposes of this guide, we will stick with 'existence' and 'non-existence'. +For the purposes of ibc-go, there are two types of proofs which are important: existence and non-existence proofs, terms which have been used interchangeably with membership and non-membership proofs. For the purposes of this guide, we will stick with "existence" and "non-existence". -## Existence Proofs +## Existence proofs Existence proofs are used in IBC transactions which involve verification of counterparty state for transactions which will result in the writing of provable state. For example, this includes verification of IBC store state for handshakes and packets. Put simply, existence proofs prove that a particular key and value exists in the tree. Under the hood, an IBC existence proof comprises of two proofs: an IAVL proof that the key exists in IBC store/IBC root hash, and a proof that the IBC root hash exists in the multistore root hash. -## Non-Existence Proofs +## Non-existence proofs Non-existence proofs verify the absence of data stored within counterparty state and are used to prove that a key does NOT exist in state. As stated above, these types of proofs can be used to timeout packets by proving that the counterparty has not written a packet receipt into the store, meaning that a token transfer has NOT successfully occurred. -Some trees (e.g. SMT) may have a sentinel empty child for nonexistent keys. In this case, the ICS23 proof spec should include this `EmptyChild` so that ICS23 handles the nonexistence proof correctly. +Some trees (e.g. SMT) may have a sentinel empty child for non-existent keys. In this case, the ICS-23 proof spec should include this `EmptyChild` so that ICS-23 handles the non-existence proof correctly. In some cases, there is a necessity to "mock" non-existence proofs if the counterparty does not have ability to prove absence. Since the verification method is designed to give complete control to client implementations, clients can support chains that do not provide absence proofs by verifying the existence of a non-empty sentinel `ABSENCE` value. In these special cases, the proof provided will be an ICS-23 `Existence` proof, and the client will verify that the `ABSENCE` value is stored under the given path for the given height. -## State Verification Methods: `VerifyMembership` and `VerifyNonMembership` +## State verification methods: `VerifyMembership` and `VerifyNonMembership` The state verification functions for all IBC data types have been consolidated into two generic methods, `VerifyMembership` and `VerifyNonMembership`. -For more information about how to implement `VerifyMembership`, please see the `ClientState` [implementation guide](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/docs/ibc/light-clients/client-state.md#verifymembership-method). - -For more information about how to implement `VerifyNonMembership`, please see the `ClientState` [implementation guide](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/docs/ibc/light-clients/client-state.md#verifynonmembership-method). - -Both are expected to be provided with a standardised key path, `exported.Path`, as defined in [ICS-24 host requirements](https://github.com/cosmos/ibc/tree/main/spec/core/ics-024-host-requirements). Membership verification requires callers to provide the marshalled value `[]byte`. Delay period values should be zero for non-packet processing verification. A zero proof height is now allowed by core IBC and may be passed into `VerifyMembership` and `VerifyNonMembership`. Light clients are responsible for returning an error if a zero proof height is invalid behaviour. \ No newline at end of file +From the [`ClientState` interface definition](https://github.com/cosmos/ibc-go/blob/e650be91614ced7be687c30eb42714787a3bbc59/modules/core/exported/client.go#L68-L91), we find: + +```go +VerifyMembership( + ctx sdk.Context, + clientStore sdk.KVStore, + cdc codec.BinaryCodec, + height Height, + delayTimePeriod uint64, + delayBlockPeriod uint64, + proof []byte, + path Path, + value []byte, +) error + +// VerifyNonMembership is a generic proof verification method which verifies the absence of a given CommitmentPath at a specified height. +// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). +VerifyNonMembership( + ctx sdk.Context, + clientStore sdk.KVStore, + cdc codec.BinaryCodec, + height Height, + delayTimePeriod uint64, + delayBlockPeriod uint64, + proof []byte, + path Path, +) error +``` + +Both are expected to be provided with a standardised key path, `exported.Path`, as defined in [ICS-24 host requirements](https://github.com/cosmos/ibc/tree/main/spec/core/ics-024-host-requirements). Membership verification requires callers to provide the value marshalled as `[]byte`. Delay period values should be zero for non-packet processing verification. A zero proof height is now allowed by core IBC and may be passed into `VerifyMembership` and `VerifyNonMembership`. Light clients are responsible for returning an error if a zero proof height is invalid behaviour. + +Please refer to the [ICS-23 implementation](https://github.com/cosmos/ibc-go/blob/e093d85b533ab3572b32a7de60b88a0816bed4af/modules/core/23-commitment/types/merkle.go#L131-L205) for a concrete example. diff --git a/docs/ibc/light-clients/proposal.md b/docs/ibc/light-clients/proposal.md deleted file mode 100644 index 74abe182fbf..00000000000 --- a/docs/ibc/light-clients/proposal.md +++ /dev/null @@ -1,13 +0,0 @@ - - -# Implementing `CheckSubstituteAndUpdateState` - -`CheckSubstituteAndUpdateState` will try to update the client with the state of the substitute client. [This type of governance proposal](https://ibc.cosmos.network/main/ibc/proposals.html) is typically used to recover an expired and frozen client, as it can recover the entire state and therefore all existing channels built on top of the client. - -Prior to updating, this function must verify that: -- the substitute client is the same type as the subject client. For a reference implementation, please see the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/proposal_handle.go#L32). -- the provided substitute may be used to update the subject client. This may mean that certain parameters must remain unaltered. For example, a [valid substitute Tendermint light client](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/proposal_handle.go#L84) must NOT change the chain ID, trust level, max clock drift, unbonding period, proof specs or upgrade path. Please note that `AllowUpdateAfterMisbehaviour` and `AllowUpdateAfterExpiry` have been deprecated (see ADR 026 for more information). - -After these checks are performed, the function must [set the updated client and consensus states](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/proposal_handle.go#L77) within the clientStore for the subject client. \ No newline at end of file diff --git a/docs/ibc/light-clients/proposals.md b/docs/ibc/light-clients/proposals.md new file mode 100644 index 00000000000..abd27b8aad5 --- /dev/null +++ b/docs/ibc/light-clients/proposals.md @@ -0,0 +1,32 @@ + + +# Handling proposals + +It is possible to update the client with the state of the substitute client through a governance proposal. [This type of governance proposal](https://ibc.cosmos.network/main/ibc/proposals.html) is typically used to recover an expired or frozen client, as it can recover the entire state and therefore all existing channels built on top of the client. `CheckSubstituteAndUpdateState` should be implemented to handle the proposal. + +## Implementing `CheckSubstituteAndUpdateState` + +In the [`ClientState`interface](https://github.com/cosmos/ibc-go/blob/e650be91614ced7be687c30eb42714787a3bbc59/modules/core/exported/client.go), we find: + +```go +// CheckSubstituteAndUpdateState must verify that the provided substitute may be used to update the subject client. +// The light client must set the updated client and consensus states within the clientStore for the subject client. +CheckSubstituteAndUpdateState( + ctx sdk.Context, + cdc codec.BinaryCodec, + subjectClientStore, + substituteClientStore sdk.KVStore, + substituteClient ClientState) + error +``` + +Prior to updating, this function must verify that: + +- the substitute client is the same type as the subject client. For a reference implementation, please see the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/proposal_handle.go#L32). +- the provided substitute may be used to update the subject client. This may mean that certain parameters must remain unaltered. For example, a [valid substitute Tendermint light client](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/proposal_handle.go#L84) must NOT change the chain ID, trust level, max clock drift, unbonding period, proof specs or upgrade path. Please note that `AllowUpdateAfterMisbehaviour` and `AllowUpdateAfterExpiry` have been deprecated (see ADR 026 for more information). + +After these checks are performed, the function must [set the updated client and consensus states](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/proposal_handle.go#L77) within the client store for the subject client. + +Please refer to the [Tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/proposal_handle.go#L27) for reference. diff --git a/docs/ibc/light-clients/setup.md b/docs/ibc/light-clients/setup.md index 8bb85b234af..a17e36cf7d8 100644 --- a/docs/ibc/light-clients/setup.md +++ b/docs/ibc/light-clients/setup.md @@ -1,14 +1,18 @@ # Setup Learn how to configure light client modules and create clients using core IBC and the `02-client` submodule. {synopsis} +A last step to finish the development of the light client, is to implement the `AppModuleBasic` interface to allow it to be added to the chain's `app.go` alongside other light client types the chain enables. + +Finally, a succinct rundown is given of the remaining steps to make the light client operational, getting the light client type passed through governance and creating the clients. + ## Configuring a light client module -An IBC light client module must implement the [`AppModuleBasic`](https://github.com/cosmos/cosmos-sdk/blob/main/types/module/module.go#L50) interface in order to register its concrete types against the core IBC interfaces defined in `modules/core/exported`. This is accomplished via the `RegisterInterfaces` method which provides the light client module with the opportunity to register codec types using the chain's `InterfaceRegistery`. Please refer to the [`07-tendermint` codec registration](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/codec.go#L11). +An IBC light client module must implement the [`AppModuleBasic`](https://github.com/cosmos/cosmos-sdk/blob/main/types/module/module.go#L50) interface in order to register its concrete types against the core IBC interfaces defined in `modules/core/exported`. This is accomplished via the `RegisterInterfaces` method which provides the light client module with the opportunity to register codec types using the chain's `InterfaceRegistry`. Please refer to the [`07-tendermint` codec registration](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/codec.go#L11). The `AppModuleBasic` interface may also be leveraged to install custom CLI handlers for light client module users. Light client modules can safely no-op for interface methods which it does not wish to implement. @@ -65,7 +69,7 @@ func (AppModuleBasic) GetQueryCmd() *cobra.Command { ## Creating clients A client is created by executing a new `MsgCreateClient` transaction composed with a valid `ClientState` and initial `ConsensusState` encoded as protobuf `Any`s. -Generally, this is normally done by an off-chain process known as an [IBC relayer](https://github.com/cosmos/ibc/tree/main/spec/relayer/ics-018-relayer-algorithms) however, this is not a strict requirement. +Generally, this is performed by an off-chain process known as an [IBC relayer](https://github.com/cosmos/ibc/tree/main/spec/relayer/ics-018-relayer-algorithms) however, this is not a strict requirement. See below for a list of IBC relayer implementations: @@ -95,7 +99,7 @@ Leveraging protobuf `Any` encoding allows core IBC to [unpack](https://github.co Within the `02-client` submodule, the [`ClientState` is then initialized](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/core/02-client/keeper/client.go#L30-L34) with its own isolated key-value store, namespaced using a unique client identifier. -In order to successfully create an IBC client using a new client type it [must be supported](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/core/02-client/keeper/client.go#L18-L24). Light client support in IBC is gated by on-chain governance. The allow list may be updated by submitting a new governance proposal to update the `02-client` parameter `AllowedClients`. +In order to successfully create an IBC client using a new client type, it [must be supported](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/core/02-client/keeper/client.go#L18-L24). Light client support in IBC is gated by on-chain governance. The allow list may be updated by submitting a new governance proposal to update the `02-client` parameter `AllowedClients`. See below for example: -``` +```shell $ %s tx gov submit-proposal param-change --from= -Where proposal.json contains: +``` + +where `proposal.json` contains: + +```json { "title": "IBC Clients Param Change", "description": "Update allowed clients", diff --git a/docs/ibc/light-clients/update.md b/docs/ibc/light-clients/update.md deleted file mode 100644 index 504cfca7c5c..00000000000 --- a/docs/ibc/light-clients/update.md +++ /dev/null @@ -1,18 +0,0 @@ - - -# Implementing the `ClientMessage` interface - -As mentioned before in the documentation about [implementing the `ConsensusState` interface](./consensus-state.md), [`ClientMessage`](https://github.com/cosmos/ibc-go/blob/main/modules/core/exported/client.go#L145) is an interface used to update an IBC client. This update may be done by a single header, a batch of headers, misbehaviour, or any type which when verified produces a change to the consensus state of the IBC client. This interface has been purposefully kept generic in order to give the maximum amount of flexibility to the light client implementer. - -```golang -type ClientMessage interface { - proto.Message - - ClientType() string - ValidateBasic() error -} -``` - -The `ClientMessage` will be passed to the client to be used in [`UpdateClient`](https://github.com/cosmos/ibc-go/blob/57da75a70145409247e85365b64a4b2fc6ddad2f/modules/core/02-client/keeper/client.go#L53), which will handle a number of cases including misbehaviour and/or updating the consensus state. However, this `UpdateClient` function will always reference the specific functions determined by the relevant `ClientState`. This is because `UpdateClient` retrieves the client state by client ID (available in `MsgUpdateClient`). This client state implements the `ClientState` interface for a specific client type (e.g. Tendermint). The functions called on the client state instance in `UpdateClient` will be the specific implementations of `VerifyClientMessage`, `CheckForMisbehaviour`, `UpdateStateOnMisbehaviour` and `UpdateState` functions of the `ClientState` interface for that particular client type. \ No newline at end of file diff --git a/docs/ibc/light-clients/updates-and-misbehaviour.md b/docs/ibc/light-clients/updates-and-misbehaviour.md index 715a876ea43..1a503ca7983 100644 --- a/docs/ibc/light-clients/updates-and-misbehaviour.md +++ b/docs/ibc/light-clients/updates-and-misbehaviour.md @@ -1,16 +1,51 @@ -# Handling Updates and Misbehaviour +# Handling `ClientMessage`s: updates and misbehaviour + +As mentioned before in the documentation about [implementing the `ConsensusState` interface](./consensus-state.md), [`ClientMessage`](https://github.com/cosmos/ibc-go/blob/main/modules/core/exported/client.go#L145) is an interface used to update an IBC client. This update may be performed by: + ++ a single header ++ a batch of headers ++ evidence of misbehaviour, ++ or any type which when verified produces a change to the consensus state of the IBC client. + +This interface has been purposefully kept generic in order to give the maximum amount of flexibility to the light client implementer. + +## Implementing the `ClientMessage` interface + +Find the `ClientMessage`interface in `modules/core/exported`: + +```go +type ClientMessage interface { + proto.Message + + ClientType() string + ValidateBasic() error +} +``` + +The `ClientMessage` will be passed to the client to be used in [`UpdateClient`](https://github.com/cosmos/ibc-go/blob/57da75a70145409247e85365b64a4b2fc6ddad2f/modules/core/02-client/keeper/client.go#L53), which retrieves the `ClientState` by client ID (available in `MsgUpdateClient`). This `ClientState` implements the [`ClientState` interface](./client-state.md) for its specific consenus type (e.g. Tendermint). + +`UpdateClient` will then handle a number of cases including misbehaviour and/or updating the consensus state, utilizing the specific methods defined in the relevant `ClientState`. + +```go +VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) error +CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) bool +UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) +UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) []Height +``` + +## Handling updates and misbehaviour The functions for handling updates to a light client and evidence of misbehaviour are all found in the [`ClientState`](https://github.com/cosmos/ibc-go/blob/v6.0.0/modules/core/exported/client.go#L40) interface, and will be discussed below. -It is important to note that `Misbehaviour` in this particular context is referring to misbehaviour on the chain level intended to fool the light client. This will be defined by each light client. +> It is important to note that `Misbehaviour` in this particular context is referring to misbehaviour on the chain level intended to fool the light client. This will be defined by each light client. ## `VerifyClientMessage` -`VerifyClientMessage` must verify a `ClientMessage`. A `ClientMessage` could be a `Header`, `Misbehaviour`, or batch update. To understand how to implement a `ClientMessage`, please refer to the [documentation](./update.md) +`VerifyClientMessage` must verify a `ClientMessage`. A `ClientMessage` could be a `Header`, `Misbehaviour`, or batch update. To understand how to implement a `ClientMessage`, please refer to the [Implementing the `ClientMessage` interface](#implementing-the-clientmessage-interface) section. It must handle each type of `ClientMessage` appropriately. Calls to `CheckForMisbehaviour`, `UpdateState`, and `UpdateStateOnMisbehaviour` will assume that the content of the `ClientMessage` has been verified and can be trusted. An error should be returned if the `ClientMessage` fails to verify. @@ -22,11 +57,11 @@ Checks for evidence of a misbehaviour in `Header` or `Misbehaviour` type. It ass For an example of a `CheckForMisbehaviour` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/07-tendermint/misbehaviour_handle.go#L18). -> The Tendermint light client [defines `Misbehaviour`](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/07-tendermint/misbehaviour.go) as two different types of situations: a situation where two conflicting `Headers` with the same height have been submitted to update a client's `ConsensusState` within the same trusting period, or that the two conflicting `Headers` have been submitted at different heights but the consensus states are not in the correct monotonic time ordering (BFT time violation). More explicitly, updating to a new height must have a timestamp greater than the previous consensus state, or, if inserting a consensus at a past height, then time must be less than those heights which come after and greater than heights which come before. +> The Tendermint light client [defines `Misbehaviour`](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/07-tendermint/misbehaviour.go) as two different types of situations: a situation where two conflicting `Header`s with the same height have been submitted to update a client's `ConsensusState` within the same trusting period, or that the two conflicting `Header`s have been submitted at different heights but the consensus states are not in the correct monotonic time ordering (BFT time violation). More explicitly, updating to a new height must have a timestamp greater than the previous consensus state, or, if inserting a consensus at a past height, then time must be less than those heights which come after and greater than heights which come before. ## `UpdateStateOnMisbehaviour` -`UpdateStateOnMisbehaviour` should perform appropriate state changes on a client state given that misbehaviour has been detected and verified. This method should only be called when misbehaviour is detected, as it does not perform any misbehaviour checks. Notably, it should freeze the client so that calling the `Status()` function on the associated client state no longer returns `Active`. +`UpdateStateOnMisbehaviour` should perform appropriate state changes on a client state given that misbehaviour has been detected and verified. This method should only be called when misbehaviour is detected, as it does not perform any misbehaviour checks. Notably, it should freeze the client so that calling the `Status` function on the associated client state no longer returns `Active`. For an example of a `UpdateStateOnMisbehaviour` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/07-tendermint/update.go#L197). @@ -40,22 +75,21 @@ For an example of a `UpdateState` implementation, please check the [Tendermint l ## Putting it all together -The `02-client Keeper` module in ibc-go offers a reference as to how these functions will be used to [update the client](https://github.com/cosmos/ibc-go/blob/main/modules/core/02-client/keeper/client.go#L48). +The `02-client` `Keeper` module in ibc-go offers a reference as to how these functions will be used to [update the client](https://github.com/cosmos/ibc-go/blob/main/modules/core/02-client/keeper/client.go#L48). -```golang +```go if err := clientState.VerifyClientMessage(clientMessage); err != nil { - return err - } - - foundMisbehaviour := clientState.CheckForMisbehaviour(clientMessage) - if foundMisbehaviour { - clientState.UpdateStateOnMisbehaviour(clientMessage) - // emit misbehaviour event - return - } - - clientState.UpdateState(clientMessage) // expects no-op on duplicate header - // emit update event - return + return err } +foundMisbehaviour := clientState.CheckForMisbehaviour(clientMessage) +if foundMisbehaviour { + clientState.UpdateStateOnMisbehaviour(clientMessage) + // emit misbehaviour event + return +} + +clientState.UpdateState(clientMessage) // expects no-op on duplicate header + // emit update event + return +} diff --git a/docs/ibc/light-clients/upgrade.md b/docs/ibc/light-clients/upgrades.md similarity index 50% rename from docs/ibc/light-clients/upgrade.md rename to docs/ibc/light-clients/upgrades.md index 6426757dc93..49c1503ae59 100644 --- a/docs/ibc/light-clients/upgrade.md +++ b/docs/ibc/light-clients/upgrades.md @@ -1,51 +1,62 @@ -# Implementing `VerifyUpgradeAndUpdateState` +# Handling upgrades It is vital that high-value IBC clients can upgrade along with their underlying chains to avoid disruption to the IBC ecosystem. Thus, IBC client developers will want to implement upgrade functionality to enable clients to maintain connections and channels even across chain upgrades. -The IBC protocol allows client implementations to provide a path to upgrading clients given the upgraded client state, upgraded consensus state and proofs for each. This path is provided in the `VerifyUpgradeAndUpdateState` function: +## Implementing `VerifyUpgradeAndUpdateState` -```golang +The IBC protocol allows client implementations to provide a path to upgrading clients given the upgraded `ClientState`, upgraded `ConsensusState` and proofs for each. This path is provided in the `VerifyUpgradeAndUpdateState` method: + +```go // NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last height committed by the current revision. Clients are responsible for ensuring that the planned last height of the current revision is somehow encoded in the proof verification process. // This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty may be cancelled or modified before the last planned height. // If the upgrade is verified, the upgraded client and consensus states must be set in the client store. -VerifyUpgradeAndUpdateState( - ctx sdk.Context, - cdc codec.BinaryCodec, - store sdk.KVStore, - newClient ClientState, - newConsState ConsensusState, - proofUpgradeClient, - proofUpgradeConsState []byte, +func (cs ClientState) VerifyUpgradeAndUpdateState( + ctx sdk.Context, + cdc codec.BinaryCodec, + store sdk.KVStore, + newClient ClientState, + newConsState ConsensusState, + proofUpgradeClient, + proofUpgradeConsState []byte, ) error ``` -It is important to note that light clients **must** handle all management of client and consensus states including the setting of updated client state and consensus state in the client store. This can include verifying that the submitted upgraded `ClientState` is of a valid `ClientState` type, that the height of the upgraded client is not greater than the height of the current client (in order to preserve BFT monotonic time), or that certain parameters which should not be changed have not been altered in the upgraded client state. +> Please refer to the [Tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/upgrade.go#L27) as an example for implementation. -Note that the clients should have prior knowledge of the merkle path that the upgraded client and upgraded consensus states will use. The height at which the upgrade has occurred should also be encoded in the proof. The Tendermint client implementation accomplishes this by including an `UpgradePath` in the ClientState itself, which is used along with the upgrade height to construct the merkle path under which the client state and consensus state are committed. +It is important to note that light clients **must** handle all management of client and consensus states including the setting of updated `ClientState` and `ConsensusState` in the client store. This can include verifying that the submitted upgraded `ClientState` is of a valid `ClientState` type, that the height of the upgraded client is not greater than the height of the current client (in order to preserve BFT monotonic time), or that certain parameters which should not be changed have not been altered in the upgraded `ClientState`. -Developers must ensure that the `UpgradeClientMsg` does not pass until the last height of the old chain has been committed, and after the chain upgrades, the `UpgradeClientMsg` should pass once and only once on all counterparty clients. +Developers must ensure that the `MsgUpgradeClient` does not pass until the last height of the old chain has been committed, and after the chain upgrades, the `MsgUpgradeClient` should pass once and only once on all counterparty clients. -Developers must ensure that the new client adopts all of the new Client parameters that must be uniform across every valid light client of a chain (chain-chosen parameters), while maintaining the Client parameters that are customizable by each individual client (client-chosen parameters) from the previous version of the client. +### Upgrade path -Upgrades must adhere to the IBC Security Model. IBC does not rely on the assumption of honest relayers for correctness. Thus users should not have to rely on relayers to maintain client correctness and security (though honest relayers must exist to maintain relayer liveness). While relayers may choose any set of client parameters while creating a new `ClientState`, this still holds under the security model since users can always choose a relayer-created client that suits their security and correctness needs or create a Client with their desired parameters if no such client exists. +Clients should have **prior knowledge of the merkle path** that the upgraded client and upgraded consensus states will use. The height at which the upgrade has occurred should also be encoded in the proof. +> The Tendermint client implementation accomplishes this by including an `UpgradePath` in the `ClientState` itself, which is used along with the upgrade height to construct the merkle path under which the client state and consensus state are committed. -However, when upgrading an existing client, one must keep in mind that there are already many users who depend on this client's particular parameters. We cannot give the upgrading relayer free choice over these parameters once they have already been chosen. This would violate the security model since users who rely on the client would have to rely on the upgrading relayer to maintain the same level of security. Thus, developers must make sure that their upgrade mechanism allows clients to upgrade the chain-specified parameters whenever a chain upgrade changes these parameters (examples in the Tendermint client include `UnbondingPeriod`, `TrustingPeriod`, `ChainID`, `UpgradePath`, etc.), while ensuring that the relayer submitting the `UpgradeClientMsg` cannot alter the client-chosen parameters that the users are relying upon (examples in Tendermint client include `TrustLevel`, `MaxClockDrift`, etc). +## Chain specific vs client specific client parameters -Developers should maintain the distinction between Client parameters that are uniform across every valid light client of a chain (chain-chosen parameters), and Client parameters that are customizable by each individual client (client-chosen parameters); since this distinction is necessary to implement the `ZeroCustomFields` method in the `ClientState` interface: +Developers should maintain the distinction between client parameters that are uniform across every valid light client of a chain (chain-chosen parameters), and client parameters that are customizable by each individual client (client-chosen parameters); since this distinction is necessary to implement the `ZeroCustomFields` method in the [`ClientState` interface](./client-state.md): ```go // Utility function that zeroes out any client customizable fields in client state // Ledger enforced fields are maintained while all custom fields are zero values // Used to verify upgrades -ZeroCustomFields() ClientState +func (cs ClientState) ZeroCustomFields() ClientState ``` -Counterparty clients can upgrade securely by using all of the chain-chosen parameters from the chain-committed `UpgradedClient` and preserving all of the old client-chosen parameters. This enables chains to securely upgrade without relying on an honest relayer, however it can in some cases lead to an invalid final `ClientState` if the new chain-chosen parameters clash with the old client-chosen parameter. This can happen in the Tendermint client case if the upgrading chain lowers the `UnbondingPeriod` (chain-chosen) to a duration below that of a counterparty client's `TrustingPeriod` (client-chosen). Such cases should be clearly documented by developers, so that chains know which upgrades should be avoided to prevent this problem. The final upgraded client should also be validated in `VerifyUpgradeAndUpdateState` before returning to ensure that the client does not upgrade to an invalid `ClientState`. +Developers must ensure that the new client adopts all of the new client parameters that must be uniform across every valid light client of a chain (chain-chosen parameters), while maintaining the client parameters that are customizable by each individual client (client-chosen parameters) from the previous version of the client. `ZeroCustomFields` is a useful utility function to ensure only chain specific fields are updated during upgrades. + +## Security + +Upgrades must adhere to the IBC Security Model. IBC does not rely on the assumption of honest relayers for correctness. Thus users should not have to rely on relayers to maintain client correctness and security (though honest relayers must exist to maintain relayer liveness). While relayers may choose any set of client parameters while creating a new `ClientState`, this still holds under the security model since users can always choose a relayer-created client that suits their security and correctness needs or create a client with their desired parameters if no such client exists. -## Putting it all together +However, when upgrading an existing client, one must keep in mind that there are already many users who depend on this client's particular parameters. **We cannot give the upgrading relayer free choice over these parameters once they have already been chosen. This would violate the security model** since users who rely on the client would have to rely on the upgrading relayer to maintain the same level of security. -Please refer to the [`07-tendermint` implementation](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/modules/light-clients/07-tendermint/upgrade.go#L27) as an example for implementation. \ No newline at end of file +Thus, developers must make sure that their upgrade mechanism allows clients to upgrade the chain-specified parameters whenever a chain upgrade changes these parameters (examples in the Tendermint client include `UnbondingPeriod`, `TrustingPeriod`, `ChainID`, `UpgradePath`, etc), while ensuring that the relayer submitting the `MsgUpgradeClient` cannot alter the client-chosen parameters that the users are relying upon (examples in Tendermint client include `TrustLevel`, `MaxClockDrift`, etc). The previous paragraph discusses how `ZeroCustomFields` helps achieve this. + +### Document potential client parameter conflicts during upgrades + +Counterparty clients can upgrade securely by using all of the chain-chosen parameters from the chain-committed `UpgradedClient` and preserving all of the old client-chosen parameters. This enables chains to securely upgrade without relying on an honest relayer, however it can in some cases lead to an invalid final `ClientState` if the new chain-chosen parameters clash with the old client-chosen parameter. This can happen in the Tendermint client case if the upgrading chain lowers the `UnbondingPeriod` (chain-chosen) to a duration below that of a counterparty client's `TrustingPeriod` (client-chosen). Such cases should be clearly documented by developers, so that chains know which upgrades should be avoided to prevent this problem. The final upgraded client should also be validated in `VerifyUpgradeAndUpdateState` before returning to ensure that the client does not upgrade to an invalid `ClientState`. diff --git a/docs/ibc/upgrades/developer-guide.md b/docs/ibc/upgrades/developer-guide.md index 73a19b93664..671ff4a64d2 100644 --- a/docs/ibc/upgrades/developer-guide.md +++ b/docs/ibc/upgrades/developer-guide.md @@ -6,45 +6,4 @@ order: 2 Learn how to implement upgrade functionality for your custom IBC client. {synopsis} -As mentioned in the [README](./README.md), it is vital that high-value IBC clients can upgrade along with their underlying chains to avoid disruption to the IBC ecosystem. Thus, IBC client developers will want to implement upgrade functionality to enable clients to maintain connections and channels even across chain upgrades. - -The IBC protocol allows client implementations to provide a path to upgrading clients given the upgraded client state, upgraded consensus state and proofs for each. - -```go -// Upgrade functions -// NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last -// height committed by the current revision. Clients are responsible for ensuring that the planned last -// height of the current revision is somehow encoded in the proof verification process. -// This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty -// may be cancelled or modified before the last planned height. -VerifyUpgradeAndUpdateState( - ctx sdk.Context, - cdc codec.BinaryCodec, - store sdk.KVStore, - newClient ClientState, - newConsState ConsensusState, - proofUpgradeClient, - proofUpgradeConsState []byte, -) (upgradedClient ClientState, upgradedConsensus ConsensusState, err error) -``` - -Note that the clients should have prior knowledge of the merkle path that the upgraded client and upgraded consensus states will use. The height at which the upgrade has occurred should also be encoded in the proof. The Tendermint client implementation accomplishes this by including an `UpgradePath` in the ClientState itself, which is used along with the upgrade height to construct the merkle path under which the client state and consensus state are committed. - -Developers must ensure that the `UpgradeClientMsg` does not pass until the last height of the old chain has been committed, and after the chain upgrades, the `UpgradeClientMsg` should pass once and only once on all counterparty clients. - -Developers must ensure that the new client adopts all of the new Client parameters that must be uniform across every valid light client of a chain (chain-chosen parameters), while maintaining the Client parameters that are customizable by each individual client (client-chosen parameters) from the previous version of the client. - -Upgrades must adhere to the IBC Security Model. IBC does not rely on the assumption of honest relayers for correctness. Thus users should not have to rely on relayers to maintain client correctness and security (though honest relayers must exist to maintain relayer liveness). While relayers may choose any set of client parameters while creating a new `ClientState`, this still holds under the security model since users can always choose a relayer-created client that suits their security and correctness needs or create a Client with their desired parameters if no such client exists. - -However, when upgrading an existing client, one must keep in mind that there are already many users who depend on this client's particular parameters. We cannot give the upgrading relayer free choice over these parameters once they have already been chosen. This would violate the security model since users who rely on the client would have to rely on the upgrading relayer to maintain the same level of security. Thus, developers must make sure that their upgrade mechanism allows clients to upgrade the chain-specified parameters whenever a chain upgrade changes these parameters (examples in the Tendermint client include `UnbondingPeriod`, `TrustingPeriod`, `ChainID`, `UpgradePath`, etc.), while ensuring that the relayer submitting the `UpgradeClientMsg` cannot alter the client-chosen parameters that the users are relying upon (examples in Tendermint client include `TrustLevel`, `MaxClockDrift`, etc). - -Developers should maintain the distinction between Client parameters that are uniform across every valid light client of a chain (chain-chosen parameters), and Client parameters that are customizable by each individual client (client-chosen parameters); since this distinction is necessary to implement the `ZeroCustomFields` method in the `ClientState` interface: - -```go -// Utility function that zeroes out any client customizable fields in client state -// Ledger enforced fields are maintained while all custom fields are zero values -// Used to verify upgrades -ZeroCustomFields() ClientState -``` - -Counterparty clients can upgrade securely by using all of the chain-chosen parameters from the chain-committed `UpgradedClient` and preserving all of the old client-chosen parameters. This enables chains to securely upgrade without relying on an honest relayer, however it can in some cases lead to an invalid final `ClientState` if the new chain-chosen parameters clash with the old client-chosen parameter. This can happen in the Tendermint client case if the upgrading chain lowers the `UnbondingPeriod` (chain-chosen) to a duration below that of a counterparty client's `TrustingPeriod` (client-chosen). Such cases should be clearly documented by developers, so that chains know which upgrades should be avoided to prevent this problem. The final upgraded client should also be validated in `VerifyUpgradeAndUpdateState` before returning to ensure that the client does not upgrade to an invalid `ClientState`. +Please see the section [Handling upgrades](../light-clients/upgrades.md) from the light client developer guide for more information. \ No newline at end of file