关于polkadot的substrate与runtime编译教程-part2

json文件的chain spec
chainspec JSON是一个大的JSON对象,通过substrate build-spec命令生成。此命令通过引用节点的导入runtime模块并查找需要定义的公开配置来工作。这些将是空值或提供默认值。
本质上,runtime模块可以依赖于“创世配置”,换句话说,我们在区块链首次初始化和构建其状态时提供的配置。这一状态是通过创世地块-第一个生产的区块链启动的。chainspec json文件的任务是定义这个初始状态。
一旦生成,我们可以在运行节点之前打开此chainspec chain并修改任何我们认为必要的值。
注意:如果我们的链写了我们不再需要的状态呢?也许我们已经更新了一个模块,或者任何链配置,并且想要反映来自Genesis块的更改?我们可以清除链-删除块历史-有效地重置节点。
您的节点为此提供了purge-chain命令,通常用于开发工作流:
# optional –dev flag to specify development chain
substrate purge-chain –dev
除此之外,框架还提供了三个默认的chain“spec”(pre-filled configurations),它们根据我们是运行节点进行测试还是生产目的来定义一些基本值。
实际上,默认情况下提供了三个spec:dev,local和staging:
· dev spec是离实际用例最远的规范,主要配置为帮助您使用链。我们为您提供了一系列帐户,并为所有预打包的runtime模块提供了配置。
· local spec类似于dev规范,在private network substrate教程中使用,由parity托管。假设您希望在本地测试多用户场景,它会为多个帐户提供“权限”。
· staging是一个更保守的规范,定义了有限数量的帐户,并省略了特定于模块的配置。这是您在构建生产链时选择的规范。
我们可以做的是使用substrate build-spec命令基于这些提供的选项之一构建新的chain spec,将结果输出到单独的文件。如果我想复制我自己的链的开发chain spec,我可以运行以下命令,在我的主目录中的新my-chianspec.json文件中输出规范:
substrate build-spec –chain=dev > ~/my-chainspec.json
在编辑器中打开此文件以查看可用的配置选项。
注意:您可能希望折叠genesis.system.runtime区块,其中包含一个无法读取的运行时区块。
id字段可以修改为您自己的名称,以及名称字段,这是一个更易于理解的chain spec名称。一些值得注意的常见选项包括:
遥测端点(Telemetry endpoints):通过遥测端点为遥测服务提供端点。这将允许您使用已连接的节点填充UI,与Polkadot遥测不同。
在您的节点处理原生令牌的情况下,提供初始帐户的余额列表。
抵押配置(staking configuration):链支持该功能。配置选项,如初始验证器帐户、验证器和存储变量。
最终,根据runtime包含的模块,还会有各种其他变量。帮助您熟悉chain spec文件的建议方法是参考主substrate节点chain spec。
substrate build-spec –chain ~/chainspec.json –raw > ~/mychain.json
最后,为了运行我们的区块链,我们提供了这种chain spec的substrate。从这里我们将假设您正在运行自定义编译的Substrate节点,我们将<node_path>替换为该节点的运行时。
<node_path> –chain ~/mychain.json –validator
注意:您的链开始生成区块需要验证者标志。
接下来让我们看看初始化和编译自定义Substrate节点。
初始化substate节点
到目前为止,我们一直在使用通过安装脚本获得的已编译substrate节点。这对于测试开发链是非常友好的。但是它限制了我们引入自己的runtime模块和自定义配置。为此,我们需要下载substrate源代码。
我们有两种方法可以开始使用我们自己的定制substrate链:
1、下载易于配置的节点模板(例如,从第一部分完整安装中下载的测试网节点模板,或特定供的Substrate Kitties节点)。
2、使用Substrate Scripts,下载官方节点模板,一个简单的Substrate节点脚本,其中包含准备好进行runtiem模板。我们可以使用我们之前安装的Substrate Scripts来完成这项工作。
使用以下命令生成新节点模板:
// substrate-node-new <node_name> <author>
substrate-node-new my-node “Ross Bulat”
这可能需要一些时间,具体取决于您的系统 – 将获取和编译最新的Substrate源代码。
完成后,节点的运行时现在可以通过lib.rs文件在runtime/src文件夹中编辑。其中还包括一个runtime模块的模板,模板为template.rs。接下来我们将查看一个runtime模块。
构建自定义节点
在节点目录中,使用附带的build.sh脚本将节点编译为wasm,然后使用cargo编译binary文件:
# build wasm
./scripts/build.sh
# build binary
cargo build –release
现在将在节点的./target/release/目录中编译节点。
在我们使用substrate调用特定于节点的命令的地方,我们现在可以参考我们新建的binary文件,在我们的定制链上运行命令。要清除链并重新运行它,我们将使用binary文件:
# clear chain state
./target/release/<node_name> purge-chain –dev
# run in dev mode
./target/release/<node_name> –dev
我们在这里介绍的最后一个主题是runtime模块。让我们探讨它们是什么以及如何将它们包含在Substrate节点中。
介绍substrate的runtime模块
什么赋予Substrate实用性是一种通用的模块化结构,允许开发人员将功能插入其runtime,从而创建符合其要求的自定义区块链。
注意:Substrate运行时的另一个术语是状态转换函数或STF。这实际上是执行块的函数,导致区块链发生状态更改。
这些功能包称为模块,或者更具体地说,是runtime模块。预先与Substrate一起打包的这些runtime模块系列共同形成了一个模块目录,称为substrate的runtime模块库或SRML。
这些模块非常有用。它们为我们期望从其他区块链框架获得的一系列功能添加了功能,并且可以在github上浏览。让这些模块随时可用可以避免开发人员重新发明轮子——在实现了全新功能的地方,它们也可以作为runtime模块开发。
以下是一些可用的模块:
assets:为可替代资产提供支持的模块——想想ERC20代币。
balance:为管理账户余额提供支持的模块。
Staking:一个模块,提供管理网络维护者所关注资金的功能。
您会注意到,每个模块都被格式化为Rust crate,旨在导入到Substrate runtime环境中。
每个SRML模块都会被打包起来,并在模块名称前面加上srml_前缀,每个模块都可以在Parity的crate库的左侧菜单中找到。
模块结构概述
每个模块都在自己的src / lib.rs文件中定义符合特定的结构。我们已经可以看到Substrate模块的高级特性:
模块可以定义为一个文件、module-name.rs或更常见的lib.rs。模块还可以有其他支持文件,通常都位于特定目录中。
模块必须符合特定结构,依赖于特定substrate API。
这最后一点究竟意味着什么?嗯,这取决于你的模块实际做了什么。模块为区块链提供了功能 – 我们已经知道了很多 – 但是这个功能可以以一系列组件的形式出现:
事件(event):模块可以定义在满足特定条件时要调用的自定义事件 – 当您制作新的不可替换的令牌时,可能是TokenCreated事件。事件包含在decl_event!marco:
decl_event!(
    pub enum Event<T>
    where
        <T as system::Trait>::AccountId,
        <T as system::Trait>::Hash
    {
        TokenCreated(AccountId, Hash),
    }
);
存储(storage):模块可以定义要在链上持久化的数据结构,如映射、列表等。我们实际上可以存储一系列数据类型,其中大部分都在这里记录。存储项在decl_storage! macro:
decl_storage! {
    trait Store for Module<T: Trait> as NFTStorage {
        TokenToOwner get(token): map T::Hash => Token<T::Hash, T::Hash>;
        TokenIndex get(get_token_by_index): map u64 => T::Hash;
        TotalTokens get(total_tokens): u64;
        …
   }
}
Dispatchable函数:可以在runtime通过JSON RPC调用执行的公共函数。所有可调度函数都包含origin参数,其中包含有关函数调用源的信息,例如调用者的公共地址和其他元数据。
如果我们查看Assets模块可调度函数,我们可以看到为我们定义了issue,transfer和destroy。可调度函数通过帐户调用。我们将进一步使用特定工具管理帐户。
public或private函数:模块可以提供可以从runtime环境中的任何位置调用的公共函数,以及只能在模块实现中调用的私有函数。这些都不是可调度的功能,例如它们无法通过JSON RPC协议从外部访问,也不需要origin参数。
结构(Structs):模块可以定义该模块可能需要的结构。例如可能会为用于跟踪全球货件的链定义ShipmentItem结构:
#[derive(Encode, Decode, Default, Clone, PartialEq)]
pub struct ShipmentItem<Hash, Balance> {
    id: Hash,
    container_id: Hash,
    price: Balance,
    weight: u64
}
请注意,我们可以将其他类型引入结构中,就像我们在上面的示例中使用Hash和Balance一样。
标准类型(如hash)在runtime原语库中定义,但类型也通常在其他runtime模块中定义,在这些模块中我们引入了依赖关系的概念。
正如我们已经发现的,模块可以是crates,因此可以作为cargo.toml中的依赖项。这样可以确保其他人依赖的模块不会丢失。
回到即插即用的模拟,模块定义了可在runtime内(执行)的可插入(导入)功能,为您的链提供额外的功能。这个可插入的方面只是意味着将所需的模块声明并导入到Substrate运行时。
通过对substrate模块实际是什么的概念性理解,让我们使用substrate-module-new用程序来生成一个简单的模块模板。
初始化新模块
与substrate-node-new程序一样,我们还下载了一个substrate-module-new程序,它可以提供最新的模块模板供我们使用。
在节点runtime目录中,使用以下命令准备新模块:
substrate-module-new <module_name>
让我们用my-module的名称来运行它。输出将提示我们将模块添加到runtime / src / lib.rs文件中:
cd runtime/src
substrate-module-new my-module
> SRML module created as ./my-module.rs and added to git.
> Ensure that you include in your ./lib.rs the line:
> mod my_module;
生成的文件my module将与最初包含在目录中的template.rs文件相同。但是运行substrate module new是在事件模板中启动新runtime模块的首选方法同时rs已被编辑。
总结
这篇关于substrate的介绍已经介绍了如何安装框架,以及如何使用包含的工具来帮助部署自定义节点和模块。
我们使用了Polkadot JS程序,了解它如何作为Substrate管理实用程序工作,同时充当链资源管理器和管理器。该应用程序旨在提供通用功能,不会假设您的链支持什么 – 应用程序的UI将根据您的chain spec和您在runtime定义的模块更新。
关于chain spec的主题,我们介绍了如何通过substrate构建规范生成规范JSON文件,其内容将根据链的runtime将runtime模块而变化。还有三个预先配置的chain spec,用于填充开发或生产节点的规范。在编译为原始状态并与运行时一起使用之前,可以编辑chain spec。