Search code examples
rustsubstratepolkadot

Why there are no changes in the mutability behaviour of storage values even after changing the source code of the substrate chain?


Reading about the mutability, I implemented the following piece of code in my substrate chain:

use support::{decl_module, decl_storage, dispatch::Result, ensure, StorageMap};
use system::ensure_signed;

pub trait Trait: balances::Trait {}

decl_storage! {
    trait Store for Module<T: Trait> as KittyStorage {
        Value: map u64 => Option<T::AccountId>;
    }
}

decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
        fn set_value(origin, value: u64) -> Result {
            let sender = ensure_signed(origin)?;
            ensure!(!<Value<T>>::exists(value), "key already exists");
            <Value<T>>::insert(value, sender);
            Ok(())
        }
    }
}

and then changed the code to this:

use support::{decl_module, decl_storage, dispatch::Result, StorageMap};
use system::ensure_signed;

pub trait Trait: balances::Trait {}

decl_storage! {
    trait Store for Module<T: Trait> as KittyStorage {
        Value: map u64 => T::AccountId;
    }
}

decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {

        fn set_value(origin, value: u64) -> Result {
            let sender = ensure_signed(origin)?;

            <Value<T>>::insert(value, sender);

            Ok(())
        }
    }
}

As you can see, in the second code, the value can be changed/overwritten. My intention was to know about the changes in the source code. I am running the demo substrate chain and to my surprise, the behavior of the substrate chain didn't change at all.

In the official documentation, it is mentioned:

Smart contracts must consciously implement upgradeability while parachains will have the ability to swap out their code entirely through a root command or via the governance pallet.

I did not purge my existing chain but had rebuilt it using the following commands:

./scripts/build.sh
cargo build --release
./target/release/substratekitties --dev

To rephrase, my substrate chain didn't change its behavior (I cannot overwrite the value) even though I changed the code and rebuilt it without purging the existing chain.

Initial Code: immutable key-value pairs in storage value Final Code: mutable key-value pairs in storage value

Initial Chain: immutable key-value Final Chain: immutable key-value

Is this expected? If yes, whats the quote(aforementioned from the docs about parachains) about? If no, how can I change the behavior of my substrate chain without purging it?


Solution

  • I did not purge my existing chain

    TLDR: That's why you didn't notice the change. Purge your chain and start over and you will see the change.

    Substrate compiles the runtime to wasm and stores the wasm on chain. This facilitates the forkless upgrade process. Although you recompiled your node, the existing chain data still had the old wasm runtime in its genesis block, and thus that old runtime was used. In order to see the change you have two options.

    1. Purge your chain and start over entirely
    2. Make an additional change to your runtime which increments the spec_version. One you've built the new runtime, use sudo (or any other on-chain governance pallet) to call system::set_code. This will perform an on-chain runtime upgrade and your changes will take effect.