本文档介绍了如何将 SDK 0.41.x 和 0.42.x 分支中包含的 IBC 模块迁移到基于 SDK 0.44 版本的 ibc-go 仓库中的 IBC 模块。

导入变更

最明显的变化是导入名发生了变化。我们需要将:
  • applications -> apps
  • cosmos-sdk/x/ibc -> ibc-go
在我的 GNU/Linux 机器上,我按顺序执行了以下命令:
grep -RiIl 'cosmos-sdk\/x\/ibc\/applications' | xargs sed -i 's/cosmos-sdk\/x\/ibc\/applications/ibc-go\/modules\/apps/g'
grep -RiIl 'cosmos-sdk\/x\/ibc' | xargs sed -i 's/cosmos-sdk\/x\/ibc/ibc-go\/modules/g'
参考:上述命令说明 如果不按顺序执行这些命令,会导致问题。 你也可以使用自己习惯的方法来修改导入名。 注意:升级到 v0.44.0 SDK 版本后再执行 go mod tidy,会为了兼容旧的 IBC 导入路径而降级到 v0.42.0。 请先更新导入路径,再执行 go mod tidy。

链升级

链可以选择通过升级提案或创世升级进行升级。支持原地存储迁移和创世迁移。 警告:在升级链之前,请至少阅读 IBC 客户端升级 的快速指南。强烈建议你不要在升级期间修改 chain-ID,否则必须遵循 IBC 客户端升级说明。 无论是原地存储迁移还是创世迁移,都会:
  • 将 solo machine 客户端状态从 v1 protobuf 定义迁移到 v2 protobuf 定义
  • 修剪所有 solo machine 共识状态
  • 修剪所有已过期的 tendermint 共识状态
链必须在原地存储迁移或创世迁移期间设置一个新的连接参数。这个新参数 max expected block time 用于在 IBC 数据包流程的接收端强制执行数据包处理延迟。

原地存储迁移

新的链二进制需要在升级处理器中运行迁移。IBC 模块的 fromVM(前一个模块版本)应为 1。这样 IBC 的迁移才能执行,并将版本从 1 更新到 2。 示例:
app.UpgradeKeeper.SetUpgradeHandler("my-upgrade-proposal",
  func(ctx sdk.Context, _ upgradetypes.Plan, _ module.VersionMap) (module.VersionMap, error) {
    / set max expected block time parameter. Replace the default with your expected value
    app.IBCKeeper.ConnectionKeeper.SetParams(ctx, ibcconnectiontypes.DefaultParams())
    fromVM := map[string]uint64{
      ... / other modules
      "ibc":          1,
      ...
}

return app.mm.RunMigrations(ctx, app.configurator, fromVM)
})

创世迁移

要执行创世迁移,需要将以下代码添加到你现有的迁移代码中。
/ add imports as necessary
import (
    
  ibcv100 "github.com/cosmos/ibc-go/modules/core/legacy/v100"
  ibchost "github.com/cosmos/ibc-go/modules/core/24-host"
)

...

/ add in migrate cmd function
/ expectedTimePerBlock is a new connection parameter
newGenState, err = ibcv100.MigrateGenesis(newGenState, clientCtx, *genDoc, expectedTimePerBlock)
    if err != nil {
    return err
}
注意: 在迁移 IBC 之前,必须先更新创世 chain-id、时间和高度,否则 tendermint 共识状态将不会被修剪。

IBC Keeper 变更

IBC Keeper 现在需要传入 Upgrade Keeper。请在 StakingKeeper 之后添加链的 UpgradeKeeper:
/ Create IBC Keeper
app.IBCKeeper = ibckeeper.NewKeeper(
- appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, scopedIBCKeeper,
+ appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper,
)

提案

UpdateClientProposal

UpdateClient 已修改为接收两个 client identifier 和一个初始高度。

UpgradeProposal

新增了一种 IBC 提案类型 UpgradeProposal,用于处理 IBC 的破坏性升级。 升级 Plan 中原有的 UpgradedClientState 字段已废弃,改为使用这种新的提案类型。

提案处理器注册

ClientUpdateProposalHandler 已重命名为 ClientProposalHandler。 它同时处理 UpdateClientProposal 和 UpgradeProposal。 添加以下导入:
+  ibcclienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types"
请确保治理模块添加了正确的路由:
-  AddRoute(ibchost.RouterKey, ibcclient.NewClientUpdateProposalHandler(app.IBCKeeper.ClientKeeper))
+  AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper))
注意:simapp 在 0.41.x 版本中的注册方式是不正确的。UpdateClient 提案处理器应当使用属于 ibc-go/core/02-client/types 的路由键进行注册, 如上面的 diff 所示。

提案 CLI 注册

