为什么即使更改了底层链的源代码,存储值的可变性行为也没有变化?
Why there are no changes in the mutability behaviour of storage values even after changing the source code of the 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(())
}
}
}
然后将代码更改为:
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(())
}
}
}
如您所见,在第二个代码中,该值可以是changed/overwritten。我的目的是了解源代码的变化。我是 运行 演示 substrate 链,令我惊讶的是,substrate 链的行为根本没有改变。
官方文档中提到:
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.
我没有清除我现有的链,而是使用以下命令重建了它:
./scripts/build.sh
cargo build --release
./target/release/substratekitties --dev
换句话说,即使我更改了代码并在没有清除现有链的情况下重建它,我的底层链也没有改变它的行为(我无法覆盖该值)。
初始代码:存储值中的不可变键值对
最终代码:存储值中的可变键值对
初始链:不可变键值
最终链:不可变键值
这是预期的吗?如果是,引述(前面提到的关于平行链的文档)是关于什么的?
如果不是,我如何在不清除它的情况下改变我的底物链的行为?
I did not purge my existing chain
TLDR:这就是您没有注意到更改的原因。清除你的链条并重新开始,你会看到变化。
Substrate 将运行时编译为 wasm 并将 wasm 存储在链上。这有助于无叉升级过程。尽管您重新编译了您的节点,但现有的链数据在其创世块中仍然具有旧的 wasm 运行时,因此使用了旧的运行时。要查看更改,您有两个选择。
- 清除链条并完全重新开始
- 对您的运行时进行额外更改,增加 spec_version。您已经构建了新的运行时,使用 sudo(或任何其他链上治理托盘)调用
system::set_code
。这将执行链上运行时升级,您的更改将生效。
阅读可变性,我在我的底层链中实现了以下代码:
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(())
}
}
}
然后将代码更改为:
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(())
}
}
}
如您所见,在第二个代码中,该值可以是changed/overwritten。我的目的是了解源代码的变化。我是 运行 演示 substrate 链,令我惊讶的是,substrate 链的行为根本没有改变。
官方文档中提到:
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.
我没有清除我现有的链,而是使用以下命令重建了它:
./scripts/build.sh
cargo build --release
./target/release/substratekitties --dev
换句话说,即使我更改了代码并在没有清除现有链的情况下重建它,我的底层链也没有改变它的行为(我无法覆盖该值)。
初始代码:存储值中的不可变键值对 最终代码:存储值中的可变键值对
初始链:不可变键值 最终链:不可变键值
这是预期的吗?如果是,引述(前面提到的关于平行链的文档)是关于什么的? 如果不是,我如何在不清除它的情况下改变我的底物链的行为?
I did not purge my existing chain
TLDR:这就是您没有注意到更改的原因。清除你的链条并重新开始,你会看到变化。
Substrate 将运行时编译为 wasm 并将 wasm 存储在链上。这有助于无叉升级过程。尽管您重新编译了您的节点,但现有的链数据在其创世块中仍然具有旧的 wasm 运行时,因此使用了旧的运行时。要查看更改,您有两个选择。
- 清除链条并完全重新开始
- 对您的运行时进行额外更改,增加 spec_version。您已经构建了新的运行时,使用 sudo(或任何其他链上治理托盘)调用
system::set_code
。这将执行链上运行时升级,您的更改将生效。