升级(Upgrade)

摘要

x/upgrade 是 Cosmos SDK 模块的一个实现,旨在帮助平滑地将一个正在运行的 Cosmos 链升级到新的(可能存在不兼容的)软件版本。它通过提供一个 PreBlocker 钩子来实现这一点,当达到预定义的升级区块高度时,该钩子会阻止区块链状态机继续执行。

该模块并未规定治理如何决定进行升级,而只是提供了一个机制,用于安全地协调升级。没有软件支持进行升级的情况下,升级一个正在运行的链是有风险的,因为所有验证人需要在完全相同的点暂停各自的状态机。如果这一过程没有正确执行,可能会导致状态不一致,且恢复起来非常困难。

概念

Plan

x/upgrade模块定义了一个Plan类型,用于安排实时升级的发生。Plan可以在特定的区块高度安排。Plan在达成一致后创建,其中包含一个(已冻结的)发布候选版本以及一个适当的升级处理器(见下文),Plan的名称对应于一个特定的处理器。通常,Plan通过治理提案流程创建,如果提案通过投票并通过,则会被安排。PlanInfo可以包含关于升级的各种元数据,通常是特定于应用程序的升级信息,这些信息会被包含在链上,例如验证人可以自动升级的 git 提交。

type Plan struct {
  Name   string
  Height int64
  Info   string
}

辅助进程

如果一个操作员运行应用程序二进制文件并同时运行一个辅助进程来协助自动下载和升级二进制文件,Info允许此过程无缝进行。这个工具是Cosmovisor

Handler

x/upgrade模块便于从主要版本X升级到主要版本Y。为了实现这一点,节点操作员必须首先将当前的二进制文件升级到具有对应于新版本Y的处理器的新二进制文件。假设该版本已由社区全面测试并批准。这个处理器定义了在新二进制Y成功运行链之前需要进行哪些状态迁移。显然,这个处理器是特定于应用程序的,而不是按模块定义的。注册一个处理器是在应用程序中通过 Keeper#SetUpgradeHandler 完成的。

type UpgradeHandler func(Context, Plan, VersionMap) (VersionMap, error)

在每次 EndBlock 执行期间,x/upgrade模块会检查是否存在应该执行的计划(是否在该高度安排)。如果是这样,执行相应的处理器。如果计划预期执行但没有注册处理器,或者二进制文件被提前升级,节点将优雅地崩溃并退出。

StoreLoader

x/upgrade模块还在升级过程中促进存储迁移。StoreLoader设置需要在新二进制文件成功运行链之前进行的迁移。这个 StoreLoader 也是特定于应用程序的,而不是按模块定义的。注册此 StoreLoader 是通过应用程序中的 app#SetStoreLoader 完成的。

func UpgradeStoreLoader (upgradeHeight int64, storeUpgrades *store.StoreUpgrades) baseapp.StoreLoader

如果有计划中的升级,并且达到了升级高度,旧的二进制文件会在崩溃之前将计划写入磁盘。 此信息对于确保 StoreUpgrades 在正确的高度和预期升级时顺利发生至关重要。它消除了每次重新启动时,新二进制文件执行 StoreUpgrades 多次的可能性。此外,如果在相同高度上有多个计划的升级,Name 将确保这些 StoreUpgrades 只在计划的升级处理器中发生。

提案

通常,Plan 通过治理提案的方式提交,其中包含一个 MsgSoftwareUpgrade 消息。此提案遵循标准治理流程。如果提案通过,目标特定处理器的计划将被持久化并安排。升级可以通过在新的提案中更新 Plan.Height 来延迟或加速。

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/upgrade/v1beta1/tx.proto#L29-L41

取消升提案

升级提案可以被取消。存在一个支持治理的 MsgCancelUpgrade 消息类型,可以嵌入在提案中,进行投票,并且如果通过,将删除已安排的升级计划。当然,这要求升级在实际进行之前就已经被认为是一个不好的主意,从而为投票提供时间。

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/upgrade/v1beta1/tx.proto#L48-L57

如果希望这种可能性,升级高度应为从升级提案开始的 2 * (VotingPeriod + DepositPeriod) + (SafetyDelta)SafetyDelta 是从升级提案成功到意识到它是一个糟糕的主意(由于外部社会共识)之间的时间。

MsgCancelUpgrade 提案也可以在原始的 MsgSoftwareUpgrade 提案仍在投票时提出,只要投票期结束时在 MsgSoftwareUpgrade 提案之后。

状态