请确保通过向 gov.NewAppModuleBasic() 添加以下参数,在治理模块中注册这两种提案类型的 CLI 命令: 添加以下导入:
+  ibcclientclient "github.com/cosmos/ibc-go/modules/core/02-client/client"
注册 CLI 命令:
gov.NewAppModuleBasic(
  paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler,
+ ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler,
),
这些提案不支持 REST 路由。

Proto 文件变更

gRPC 查询服务端点有少量变化。之前的文件使用的是 v1beta1 gRPC 路由,现在已更新为 v1。 solo machine 将 FrozenSequence 的 uint64 字段替换为 IsFrozen 布尔字段。对应的包版本也从 v1 升级到了 v2。

IBC 回调变更

OnRecvPacket

应用开发者需要更新其 OnRecvPacket 回调逻辑。 OnRecvPacket 回调现在只返回 acknowledgement。返回的 acknowledgement 必须实现 Acknowledgement 接口。该 acknowledgement 应通过在 Success() 上返回 true 来表明数据包已成功处理,其他所有情况都应返回 false。如果 Success() 返回 false,则回调中发生的所有状态变更都会被丢弃。更多信息请参见文档。 OnRecvPacket、OnAcknowledgementPacket 和 OnTimeoutPacket 回调现在都会接收中继该 IBC 数据包的 relayer 的 sdk.AccAddress。应用可以使用或忽略该信息。

IBC 事件变更

packet_data 属性已废弃,改为使用 packet_data_hex,以便为事件中的数据包数据提供标准化的编码/解码方式。虽然 packet_data 事件仍然存在,但强烈建议所有 relayer 和 IBC 事件消费者尽快切换到 packet_data_hex。 packet_ack 属性也因相同原因废弃,改为使用 packet_ack_hex。强烈建议所有 relayer 和 IBC 事件消费者尽快切换到 packet_ack_hex。 已移除 Misbehaviour 事件中的 consensus_height 属性。IBC 客户端不再具有 frozen height,且 misbehaviour 也不一定关联某个高度。

相关 SDK 变更

  • (codec)#9226 重命名了 codec 接口和方法,以遵循 Go 接口的一般惯例:
    • codec.Marshaler → codec.Codec(用于定义对其他对象进行序列化的对象)
    • codec.BinaryMarshaler → codec.BinaryCodec
    • codec.JSONMarshaler → codec.JSONCodec
    • 从 BinaryCodec 方法中移除了 BinaryBare 后缀(MarshalBinaryBare、UnmarshalBinaryBare 等)
    • 从 BinaryCodec 方法中移除了 Binary 中缀(MarshalBinaryLengthPrefixed、UnmarshalBinaryLengthPrefixed 等)

This file contains information on how to migrate from the IBC module contained in the SDK 0.41.x and 0.42.x lines to the IBC module in the ibc-go repository based on the 0.44 SDK version.

Import Changes

The most obvious changes is import name changes. We need to change:
  • applications -> apps
  • cosmos-sdk/x/ibc -> ibc-go
On my GNU/Linux based machine I used the following commands, executed in order:
grep -RiIl 'cosmos-sdk\/x\/ibc\/applications' | xargs sed -i 's/cosmos-sdk\/x\/ibc\/applications/ibc-go\/modules\/apps/g'
grep -RiIl 'cosmos-sdk\/x\/ibc' | xargs sed -i 's/cosmos-sdk\/x\/ibc/ibc-go\/modules/g'
ref: explanation of the above commands Executing these commands out of order will cause issues. Feel free to use your own method for modifying import names. NOTE: Updating to the v0.44.0 SDK release and then running go mod tidy will cause a downgrade to v0.42.0 in order to support the old IBC import paths. Update the import paths before running go mod tidy.

Chain Upgrades

Chains may choose to upgrade via an upgrade proposal or genesis upgrades. Both in-place store migrations and genesis migrations are supported. WARNING: Please read at least the quick guide for IBC client upgrades before upgrading your chain. It is highly recommended you do not change the chain-ID during an upgrade, otherwise you must follow the IBC client upgrade instructions. Both in-place store migrations and genesis migrations will:
  • migrate the solo machine client state from v1 to v2 protobuf definitions
  • prune all solo machine consensus states
  • prune all expired tendermint consensus states
Chains must set a new connection parameter during either in place store migrations or genesis migration. The new parameter, max expected block time, is used to enforce packet processing delays on the receiving end of an IBC packet flow.

In-Place Store Migrations

The new chain binary will need to run migrations in the upgrade handler. The fromVM (previous module version) for the IBC module should be 1. This will allow migrations to be run for IBC updating the version from 1 to 2. Ex:
app.UpgradeKeeper.SetUpgradeHandler("my-upgrade-proposal",
  func(ctx sdk.Context, _ upgradetypes.Plan, _ module.VersionMap) (module.VersionMap, error) {
    / set max expected block time parameter. Replace the default with your expected value
    app.IBCKeeper.ConnectionKeeper.SetParams(ctx, ibcconnectiontypes.DefaultParams())
    fromVM := map[string]uint64{
      ... / other modules
      "ibc":          1,
      ...
}

return app.mm.RunMigrations(ctx, app.configurator, fromVM)
})

