本文旨在强调一些重要变更,这些变更可能需要比 CHANGELOG 中提供的更多信息。 任何需要由 ibc-go 用户执行的变更,都应记录在此处。 本文档根据四类潜在用户群体分为四个部分:
  • 链
  • IBC 应用
  • Relayer
  • IBC 轻客户端
当链从不支持带斜杠的基础 denom 的版本(例如 v3.0.0)升级到支持该特性的版本(例如 v3.2.0)时,就需要本文档。对于 v1.x 发布线中小于 v1.5.0 的所有 ibc-go 版本、v2.x 发布线中小于 v2.3.0 的版本,以及 v3.x 发布线中小于 v3.1.0 的版本,都不支持基础 denom 中包含斜杠的代币进行 IBC 转账。因此,在升级时需要执行本文档中描述的原地或创世迁移。 如果链在升级支持该特性之前接收到基础 denom 中带斜杠的代币,接收过程可能会通过,但 trace 信息会不正确。 例如,如果基础 denom testcoin/testcoin/testcoin 被发送到一条不支持基础 denom 中包含斜杠的链上,接收将会成功。然而,接收链上存储的 trace 信息将会是:Trace: "transfer/{channel-id}/testcoin/testcoin", BaseDenom: "testcoin"。 当链升级为完全支持带斜杠的 denom 时,必须修正这些错误的 trace 信息。 为此,链的二进制程序应包含一个迁移脚本,在链从不支持基础 denom 中包含斜杠升级为支持该特性时执行。

链

ICS20 - Transfer

Transfer 模块现在将支持基础 denom 中包含斜杠,因此我们必须遍历当前的 traces,检查其中是否存在格式错误的条目,并修正 trace 信息。

升级提案

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)
})
只有当存储中存在 denom trace,并且这些 trace 来自此前接收的、基础 denom 中带斜杠的代币且其 trace 信息不正确时,才有必要这样做。不过,出于安全考虑,仍然建议任何要升级以支持带斜杠基础 denom 的链运行这段代码。 如需更详细的示例,请查看这个 pull request中的代码变更。

创世迁移

如果链选择通过导出创世状态的方式为基础 denom 中的斜杠提供支持,那么必须在创世迁移期间修正 trace 信息。 所需的迁移代码可能如下所示:
func migrateGenesisSlashedDenomsUpgrade(appState genutiltypes.AppMap, clientCtx client.Context, genDoc *tmtypes.GenesisDoc) (genutiltypes.AppMap, error) {
    if appState[ibctransfertypes.ModuleName] != nil {
    transferGenState := &ibctransfertypes.GenesisState{
}

clientCtx.Codec.MustUnmarshalJSON(appState[ibctransfertypes.ModuleName], transferGenState)
    substituteTraces := make([]ibctransfertypes.DenomTrace, len(transferGenState.DenomTraces))
    for i, dt := range transferGenState.DenomTraces {
    / replace all previous traces with the latest trace if validation passes
    / note most traces will have same value
    newTrace := ibctransfertypes.ParseDenomTrace(dt.GetFullDenomPath())
    if err := newTrace.Validate(); err != nil {
    substituteTraces[i] = dt
}

else {
    substituteTraces[i] = newTrace
}
 
}

transferGenState.DenomTraces = substituteTraces

  / delete old genesis state
  delete(appState, ibctransfertypes.ModuleName)

  / set new ibc transfer genesis state
  appState[ibctransfertypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(transferGenState)
}

return appState, nil
}
如需更详细的示例,请查看这个 pull request中的代码变更。
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
This document is necessary when chains are upgrading from a version that does not support base denoms with slashes (e.g. v3.0.0) to a version that does (e.g. v3.2.0). All versions of ibc-go smaller than v1.5.0 for the v1.x release line, v2.3.0 for the v2.x release line, and v3.1.0 for the v3.x release line do NOT support IBC token transfers of coins whose base denoms contain slashes. Therefore the in-place of genesis migration described in this document are required when upgrading. 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. To do so, chain binaries should include a migration script that will run when the chain upgrades from not supporting base denominations with slashes to supporting base denominations with slashes.

Chains

ICS20 - Transfer

The transfer module will now support slashes in base denoms, so we must iterate over current traces to check if any of them are incorrectly formed and correct the trace information.

Upgrade Proposal

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)
})
This is only necessary if there are denom traces in the store with incorrect trace information from previously received coins that had a slash in the base denom. However, it is recommended that any chain upgrading to support base denominations with slashes runs this code for safety. For a more detailed sample, please check out the code changes in this pull request.

Genesis Migration

If the chain chooses to add support for slashes in base denoms via genesis export, then the trace information must be corrected during genesis migration. The migration code required may look like:
func migrateGenesisSlashedDenomsUpgrade(appState genutiltypes.AppMap, clientCtx client.Context, genDoc *tmtypes.GenesisDoc) (genutiltypes.AppMap, error) {
    if appState[ibctransfertypes.ModuleName] != nil {
    transferGenState := &ibctransfertypes.GenesisState{
}

clientCtx.Codec.MustUnmarshalJSON(appState[ibctransfertypes.ModuleName], transferGenState)
    substituteTraces := make([]ibctransfertypes.DenomTrace, len(transferGenState.DenomTraces))
    for i, dt := range transferGenState.DenomTraces {
    / replace all previous traces with the latest trace if validation passes
    / note most traces will have same value
    newTrace := ibctransfertypes.ParseDenomTrace(dt.GetFullDenomPath())
    if err := newTrace.Validate(); err != nil {
    substituteTraces[i] = dt
}

else {
    substituteTraces[i] = newTrace
}
 
}

transferGenState.DenomTraces = substituteTraces

  / delete old genesis state
  delete(appState, ibctransfertypes.ModuleName)

  / set new ibc transfer genesis state
  appState[ibctransfertypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(transferGenState)
}

return appState, nil
}
For a more detailed sample, please check out the code changes in this pull request.