x/upgrade模块的内部状态相对简单且最小化。该状态包含当前活动的升级计划(如果存在),通过键 0x0 存储;如果计划被标记为“完成”,则通过键 0x1 存储。状态还包含应用程序中所有应用模块的共识版本。版本以大端格式的 uint64 存储,可以通过前缀 0x2 加上相应模块名称(字符串类型)进行访问。状态还维护一个协议版本,可以通过键 0x3 访问。

  • Plan: 0x0 -> Plan

  • Done: 0x1 | byte(plan name) -> BigEndian(Block Height)

  • ConsensusVersion: 0x2 | byte(module name) -> BigEndian(Module Consensus Version)

  • ProtocolVersion: 0x3 -> BigEndian(Protocol Version)

x/upgrade模块不包含创世状态。

事件

x/upgrade模块本身不发出任何事件。所有与提案相关的事件都是通过 x/gov 模块发出的。

客户端

CLI

用户可以使用CLI查询和与升级模块进行交互。

Query

查询命令允许用户查询升级状态。

simd query upgrade --help

applied

applied 命令允许用户查询已完成升级应用的区块头信息及其高度。

simd query upgrade applied [upgrade-name] [flags]

如果 upgrade-name 之前在链上执行过,则返回该升级应用的区块头信息及其区块高度。这有助于客户端确定在给定区块范围内哪个二进制文件有效,并提供更多上下文以理解过去的迁移。

示例:

simd query upgrade applied "test-upgrade"

示例输出:

"block_id": {
    "hash": "A769136351786B9034A5F196DC53F7E50FCEB53B48FA0786E1BFC45A0BB646B5",
    "parts": {
      "total": 1,
      "hash": "B13CBD23011C7480E6F11BE4594EE316548648E6A666B3575409F8F16EC6939E"
    }
  },
  "block_size": "7213",
  "header": {
    "version": {
      "block": "11"
    },
    "chain_id": "testnet-2",
    "height": "455200",
    "time": "2021-04-10T04:37:57.085493838Z",
    "last_block_id": {
      "hash": "0E8AD9309C2DC411DF98217AF59E044A0E1CCEAE7C0338417A70338DF50F4783",
      "parts": {
        "total": 1,
        "hash": "8FE572A48CD10BC2CBB02653CA04CA247A0F6830FF19DC972F64D339A355E77D"
      }
    },
    "last_commit_hash": "DE890239416A19E6164C2076B837CC1D7F7822FC214F305616725F11D2533140",
    "data_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
    "validators_hash": "A31047ADE54AE9072EE2A12FF260A8990BA4C39F903EAF5636B50D58DBA72582",
    "next_validators_hash": "A31047ADE54AE9072EE2A12FF260A8990BA4C39F903EAF5636B50D58DBA72582",
    "consensus_hash": "048091BC7DDC283F77BFBF91D73C44DA58C3DF8A9CBC867405D8B7F3DAADA22F",
    "app_hash": "28ECC486AFC332BA6CC976706DBDE87E7D32441375E3F10FD084CD4BAF0DA021",
    "last_results_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
    "evidence_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
    "proposer_address": "2ABC4854B1A1C5AA8403C4EA853A81ACA901CC76"
  },
  "num_txs": "0"
}

module versions

module_versions 命令获取模块名称及其各自的共识版本列表。 在命令后跟上特定模块名称将只返回该模块的信息。

simd query upgrade module_versions [optional module_name] [flags]

示例:

simd query upgrade module_versions

示例输出:

module_versions:
- name: auth
  version: "2"
- name: authz
  version: "1"
- name: bank
  version: "2"
- name: crisis
  version: "1"
- name: distribution
  version: "2"
- name: evidence
  version: "1"
- name: feegrant
  version: "1"
- name: genutil
  version: "1"
- name: gov
  version: "2"
- name: ibc
  version: "2"
- name: mint
  version: "1"
- name: params
  version: "1"
- name: slashing
  version: "2"
- name: staking
  version: "2"
- name: transfer
  version: "1"
- name: upgrade
  version: "1"
- name: vesting
  version: "1"

示例:

regen query upgrade module_versions ibc

示例输出:

module_versions:
- name: ibc
  version: "2"

plan

plan 命令获取当前已安排的升级计划(如果存在)。

regen query upgrade plan [flags]

示例:

simd query upgrade plan

示例输出:

height: "130"
info: ""
name: test-upgrade
time: "0001-01-01T00:00:00Z"
upgraded_client_state: null

Transactions

升级模块支持以下交易:

  • software-proposal - 提交一个升级提案:

