-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IBC Upgrade docs #8298
IBC Upgrade docs #8298
Changes from 4 commits
ae80d21
8cbe60a
ae3b1af
9b0492a
37e0686
6e25e9f
74d5412
fce5bc7
2a6f315
9edd8db
00e0a7f
ee1669e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# IBC Client Developer Guide to Upgrades | ||
AdityaSripal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
As mentioned in the [overview](./overview.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.BinaryMarshaler, | ||
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. In the Tendermint client implementation, the upgrade height is encoded in the proof key. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
where do clients know this info? I'd be nice to add that |
||
|
||
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. | ||
|
||
Upgrades must also adhere to the IBC Security Model. IBC does not rely on the assumption of honest relayers. While relayers may choose any set of client parameters while creating a new `Client`, this still holds under the 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. 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. Thus, we cannot give the upgrading relayer free choice over these parameters once they have already been chosen. 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`, `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 `TrustingPeriod`, `TrustLevel`, `MaxClockDrift`, etc). | ||
colin-axner marked this conversation as resolved.
Show resolved
Hide resolved
colin-axner marked this conversation as resolved.
Show resolved
Hide resolved
colin-axner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Developers should maintain this 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: | ||
AdityaSripal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```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`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
### Upgrading IBC Chains Overview | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto |
||
|
||
This directory contains information on how to upgrade an IBC chain without breaking counterparty clients and connections. | ||
|
||
IBC-connnected chains must be able to upgrade without breaking connections to other chains. Otherwise there would be a massive disincentive towards upgrading and disrupting high-value IBC connections, thus preventing chains in the IBC ecosystem from evolving and improving. Many chain upgrades may be irrelevant to IBC, however some upgrades could potentially break counterparty clients if not handled correctly. Thus, any IBC chain that wishes to perform a IBC-client-breaking upgrade must perform an IBC upgrade in order to allow counterparty clients to securely upgrade to the new light client. | ||
|
||
1. The [quick-guide](./quick-guide.md) describes how IBC-connected chains can perform client-breaking upgrades and how relayers can securely upgrade counterparty clients using the SDK. | ||
2. The [developer-guide](./developer-guide.md) is a guide for developers intending to develop IBC client implementations with upgrade functionality. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# How to Upgrade IBC Chains and their Clients | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand the difference with the first doc from this title There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doc is intended for the end users of the upgrade process. Relayers and stake holders of the upgrading chain. |
||
|
||
The information in this doc for upgrading chains is relevant to SDK chains. However, the guide for counterparty clients is relevant to any Tendermint client that enables upgrades. | ||
|
||
## Upgrading Chains | ||
colin-axner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
### IBC Client Breaking Upgrades | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should outline the types of upgrades that clients could encounter (planned, unplanned) and with breaking an non-breaking state machine changes. This doc should also document the recommended steps for each of the 4 combinations There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup good point. Currently unplanned upgrades are not supported. All of the cases given only apply if they are planned. Will write this point in. |
||
|
||
IBC-connected chains must perform an IBC upgrade if their upgrade will break counterparty IBC clients. The current IBC protocol supports upgrading tendermint chains for a specific subset of IBC-client-breaking upgrades. Here is the exhaustive list of IBC client-breaking upgrades and whether the IBC protocol currently supports such upgrades. | ||
AdityaSripal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Note: Since upgrades are only implemented for Tendermint clients, this doc only discusses upgrades on Tendermint chains that would break counterparty IBC Tendermint Clients. | ||
|
||
1. Changing the Chain-ID: **Supported** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Future improvements may turn this list to a flowchart |
||
2. Changing the UnbondingPeriod: **Partially Supported**, chains may increase the unbonding period with no issues. However, decreasing the unbonding period may irreversibly break some counterparty clients. Thus, it is **not recommended** that chains reduce the unbonding period. | ||
3. Changing the height (resetting to 0): **Supported**, so long as chains remember to increment the revision number in their chain-id. | ||
4. Changing the ProofSpecs: **Supported**, this should be changed if the proof structure needed to verify IBC proofs is changed across the upgrade. Ex: Switching from an IAVL store, to a SimpleTree Store | ||
5. Changing the UpgradePath: **Supported**, this might involve changing the key under which upgraded clients and consensus states are stored in the upgrade store, or even migrating the upgrade store itself. | ||
6. Migrating the IBC store: **Unsupported**, as the IBC store location is negotiated by the connection. | ||
7. Upgrading to a IBC path-breaking version of IBC: **Unsupported**, as IBC version is negotiated on connection handshake. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't it supported so long as the old versions use the old path? Adding support for a new version with new path should be supported There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider chainA and chainB are connected by an IBC channel. chainA decides to upgrade to a different version of IBC such that the paths in This is theoretically possible by using the upgraded client state and then "converting" it into a new type that implements the different However, the IBC version that is used is negotiated in the connection. So that field needs to change as well which isn't supported with client upgrades. Upgrading and breaking IBC paths is theoretically possible, it just isn't implemented yet and client upgrades alone will not upgrade the connection. Technically the new IBC version could also store information in the old paths as well, and thus create "backwards-compatibility" for old connections, but this wouldn't be path breaking. cc: @cwgoes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer to avoid duplicating storage, though it is possible. Generally upgrading the version of IBC is a completely separate concern from upgrading a particular light client algorithm, and it should be treated as such - for example, the IBC version needs to be agreed on by both ends, while the light client versions are independent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (sorry, I may have misunderstood the original comment - the light client upgrades should support changing paths used by the light client algorithm, but not IBC protocol paths in general, I think) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we could add this for clarity. It may not be immediately clear what a |
||
8. Changing the Tendermint LightClient algorithm: **Partially Supported**. Changes to the light client algorithm that do not change the ClientState or ConsensusState struct may be supported, provided that the counterparty is also upgraded to support the new light client algorithm. Changes that require updating the ClientState and ConsensusState structs themselves are theoretically possible by providing a path to translate an older ClientState struct into the new ClientState struct; however this is not currently implemented. | ||
|
||
### Upgrade Process for SDK chains | ||
|
||
If the IBC-connected chain is conducting an upgrade that will break counterparty clients, it must ensure that the upgrade is first supported by IBC using the list above and then execute the upgrade process described below in order to prevent counterparty clients from breaking. | ||
|
||
1. Create a `SoftwareUpgradeProposal` with an `UpgradePlan` that includes the new IBC ClientState in the `UpgradedClientState`. Note that the `UpgradePlan` must specify an upgrade height **only** (no upgrade time), and the `ClientState` should only include the fields common to all valid clients and zero out any client-customizable fields (such as TrustingPeriod). | ||
|
||
Upon the `SoftwareUpgradeProposal` passing, the upgrade module will commit the UpgradedClient under the key: `upgrade/UpgradedIBCState/{upgradeHeight}/upgradedClient`. On the block right before the upgrade height, the upgrade module will also commit an initial consensus state for the next chain under the key: `upgrade/UpgradedIBCState/{upgradeHeight}/upgradedConsState`. | ||
|
||
Once the chain reaches the upgrade height and halts, a relayer can upgrade the counterparty clients to the last block of the old chain. They can then submit the proofs of the `UpgradedClient` and `UpgradedConsensusState` against this last block and upgrade the counterparty client. | ||
|
||
### Upgrade Process for Relayers Upgrading Counterparty Clients | ||
|
||
Once the upgrading chain has committed to upgrading, relayers must wait till the chain halts at the upgrade height before upgrading counterparty clients. This is because chains may reschedule or cancel upgrade plans before they occur. Thus, relayers must wait till the chain reaches the upgrade height and halts before they can be sure the upgrade will take place. | ||
|
||
Thus, the upgrade process for relayers trying to upgrade the counterparty clients is as follows: | ||
|
||
1. Wait for the upgrading chain to reach the upgrade height and halt | ||
2. Query a full node for the proofs of `UpgradedClient` and `UpgradedConsensusState` at the last height of the old chain. | ||
3. Update the counterparty client to the last height of the old chain using the `UpdateClient` msg. | ||
4. Submit an `UpgradeClient` msg to the counterpart chain with the `UpgradedClient`, `UpgradedConsensusState` and their respective proofs. | ||
AdityaSripal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The Tendermint client on the counterparty chain will verify that the upgrading chain did indeed commit to the upgraded client and upgraded consensus state at the upgrade height (since the upgrade height is included in the key). If the proofs are verified against the upgrade height, then the client will upgrade to the new client while retaining all of its client-customized fields. Thus, it will retain its old TrustingPeriod, TrustLevel, MaxClockDrift, etc; while adopting the new chain-specified fields such as UnbondingPeriod, ChainId, UpgradePath, etc. Note, this can lead to an invalid client since the old client-chosen fields may no longer be valid given the new chain-chosen fields. Upgrading chains should try to avoid these situations by not altering parameters that can break old clients. For an example, see the UnbondingPeriod example in the supported upgrades section. | ||
colin-axner marked this conversation as resolved.
Show resolved
Hide resolved
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This document is specifically for developers who are trying to implement an IBC client. It is not relevant for end users. Is there a better title you had in mind that makes it clear this is for developers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, it's just that client developer sounds like wallets, exchanges, etc. Maybe light client devs?