参考:https://docs.substrate.io/tutorials/v3/private-network/
实现目标
这里我们学习:
- 如何基于Substrate来构成一个两节点的链网络。
- 如何配置使用Aura的共识机制。
- 如何定制账户,并设置其为Aura的Validator。
启动两个节点的链网络
确认环境准备好了
- Rust及相关Rust的工具链已安装。
- Substrate node template源码已下载好,且编译通过。
- Subkey已安装好(它的安装步骤将在“自主生成key”部分详细讲)。
基于Substrate节点模板启动两节点的链网络
这里,我们将基于节点模板里缺省有的两个账户Alice和Bob,来启动两个Substrate节点,并让这个两个节点相互连接,形成一个链网络。因此,经过这部分学习后,我们应掌握基于Substrate构建多节点链网络的基本步骤。
基于Alice启动Substrate节点
- 执行以下的命令,清除之前节点启动可能残留的数据
./target/release/node-template purge-chain --base-path /tmp/alice --chain local
该命令会提示,敲入y
Are you sure to remove "/tmp/alice/chains/local_testnet/db/full"? [y/N]
注:如果希望新建的链是纯净的,就应清除之前启动过的链的数据。
- 执行以下的命令,用alice这个账户来启动一个substrate节点。
./target/release/node-template \
--base-path /tmp/alice \
--chain local \
--alice \
--port 30333 \
--ws-port 9945 \
--rpc-port 9933 \
--node-key 0000000000000000000000000000000000000000000000000000000000000001 \
--telemetry-url "wss://telemetry.polkadot.io/submit/ 0" \
--validator
下面是该命令用到的选项的含义:
:Option | :Description |
---|---|
--base-path | Specifies the directory for storing all of the data related to this chain. |
--chain local | Specifies the chain specification to use. Valid predefined chain specifications include local , development , and staging . |
--alice | Adds the predefined keys for the alice account to the node’s keystore. With this setting, the alice account is used for block production and finalization. |
--port 30333 | Specifies the port to listen on for peer-to-peer (p2p ) traffic. Because this tutorial uses two nodes running on the same physical computer to simulate a network, you must explicitly specify a different port for at least one account. |
--ws-port 9945 | Specifies the port to listen on for incoming WebSocket traffic. The default port is 9944 . This tutorial uses a custom web socket port number (9945 ). |
--rpc-port 9933 | Specifies the port to listen on for incoming RPC traffic. The default port is 9933 . |
--node-key <key> | Specifies the Ed25519 secret key to use for libp2p networking. You should only use this option for development and testing. |
--telemetry-url | Specifies where to send telemetry data. For this tutorial, you can send telemetry data to a server hosted by Parity that is available for anyone to use. |
--validator | Specifies that this node participates in block production and finalization for the network. |
如果想更详细地了解这些选项,可以输入以下的命令
./target/release/node-template --help
- 我们查看节点输出信息,以确认该节点是否运行正常:
- 先关注
🔨 Initializing Genesis block/state (state: 0x7384…0308, header-hash: 0xd2dc…3cc2)
, 它表示节点应完成初始化,而且生成了创世区块,后面再启动节点,并要与该节点,连成一个网络,这里的信息就应一样; - 再看
🏷 Local node identity is: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp
它指定了该节点的唯一ID:- 它的值是由上面命令的选项
--node-key
决定的; - 后面Bob节点想要连接这个节点,就会用到这个ID。
- 它的值是由上面命令的选项
💤 Idle (0 peers), best: #0 (0xd2dc…3cc2), finalized #0 (0xd2dc…3cc2), ⬇ 0 ⬆ 0
, 这个信息中的0 peers
表示链网络中没有其它的节点;后面的两个#0
则分别表示没有区块产生和确认。- 我们还看到报错信息
❌ Error while dialing /dns/telemetry.polkadot.io/tcp/443/x-parity-wss/%2Fsubmit%2F: Custom { kind: Other, error: Timeout }
, 这是由于连接遥测服务器失败。
这个错误,我们后面再分析。
- 浏览器中打开以下网址,以查看节点信息
https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9945#/explorer
会看到以下信息:
基于Bob启动Substrate节点
- 清除与Bot账户相关的数据。
./target/release/node-template purge-chain --base-path /tmp/bob --chain local -y
- 启动关联着账户Bob的第二个Substrate节点:
./target/release/node-template \
--base-path /tmp/bob \
--chain local \
--bob \
--port 30334 \
--ws-port 9946 \
--rpc-port 9934 \
--telemetry-url "wss://telemetry.polkadot.io/submit/ 0" \
--validator \
--bootnodes /ip4/127.0.0.1/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp
从输出信息来看:
- 两个节点的
peers
都是1
了,也就是双方都看到了对方,它们俩组成了一个链网络。 - 另外,整个链网络也出块了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DmixwKtR-1656495046021)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\1652081062719.png)]
- 几个注意点
- 命令选项
--bootnodes
中的ID,应与Alice那个节点一致; - 由于我们两个节点是运行在同一台机器上,所以
--port --ws-port --rpc-port
指定的端口号,应与Alice节点不一样,也应与机器中其它应用占用的端口号不一样。
自主生成key
如果是一条私有链,肯定不能用模板代码里缺省的Alice、Bob、Charly等的账户密钥。所以这个章节里来学习如何为私有定制的链创建自有的账户密钥组。
生成密钥工具准备
生成Substrate的密钥组,有两种方式:
- 基于
node-template
的子命令key
来生成。 - 通过Subkey命令行程序来生成。
由于Subkey具有密钥生成功能,还有密钥解析等功能。所以这里我们将通过Subkey这个工具来生成Substrate的密钥工具。
- 下载paritytech substrate的git仓库
git clone https://github.com/paritytech/substrate.git
cd substrate
- 编译出substrate可执行的二进制程序
# Run this in the Substrate working directory
cargo build -p subkey --release
- 确认substrate编译成功
# 查看命令帮助
subkey -h# 查看具体子命令帮助
subkey <sub-command> -h# 查看版本
subkey --version
注:上编译生成的二进制可执行文件在./target/release/subkey
- 下面则是用subkey来查阅助记词对应的密钥组信息
subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very"
该命令的输出如下:
Secret phrase: caution juice atom organ advance problem want pledge someone senior holiday veryNetwork ID: substrateSecret seed: 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849Public key (hex): 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746Account ID: 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyRSS58 Address: 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR
- 下面则是用subkey来查阅密钥种子对应的密钥信息
subkey inspect 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849
该命令的输出是:
Secret Key URI `0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849` is account:Network ID: substrate Secret seed: 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849Public key (hex): 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746Account ID: 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyRSS58 Address: 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR
- 这里顺便讲讲密钥的两种格式
- 纯十六进制;
- ss58编码格式。
密钥生成
- 生成sr25519密钥
subkey generate
该命令的输出:
Secret phrase: cheese member coin boring actual vehicle mountain obtain obey expect together chatNetwork ID: substrateSecret seed: 0xacc29d509e2ccbdc2e3e6e40f7793c2186133b0f50a5b90de3fa4c8f12b8e7baPublic key (hex): 0x90917068a441d2ea0e1aed40fb30d57d290efe705e937ef2c52f3bfb82aa3e4fAccount ID: 0x90917068a441d2ea0e1aed40fb30d57d290efe705e937ef2c52f3bfb82aa3e4fPublic key (SS58): 5FLFxTafwbAHxBmKs1pS3MVcfFFDo9N3Vpo23eGzddxS6itxSS58 Address: 5FLFxTafwbAHxBmKs1pS3MVcfFFDo9N3Vpo23eGzddxS6itx
该命令缺省用的助记词是12个。为了安全,可以用选项--word 24
来选择用24个助记词。除了12与24这两个参数,还支持15、18、21。
- 生成ed25519密钥
subkey generate --scheme ed25519
这里使用了--scheme
来指定所用的密钥格式。
该命令的输出:
Secret phrase: enact acoustic logic soap witness hurt knee web gravity bid hawk projectNetwork ID: substrateSecret seed: 0xa30dd474ade0684aa08f6cf28370613c193d92a1215b98a6ed0248dbe60d68f5Public key (hex): 0xdf12dc2da06e364c6bfe6bac80afe74356e9784d10ad1d72df41183c5b7aa5dfAccount ID: 0xdf12dc2da06e364c6bfe6bac80afe74356e9784d10ad1d72df41183c5b7aa5dfPublic key (SS58): 5H7C8xgztQ5AyiXN36LXMygcy7AcAsUbrkY9AAbcF4R6p8JJSS58 Address: 5H7C8xgztQ5AyiXN36LXMygcy7AcAsUbrkY9AAbcF4R6p8JJ
- 下面是关于输出信息的解释
- Secret phrase,助记词。
- Secret seed,私钥,可以通过它来恢复公、私钥对。
- Public key (hex),公钥,十六机制格式。
- Account ID,十六机制公钥的别名。
- SS58 Address,与公钥绑定的基于SS58格式的地址。
- Substrate为一个账户创建密钥,要同时创建两对
- Sr25519密钥对,用于aura共识;
- Ed25519密钥对,用于GRANDPA共识;
- 创建Ed25519密钥对,应当使用前面Sr25519密钥对产生的助记词,以确保两对密钥对,是授予同一个账户。
- 为了组建私有定制的链网络,我们应该按照上面的命令,至少为两个账户生成密钥组。
定制私有链规格(Spec)
一条链区别与其它的链,关键在于创世区块不同。而创世区块的生成,又依赖于链的Spec配置。因此,这里将讲讲基于Substrate,链的Spec获取与定制。
在这个Spec定制中,我们将使用上面生成的两个密钥组,以便两组密钥账户成为该私有链的Validators。
获得链Spec
执行以下的命令,将模板节点local
链的Spec,导致指定文件customSpec.json
./target/release/node-template build-spec --disable-default-bootnode --chain local > customSpec.json
修改链Spec
下面就是基于上面导出的Spec文件customSpec.json
,进行修改。
- 修改Spec里的
name
配置为下面的内容。
"name": "My Custom Testnet",
- 用前面生成的两个Sr25519 SS58地址更换
aura
域的对应地址。 - 用前面生成的两个Ed25519 SS58地址更换
grandpa
域的对应地址。
- 我们看到grandpa域里,除了地址值,还有个数字,它用来设定该账户的投票权重。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5BUHIMKa-1656495046023)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\1652170469802.png)]
- 将上面编辑好的Spec文件``,转换成Raw格式,以便运行的节点,可以访问。
./target/release/node-template build-spec --chain=customSpec.json --raw --disable-default-bootnode > customSpecRaw.json
- 将生成好的Raw格式的Spec文件,分发给需要连入同一私有链的同事。
启动私有链
这里则讲讲如何使用定制的链Spec业启动这条具体的链。
- 执行以下的命令,启动引导节点(bootnode)
./target/release/node-template \
--base-path /tmp/node01 \
--chain ./customSpecRaw.json \
--port 30333 \
--ws-port 9945 \
--rpc-port 9933 \
--telemetry-url "wss://telemetry.polkadot.io/submit/ 0" \
--validator \
--rpc-methods Unsafe \
--name MyNode01
下面是上面命令,几个选项的含义:
- –base-path,指定了该节点的工作运行时的工作目录;
- –chain,指定该节点启动所遵循的Spec
- –rpc-methods Unsafe,表明该节点是测试用,允许使用非安全的通信模式
- –name,为该节点起了一个名字
- 查看bootnode启动的信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MOOkKyzh-1656495046024)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\1652171979593.png)]
- 可以看到该节点的创世区块的Hash与缺省模板节点不一样;
- 同样,请记下该节点的ID:12D3KooWLkg3xZFTf6YEyonVjQheBWQgFJ6x29bpKuJJYb5ysWFv
- 执行以下的命令,以将一个aura的密钥,存放到keystore,以便对aura共识签名
./target/release/node-template key insert --base-path /tmp/node01 \
--chain customSpecRaw.json \
--scheme Sr25519 \
--suri <your-secret-seed> \
--password-interactive \
--key-type aura
- 其中,应替换为你生成一个密钥对时的助记词,或密码种子。
- 执行以下的命令,将与上面同用户的grandpa密钥插入keystore,以便对grandpa共识进行签名
./target/release/node-template key insert --base-path /tmp/node01 \
--chain customSpecRaw.json \
--scheme Ed25519 \
--suri <your-secret-key> \
--password-interactive \
--key-type gran
其中,应替换为你生成一个密钥对时的助记词,或密码种子。
- 通过以下的命令,可以查阅keystore的变化
ls /tmp/node01/chains/local_testnet/keystore
该命令将输出如下
617572611441ddcb22724420b87ee295c6d47c5adff0ce598c87d3c749b776ba9a647f04
6772616e1441ddcb22724420b87ee295c6d47c5adff0ce598c87d3c749b776ba9a647f04
- 下面是启动其它节点来与bootnode组建成一个私有链。
- 执行以下命令启动第二个节点
./target/release/node-template \
--base-path /tmp/node02 \
--chain ./customSpecRaw.json \
--port 30334 \
--ws-port 9946 \
--rpc-port 9934 \
--telemetry-url "wss://telemetry.polkadot.io/submit/ 0" \
--validator \
--rpc-methods Unsafe \
--name MyNode02 \
--bootnodes /ip4/127.0.0.1/tcp/30333/p2p/12D3KooWLkg3xZFTf6YEyonVjQheBWQgFJ6x29bpKuJJYb5ysWFv \
--password-interactive
- 为这个节点添加aura和grandpa的密钥对
- 重启这个节点。
碰到的问题
访问telemetry.polkadot.io报错
这主要是网络所致。所以请通过以下几步,来确保网络通畅:
- 防火墙:如果是调试机器,不妨把防火墙关闭。
- 在启动节点的命令里加上以下两个选项:
- –unsafe-rpc-external
- –unsafe-ws-external
由于我们的节点是本地定制开发的,可能存在不安全的情形。因此就通过这两个选项,告诉远端服务器本地节点的相应接口调用,可能存在不安全的情形。
我这边确认上面步后,也许由于网络本身的问题,可能会存在超时的问题,但总体的工作正常。
报文件描述符limit太低
按告警提示,执行以下命令,将Ubuntu的最大打开文件数,设置为10000。
ulimit -SHn 10000
执行完命令,不妨再执行以下的命令查验一下
ulimit -n