# Upgrade a Running Network

Unlike many blockchains, the Substrate development framework supports **forkless upgrades** to the runtime that is the core of the blockchain. Most blockchain projects require a [hard fork](https://github.com/InfraBlockchainTeam/infrablockspace-docs/blob/master/reference/glossary/README.md#fork) of the code base to support ongoing development of new features or enhancements to existing features. With Substrate, you can deploy enhanced runtime capabilities—including breaking changes—without a hard fork. Because the definition of the runtime is itself an element in the state of a Substrate-based chain, network participants can update this value by calling the [`set_code`](https://paritytech.github.io/substrate/master/frame_system/pallet/enum.Call.html#variant.set_code) function in a transaction. Because updates to the runtime state are validated using the blockchain's consensus mechanisms and cryptographic guarantees, network participants can use the blockchain itself to distribute updated or extended runtime logic without needing to fork the chain or release a new blockchain client.

This tutorial illustrates how to upgrade the runtime without creating a fork of the code base or stopping the progress of the chain. In this tutorial, you'll make the following changes to a Substrate runtime on a running network node:

* Increase the `spec_version` of the runtime.
* Add the Utility pallet to the runtime.
* Increase the minimum balance for network accounts.

### Before you begin

Before you begin, verify the following:

* You have configured your environment for Substrate development by installing [Rust and the Rust toolchain](https://docs.infrablockchain.net/infrablockchain-docs/infrablockchain/learn/substrate/tutorials/install).
* You have completed [Build a local blockchain](https://docs.infrablockchain.net/infrablockchain-docs/infrablockchain/learn/substrate/tutorials/build-a-blockchain/build-local-blockchain) and have the Substrate node template installed locally.
* You have reviewed [Add a pallet to the runtime](https://docs.infrablockchain.net/infrablockchain-docs/infrablockchain/learn/substrate/tutorials/build-application-logic/add-a-pallet) for an introduction to adding a new pallet to the runtime.

### Tutorial objectives

By completing this tutorial, you will accomplish the following objectives:

* Use the Sudo pallet to simulate governance for a chain upgrade.
* Upgrade the runtime for a running node to include a new pallet.
* Submit a transaction to upload the modified runtime onto a running node.

### Authorize an upgrade with Sudo

Typically, runtime upgrades are managed through governance with community members voting to approve or reject upgrade proposals. In place of governance, this tutorial uses the Sudo pallet and the `Root` origin to identify the runtime administrator with permission to upgrade the runtime. Only this root-level administrator can update the runtime by calling the `set_code` function. The Sudo pallet enables you to invoke the `set_code` function using the `Root` origin by specifying the account that has root-level administrative permissions.

By default, the chain specification file for the node template specifies that the `alice` development account is the owner of the Sudo administrative account. Therefore, this tutorial uses the `alice` account to perform runtime upgrades.

#### Resource accounting for runtime upgrades

Function calls that are dispatched to the Substrate runtime are always associated with a [weight](https://github.com/InfraBlockchainTeam/infrablockspace-docs/blob/master/reference/glossary/README.md#weight) to account for resource usage. The FRAME System module sets boundaries on the block length and block weight that these transactions can use. However, the `set_code` function is intentionally designed to consume the maximum weight that can fit in a block. Forcing a runtime upgrade to consume an entire block prevents transactions in the same block from executing on different versions of a runtime.

The weight annotation for the `set_code` function also specifies that the function is in the `Operational` class because it provides network capabilities. Function calls that are identified as operational:

* Can consume the entire weight limit of a block.
* Are given maximum priority.
* Are exempt from paying transaction fees.

#### Managing resource accounting

In this tutorial, the [`sudo_unchecked_weight`](https://paritytech.github.io/substrate/master/pallet_sudo/pallet/enum.Call.html#variant.sudo_unchecked_weight) function is used to invoke the `set_code` function for the runtime upgrade. The `sudo_unchecked_weight` function is the same as the `sudo` function except that it supports an additional parameter to specify the weight to use for the call. This parameter enables you to work around resource accounting safeguards to specify a weight of zero for the call that dispatches the `set_code` function. This setting allows for a block to take *an indefinite time to compute* to ensure that the runtime upgrade does not fail, no matter how complex the operation is. It can take all the time it needs to succeed or fail.

### Add the Utility pallet to the runtime

By default, the node template doesn't include the [Utility pallet](https://paritytech.github.io/substrate/master/pallet_utility/index.html) in its runtime. To illustrate a runtime upgrade, you can add the Utility pallet to a running node.

#### Start the local node

This tutorial illustrates how to update a running node, so the first step is to start the local node with the current runtime.

To start the node with the current runtime:

1. Open a terminal shell on your computer.
2. Change to the root directory where you compiled the Substrate node template.
3. Start the previously-compiled local node in development mode by running the following command:

   ```bash
   cargo run --release -- --dev
   ```

   Leave this node running. You can edit and re-compile to upgrade the runtime without stopping or restarting the running node.
4. Open the [Polkadot/Substrate Portal](https://polkadot.js.org/apps/#/explorer) in a browser and connect to the local node.
5. Click the left-most dropdown menu to select the network.

   ![Select network](https://github.com/InfraBlockchainTeam/infrablockspace-docs/blob/master/media/images/docs/tutorials/forkless-upgrade/polkadot-js-select-network.png)
6. Under **Development**, select **Local Node**, then click **Switch**.

   ![Select network](https://3394686052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5FcHUSDzEQOuSRhER7FQ%2Fuploads%2Fgit-blob-321683ab8f954353f25daa4ef6511e34a64f18e8%2Fpolkadot-js-select-network.png?alt=media)

   In the upper left, notice the node template version is the default version 100.

#### Add the Utility pallet to the runtime dependencies

To update the dependencies for the runtime to include the Utility pallet:

1. Open a second terminal shell window or tab.
2. Change to the root directory where you compiled the Substrate node template.
3. Open the `runtime/Cargo.toml` file in a text editor.
4. Locate the `[dependencies]` section.

   For example:

   ```
   [dependencies]
   codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
   scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }

   pallet-aura = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/polkadot-sdk.git", branch = "polkadot-v1.0.0" }
   ```
5. Add the Utility pallet as a dependency.

   For example, add a single line with the following fields:

   ```toml
   pallet-utility = {
      version = "4.0.0-dev",
      default-features = false,
      git = "https://github.com/paritytech/polkadot-sdk.git",
      branch = "polkadot-v1.0.0"
   }
   ```
6. Locate the `[features]` section and the list of the default features for the standard binary.

   For example:

   ```
   [features]
   default = ["std"]
   std = [
      "frame-try-runtime?/std",
      "frame-system-benchmarking?/std",
      "frame-benchmarking?/std",
      "codec/std",
      "scale-info/std",
   ```
7. Add the Utility pallet to the list.

   ```toml
   "pallet-utility/std",
   ```
8. Save your changes and close the `Cargo.toml` file.

#### Add the Utility pallet configuration

To add the Utility types and configuration trait:

1. Open the `runtime/src/lib.rs` file in a text editor.
2. Add the implementation for the Config trait for the Utility pallet.

   ```rust
   impl pallet_utility::Config for Runtime {
      type RuntimeEvent = RuntimeEvent;
      type RuntimeCall = RuntimeCall;
      type PalletsOrigin = OriginCaller;
      type WeightInfo = pallet_utility::weights::SubstrateWeight<Runtime>;
   }
   ```
3. Locate the `construct_runtime!` macro.

   ```
   construct_runtime!(
     pub struct Runtime
     where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic
     {
            System: frame_system,
            RandomnessCollectiveFlip: pallet_randomness_collective_flip,
            Timestamp: pallet_timestamp,
            Aura: pallet_aura,
   ```
4. Add the Utility pallet inside the `construct_runtime!` macro.

   ```rust
   Utility: pallet_utility,
   ```
5. Locate the `runtime_version` macro.

   ```
   #[sp_version::runtime_version]
   pub const VERSION: RuntimeVersion = RuntimeVersion {
        spec_name: create_runtime_str!("node-template"),
        impl_name: create_runtime_str!("node-template"),
        authoring_version: 1,
        spec_version: 100,
        impl_version: 1,
        apis: RUNTIME_API_VERSIONS,
        transaction_version: 1,
        state_version: 1,
   };
   ```
6. Update the value for the EXISTENTIAL\_DEPOSIT for the Balances pallet.

   ```rust
   pub const EXISTENTIAL_DEPOSIT: u128 = 1000 // Update this value.
   ```

   This change increases the minimum balance an account is required to have on deposit to be viewed as a valid active account. This change doesn't remove any accounts with balances between 500 and 1000. Removing accounts would require a storage migration. For information about upgrading data storage, see [storage migration](https://docs.infrablockchain.net/infrablockchain-docs/infrablockchain/learn/substrate/learn/runtime-development/storage-migrations)
7. Increment the [`spec_version`](https://paritytech.github.io/substrate/master/sp_version/struct.RuntimeVersion.html#structfield.spec_version) to specify the new runtime version.

   ```rust
   spec_version: 101,  // Change the spec_version from 100 to 101
   ```

   The fields for the `runtime_version` specify the following information:

   * `spec_name` specifies the name of the runtime.
   * `impl_name` specifies the name of the outer node client.
   * `authoring_version` specifies the version for [block authors](https://github.com/InfraBlockchainTeam/infrablockspace-docs/blob/master/reference/glossary/README.md#author).
   * `spec_version` specifies the version of the runtime.
   * `impl_version` specifies the version of the outer node client.
   * `apis` specifies the list of supported APIs.
   * `transaction_version` specifies the version of the [dispatchable function](https://github.com/InfraBlockchainTeam/infrablockspace-docs/blob/master/reference/glossary/README.md#dispatch) interface.
   * `state_version` specifies the version of the key-value trie data structure that the runtime uses.

   To upgrade the runtime, you must *increase* the `spec_version`. For more information, see the [FRAME System](https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/system/src/lib.rs) module and the `can_set_code` method.
8. Save your changes and close the `runtime/src/lib.rs` file.

#### Recompile and connect to the local node

1. Verify that the local node continues to run in the first terminal.
2. In the second terminal where you updated the runtime `Cargo.toml` and `lib.rs` files, recompile the runtime by running the following command

   ```shell
   cargo build --release --package node-template-runtime
   ```

   The `--release` command-line option requires a longer compile time. However, it generates a smaller build artifact that is better suited for submitting to the blockchain network. Storage optimization is *critical* for any blockchain. With this command, the build artifacts are output to the `target/release` directory. The WebAssembly build artifacts are in the `target/release/wbuild/node-template-runtime` directory. For example, you should see the following WebAssembly artifacts:

   ```
   node_template_runtime.compact.compressed.wasm
   node_template_runtime.compact.wasm
   node_template_runtime.wasm
   ```

### Execute a runtime upgrade

You now have a WebAssembly artifact that describes the modified runtime logic. However, the running node isn't using the upgraded runtime yet. To complete the upgrade, you need to submit a transaction that updates the node to use the upgraded runtime.

To update the network with the upgraded runtime:

1. Open the [Polkadot/Substrate Portal](https://polkadot.js.org/apps/#/explorer) in a browser and connect to the local node.
2. Click **Developer** and select **Extrinsics** to submit a transaction for the runtime to use the new build artifact.
3. Select the administrative **Alice** account.
4. Select the **sudo** pallet and the **sudoUncheckedWeight(call, weight)** function.
5. Select **system** and **setCode(code)** as the call to make using the Alice account.
6. Click **file upload**, then select or drag and drop the compact and compressed WebAssembly file—`node_template_runtime.compact.compressed.wasm`—that you generated for the updated runtime.

   For example, navigate to the `target/release/wbuild/node-template-runtime` directory and select `node_template_runtime.compact.compressed.wasm` as the file to upload.
7. Leave both of the **weight** parameters set to the default value of `0`.

   ![Runtime upgrade settings](https://3394686052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5FcHUSDzEQOuSRhER7FQ%2Fuploads%2Fgit-blob-d1940c446ac4630ca445ae3beb33b97668568180%2Fset-code-transaction.png?alt=media)
8. Click **Submit Transaction**.
9. Review the authorization, then click **Sign and Submit**.
10. Click **Network** and select **Explorer** to see that there has been a successful `sudo.Sudid` event.

    ![Successful sudo event](https://3394686052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5FcHUSDzEQOuSRhER7FQ%2Fuploads%2Fgit-blob-db2cac4823018d5e900961030029c67235fd9fc9%2Fset-code-sudo-event.png?alt=media)

    After the transaction is included in a block, the node template version number indicates that the runtime version is now `101`. For example:

    ![Updated runtime version is 101](https://3394686052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5FcHUSDzEQOuSRhER7FQ%2Fuploads%2Fgit-blob-36532ac079de40ae7437fdaec093f07e7b749e19%2Fruntime-version-101.png?alt=media)

    If your local node is producing blocks in the terminal that match what is displayed in the browser, you have completed a successful runtime upgrade.
11. Click **Developer** and select **Extrinsics**. Click on *submit the following extrinsic* and scroll to the bottom of the list. You will see **utility** as an option.
12. Verify the constant value by querying the chain state in the [Polkadot/Substrate Portal](https://polkadot.js.org/apps/#/chainstate/constants?rpc=ws://127.0.0.1:9944).

    * Click **Developer** and select **Chain state**.
    * Click **Constants**.
    * Select the **balances** pallet.
    * Select **existentialDeposit** as the constant value as the value to query.

    ![Verify the constant value change](https://github.com/InfraBlockchainTeam/infrablockspace-docs/blob/master/media/images/docs/tutorials/forkless-upgrade/constant-value-lookup.png)

### Where to go next

* [Runtime version 101](https://github.com/InfraBlockchainTeam/infrablockspace-docs/blob/master/assets/tutorials/runtime-upgrade/lib-spec-version-101.rs)
* [Runtime version 102](https://github.com/InfraBlockchainTeam/infrablockspace-docs/blob/master/assets/tutorials/runtime-upgrade/lib-spec-version-102.rs)
* [Storage migrations](https://github.com/InfraBlockchainTeam/infrablockspace-docs/blob/master/maintain/runtime-upgrades/README.md#storage-migration)
