创建第一个 Substrate 区块链
Posted 盐水煮毛豆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了创建第一个 Substrate 区块链相关的知识,希望对你有一定的参考价值。
创建第一个 Substrate 区块链
区块链软件使单个计算机(称为节点)能够相互通信以形成分散的点对点 (P2P) 网络。为保证链上数据的安全和链上的持续进展,节点通过某种形式的共识,就每个数据块中的数据状态以及块的处理顺序达成一致。
安装所需的软件包
OS | Installation commands |
---|---|
Ubuntu or Debian | sudo apt update && sudo apt install -y git clang curl libssl-dev llvm libudev-dev |
Arch Linux | pacman -Syu --needed --noconfirm curl git clang |
Fedora | sudo dnf update sudo dnf install clang curl git openssl-devel |
OpenSUSE | sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel |
macOS | brew update && brew install openssl |
Windows | Refer to this installation guide. |
如果您使用的是 macOS 并且没有安装 Homebrew,请运行以下命令来安装 Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
安装 Homebrew 后,运行brew install openssl
安装 Rust 和 Rust 工具链
手动安装和配置 Rust:
-
rustup
通过运行以下命令进行安装:curl https://sh.rustup.rs -sSf | sh
-
bin
通过运行以下命令,配置当前 shell 以重新加载 PATH 环境变量,使其包含 Cargo目录:source ~/.cargo/env
-
stable
通过运行以下命令将 Rust 工具链配置为默认为最新版本:rustup default stable rustup update
-
通过运行以下命令添加
nightly
版本和nightly
WebAssembly ( ) 目标:wasm
rustup update nightly rustup target add wasm32-unknown-unknown --toolchain nightly
-
通过运行以下命令来验证您的安装:
rustc --version rustup show
前面的步骤将引导您完成 Rust 和 Rust 工具链的安装和配置,以便您自己看到完整的过程。
启动区块链节点并探索
节点编译后,您就可以开始使用前端模板探索它的功能了。
启动本地 Substrate 节点
启动本地 Substrate 节点:
-
打开终端外壳。
-
切换到编译 Substrate 节点模板的根目录。
-
通过运行以下命令以开发模式启动节点:
./target/release/node-template --dev
node-template
命令行选项指定您希望正在运行的节点如何操作。在这种情况下,该--dev
选项指定节点使用预定义的development
链规范在开发者模式下运行。默认情况下,当您按 Control-c 停止节点时,此选项还会删除所有活动数据,例如密钥、区块链数据库和网络信息。使用该--dev
选项可确保您在任何时候停止和重新启动节点时都处于干净的工作状态。 -
通过查看终端中显示的输出来验证您的节点是否已启动并成功运行。
终端应显示类似于此的输出:
2021-11-24 15:36:35 Running in --dev mode, RPC CORS has been disabled.
2021-11-24 15:36:35 Substrate Node
2021-11-24 15:36:35 ✌️ version 4.0.0-dev-82b7c2c-aarch64-macos
2021-11-24 15:36:35 ❤️ by Substrate DevHub <https://github.com/substrate-developer-hub>, 2017-2021
2021-11-24 15:36:35 📋 Chain specification: Development
2021-11-24 15:36:35 🏷 Node name: six-wash-9274
2021-11-24 15:36:35 👤 Role: AUTHORITY
2021-11-24 15:36:35 💾 Database: RocksDb at /tmp/substrateP1jD7H/chains/dev/db
2021-11-24 15:36:35 ⛓ Native runtime: node-template-100 (node-template-1.tx1.au1)
2021-11-24 15:36:35 🔨 Initializing Genesis block/state (state: 0xa59b…5331, header-hash: 0xc5d2…37f3)
2021-11-24 15:36:35 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.
2021-11-24 15:36:35 ⏱ Loaded block-time = 6s from block 0xc5d2fdad35e14684753f087c1a20f022274e154d39add4f7efe34e95476a37f3
2021-11-24 15:36:35 Using default protocol ID "sup" because none is configured in the chain specs
2021-11-24 15:36:35 🏷 Local node identity is: 12D3KooWG5niQF5bjsFao3D8DZRpUUB6uWZC2pK8hCDZ94zsr8Sc
2021-11-24 15:36:35 📦 Highest known block at #0
...
...
...
2021-11-24 15:36:40 💤 Idle (0 peers), best: #1 (0xd2b5…d03f), finalized #0 (0xc5d2…37f3), ⬇ 0 ⬆ 0
如果之后的数字在finalized
增加,则您的区块链正在生成新块并就它们所描述的状态达成共识。
我们将在后面的教程中查看日志输出中报告的详细信息。目前,只需要知道您的节点正在运行并生成块即可。
- 保持显示节点输出的终端打开以继续。
启动前端模板
Substrate 前端模板由用户界面组件组成,使您能够与 Substrate 节点交互并执行一些常见任务。
要使用前端模板:
- 在您的计算机上打开一个新的终端 shell,切换到安装前端模板的根目录。
- 通过运行以下命令启动前端模板:
yarn start
3.在浏览器中打开http://localhost:8000查看前端模板。
顶部有一个账户选择列表,用于在您想要执行链上操作时选择要使用的账户。模板的顶部还显示有关您连接到的链的信息。
您可能还注意到,前端模板显示了一个带有一些预定义账户的余额表,并且其中一些账户预配置了资金。您可以使用此示例数据来尝试转账等操作。
将资金从一个帐户转移到另一个帐户
既然您在本地计算机上运行了一个区块链节点,并且您有一个可用于执行链上操作的前端模板,那么您就可以探索与区块链交互的不同方式了。
默认情况下,前端模板包含多个组件,可让您尝试不同的常见任务。对于本教程,您可以执行简单的转账操作,将资金从一个账户转移到另一个账户。
将资金转入账户:
- 在余额表中,请注意预定义的帐户(例如 dave)没有与其关联的资金。
在 Balances 表下,前端模板还显示一个Transfer组件。您使用此组件将资金从一个帐户转移到另一个帐户。
2.复制并粘贴dave帐户的地址,以指定您将资金转移到的地址。
3.指定至少1000000000000作为转账金额,然后点击提交。
4.请注意,余额表中的值随转移而更新。
5.检查事件组件以查看与您刚刚完成的传输相关的事件。
Substrate 区块链将异步操作的结果报告为事件,因此您可以使用事件组件查看作为传输的一部分执行的每个操作的详细信息。例如:
当交易完成并包含在区块中时,您会看到类似于以下内容的确认消息:
😉 Finalized. Block hash: 0xda7e9e935abf5a3a2fdb0a27d67cd7a69e628165b5827255af2635ba226411a4
停止本地节点
传输成功后,您可以继续探索前端模板组件或停止本地 Substrate 节点。因为您--dev
在启动节点时指定了该选项,所以停止本地节点会停止区块链并清除所有持久块数据,以便您下次启动节点时可以以干净的状态开始。
停止本地 Substrate 节点:
- 返回到显示节点输出的终端 shell。
- 按 Control-c 终止正在运行的进程。
- 验证您的终端返回到
substrate-node-template
目录中的终端提示符。
Substrate区块链及运行时模块简介
Parity的Substrate区块链框架在最近几个月里的开发进展很迅速,基于 Substrate的Polkadot区块链的开发也是如火如荼。这个教程的目的是介绍 如何构建一个可以支持自己的运行时模块的Substrate链。
本教程的主要内容包括:
- 学习Susbtrate链的安装与设置
- 学习Susbtrate链的配置方法,以及如何使用Polkadot JS浏览区块链状态
- 学习运行时模块的结构,以及如何使用运行时模块为你自己的定制区块链添加功能
关于Rust
Substrate和运行时模块都是使用Rust开发的。
Rust是一种底层静态类型语言,它的特点在于速度保障与可靠性,但是学习难度 比较高。在区块链开发中一个非常重要但却经常被忽略的话题是:如何掌握Rust。在这个 教程中我们不会分析Rust代码,但是对于希望使用Susbtrate进行区块链开发的 工程师来说,掌握Rust是一个前提条件。
作为一种程序开发语言,Rust的学习曲线是比较陡峭的。部分原因在于Rust所采用 的语法规范,极其依赖于像泛型、特性萃取、生命周期和宏这样的特性,以及其他 一些考虑例如作用于和不变性。
其他的Substrate学习资源,例如Substrate Kitties collectibles workshop 生成Rust非常容易掌握,但这不是真实的情况,除非你已经有比较多的底层语言的 开发经历,例如C++,而且接触过比较多的涉及系统级管理的API。
实际上,如果你是刚接触Rust,那么需要一点耐心,需要花时间来了解这门开发语言 的核心概念和特性。在掌握Rust之后,Substrate的开发将变得令人享受。这门Rust书 写的很好,很适合新手学习,也适合有经验的用户温习Rust。
安装Susbtrate
安装Substrate只需要调用Parity网站上的一个bash脚本。Substrate提供了两种 安装方式:
如果希望快速掌握区块链应用的开发,推荐汇智网的区块链应用开发系列教程, 内容涵盖比特币、以太坊、eos、超级账本fabric和tendermint等多种区块链, 以及 java、go、nodejs、python、php、dart等多种开发语言
快速安装
快速安装将安装预构建的Substrate开发链、Substrate脚本、Substrate链命令行 配置工具和运行时模块。
使用--fast
标志来运行Substrate安装脚本会跳过安装那些对运行Sbustrate来说 并非必要的工具:
1 | ~$ curl https://getsubstrate.io -sSf | bash -s -- --fast |
上面的命令将拉取Susbtrate的依赖项,包括Rust、OpenSSL、LLVM等等,然后进行 安装。
完整安装
完整安装除了包含上面的内容,还将安装以下两个工具:
- SubKey:用于创建或恢复Substrate密钥的命令行工具,当你需要在命令行管理账户时会比较有用
- Substrate node:预配置的Substrate节点,可以直接接入Substrate测试网络
运行下面的命令进行完整安装:
1 2 | // full Substrate installation ~$ curl https://getsubstrate.io -sSf | bash |
一旦安装脚本执行完毕,更新你的cargo环境以便调用新安装的程序:
1 | ~$ source ~/.cargo/env |
现在使用substrate命令就可以访问预编译好的Substrate节点了。要验证Substrate node 和SubKey是否正确安装,可以检查这两个程序的版本:
1 2 | ~$ substrate --version ~$ subkey --version |
注意:Polkadot JS 应用已经在其账户管理界面中实现了subkey的功能 —— 可以在浏览器 中管理账户而无需subkey,这也是subkey是可选安装的原因。
默认情况下,Substrate和工具程序安装在 ~/.cargo/bin目录中。你可以看一下具体的 安装内容:
1 2 | ~$ cd ~/.cargo/bin ~/.cargo/bin$ ls |
你会注意到除了substrate和subkey,还有substrate-node-new和substrate-module-new 这两个程序,接下来我们将使用这些程序来创建新的定制节点和运行时模块。
更新Substrate脚本
更新Substrate脚本需要克隆最新版本,然后使用下面的命令替换cargo的二进制程序:
1 2 3 4 | ~$ f=`mktemp -d` ~$ git clone https://github.com/paritytech/substrate-up $f ~$ cp -a $f/substrate-* ~/.cargo/bin ~$ cp -a $f/polkadot-* ~/.cargo/bin |
现在我们已经安装好了Substrate工具,可以运行Substrate开发节点了。这个节点会 开始出块,但是对于开发而言没什么用。
在任何情况下,我们可以使用下面的命令启动Substrate开发链:
1 | ~$ substrate --dev |
节点现在就起来了,你可以看到开始出块。要查看区块链的更多信息,例如每个支持 模块的状态,我们将使用Polkadot JS应用。
要查看substrate的命令行选项,可以查看--help
的输出:
1 | ~$ substrate --help |
熟悉一下help命令的输出,是了解命令行程序的功能的得到验证的方法。目前的版本 包含了一些对测试有用的标志,例如预配置的账户--alice
、 --bob
等等。 --light
标志可以按轻量模式运行节点,在框架中内置了对轻量客户端的支持。
在我们开始定制构建之前,然我们回顾一下如何查看Substrate链。基本的方法是 使用Polkadot JS应用,该应用使用Typescript和react开发。
使用Polkadot JS App
Polkadot JS应用提供了基本的区块链浏览器功能,同时也提供了管理Substrate模块 的API和接口。正如其名称所示,这个应用也支持Polkadot区块链。我们有两种 途径来使用Polkadot JS:
- 使用一个Parity托管的应用,访问地址:https://polkadot.js.org/apps
- 克隆项目仓库,在本地机器运行应用
让我们克隆项目在本地运行,一旦安装完成,我们可以指向我们的Susbtrate链的 节点,在我们机器上的另一个运行进程。
首先克隆并运行Polkadot JS应用:
1 2 3 | ~$ git clone https://github.com/polkadot-js/apps.git ~$ mv apps polkadot.js ~$ cd polkadot.js && yarn start |
然后在另一个终端启动substrate开发链:
1 | substrate --dev |
在浏览器中访问localhost:3000
。为了让JS App连接到我们本地的开发链, 在侧栏菜单中选择Settings,然后切换到Local Node endpoint,类似下图:
点击Save & Reload,你将注意到侧栏菜单中的许多链接激活了,具体哪些 链接会激活取决于你的链的支持。
让我们看一下几乎所有链都会支持的特性 - 账户。进入到应用的Accounts 部分 - 在My Account选项页你将看到一组账户,这些都是预配置的含余额的 账户,我们也可以在这些账户之间转账、删除账户以及备份账户密钥。这 表明了Plokadot JS App的定位 —— 在UI层与你的Substrate链交互。
在继续之前,我们要提一下Polkadot UI可以完成的任务:
- 可以上传wasm编译的Ink智能合约
- 作为一个POS共识链,Staking区域允许你抵押资金以成为交易验证人。
- 设计Democracy区域的目的是处理链上的投票和管理
- 在Toolbox区域可以测试Substrate的JSON RPC
你可以会困惑,哪些预配置的账户是哪里来的。事实上,这些账户,包括运行时 逻辑自身的编译代码,都是保存在一个Chain Specification文件中,也被成为 chain spec。
使用Chain Spec JSON文件配置链
链配置是一个大型JSON对象,使用substrate的build-spec命令生成。该命令将 提取节点引入的运行时模块的配置项,有些是空值,有些则提供了默认值。
基本上,运行时模块可以依赖于创世配置,也就是在区块链初始化时我们提供的 配置。区块链状态是由创世区块 —— 链的第一个区块 —— 来初始化的。chain spec JSON文件的工作,就是定义这个初始状态。
一旦生成配置文件,我们就可以打开该文件,根据我们的需要进行修改。
节点提供了purge-chain
命令来复位区块链,这通常用于开发中:
1 | ~$ substrate purge-chain --dev |
框架提供了三个默认的链规格,也就是配置:dev、local和staging。
- dev:dev规格提供了主要用于开发,该配置中包含了一组账户以及运行时模块
- local:local规格类似于dev,主要用于私有链。
- staging:staging规格更加保守一些,定义了有限数量的账户,需要自己定义 模块相关的配置。当构建产品链时,应当选择这个规格。
我们现在要做的,就是使用build-spec命令创建一个新的chainspec,将输出结果 存入单独的文件。例如,将规格写入当前用户主目录的my-chainspec.json文件:
1 | ~$ substrate build-spec --chain=dev > ~/my-chainspec.json |
在文件编辑器里打开这个文件,查看可用的配置选项。
- id:可以改为你自己的名字
- name:给人看的名字
- telemetryEndpoints:提供Telemetry服务的访问端结点
- …
一旦修改完chainspec文件,我们可以用--raw
标志将其转化为原始编码状态:
1 | ~$ substrate build-spec --chain ~/chainspec.json --raw > ~/mychain.json |
最终,我们使用这个链规格文件来启动我们的substrate链。以下假设你运行了一个 自定义编译的substrate节点,使用节点的路径替换下面的<node_path>
:
1 | <node_path> --chain ~/mychain.json --validator |
接下来让我们看看如何初始化并编译自定义的Substrate节点。
初始化Substrate节点
到目前位置,我们已经使用了预编译的Substrate节点。对于测试一下开发链很好, 但是这限制了我们使用自己的运行时模块以及自定义配置。为解决此问题,我们 需要下载Substrate源代码。
有两种方法来着手我们的自定义Substrate链:
- 下载一个已经配置好的节点模板,例如使用下载脚本完整安装时包含的测试网节点模板
- 使用Substrate脚本,下载官方的节点模板
基本上所有的Substrate项目都会基于官方的节点模板展开,除非一些特殊情况。
用下面的命令生成一个新的节点模板:
1 | ~$ substrate-node-new my-node "Ross Bulat" |
命令执行需要花点时间 —— 要拉取最新的Substrate源码并且进行编译。
一旦完成,可以修改runtime/src目录下的lib.rs文件。同时也包含了运行时模块的模板template.rs。 接下来我们看一下运行时模块。
构建自定义节点
在节点目录中,在使用cargo编译出二进制程序之前,使用build.sh脚本将节点编译为wasm:
1 2 3 4 5 | # build wasm ./scripts/build.sh # build binary cargo build --release |
节点程序现在位于./target/release/ 目录。
之前我们已经使用substrate调用了一些命令,现在可以使用我们新编译出来的程序。 要复位区块链并重新运行,执行如下命令:
1 2 3 4 5 | # clear chain state ./target/release/<node_name> purge-chain --dev # run in dev mode ./target/release/<node_name> --dev |
我们要介绍的最后一部分内容,是运行时模块。让我们看看什么是运行时模块 以及如何在substrate节点中引入运行时模块。
Substrate运行时模块:区块链的插件机制
Substrate的通用和模块化结构使其实用性大大增强,开发人员可以将功能以插件 形式加载到节点运行时,从而可以轻松地创建满足个性化需求的区块链。
这些插件化的功能包被称为模块,或者更确切地说,运行时模块。Substrate 预置的运行时模块集合被称为Substrate运行时模块库 —— SRML。
这些模块非常有用,它们实现了其他区块链框架中的很多功能,可以在github浏览 这些模块的代码。有了这些模块,开发人员不需要重新发明轮子,可以节省大量时间。 当实现新特性时,也是以运行时模块的形式开发的。
SRML模块由Substrate统一维护,因此可靠性得到保障。下面是现在可用的一些模块:
- Assets:提供类似ERC20代币支持的资产模块
- Balances:管理账户余额的模块
- Staking:: 网络维护者管理抵押资金的模块
你会注意到这些模块都是Rust crate格式,该格式被设计用于Substrate运行时环境。
每个SRML模块都打包为crates,并在模块名前加以srml_前缀,在Parity的crate库 的左侧菜单中,可以找到这些模块。
运行时模块结构概述
每个模块都是定义在它自己的src/lib.rs文件中,遵循约定的结果。我们可以看一下 一个substrate模块的顶层特征:
- 一个模块通常自身是一个crate,但不是必须要求
- 一个模块可以定义为单一文件module-name.rs,或者更常见的lib.rs,如果模块 是一个crate。一个模块也可以有其他支持文件
- 一个模块必须遵守特定的结构,依赖于特定的Substrate API
最后一点指的是什么?一个模块为你的区块链增加功能,功能可以多种形式的组件提供:
事件:一个模块可以声明自定义事件,当特定条件满足时触发,例如,当你铸造非同质化 通证时,可能是一个TokenCreated事件。事件被封装在 decl_event! 宏里:
1 2 3 4 5 6 7 8 9 | decl_event!( pub enum Event<T> where <T as system::Trait>::AccountId, <T as system::Trait>::Hash { TokenCreated(AccountId, Hash), } ); |
存储:一个模块可以定义链上的持久化数据结构,例如映射表、列表等等。存储条目定义 在decl_storage!宏里:
1 2 3 4 5 6 7 8 | 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; ... } } |
可分发函数:JSON RPC可以调用的函数。
公开/私有函数:模块可以提供在运行时环境中可调用的公开函数,以及只可以在模块中 调用的私有函数。
结构:模块可以定义结构,例如,在一个跟踪全球运输的区块链实现中,可能会定义 一个ShipmenItem结构。
1 2 3 4 5 6 7 | #[derive(Encode, Decode, Default, Clone, PartialEq)] pub struct ShipmentItem<Hash, Balance> { id: Hash, container_id: Hash, price: Balance, weight: u64 } |
初始化模块
类似于substrate-node-new工具,我们也下载了substrate-module-new工具。在节点 运行时目录,使用下面的命令准备一个新的模块:
1 | substrate-module-new <module_name> |
让我们将其命名为my-module:
1 2 3 4 5 6 7 | 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是初始化一个新的运行时模块的官方推荐的方式。
现在我们可以开发这个模块,打包称create,甚至分发到github以便大家都可以维护。
原文链接:Substrate Blockchains and Runtime Modules: An Introduction
以上是关于创建第一个 Substrate 区块链的主要内容,如果未能解决你的问题,请参考以下文章
Substrate knowledgebase: Benchmarking