Synopsis
Learn how to upgrade existing IBC channels. Channel upgradability is an IBC-level protocol that allows chains to leverage new application and channel features without having to create new channels or perform a network-wide upgrade. Prior to this feature, developers who wanted to update an application module or add a middleware to their application flow would need to create a new channel in order to use the updated application feature/middleware, resulting in a loss of the accumulated state/liquidity, token fungibility (as the channel ID is encoded in the IBC denom), and any other larger network effects of losing usage of the existing channel from relayers monitoring, etc. With channel upgradability, applications will be able to implement features such as but not limited to: potentially adding denom metadata to tokens, or utilizing the fee middleware, all while maintaining the channels on which they currently operate. This document outlines the channel upgrade feature, and the multiple steps used in the upgrade process.Channel Upgrade Handshake
Channel upgrades will be achieved using a handshake process that is designed to be similar to the standard connection/channel opening handshake.- The chain initiating the upgrade process will propose an upgrade.
- If the counterparty agrees with the proposal, it will block sends and begin flushing any in-flight packets on its channel end. This flushing process will be covered in more detail below.
- Upon successful completion of the previous step, the initiating chain will also block packet sends and begin flushing any in-flight packets on its channel end.
- Once both channel ends have completed flushing packets within the upgrade timeout window, both channel ends can be opened and upgraded to the new channel fields.
Initializing a Channel Upgrade
A channel upgrade is initialised by submitting theMsgChannelUpgradeInit message, which can be submitted only by the chain itself upon governance authorization. It is possible to upgrade the channel ordering, the channel connection hops, and the channel version, which can be found in the UpgradeFields.
MsgChannelUpgradeInit message, the application’s OnChanUpgradeInit callback will be triggered as well.
After this message is handled successfully, the channel’s upgrade sequence will be incremented. This upgrade sequence will serve as a nonce for the upgrade process to provide replay protection.
Governance gating on ChanUpgradeInit
The message signer for MsgChannelUpgradeInit must be the address which has been designated as the authority of the IBCKeeper. If this proposal passes, the counterparty’s channel will upgrade by default.
If chains want to initiate the upgrade of many channels, they will need to submit a governance proposal with multiple MsgChannelUpgradeInit messages, one for each channel they would like to upgrade, again with message signer as the designated authority of the IBCKeeper. The upgrade-channels CLI command can be used to submit a proposal that initiates the upgrade of multiple channels; see section Upgrading channels with the CLI below for more information.
Channel State and Packet Flushing
FLUSHING and FLUSHCOMPLETE are additional channel states which have been added to enable the upgrade feature.
These states may consist of:
State on the Channel struct:
startFlushing is the specific method which is called in ChanUpgradeTry and ChanUpgradeAck to update the state on the channel end. This will set the timeout on the upgrade and update the channel state to FLUSHING which will block the upgrade from continuing until all in-flight packets have been flushed.
This will also set the upgrade timeout for the counterparty (i.e. the timeout before which the counterparty chain must move from FLUSHING to FLUSHCOMPLETE; if it doesn’t then the chain will cancel the upgrade and write an error receipt). The timeout is a relative time duration in nanoseconds that can be changed with MsgUpdateParams and by default is 10 minutes.
The state will change to FLUSHCOMPLETE once there are no in-flight packets left and the channel end is ready to move to OPEN. This flush state will also have an impact on how a channel upgrade can be cancelled, as detailed below.
All other parameters will remain the same during the upgrade handshake until the upgrade handshake completes. When the channel is reset to OPEN on a successful upgrade handshake, the relevant fields on the channel end will be switched over to the UpgradeFields specified in the upgrade.
When transitioning a channel from UNORDERED to ORDERED, new packet sends from the channel end which upgrades first will be incapable of being timed out until the counterparty has finished upgrading.
Cancelling a Channel Upgrade
Channel upgrade cancellation is performed by submitting aMsgChannelUpgradeCancel message.
It is possible for the authority to cancel an in-progress channel upgrade if the following are true:
- The signer is the authority
- The channel state has not reached FLUSHCOMPLETE
- If the channel state has reached FLUSHCOMPLETE, an existence proof of an
ErrorReceipton the counterparty chain is provided at our upgrade sequence or greater
- An existence proof of an
ErrorReceipton the counterparty chain is provided at our upgrade sequence or greater
Note: if the signer is the authority, e.g. theUpon cancelling a channel upgrade, angovaddress, noErrorReceiptor proof is required if the current channel state is not in FLUSHCOMPLETE. These can be left empty in theMsgChannelUpgradeCancelmessage in that case.
ErrorReceipt will be written with the channel’s current upgrade sequence, and
the channel will move back to OPEN state keeping its original parameters.
It will then be possible to re-initiate an upgrade by sending a MsgChannelOpenInit message.
Timing Out a Channel Upgrade
Timing out an outstanding channel upgrade may be necessary during the flushing packet stage of the channel upgrade process. As stated above, withChanUpgradeTry or ChanUpgradeAck, the channel state has been changed from OPEN to FLUSHING, so no new packets will be allowed to be sent over this channel while flushing. If upgrades cannot be performed in a timely manner (due to unforeseen flushing issues), upgrade timeouts allow the channel to avoid blocking packet sends indefinitely. If flushing exceeds the time limit set in the UpgradeTimeout channel Params, the upgrade process will need to be timed out to abort the upgrade attempt and resume normal channel processing.
Channel upgrades require setting a valid timeout value in the channel Params before submitting a MsgChannelUpgradeTry or MsgChannelUpgradeAck message (by default, 10 minutes):
Upgrade struct itself when flushing is started.
MsgChannelUpgradeTimeout to timeout the channel upgrade process:
ErrorReceipt will be written with the channel’s current upgrade sequence, and the channel will move back to OPEN state keeping its original parameters.
Note that timing out a channel upgrade will end the upgrade process, and a new MsgChannelUpgradeInit will have to be submitted via governance in order to restart the upgrade process.
Pruning Acknowledgements
Acknowledgements can be pruned by broadcasting theMsgPruneAcknowledgements message.
Note: It is only possible to prune acknowledgements after a channel has been upgraded, so pruning will fail if the channel has not yet been upgraded.
port_id and channel_id specify the port and channel to act on, and the limit specifies the upper bound for the number
of acknowledgements and packet receipts to prune.
CLI Usage
Acknowledgements can be pruned via the cli with theprune-acknowledgements command.
IBC App Recommendations
IBC application callbacks should be primarily used to validate data fields and do compatibility checks. Application developers should be aware that callbacks will be invoked before any core ibc state changes are written.OnChanUpgradeInit should validate the proposed version, order, and connection hops, and should return the application version to upgrade to.
OnChanUpgradeTry should validate the proposed version (provided by the counterparty), order, and connection hops. The desired upgrade version should be returned.
OnChanUpgradeAck should validate the version proposed by the counterparty.
OnChanUpgradeOpen should perform any logic associated with changing of the channel fields.
IBC applications should not attempt to process any packet data under the new conditions until after OnChanUpgradeOpen
has been executed, as up until this point it is still possible for the upgrade handshake to fail and for the channel
to remain in the pre-upgraded state.
Upgrade an existing transfer application stack to use 29-fee middleware
Wire up the transfer stack and middleware in app.go
In app.go, the existing transfer stack must be wrapped with the fee middleware.Submit a governance proposal to execute a MsgChannelUpgradeInit message
This process can be performed with the new CLI that has been added outlined here.Only the configured authority for the ibc module is able to initiate a channel upgrade by submitting a
MsgChannelUpgradeInit message.
Execute a governance proposal specifying the relevant fields to perform a channel upgrade.
Update the following json sample, and copy the contents into proposal.json.
Note: ensure the correct fields.version is specified. This is the new version that the channels will be upgraded to.
Submit the proposal
Upgrading channels with the CLI
A new cli has been added which enables either - submitting a governance proposal which contains aMsgChannelUpgradeInit for every channel to be upgraded.
- generating a proposal.json file which contains the proposal contents to be edited/submitted at a later date.
The following example, would submit a governance proposal with the specified deposit, title and summary which would
contain a MsgChannelUpgradeInit for all OPEN channels whose port matches the regular expression transfer.
Note: by adding the--jsonflag, the command would instead output the contents of the proposal which could be stored in aproposal.jsonfile to be edited and submitted at a later date.
--port-pattern (which defaults to transfer) still applies.
For example the following command would generate the contents of a proposal.json file which would attempt to upgrade
channels with a port ID of transfer and a channelID of channel-0, channel-1 or channel-2.