本文旨在重点说明一些重要变更,这些变更可能需要比 CHANGELOG 中提供的更多信息。 凡是 ibc-go 用户必须执行的变更,都应记录在此文档中。 本文档按四类潜在用户群体分为四个部分:
  • 链
  • IBC 应用
  • 中继器
  • IBC 轻客户端
注意: ibc-go 遵循 Golang 语义化版本规范,因此所有导入路径都必须在主版本发布时更新版本号。
github.com/cosmos/ibc-go/v3 -> github.com/cosmos/ibc-go/v4
从 ibc-go 的 v1 或 v2 升级时,不需要执行 genesis 迁移或原地迁移。

链

ICS27 - 链间账户

控制器子模块现在实现的是 05-port Middleware 接口,而不是 05-port IBCModule 接口。集成控制器子模块的链需要使用 NewIBCMiddleware 构造函数来创建它。例如:
- icacontroller.NewIBCModule(app.ICAControllerKeeper, icaAuthIBCModule)
+ icacontroller.NewIBCMiddleware(icaAuthIBCModule, app.ICAControllerKeeper)
其中,icaAuthIBCModule 是链间账户认证 IBC 模块。

ICS29 - 手续费中间件

顾名思义,Fee Middleware 模块承担 IBC 中间件的角色,因此链开发者必须正确配置它,以便正确路由和处理 IBC 消息。 请阅读 Fee Middleware 集成文档,深入了解如何正确配置该模块,从而为 IBC 数据包提供激励。 可参考以下 diff,查看如何为 ics27 通道提供激励的示例配置。

修复支持带斜杠基础面额的迁移

作为 v1.5.0、v2.3.0 和 v3.1.0 的一部分,文档中曾提供过一些迁移处理器代码示例,需要运行这些代码,以修正通过 ICS20 转移且其基础面额包含斜杠的代币追踪信息。 根据社区反馈,我们现在提供了一个改进方案,用于执行同样的迁移。该方案不再需要从迁移文档中复制大段代码,而只需要增加一行升级处理器。 如果链要迁移为支持带斜杠的基础面额,则必须在 app.go 中执行升级处理器时设置相应参数:
app.UpgradeKeeper.SetUpgradeHandler("MigrateTraces",
  func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
    // transfer module consensus version has been bumped to 2
    return app.mm.RunMigrations(ctx, app.configurator, fromVM)
})
如果链在升级支持该特性之前就接收到了基础面额中带斜杠的代币,则接收过程可能会通过,但追踪信息会不正确。 例如,如果基础面额 testcoin/testcoin/testcoin 被发送到一条尚不支持基础面额中包含斜杠的链上,接收会成功。但接收链上存储的追踪信息将为:Trace: "transfer/{channel-id}/testcoin/testcoin", BaseDenom: "testcoin"。 当链升级为完全支持带斜杠的面额时,必须修正这类错误的追踪信息。

IBC 应用

ICS03 - 连接

03-connection 握手协商中已移除 crossing hellos。 MsgConnectionOpenTry 中的 PreviousConnectionId 已被弃用,核心 IBC 不再使用它。 由于不再支持 crossing hellos,NewMsgConnectionOpenTry 不再接收 PreviousConnectionId。若该消息中的 PreviousConnectionId 非空,则基础校验会失败。

ICS04 - 通道

WriteAcknowledgement API 现在接收 exported.Acknowledgement 类型,而不是直接传入 acknowledgement 字节数组。 这是一个 API 破坏性变更,因此 IBC 应用开发者需要更新所有对 WriteAcknowledgement 的调用。 OnChanOpenInit 应用回调已被修改。 返回签名现在包含应用版本,具体见最新 IBC 规范变更。 NewErrorAcknowledgement 方法签名已变更。 它现在接收 error 而不是 string。这样做是为了防止意外的状态变更。 现在所有错误 acknowledgement 都包含确定性的 ABCI 代码和错误消息。应用开发者有责任在事件中输出错误详情。 04-channel 握手协商中已移除 crossing hellos。 IBC 应用不再需要在 OnChanOpenTry 回调中处理已声明 capability 的情况。核心 IBC 提供的 capability 必须能够以无错误方式被声明。 MsgChannelOpenTry 中的 PreviousChannelId 已被弃用,核心 IBC 不再使用它。 由于不再支持 crossing hellos,NewMsgChannelOpenTry 不再接收 PreviousChannelId。若该消息中的 PreviousChannelId 非空,则基础校验会失败。

ICS27 - 链间账户

