github.com/cosmos/cosmos-sdk@v0.50.10/docs/architecture/adr-047-extend-upgrade-plan.md (about)

     1  # ADR 047: Extend Upgrade Plan
     2  
     3  ## Changelog
     4  
     5  * Nov, 23, 2021: Initial Draft
     6  * May, 16, 2023: Proposal ABANDONED. `pre_run` and `post_run` are not necessary anymore and adding the `artifacts` brings minor benefits.
     7  
     8  ## Status
     9  
    10  ABANDONED
    11  
    12  ## Abstract
    13  
    14  This ADR expands the existing x/upgrade `Plan` proto message to include new fields for defining pre-run and post-run processes within upgrade tooling.
    15  It also defines a structure for providing downloadable artifacts involved in an upgrade.
    16  
    17  ## Context
    18  
    19  The `upgrade` module in conjunction with Cosmovisor are designed to facilitate and automate a blockchain's transition from one version to another.
    20  
    21  Users submit a software upgrade governance proposal containing an upgrade `Plan`.
    22  The [Plan](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/proto/cosmos/upgrade/v1beta1/upgrade.proto#L12) currently contains the following fields:
    23  
    24  * `name`: A short string identifying the new version.
    25  * `height`: The chain height at which the upgrade is to be performed.
    26  * `info`: A string containing information about the upgrade.
    27  
    28  The `info` string can be anything.
    29  However, Cosmovisor will try to use the `info` field to automatically download a new version of the blockchain executable.
    30  For the auto-download to work, Cosmovisor expects it to be either a stringified JSON object (with a specific structure defined through documentation), or a URL that will return such JSON.
    31  The JSON object identifies URLs used to download the new blockchain executable for different platforms (OS and Architecture, e.g. "linux/amd64").
    32  Such a URL can either return the executable file directly or can return an archive containing the executable and possibly other assets.
    33  
    34  If the URL returns an archive, it is decompressed into `{DAEMON_HOME}/cosmovisor/{upgrade name}`.
    35  Then, if `{DAEMON_HOME}/cosmovisor/{upgrade name}/bin/{DAEMON_NAME}` does not exist, but `{DAEMON_HOME}/cosmovisor/{upgrade name}/{DAEMON_NAME}` does, the latter is copied to the former.
    36  If the URL returns something other than an archive, it is downloaded to `{DAEMON_HOME}/cosmovisor/{upgrade name}/bin/{DAEMON_NAME}`.
    37  
    38  If an upgrade height is reached and the new version of the executable version isn't available, Cosmovisor will stop running.
    39  
    40  Both `DAEMON_HOME` and `DAEMON_NAME` are [environment variables used to configure Cosmovisor](https://github.com/cosmos/cosmos-sdk/blob/cosmovisor/v1.0.0/cosmovisor/README.md#command-line-arguments-and-environment-variables).
    41  
    42  Currently, there is no mechanism that makes Cosmovisor run a command after the upgraded chain has been restarted.
    43  
    44  The current upgrade process has this timeline:
    45  
    46  1. An upgrade governance proposal is submitted and approved.
    47  1. The upgrade height is reached.
    48  1. The `x/upgrade` module writes the `upgrade_info.json` file.
    49  1. The chain halts.
    50  1. Cosmovisor backs up the data directory (if set up to do so).
    51  1. Cosmovisor downloads the new executable (if not already in place).
    52  1. Cosmovisor executes the `${DAEMON_NAME} pre-upgrade`.
    53  1. Cosmovisor restarts the app using the new version and same args originally provided.
    54  
    55  ## Decision
    56  
    57  ### Protobuf Updates
    58  
    59  We will update the `x/upgrade.Plan` message for providing upgrade instructions.
    60  The upgrade instructions will contain a list of artifacts available for each platform.
    61  It allows for the definition of a pre-run and post-run commands.
    62  These commands are not consensus guaranteed; they will be executed by Cosmosvisor (or other) during its upgrade handling.
    63  
    64  ```protobuf
    65  message Plan {
    66    // ... (existing fields)
    67  
    68    UpgradeInstructions instructions = 6;
    69  }
    70  ```
    71  
    72  The new `UpgradeInstructions instructions` field MUST be optional.
    73  
    74  ```protobuf
    75  message UpgradeInstructions {
    76    string pre_run              = 1;
    77    string post_run             = 2;
    78    repeated Artifact artifacts = 3;
    79    string description          = 4;
    80  }
    81  ```
    82  
    83  All fields in the `UpgradeInstructions` are optional.
    84  
    85  * `pre_run` is a command to run prior to the upgraded chain restarting.
    86    If defined, it will be executed after halting and downloading the new artifact but before restarting the upgraded chain.
    87    The working directory this command runs from MUST be `{DAEMON_HOME}/cosmovisor/{upgrade name}`.
    88    This command MUST behave the same as the current [pre-upgrade](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/docs/migrations/pre-upgrade.md) command.
    89    It does not take in any command-line arguments and is expected to terminate with the following exit codes:
    90  
    91    | Exit status code | How it is handled in Cosmosvisor                                                                                    |
    92    |------------------|---------------------------------------------------------------------------------------------------------------------|
    93    | `0`              | Assumes `pre-upgrade` command executed successfully and continues the upgrade.                                      |
    94    | `1`              | Default exit code when `pre-upgrade` command has not been implemented.                                              |
    95    | `30`             | `pre-upgrade` command was executed but failed. This fails the entire upgrade.                                       |
    96    | `31`             | `pre-upgrade` command was executed but failed. But the command is retried until exit code `1` or `30` are returned. |
    97    If defined, then the app supervisors (e.g. Cosmovisor) MUST NOT run `app pre-run`.
    98  * `post_run` is a command to run after the upgraded chain has been started. If defined, this command MUST be only executed at most once by an upgrading node.
    99    The output and exit code SHOULD be logged but SHOULD NOT affect the running of the upgraded chain.
   100    The working directory this command runs from MUST be `{DAEMON_HOME}/cosmovisor/{upgrade name}`.
   101  * `artifacts` define items to be downloaded.
   102    It SHOULD have only one entry per platform.
   103  * `description` contains human-readable information about the upgrade and might contain references to external resources.
   104    It SHOULD NOT be used for structured processing information.
   105  
   106  ```protobuf
   107  message Artifact {
   108    string platform      = 1;
   109    string url           = 2;
   110    string checksum      = 3;
   111    string checksum_algo = 4;
   112  }
   113  ```
   114  
   115  * `platform` is a required string that SHOULD be in the format `{OS}/{CPU}`, e.g. `"linux/amd64"`.
   116    The string `"any"` SHOULD also be allowed.
   117    An `Artifact` with a `platform` of `"any"` SHOULD be used as a fallback when a specific `{OS}/{CPU}` entry is not found.
   118    That is, if an `Artifact` exists with a `platform` that matches the system's OS and CPU, that should be used;
   119    otherwise, if an `Artifact` exists with a `platform` of `any`, that should be used;
   120    otherwise no artifact should be downloaded.
   121  * `url` is a required URL string that MUST conform to [RFC 1738: Uniform Resource Locators](https://www.ietf.org/rfc/rfc1738.txt).
   122    A request to this `url` MUST return either an executable file or an archive containing either `bin/{DAEMON_NAME}` or `{DAEMON_NAME}`.
   123    The URL should not contain checksum - it should be specified by the `checksum` attribute.
   124  * `checksum` is a checksum of the expected result of a request to the `url`.
   125    It is not required, but is recommended.
   126    If provided, it MUST be a hex encoded checksum string.
   127    Tools utilizing these `UpgradeInstructions` MUST fail if a `checksum` is provided but is different from the checksum of the result returned by the `url`.
   128  * `checksum_algo` is a string identify the algorithm used to generate the `checksum`.
   129    Recommended algorithms: `sha256`, `sha512`.
   130    Algorithms also supported (but not recommended): `sha1`, `md5`.
   131    If a `checksum` is provided, a `checksum_algo` MUST also be provided.
   132  
   133  A `url` is not required to contain a `checksum` query parameter.
   134  If the `url` does contain a `checksum` query parameter, the `checksum` and `checksum_algo` fields MUST also be populated, and their values MUST match the value of the query parameter.
   135  For example, if the `url` is `"https://example.com?checksum=md5:d41d8cd98f00b204e9800998ecf8427e"`, then the `checksum` field must be `"d41d8cd98f00b204e9800998ecf8427e"` and the `checksum_algo` field must be `"md5"`.
   136  
   137  ### Upgrade Module Updates
   138  
   139  If an upgrade `Plan` does not use the new `UpgradeInstructions` field, existing functionality will be maintained.
   140  The parsing of the `info` field as either a URL or `binaries` JSON will be deprecated.
   141  During validation, if the `info` field is used as such, a warning will be issued, but not an error.
   142  
   143  We will update the creation of the `upgrade-info.json` file to include the `UpgradeInstructions`.
   144  
   145  We will update the optional validation available via CLI to account for the new `Plan` structure.
   146  We will add the following validation:
   147  
   148  1.  If `UpgradeInstructions` are provided:
   149      1.  There MUST be at least one entry in `artifacts`.
   150      1.  All of the `artifacts` MUST have a unique `platform`.
   151      1.  For each `Artifact`, if the `url` contains a `checksum` query parameter:
   152          1. The `checksum` query parameter value MUST be in the format of `{checksum_algo}:{checksum}`.
   153          1. The `{checksum}` from the query parameter MUST equal the `checksum` provided in the `Artifact`.
   154          1. The `{checksum_algo}` from the query parameter MUST equal the `checksum_algo` provided in the `Artifact`.
   155  1.  The following validation is currently done using the `info` field. We will apply similar validation to the `UpgradeInstructions`.
   156      For each `Artifact`:
   157      1.  The `platform` MUST have the format `{OS}/{CPU}` or be `"any"`.
   158      1.  The `url` field MUST NOT be empty.
   159      1.  The `url` field MUST be a proper URL.
   160      1.  A `checksum` MUST be provided either in the `checksum` field or as a query parameter in the `url`.
   161      1.  If the `checksum` field has a value and the `url` also has a `checksum` query parameter, the two values MUST be equal.
   162      1.  The `url` MUST return either a file or an archive containing either `bin/{DAEMON_NAME}` or `{DAEMON_NAME}`.
   163      1.  If a `checksum` is provided (in the field or as a query param), the checksum of the result of the `url` MUST equal the provided checksum.
   164  
   165  Downloading of an `Artifact` will happen the same way that URLs from `info` are currently downloaded.
   166  
   167  ### Cosmovisor Updates
   168  
   169  If the `upgrade-info.json` file does not contain any `UpgradeInstructions`, existing functionality will be maintained.
   170  
   171  We will update Cosmovisor to look for and handle the new `UpgradeInstructions` in `upgrade-info.json`.
   172  If the `UpgradeInstructions` are provided, we will do the following:
   173  
   174  1.  The `info` field will be ignored.
   175  1.  The `artifacts` field will be used to identify the artifact to download based on the `platform` that Cosmovisor is running in.
   176  1.  If a `checksum` is provided (either in the field or as a query param in the `url`), and the downloaded artifact has a different checksum, the upgrade process will be interrupted and Cosmovisor will exit with an error.
   177  1.  If a `pre_run` command is defined, it will be executed at the same point in the process where the `app pre-upgrade` command would have been executed.
   178      It will be executed using the same environment as other commands run by Cosmovisor.
   179  1.  If a `post_run` command is defined, it will be executed after executing the command that restarts the chain.
   180      It will be executed in a background process using the same environment as the other commands.
   181      Any output generated by the command will be logged.
   182      Once complete, the exit code will be logged.
   183  
   184  We will deprecate the use of the `info` field for anything other than human readable information.
   185  A warning will be logged if the `info` field is used to define the assets (either by URL or JSON).
   186  
   187  The new upgrade timeline is very similar to the current one. Changes are in bold:
   188  
   189  1. An upgrade governance proposal is submitted and approved.
   190  1. The upgrade height is reached.
   191  1. The `x/upgrade` module writes the `upgrade_info.json` file **(now possibly with `UpgradeInstructions`)**.
   192  1. The chain halts.
   193  1. Cosmovisor backs up the data directory (if set up to do so).
   194  1. Cosmovisor downloads the new executable (if not already in place).
   195  1. Cosmovisor executes **the `pre_run` command if provided**, or else the `${DAEMON_NAME} pre-upgrade` command.
   196  1. Cosmovisor restarts the app using the new version and same args originally provided.
   197  1. **Cosmovisor immediately runs the `post_run` command in a detached process.**
   198  
   199  ## Consequences
   200  
   201  ### Backwards Compatibility
   202  
   203  Since the only change to existing definitions is the addition of the `instructions` field to the `Plan` message, and that field is optional, there are no backwards incompatibilities with respects to the proto messages.
   204  Additionally, current behavior will be maintained when no `UpgradeInstructions` are provided, so there are no backwards incompatibilities with respects to either the upgrade module or Cosmovisor.
   205  
   206  ### Forwards Compatibility
   207  
   208  In order to utilize the `UpgradeInstructions` as part of a software upgrade, both of the following must be true:
   209  
   210  1.  The chain must already be using a sufficiently advanced version of the Cosmos SDK.
   211  1.  The chain's nodes must be using a sufficiently advanced version of Cosmovisor.
   212  
   213  ### Positive
   214  
   215  1.  The structure for defining artifacts is clearer since it is now defined in the proto instead of in documentation.
   216  1.  Availability of a pre-run command becomes more obvious.
   217  1.  A post-run command becomes possible.
   218  
   219  ### Negative
   220  
   221  1.  The `Plan` message becomes larger. This is negligible because A) the `x/upgrades` module only stores at most one upgrade plan, and B) upgrades are rare enough that the increased gas cost isn't a concern.
   222  1.  There is no option for providing a URL that will return the `UpgradeInstructions`.
   223  1.  The only way to provide multiple assets (executables and other files) for a platform is to use an archive as the platform's artifact.
   224  
   225  ### Neutral
   226  
   227  1. Existing functionality of the `info` field is maintained when the `UpgradeInstructions` aren't provided.
   228  
   229  ## Further Discussions
   230  
   231  1.  [Draft PR #10032 Comment](https://github.com/cosmos/cosmos-sdk/pull/10032/files?authenticity_token=pLtzpnXJJB%2Fif2UWiTp9Td3MvRrBF04DvjSuEjf1azoWdLF%2BSNymVYw9Ic7VkqHgNLhNj6iq9bHQYnVLzMXd4g%3D%3D&file-filters%5B%5D=.go&file-filters%5B%5D=.proto#r698708349):
   232      Consider different names for `UpgradeInstructions instructions` (either the message type or field name).
   233  1.  [Draft PR #10032 Comment](https://github.com/cosmos/cosmos-sdk/pull/10032/files?authenticity_token=pLtzpnXJJB%2Fif2UWiTp9Td3MvRrBF04DvjSuEjf1azoWdLF%2BSNymVYw9Ic7VkqHgNLhNj6iq9bHQYnVLzMXd4g%3D%3D&file-filters%5B%5D=.go&file-filters%5B%5D=.proto#r754655072):
   234      1.  Consider putting the `string platform` field inside `UpgradeInstructions` and make `UpgradeInstructions` a repeated field in `Plan`.
   235      1.  Consider using a `oneof` field in the `Plan` which could either be `UpgradeInstructions` or else a URL that should return the `UpgradeInstructions`.
   236      1.  Consider allowing `info` to either be a JSON serialized version of `UpgradeInstructions` or else a URL that returns that.
   237  1.  [Draft PR #10032 Comment](https://github.com/cosmos/cosmos-sdk/pull/10032/files?authenticity_token=pLtzpnXJJB%2Fif2UWiTp9Td3MvRrBF04DvjSuEjf1azoWdLF%2BSNymVYw9Ic7VkqHgNLhNj6iq9bHQYnVLzMXd4g%3D%3D&file-filters%5B%5D=.go&file-filters%5B%5D=.proto#r755462876):
   238      Consider not including the `UpgradeInstructions.description` field, using the `info` field for that purpose instead.
   239  1.  [Draft PR #10032 Comment](https://github.com/cosmos/cosmos-sdk/pull/10032/files?authenticity_token=pLtzpnXJJB%2Fif2UWiTp9Td3MvRrBF04DvjSuEjf1azoWdLF%2BSNymVYw9Ic7VkqHgNLhNj6iq9bHQYnVLzMXd4g%3D%3D&file-filters%5B%5D=.go&file-filters%5B%5D=.proto#r754643691):
   240      Consider allowing multiple artifacts to be downloaded for any given `platform` by adding a `name` field to the `Artifact` message.
   241  1.  [PR #10502 Comment](https://github.com/cosmos/cosmos-sdk/pull/10602#discussion_r781438288)
   242      Allow the new `UpgradeInstructions` to be provided via URL.
   243  1.  [PR #10502 Comment](https://github.com/cosmos/cosmos-sdk/pull/10602#discussion_r781438288)
   244      Allow definition of a `signer` for assets (as an alternative to using a `checksum`).
   245  
   246  ## References
   247  
   248  * [Current upgrade.proto](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/proto/cosmos/upgrade/v1beta1/upgrade.proto)
   249  * [Upgrade Module README](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/x/upgrade/spec/README.md)
   250  * [Cosmovisor README](https://github.com/cosmos/cosmos-sdk/blob/cosmovisor/v1.0.0/cosmovisor/README.md)
   251  * [Pre-upgrade README](https://github.com/cosmos/cosmos-sdk/blob/v0.44.5/docs/migrations/pre-upgrade.md)
   252  * [Draft/POC PR #10032](https://github.com/cosmos/cosmos-sdk/pull/10032)
   253  * [RFC 1738: Uniform Resource Locators](https://www.ietf.org/rfc/rfc1738.txt)