在创建第一个底物链之后,一切都很好。
然后我想进一步走一步,在demo.rs
文件上自定义我的文件,这是我正在做的事情:
Demo: demo::{Module, Call, Storage, Event<T>},
和
impl demo::Trait for Runtime {
type Event = Event;
}
./scripts/build.rs
./target/release/node-name --dev
然后,我看到更新的外部函数未在Polkadot Web App上列出,或者通过遵循step 5 on tutorial
上传substrate_node_template_runtime_wasm.compact.wasm
文件
所以我必须运行以下代码来进行更新:
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
的{{1}}和substrate_node_template_runtime_wasm.compact.wasm
都不会更新。
引用here
通过升级运行时,您只需切换将要接收外部和读取存储的代码块。
但是我想更深入地了解,当升级运行时节点时,./target/release/node-name
和build.sh
之间有什么区别?是因为上述情况下cargo build
和/或substrate_node_template_runtime_wasm.compact.wasm
二进制文件未更新?
答案 0 :(得分:3)
让我们尝试解决您提出的一些不同主题:
build.sh和cargo build的区别是什么
Substrate运行时被编译为本机二进制文件和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存储在链上,used to determine which version应该运行(本地与Wasm)。
如果您重新编译Wasm和本机二进制文件,然后不做任何其他事情就运行它,您将看不到任何差异。即使您的节点二进制文件是全新的且已更新,它仍使用相同的具有旧链状态的数据库。这意味着在数据库中,您还拥有旧的Wasm,并且当节点执行此操作时,将检查要使用的版本,它将回退以使用数据库中的Wasm!
如果您希望节点提取所做的最新更改,则可以执行以下两项操作之一:
触发Wasm运行时的链上升级。这将使您的数据库具有最新的运行时代码,因此您的节点将使用最新的更改。
清除链条以重新开始创世。这将删除您的Substrate区块链的任何旧状态,并最终使用最新的Wasm运行时填充链状态,这应与您的节点一致。
我的建议:
./scripts/build.sh
cargo build --release
./target/release/node-name purge-chain --dev
./target/release/node-name --dev
将执行第二种方法,清理数据库,并在每次升级运行时逻辑时从块0重新启动节点。在开发运行时时,这通常是最容易的事情,因为在执行运行时升级时,有许多因素可能导致意外的行为。
我更改了大部分代码,并在其中添加了事件。
很遗憾,您在这里没有共享任何代码,这可能有助于调试此问题。尽管需要特别注意的是,您不能对运行时的每次更新都使用运行时升级功能。
您应该将您的区块链视为两个可以协同工作的独立部分:
进行升级时,您基本上是将区块链逻辑从一件事换成另一件事。从技术上讲,您可以从字面上交换任何内容。但是实际上,这并不意味着它将起作用。如果您的新逻辑不了解您当前的区块链存储,那么您将打破链条。
因此,假设您对函数进行了更改,假设您拥有与以前完全不同的存储项目。...结果不会很好。
通常,附加更改对于运行时升级来说就很好。由于新功能不会影响旧功能,因此您的存储应该始终能够与新的运行时一起正常工作。但是,如果您进行运行时升级时假设区块链存储发生了某些变化,那么您将需要在实际执行任何运行时逻辑之前触发这些存储项的 migration 。您可以使用一次性on_initialize
调用来完成此操作,该调用会将一组存储项目转换为新格式,但是当您谈到迁移大量数据时,实现细节开始出现。 / p>
总而言之,总而言之,升级运行时周围的因素太多,可能会引起问题,也许就像您所看到的那样。通常,您应该不要使用运行时升级进行初步开发。相反,通常应该清除链并在运行时的迭代之间从头开始。