RegisterInterchainAccount API 已修改,新增了一个 version 参数。此变更是为了支持 ICS29 fee middleware,从而为 ICS27 数据包提供中继激励。 RegisterInterchainAccount 的调用方现在需要自行构造合适的 JSON 编码版本字符串,并将其传入。 这应当在链间账户认证模块中完成,该模块会使用链间账户 controllerKeeper 暴露的 API。如果在 version 参数中传入空字符串,则控制器处理器的 OnChanOpenInit 回调会将版本初始化为默认值,以便通道握手继续进行。 以下代码片段演示了如何构造合适的链间账户 Metadata 并将其编码为 JSON 字节串:
icaMetadata := icatypes.Metadata{
    Version:                icatypes.Version,
    ControllerConnectionId: controllerConnectionID,
    HostConnectionId:       hostConnectionID,
    Encoding:               icatypes.EncodingProtobuf,
    TxType:                 icatypes.TxTypeSDKMultiMsg,
}

appVersion, err := icatypes.ModuleCdc.MarshalJSON(&icaMetadata)
    if err != nil {
    return err
}
    if err := k.icaControllerKeeper.RegisterInterchainAccount(ctx, msg.ConnectionId, msg.Owner, string(appVersion)); err != nil {
    return err
}
类似地,如果应用栈被配置为通过 ICS29 fee middleware 路由,并且希望使用启用手续费的通道,则需要构造合适的 ICS29 Metadata 类型:
icaMetadata := icatypes.Metadata{
    Version:                icatypes.Version,
    ControllerConnectionId: controllerConnectionID,
    HostConnectionId:       hostConnectionID,
    Encoding:               icatypes.EncodingProtobuf,
    TxType:                 icatypes.TxTypeSDKMultiMsg,
}

appVersion, err := icatypes.ModuleCdc.MarshalJSON(&icaMetadata)
    if err != nil {
    return err
}
    feeMetadata := feetypes.Metadata{
    AppVersion: string(appVersion),
    FeeVersion: feetypes.Version,
}

feeEnabledVersion, err := feetypes.ModuleCdc.MarshalJSON(&feeMetadata)
    if err != nil {
    return err
}
    if err := k.icaControllerKeeper.RegisterInterchainAccount(ctx, msg.ConnectionId, msg.Owner, string(feeEnabledVersion)); err != nil {
    return err
}

中继器

在使用 DenomTrace gRPC 时,现在可以传入带有 ibc/ 前缀的完整 IBC 面额。 对于 03-connection 和 04-channel,核心 IBC 已不再支持 crossing hellos。握手应按照逻辑上的四步流程完成(INIT、TRY、ACK、CONFIRM)。
This document is intended to highlight significant changes which may require more information than presented in the CHANGELOG. Any changes that must be done by a user of ibc-go should be documented here. There are four sections based on the four potential user groups of this document:
  • Chains
  • IBC Apps
  • Relayers
  • IBC Light Clients
Note: ibc-go supports golang semantic versioning and therefore all imports must be updated to bump the version number on major releases.
github.com/cosmos/ibc-go/v3 -> github.com/cosmos/ibc-go/v4
No genesis or in-place migrations required when upgrading from v1 or v2 of ibc-go.

Chains

ICS27 - Interchain Accounts

The controller submodule implements now the 05-port Middleware interface instead of the 05-port IBCModule interface. Chains that integrate the controller submodule, need to create it with the NewIBCMiddleware constructor function. For example:
- icacontroller.NewIBCModule(app.ICAControllerKeeper, icaAuthIBCModule)
+ icacontroller.NewIBCMiddleware(icaAuthIBCModule, app.ICAControllerKeeper)
where icaAuthIBCModule is the Interchain Accounts authentication IBC Module.

ICS29 - Fee Middleware

The Fee Middleware module, as the name suggests, plays the role of an IBC middleware and as such must be configured by chain developers to route and handle IBC messages correctly. Please read the Fee Middleware integration documentation for an in depth guide on how to configure the module correctly in order to incentivize IBC packets. Take a look at the following diff for an example setup of how to incentivize ics27 channels.

Migration to fix support for base denoms with slashes

As part of v1.5.0, v2.3.0 and v3.1.0 some migration handler code sample was documented that needs to run in order to correct the trace information of coins transferred using ICS20 whose base denom contains slashes. Based on feedback from the community we add now an improved solution to run the same migration that does not require copying a large piece of code over from the migration document, but instead requires only adding a one-line upgrade handler. If the chain will migrate to supporting base denoms with slashes, it must set the appropriate params during the execution of the upgrade handler in app.go:
app.UpgradeKeeper.SetUpgradeHandler("MigrateTraces",
  func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
    / transfer module consensus version has been bumped to 2
    return app.mm.RunMigrations(ctx, app.configurator, fromVM)
})
If a chain receives coins of a base denom with slashes before it upgrades to supporting it, the receive may pass however the trace information will be incorrect. E.g. If a base denom of testcoin/testcoin/testcoin is sent to a chain that does not support slashes in the base denom, the receive will be successful. However, the trace information stored on the receiving chain will be: Trace: "transfer/{channel-id}/testcoin/testcoin", BaseDenom: "testcoin". This incorrect trace information must be corrected when the chain does upgrade to fully supporting denominations with slashes.

