Upgrade
Abstract
x/upgrade
is an implementation of a Cosmos SDK module that facilitates smoothly upgrading a live Cosmos chain to a new (breaking) software version. It accomplishes this by providing a PreBlocker
hook that prevents the blockchain state machine from proceeding once a pre-defined upgrade block height has been reached.
The module does not prescribe anything regarding how governance decides to do an upgrade, but just the mechanism for coordinating the upgrade safely. Without software support for upgrades, upgrading a live chain is risky because all of the validators need to pause their state machines at exactly the same point in the process. If this is not done correctly, there can be state inconsistencies which are hard to recover from.
Concepts
Plan
The x/upgrade
module defines a Plan
type in which a live upgrade is scheduled to occur. A Plan
can be scheduled at a specific block height. A Plan
is created once a (frozen) release candidate along with an appropriate upgrade Handler
(see below) is agreed upon, where the Name
of a Plan
corresponds to a specific Handler
. Typically, a Plan
is created through a governance proposal process, where if voted upon and passed, will be scheduled. The Info
of a Plan
may contain various metadata about the upgrade, typically application specific upgrade info to be included on-chain such as a git commit that validators could automatically upgrade to.
Sidecar Process
If an operator running the application binary also runs a sidecar process to assist in the automatic download and upgrade of a binary, the Info
allows this process to be seamless. This tool is Cosmovisor.
Handler
The x/upgrade
module facilitates upgrading from major version X to major version Y. To accomplish this, node operators must first upgrade their current binary to a new binary that has a corresponding Handler
for the new version Y. It is assumed that this version has fully been tested and approved by the community at large. This Handler
defines what state migrations need to occur before the new binary Y can successfully run the chain. Naturally, this Handler
is application specific and not defined on a per-module basis. Registering a Handler
is done via Keeper#SetUpgradeHandler
in the application.
During each EndBlock
execution, the x/upgrade
module checks if there exists a Plan
that should execute (is scheduled at that height). If so, the corresponding Handler
is executed. If the Plan
is expected to execute but no Handler
is registered or if the binary was upgraded too early, the node will gracefully panic and exit.
StoreLoader
The x/upgrade
module also facilitates store migrations as part of the upgrade. The StoreLoader
sets the migrations that need to occur before the new binary can successfully run the chain. This StoreLoader
is also application specific and not defined on a per-module basis. Registering this StoreLoader
is done via app#SetStoreLoader
in the application.
If there's a planned upgrade and the upgrade height is reached, the old binary writes Plan
to the disk before panicking.
This information is critical to ensure the StoreUpgrades
happens smoothly at correct height and expected upgrade. It eliminiates the chances for the new binary to execute StoreUpgrades
multiple times everytime on restart. Also if there are multiple upgrades planned on same height, the Name
will ensure these StoreUpgrades
takes place only in planned upgrade handler.
Proposal
Typically, a Plan
is proposed and submitted through governance via a proposal containing a MsgSoftwareUpgrade
message. This proposal prescribes to the standard governance process. If the proposal passes, the Plan
, which targets a specific Handler
, is persisted and scheduled. The upgrade can be delayed or hastened by updating the Plan.Height
in a new proposal.
Cancelling Upgrade Proposals
Upgrade proposals can be cancelled. There exists a gov-enabled MsgCancelUpgrade
message type, which can be embedded in a proposal, voted on and, if passed, will remove the scheduled upgrade Plan
. Of course this requires that the upgrade was known to be a bad idea well before the upgrade itself, to allow time for a vote.
If such a possibility is desired, the upgrade height is to be 2 * (VotingPeriod + DepositPeriod) + (SafetyDelta)
from the beginning of the upgrade proposal. The SafetyDelta
is the time available from the success of an upgrade proposal and the realization it was a bad idea (due to external social consensus).
A MsgCancelUpgrade
proposal can also be made while the original MsgSoftwareUpgrade
proposal is still being voted upon, as long as the VotingPeriod
ends after the MsgSoftwareUpgrade
proposal.
State
The internal state of the x/upgrade
module is relatively minimal and simple. The state contains the currently active upgrade Plan
(if one exists) by key 0x0
and if a Plan
is marked as "done" by key 0x1
. The state contains the consensus versions of all app modules in the application. The versions are stored as big endian uint64
, and can be accessed with prefix 0x2
appended by the corresponding module name of type string
. The state maintains a Protocol Version
which can be accessed by key 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)
The x/upgrade
module contains no genesis state.
Events
The x/upgrade
does not emit any events by itself. Any and all proposal related events are emitted through the x/gov
module.
Client
CLI
A user can query and interact with the upgrade
module using the CLI.
Query
The query
commands allow users to query upgrade
state.
applied
The applied
command allows users to query the block header for height at which a completed upgrade was applied.
If upgrade-name was previously executed on the chain, this returns the header for the block at which it was applied. This helps a client determine which binary was valid over a given range of blocks, as well as more context to understand past migrations.
Example:
Example Output:
module versions
The module_versions
command gets a list of module names and their respective consensus versions.
Following the command with a specific module name will return only that module's information.
Example:
Example Output:
Example:
Example Output:
plan
The plan
command gets the currently scheduled upgrade plan, if one exists.
Example:
Example Output:
Transactions
The upgrade module supports the following transactions:
software-proposal
- submits an upgrade proposal:
cancel-software-upgrade
- cancels a previously submitted upgrade proposal:
REST
A user can query the upgrade
module using REST endpoints.
Applied Plan
AppliedPlan
queries a previously applied upgrade plan by its name.
Example:
Example Output:
Current Plan
CurrentPlan
queries the current upgrade plan.
Example:
Example Output:
Module versions
ModuleVersions
queries the list of module versions from state.
Example:
Example Output:
gRPC
A user can query the upgrade
module using gRPC endpoints.
Applied Plan
AppliedPlan
queries a previously applied upgrade plan by its name.
Example:
Example Output:
Current Plan
CurrentPlan
queries the current upgrade plan.
Example:
Example Output:
Module versions
ModuleVersions
queries the list of module versions from state.
Example:
Example Output:
Resources
A list of (external) resources to learn more about the x/upgrade
module.
Cosmos Dev Series: Cosmos Blockchain Upgrade - The blog post that explains how software upgrades work in detail.
Last updated