如何正确升级 Substrate 节点上的运行时?

How to correctly upgrade a runtime on Substrate node?

接着创建了第一个 substrate 链,一切正常。

然后我想更进一步在 demo.rs 文件上自定义我的,这就是我正在做的事情:

  1. 完全替换demo.rs with code here中的代码,现在有事件参与 .

  2. lib.rs 更新为

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

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

然后我发现 Polkadot Web App or by upload the substrate_node_template_runtime_wasm.compact.wasm file by following the the step 5 on tutorial

上没有列出我更新的外部函数

所以我必须运行以下代码来进行更新:

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

通过与@shawntabrizi 讨论,他建议使用以下命令

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

似乎没有 purge-chain substrate_node_template_runtime_wasm.compact.wasm./target/release/node-name 都没有更新。

引用here

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

但我想更深入地了解一下,升级运行时间节点时,build.shcargo build有什么区别?那是因为 substrate_node_template_runtime_wasm.compact.wasm and/or ./target/release/node-name 二进制文件在上述情况下没有更新吗?

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

what is the difference behind build.sh and cargo build

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

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

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

请记住,作为节点创世配置的一部分,运行时 Wasm 存储在链上, 运行 时间你应该 运行(原生 vs Wasm)。

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

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

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

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

我的建议是:

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

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

I changed most of the code, and add Event in it.

很遗憾,您没有在此处共享任何有助于调试此问题的代码。尽管请务必注意,您不能对 运行 时间的每次更新都使用 运行 时间升级功能。

您应该将区块链视为协同工作的两个独立部分:

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

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

因此,假设您对一个函数进行了更改,假设您拥有与以前完全不同的存储项……好吧,结果不会很好。

总的来说,加法改动对于运行时间升级来说就可以了。由于新功能不会影响旧功能,因此您的存储设备应该始终能够很好地适应新的 运行 时间。但是,如果您进行 运行time 升级,假设您的区块链存储发生了某些变化,您将需要在任何 运行时间逻辑实际执行。您可以通过一次性 on_initialize 调用来完成此操作,这会将一组存储项目转换为新格式,但是当您谈论迁移大量数据时,实施细节开始发挥作用......

总而言之,升级您的 运行time 有太多因素可能会导致问题,可能就像您所看到的那样。一般来说,您应该不使用运行时间升级进行初始开发。相反,您通常应该在 运行time.

迭代之间清除链并从头开始