IBC Apps

ICS03 - Connection

Crossing hellos have been removed from 03-connection handshake negotiation. PreviousConnectionId in MsgConnectionOpenTry has been deprecated and is no longer used by core IBC. NewMsgConnectionOpenTry no longer takes in the PreviousConnectionId as crossing hellos are no longer supported. A non-empty PreviousConnectionId will fail basic validation for this message.

ICS04 - Channel

The WriteAcknowledgement API now takes the exported.Acknowledgement type instead of passing in the acknowledgement byte array directly. This is an API breaking change and as such IBC application developers will have to update any calls to WriteAcknowledgement. The OnChanOpenInit application callback has been modified. The return signature now includes the application version as detailed in the latest IBC spec changes. The NewErrorAcknowledgement method signature has changed. It now accepts an error rather than a string. This was done in order to prevent accidental state changes. All error acknowledgements now contain a deterministic ABCI code and error message. It is the responsibility of the application developer to emit error details in events. Crossing hellos have been removed from 04-channel handshake negotiation. IBC Applications no longer need to account from already claimed capabilities in the OnChanOpenTry callback. The capability provided by core IBC must be able to be claimed with error. PreviousChannelId in MsgChannelOpenTry has been deprecated and is no longer used by core IBC. NewMsgChannelOpenTry no longer takes in the PreviousChannelId as crossing hellos are no longer supported. A non-empty PreviousChannelId will fail basic validation for this message.

ICS27 - Interchain Accounts

The RegisterInterchainAccount API has been modified to include an additional version argument. This change has been made in order to support ICS29 fee middleware, for relayer incentivization of ICS27 packets. Consumers of the RegisterInterchainAccount are now expected to build the appropriate JSON encoded version string themselves and pass it accordingly. This should be constructed within the interchain accounts authentication module which leverages the APIs exposed via the interchain accounts controllerKeeper. If an empty string is passed in the version argument, then the version will be initialized to a default value in the OnChanOpenInit callback of the controller’s handler, so that channel handshake can proceed. The following code snippet illustrates how to construct an appropriate interchain accounts Metadata and encode it as a JSON bytestring:
icaMetadata := icatypes.Metadata{
    Version:                icatypes.Version,
    ControllerConnectionId: controllerConnectionID,
    HostConnectionId:       hostConnectionID,
    Encoding:               icatypes.EncodingProtobuf,
    TxType:                 icatypes.TxTypeSDKMultiMsg,
}

appVersion, err := icatypes.ModuleCdc.MarshalJSON(&icaMetadata)
    if err != nil {
    return err
}
    if err := k.icaControllerKeeper.RegisterInterchainAccount(ctx, msg.ConnectionId, msg.Owner, string(appVersion)); err != nil {
    return err
}
Similarly, if the application stack is configured to route through ICS29 fee middleware and a fee enabled channel is desired, construct the appropriate ICS29 Metadata type:
icaMetadata := icatypes.Metadata{
    Version:                icatypes.Version,
    ControllerConnectionId: controllerConnectionID,
    HostConnectionId:       hostConnectionID,
    Encoding:               icatypes.EncodingProtobuf,
    TxType:                 icatypes.TxTypeSDKMultiMsg,
}

appVersion, err := icatypes.ModuleCdc.MarshalJSON(&icaMetadata)
    if err != nil {
    return err
}
    feeMetadata := feetypes.Metadata{
    AppVersion: string(appVersion),
    FeeVersion: feetypes.Version,
}

feeEnabledVersion, err := feetypes.ModuleCdc.MarshalJSON(&feeMetadata)
    if err != nil {
    return err
}
    if err := k.icaControllerKeeper.RegisterInterchainAccount(ctx, msg.ConnectionId, msg.Owner, string(feeEnabledVersion)); err != nil {
    return err
}

Relayers

When using the DenomTrace gRPC, the full IBC denomination with the ibc/ prefix may now be passed in. Crossing hellos are no longer supported by core IBC for 03-connection and 04-channel. The handshake should be completed in the logical 4 step process (INIT, TRY, ACK, CONFIRM).