simd tx upgrade software-upgrade v2 --title="Test Proposal" --summary="testing" --deposit="100000000stake" --upgrade-height 1000000 \
--upgrade-info '{ "binaries": { "linux/amd64":"https://example.com/simd.zip?checksum=sha256:aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f" } }' --from cosmos1..
  • cancel-software-upgrade - 取消之前提交的升级提案:

simd tx upgrade cancel-software-upgrade --title="Test Proposal" --summary="testing" --deposit="100000000stake" --from cosmos1..

REST

用户可以使用REST端点查询升级模块。

Applied Plan

AppliedPlan 查询通过其名称之前应用的升级计划。

/cosmos/upgrade/v1beta1/applied_plan/{name}

示例:

curl -X GET "http://localhost:1317/cosmos/upgrade/v1beta1/applied_plan/v2.0-upgrade" -H "accept: application/json"

示例输出:

{
  "height": "30"
}

Current Plan

CurrentPlan 查询当前的升级计划。

/cosmos/upgrade/v1beta1/current_plan

示例:

curl -X GET "http://localhost:1317/cosmos/upgrade/v1beta1/current_plan" -H "accept: application/json"

示例输出:

{
  "plan": "v2.1-upgrade"
}

Module versions

ModuleVersions 查询状态中的模块版本列表。

/cosmos/upgrade/v1beta1/module_versions

示例:

curl -X GET "http://localhost:1317/cosmos/upgrade/v1beta1/module_versions" -H "accept: application/json"

示例输出:

{
  "module_versions": [
    {
      "name": "auth",
      "version": "2"
    },
    {
      "name": "authz",
      "version": "1"
    },
    {
      "name": "bank",
      "version": "2"
    },
    {
      "name": "crisis",
      "version": "1"
    },
    {
      "name": "distribution",
      "version": "2"
    },
    {
      "name": "evidence",
      "version": "1"
    },
    {
      "name": "feegrant",
      "version": "1"
    },
    {
      "name": "genutil",
      "version": "1"
    },
    {
      "name": "gov",
      "version": "2"
    },
    {
      "name": "ibc",
      "version": "2"
    },
    {
      "name": "mint",
      "version": "1"
    },
    {
      "name": "params",
      "version": "1"
    },
    {
      "name": "slashing",
      "version": "2"
    },
    {
      "name": "staking",
      "version": "2"
    },
    {
      "name": "transfer",
      "version": "1"
    },
    {
      "name": "upgrade",
      "version": "1"
    },
    {
      "name": "vesting",
      "version": "1"
    }
  ]
}

gRPC

用户可以使用 gRPC 端点查询升级模块。

Applied Plan

AppliedPlan 查询通过其名称之前应用的升级计划。

cosmos.upgrade.v1beta1.Query/AppliedPlan

示例:

grpcurl -plaintext \
    -d '{"name":"v2.0-upgrade"}' \
    localhost:9090 \
    cosmos.upgrade.v1beta1.Query/AppliedPlan

示例输出:

{
  "height": "30"
}

Current Plan

CurrentPlan 查询当前的升级计划。

cosmos.upgrade.v1beta1.Query/CurrentPlan

示例:

grpcurl -plaintext localhost:9090 cosmos.slashing.v1beta1.Query/CurrentPlan

示例输出:

{
  "plan": "v2.1-upgrade"
}

Module versions

ModuleVersions 查询状态中的模块版本列表。

cosmos.upgrade.v1beta1.Query/ModuleVersions

示例:

grpcurl -plaintext localhost:9090 cosmos.slashing.v1beta1.Query/ModuleVersions

示例输出:

{
  "module_versions": [
    {
      "name": "auth",
      "version": "2"
    },
    {
      "name": "authz",
      "version": "1"
    },
    {
      "name": "bank",
      "version": "2"
    },
    {
      "name": "crisis",
      "version": "1"
    },
    {
      "name": "distribution",
      "version": "2"
    },
    {
      "name": "evidence",
      "version": "1"
    },
    {
      "name": "feegrant",
      "version": "1"
    },
    {
      "name": "genutil",
      "version": "1"
    },
    {
      "name": "gov",
      "version": "2"
    },
    {
      "name": "ibc",
      "version": "2"
    },
    {
      "name": "mint",
      "version": "1"
    },
    {
      "name": "params",
      "version": "1"
    },
    {
      "name": "slashing",
      "version": "2"
    },
    {
      "name": "staking",
      "version": "2"
    },
    {
      "name": "transfer",
      "version": "1"
    },
    {
      "name": "upgrade",
      "version": "1"
    },
    {
      "name": "vesting",
      "version": "1"
    }
  ]
}

资源

以下是学习更多关于 x/upgrade 模块的(外部)资源列表:

Last updated