8

Followed the create a first substrate chain it all works good.

And then I want to go one step further to customize my on the demo.rs file, here is what I am doing:

  1. Totally replace code in demo.rs with code here, there is event involved now .

  2. update the lib.rs with

Demo: demo::{Module, Call, Storage, Event<T>},  

and

impl demo::Trait for Runtime {
    type Event = Event;
}
  1. run ./scripts/build.rs
  2. run ./target/release/node-name --dev

Then I see my updated extrinsic function is NOT listed here on the Polkadot Web App or by upload the substrate_node_template_runtime_wasm.compact.wasm file by following the the step 5 on tutorial

So I have to run the following code to make the update happens:

rm -rf ./target
cargo build --release
./target/release/node-name --dev

By discuss with @shawntabrizi he suggest with the following command

./scripts/build.sh
cargo build --release
./target/release/node-name purge-chain --dev
./target/release/node-name --dev

It seems that without purge-chain both the substrate_node_template_runtime_wasm.compact.wasm and ./target/release/node-name are not updated.

Quoted here

By upgrading the runtime, you're simply switching out the block of code that is going to be receiving extrinsics and reading storage.

But I want know one step deeper, when upgrade a runtime node, what is the difference behind build.sh and cargo build? Is that because that substrate_node_template_runtime_wasm.compact.wasm and/or ./target/release/node-name binary is not updated in the case above?

4

1 回答 1

6

让我们尝试解决您提出的一些不同主题:

build.sh 和 cargo build 有什么区别

Substrate 运行时被编译为 Native 二进制文件和 Wasm blob。在 Substrate v1.0 中,这些编译步骤是分开的。build.sh将运行时编译为 Wasm,同时cargo build编译整个节点(如 CLI、数据库等),包括运行时的本机版本。

似乎没有清除链,substrate_node_template_runtime_wasm.compact.wasm./target/release/node-name都没有更新。

了解这里背景中发生的细节很重要。当你运行一个节点时,一个数据库存储在本地,它具有你的链状态。因此,如果您./target/release/node-name --dev以 50 个块启动一个节点,停止该节点,然后再次启动它,它将从您离开的地方继续(在 51 块)。

请记住,作为节点创世配置的一部分,Runtime Wasm 存储在链上,并用于确定您应该运行哪个版本的运行时(本机与 Wasm)。

如果你重新编译你的 Wasm 和你的 Native 二进制文件,并且不做任何其他事情就运行它,你将看不到任何差异。即使您的节点二进制文件是全新的和更新的,它使用与旧链状态相同的数据库。这意味着在您的数据库中,您还拥有旧的 Wasm,并且当节点检查要使用的版本时,它将回退到使用数据库中的 Wasm!

如果您希望您的节点提取您所做的最新更改,您可以执行以下两项操作之一:

  1. 触发 Wasm 运行时的链上升级。这将使您的数据库具有最新的运行时代码,因此您的节点将使用最新的更改。

  2. 清除您的链以重新启动您的创世。这将删除您的 Substrate 区块链的任何旧状态,并最终使用最新的 Wasm 运行时填充链状态,这应该与您的节点一致。

我的建议:

./scripts/build.sh
cargo build --release
./target/release/node-name purge-chain --dev
./target/release/node-name --dev

将执行第二种方法,清理数据库,并在每次升级运行时逻辑时从块 0 重新启动节点。这通常是开发运行时最容易做的事情,因为在执行运行时升级时有许多因素可能导致意外行为。

我更改了大部分代码,并在其中添加了 Event。

不幸的是,您没有在此处共享任何代码,这有助于调试此问题。尽管重要的是要注意,您不能对运行时的每次更新都使用运行时升级功能。

您应该将您的区块链视为两个独立的部分,它们一起工作:

  1. 区块链存储
  2. 区块链逻辑

当您进行升级时,您基本上是将区块链逻辑从一件事换到另一件事。从技术上讲,您可以将任何东西换成任何东西。但实际上,这并不意味着它会起作用。如果你的新逻辑不理解你当前的区块链存储,你就会断链。

因此,假设您对一个函数进行了更改,该函数假设您拥有与以前完全不同的存储项目......好吧,事情不会好转。

通常,附加更改非常适合运行时升级。由于新功能不会影响旧功能,因此您的存储应该始终能够与新运行时良好配合。但是,如果您进行运行时升级并假设您的区块链存储发生了某些变化,您将需要在任何运行时逻辑实际执行之前触发这些存储项的迁移。您可以通过一次性on_initialize调用来执行此操作,这会将一组存储项目转换为新格式,但是当您谈论迁移大量数据时,实施细节开始发挥作用......

无论如何,总而言之,升级运行时有太多可能导致问题的因素,可能就像您所看到的那样。通常,您不应该使用运行时升级进行初始开发。相反,您通常应该在运行时的迭代之间清除您的链并从头开始。

于 2019-09-14T10:59:12.587 回答