Genesis Migrations

To perform genesis migrations, the following code must be added to your existing migration code.
/ add imports as necessary
import (
    
  ibcv100 "github.com/cosmos/ibc-go/modules/core/legacy/v100"
  ibchost "github.com/cosmos/ibc-go/modules/core/24-host"
)

...

/ add in migrate cmd function
/ expectedTimePerBlock is a new connection parameter
newGenState, err = ibcv100.MigrateGenesis(newGenState, clientCtx, *genDoc, expectedTimePerBlock)
    if err != nil {
    return err
}
NOTE: The genesis chain-id, time and height MUST be updated before migrating IBC, otherwise the tendermint consensus state will not be pruned.

IBC Keeper Changes

The IBC Keeper now takes in the Upgrade Keeper. Please add the chains’ Upgrade Keeper after the Staking Keeper:
/ Create IBC Keeper
app.IBCKeeper = ibckeeper.NewKeeper(
- appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, scopedIBCKeeper,
+ appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper,
)

Proposals

UpdateClientProposal

The UpdateClient has been modified to take in two client-identifiers and one initial height.

UpgradeProposal

A new IBC proposal type has been added, UpgradeProposal. This handles an IBC (breaking) Upgrade. The previous UpgradedClientState field in an Upgrade Plan has been deprecated in favor of this new proposal type.

Proposal Handler Registration

The ClientUpdateProposalHandler has been renamed to ClientProposalHandler. It handles both UpdateClientProposals and UpgradeProposals. Add this import:
+  ibcclienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types"
Please ensure the governance module adds the correct route:
-  AddRoute(ibchost.RouterKey, ibcclient.NewClientUpdateProposalHandler(app.IBCKeeper.ClientKeeper))
+  AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper))
NOTE: Simapp registration was incorrect in the 0.41.x releases. The UpdateClient proposal handler should be registered with the router key belonging to ibc-go/core/02-client/types as shown in the diffs above.

Proposal CLI Registration

Please ensure both proposal type CLI commands are registered on the governance module by adding the following arguments to gov.NewAppModuleBasic(): Add the following import:
+  ibcclientclient "github.com/cosmos/ibc-go/modules/core/02-client/client"
Register the cli commands:
gov.NewAppModuleBasic(
  paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler,
+ ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler,
),
REST routes are not supported for these proposals.

Proto file changes

The gRPC querier service endpoints have changed slightly. The previous files used v1beta1 gRPC route, this has been updated to v1. The solo machine has replaced the FrozenSequence uint64 field with a IsFrozen boolean field. The package has been bumped from v1 to v2

IBC callback changes

OnRecvPacket

Application developers need to update their OnRecvPacket callback logic. The OnRecvPacket callback has been modified to only return the acknowledgement. The acknowledgement returned must implement the Acknowledgement interface. The acknowledgement should indicate if it represents a successful processing of a packet by returning true on Success() and false in all other cases. A return value of false on Success() will result in all state changes which occurred in the callback being discarded. More information can be found in the documentation. The OnRecvPacket, OnAcknowledgementPacket, and OnTimeoutPacket callbacks are now passed the sdk.AccAddress of the relayer who relayed the IBC packet. Applications may use or ignore this information.

IBC Event changes

The packet_data attribute has been deprecated in favor of packet_data_hex, in order to provide standardized encoding/decoding of packet data in events. While the packet_data event still exists, all relayers and IBC Event consumers are strongly encouraged to switch over to using packet_data_hex as soon as possible. The packet_ack attribute has also been deprecated in favor of packet_ack_hex for the same reason stated above. All relayers and IBC Event consumers are strongly encouraged to switch over to using packet_ack_hex as soon as possible. The consensus_height attribute has been removed in the Misbehaviour event emitted. IBC clients no longer have a frozen height and misbehaviour does not necessarily have an associated height.

Relevant SDK changes

  • (codec) #9226 Rename codec interfaces and methods, to follow a general Go interfaces:
    • codec.Marshaler → codec.Codec (this defines objects which serialize other objects)
    • codec.BinaryMarshaler → codec.BinaryCodec
    • codec.JSONMarshaler → codec.JSONCodec
    • Removed BinaryBare suffix from BinaryCodec methods (MarshalBinaryBare, UnmarshalBinaryBare, …)
    • Removed Binary infix from BinaryCodec methods (MarshalBinaryLengthPrefixed, UnmarshalBinaryLengthPrefixed, …)