本文档演示了如何通过治理流程在链上执行实时升级。
  1. 启动网络并触发升级
    # start a gaia application full-node
    $ gaiad start
    
    # set up the cli config
    $ gaiad config chain-id testing
    
    # create an upgrade governance proposal
    $ gaiad tx gov submit-proposal  <path-to-proposal-json> --from <name-or-key>
    
    Where proposal json file contains MsgSoftwareUpgrade e.g.
    `{
     	"messages": [
     	 {
     	  "@type": "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade",
     	  "authority":"cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" ,
     	  "plan": {
     	   "name": "plan name",
     	   "height": "1000" ,
     	   "info": "proposal info" ,
     	   "upgraded_client_state": null
     	  }
     	 }
     	],
     	"metadata": "ipfs://CID",
     	"deposit": "10000000stake",
     	"title": "proposal title",
     	"summary": "proposal summary"
     }`
    
    # once the proposal passes you can query the pending plan
    $ gaiad query upgrade plan
    
  2. 执行升级 假设提案已经通过,链会在指定的升级高度停止。 你可以任意停止并重新启动原始二进制文件,但在达到升级高度之后,它将拒绝继续运行。 我们需要一个安装了升级处理器的新二进制文件。日志看起来应类似于:
    E[2019-11-05|12:44:18.913] UPGRADE "<plan-name>" NEEDED at height: <desired-upgrade-height>:       module=main
    E[2019-11-05|12:44:18.914] CONSENSUS FAILURE!!!
    ...
    
    请注意,进程会无限期挂起(不会退出,以避免重启循环)。因此,你必须手动终止该进程,并将其替换为新的二进制文件。现在请使用 Ctrl+C 或 killall gaiad 完成此操作。 在 gaia/app/app.go 中,在 upgrade.Keeper 初始化并设置到应用之后,使用正确的 <plan-name> 设置对应的升级 Handler:
    app.upgradeKeeper.SetUpgradeHandler("<plan-name>", func(ctx sdk.Context, plan upgrade.Plan) {
            // custom logic after the network upgrade has been executed
    })
    
    请注意,出现任何错误时我们都会触发 panic。如果迁移无法执行,这会导致升级失败,并且不会有节点继续推进,从而为手动恢复留下空间。 如果忽略这些错误,系统就会在升级不完整的情况下继续运行,之后几乎很难再恢复到正确状态。 现在,编译新的二进制文件并运行升级后的代码以完成升级:
    # create a new binary of gaia with the added upgrade handler
    $ make install
    
    # Restart the chain using the new binary. You should see the chain resume from
    # the upgrade height:
    # `I[2019-11-05|12:48:15.184] applying upgrade <plan-name> at height: <desired-upgrade-height>      module=main`
    $ gaiad start
    
    # verify there is no pending plan
    $ gaiad query upgrade plan
    
    # verify you can query the block header of the completed upgrade
    $ gaiad query upgrade applied <plan-name>
    

This document demonstrates how a live upgrade can be performed on-chain through a governance process.
  1. Start the network and trigger upgrade
    # start a gaia application full-node
    $ gaiad start
    
    # set up the cli config
    $ gaiad config chain-id testing
    
    # create an upgrade governance proposal
    $ gaiad tx gov submit-proposal  <path-to-proposal-json> --from <name-or-key>
    
    Where proposal json file contains MsgSoftwareUpgrade e.g.
    `{
     	"messages": [
     	 {
     	  "@type": "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade",
     	  "authority":"cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" ,
     	  "plan": {
     	   "name": "plan name",
     	   "height": "1000" ,
     	   "info": "proposal info" ,
     	   "upgraded_client_state": null
     	  }
     	 }
     	],
     	"metadata": "ipfs://CID",
     	"deposit": "10000000stake",
     	"title": "proposal title",
     	"summary": "proposal summary"
     }`
    
    # once the proposal passes you can query the pending plan
    $ gaiad query upgrade plan
    
  2. Performing an upgrade Assuming the proposal passes the chain will stop at given upgrade height. You can stop and start the original binary all you want, but it will refuse to run after the upgrade height. We need a new binary with the upgrade handler installed. The logs should look something like:
    E[2019-11-05|12:44:18.913] UPGRADE "<plan-name>" NEEDED at height: <desired-upgrade-height>:       module=main
    E[2019-11-05|12:44:18.914] CONSENSUS FAILURE!!!
    ...
    
    Note that the process will hang indefinitely (doesn’t exit to avoid restart loops). So, you must manually kill the process and replace it with a new binary. Do so now with Ctrl+C or killall gaiad. In gaia/app/app.go, after upgrade.Keeper is initialized and set in the app, set the corresponding upgrade Handler with the correct <plan-name>:
    app.upgradeKeeper.SetUpgradeHandler("<plan-name>", func(ctx sdk.Context, plan upgrade.Plan) {
            // custom logic after the network upgrade has been executed
    })
    
    Note that we panic on any error - this would cause the upgrade to fail if the migration could not be run, and no node would advance - allowing a manual recovery. If we ignored the errors, then we would proceed with an incomplete upgrade and have a very difficult time every recovering the proper state. Now, compile the new binary and run the upgraded code to complete the upgrade:
    # create a new binary of gaia with the added upgrade handler
    $ make install
    
    # Restart the chain using the new binary. You should see the chain resume from
    # the upgrade height:
    # `I[2019-11-05|12:48:15.184] applying upgrade <plan-name> at height: <desired-upgrade-height>      module=main`
    $ gaiad start
    
    # verify there is no pending plan
    $ gaiad query upgrade plan
    
    # verify you can query the block header of the completed upgrade
    $ gaiad query upgrade applied <plan-name>