没有忽略此网络_【Substrate入门】创建我们自己的区块链网络

e5a7861a950d2d3b3162528f5b3ee929.png

文章内容持续更新中...

本文目标

掌握如何创建我们自己的区块链网络。

操作步骤

  • 先看看效果——启动Alice 和 Bob两个节点的区块链网络
  • 依葫芦画瓢——定制并启动我们自己的区块链网络

前提条件

本文的操作是基于substrate-node-template v2.0.0和前端界面substrate-front-end-template构建的环境,如果我们还没有构建好,请参考之前的文章【Substrate入门】搭建第一条substrate链

开始吧!

一、启动Alice和Bob两个节点的区块链网络

在官方的学习教程里,为了我们学习的便利性,特意做了些设计,比如预置了Alice、Bob、Dave...这些虚拟的人物,并为每个人物预先分配了账号(即公私钥),这里所说的启动Alice和Bob两个节点的区块链网络,是指用Alice和Bob的私钥分别启动两个区块链节点,并组成一个区块链网络,Alice和Bob都作为验证人参与出块。通过官方内置的数据,快速创建一个样板网络,来看看效果。

启动Alice节点

废话少说,先把创世节点拉起来:

cd substrate-node-template  //以我们clone时的目录所在位置为准
# Start Alice's node
./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

如果我们之前有启动过Alice这个测试节点,建议先把老数据清理一下:

# Purge any chain data from previous runs
# You will be prompted to type `y`
./target/release/node-template purge-chain --base-path /tmp/alice --chain local
purge-chain参数的作用:清理老的区块数据。

当Alice的节点启动起来后,我们能看到如下内容:

Dec 31 10:13:09.212  INFO Substrate Node    
Dec 31 10:13:09.212  INFO ✌️  version 2.0.0-655bfdc-x86_64-linux-gnu  //substrate版本号
Dec 31 10:13:09.212  INFO ❤️  by Substrate DevHub <https://github.com/substrate-developer-hub>, 2017-2020    
Dec 31 10:13:09.212  INFO   Chain specification: Local Testnet //当前区块链节点所在网络名称   
Dec 31 10:13:09.212  INFO    Node name: Alice  //节点名称  
Dec 31 10:13:09.212  INFO   Role: AUTHORITY    
Dec 31 10:13:09.212  INFO   Database: RocksDb at /tmp/alice/chains/local_testnet/db //数据库类型与当前节点数据保存位置   
Dec 31 10:13:09.212  INFO ⛓  Native runtime: node-template-1 (node-template-1.tx1.au1)    
Dec 31 10:13:10.095  INFO   Initializing Genesis block/state (state: 0x2751…2e34, header-hash: 0x67cf…dc66) //创世区块的哈希值    
Dec 31 10:13:10.123  INFO   Loading GRANDPA authority set from genesis on what appears to be first startup.    
Dec 31 10:13:10.208  INFO ⏱  Loaded block-time = 6000 milliseconds from genesis on first-launch    
Dec 31 10:13:10.208  WARN Using default protocol ID "sup" because none is configured in the chain specs    
Dec 31 10:13:10.221  INFO    Local node identity is: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp //Alice节点ID (legacy representation: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp)    
Dec 31 10:13:10.405  INFO   Highest known block at #0    
Dec 31 10:13:10.406  INFO 〽️ Prometheus server started at 127.0.0.1:9615   //普罗米修斯 节点监控端口 
Dec 31 10:13:10.446  INFO Listening for new connections on 127.0.0.1:9945.    //websocket监听端口
Dec 31 10:13:15.449  INFO   Idle (0 peers), best: #0 (0x67cf…dc66), finalized #0 (0x67cf…dc66), ⬇ 0 ⬆ 0    
Dec 31 10:13:20.449  INFO   Idle (0 peers), best: #0 (0x67cf…dc66), finalized #0 (0x67cf…dc66), ⬇ 0 ⬆ 0 
Initializing Genesis block/state (state: 0x2751…2e34, header-hash: 0x67cf…dc66)告知开发者节点正在使用哪个创世块。 当我们启动下一个节点时,注意验证这些值是否相等,确保是在同一个区块链网络。
Local node identity is: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp...显示Alice的节点ID, 启动Bob节点时需要它。 这个值是由--node-key决定的,该值之前用来启动Alice的节点。

针对以上启动创世节点时的命令参数,这里展开学习一下,对后续创建自己的节点有帮助:

标签名描述
--base-path指定一个目录,Substrate 将用它来存储与此链有关的所有数据。 如果未指定目录,将使用默认路径。 如果目录不存在,将创建它。 若该路径下已经存在其它区块链的数据,系统将会报错。 在该情况下,请清除此目录,或选择不同的目录。
--chain local指定要使用的链的规范。 这里有一些预设的选项,包括 local development 和 staging ,但通常由开发者指定自己的chain spec文件。 我们将在后续阶段指定自己的文件。
--alice--name Alice --validator的快捷写法,将预定义的Alice密钥(用于产生区块和达到最终确定性) 存入节点的密钥库。 一般来说,开发者应该自己生成密钥,并通过RPC调用插入。 我们将在后续阶段指定自己的密钥。 这个 flag 也可将 Alice 作为验证节点。
--port 30333指定用于监听 p2p 流量的节点端口。 30333 是默认端口,若无需更改,可以忽略该 flag。 如果Bob的节点也运行在同一个物理机上,我们需要明确地为其指定一个不同的端口。
--ws-port 9945指定节点用于监听 WebSocket 的端口。 默认端口为 9944 。 该示例使用了一个自定义的web socket端口(9945).
-rpc-port 9933指定节点监听RPC的端口。 9933 是默认值,因此该参数也可忽略。
--node-key <key>用于libp2p联网的Ed25519密钥。 该值被解析为一个十六进制编码的Ed25519 32字节密钥,即64个十六进制字符。 警告:作为命令行参数提供的隐私信息很容易被暴露。 该选项的使用应仅限于开发和测试。
--telemetry-url告诉节点向某个特定服务器发送监测数据。 我们在此选择的是由Parity托管,任何人都可以使用的服务器。 也可以选择自有的服务器(超出该本文描述的范围)或完全省略这个 flag。
--validator意味着我们也要参与区块的生产和达到最终确定性,而不仅仅是同步区块链网络。

更多帮助信息,可以通过./target/release/node-template --help查看 。

连接UI

从UI界面上来看看Alice单节点网络的状况,通过浏览器(chorme)访问Polkadot-JS Apps(在后续文章中简称Apps),如下图所示操作:

d5758e561b2db0fcafdf95bce065ebc3.png

先填写本地监听端口(即上述命令中的--ws-port 9945),然后点击“转换”,切换到本地测试网络。

a6dd0b887702b624a37bce79597b65a5.png

在上图中,我们可以了解到,当前网络中只有Alice一个节点,虽然产生了创世区块,但并没有正常出块,等待别的节点加入后,再开始生产区块。

启动Bob节点

接下来将Bob加入到Alice创建的区块链网络当中, 命令与启动Alice相似,如下:

./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

由于我们是在本地同一台物理机上运行多个节点,所以启动Bob节点时,需要指定不同的数据保存路径和端口号,如--base-path, --port, --ws-port, 和 --rpc-port 的值。

值得一提的是:Bob添加了--bootnodes标志,并指定了一个单一的引导节点,即Alice节点。 --bootnodes包含以下三项信息且必须填写正确:

  • Alice的IP地址:127.0.0.1
  • Alice的p2p端口:30333
  • 回到Alice节点启动窗口,在启动输出信息中寻找她的Peer ID,即这一行内容: Dec 31 10:13:10.221 INFO Local node identity is: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp...

如果顺利,节点之间很快就会匹配同步,并开始生产和确认区块。 在启动Alice节点的窗口中,我们看到如下行的输出:

Dec 31 10:19:40.551  INFO   Idle (0 peers), best: #0 (0x67cf…dc66), finalized #0 (0x67cf…dc66), ⬇ 0 ⬆ 0    
Dec 31 10:19:45.552  INFO   Idle (1 peers), best: #0 (0x67cf…dc66), finalized #0 (0x67cf…dc66), ⬇ 0.8kiB/s ⬆ 0.8kiB/s    
Dec 31 10:19:45.669  INFO   Discovered new external address for our node: /ip4/127.0.0.1/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp    
Dec 31 10:19:45.712  INFO   Discovered new external address for our node: /ip4/192.168.112.129/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp    
Dec 31 10:19:48.022  INFO   Starting consensus session on top of parent 0x67cfc2c0511495e9e6e37d2dc3fc80ef64e7655f88d89a4a1c1984ae3501dc66    
Dec 31 10:19:48.150  INFO   Prepared block for proposing at 1 [hash: 0x4b0b94d2fbc5e23bb09fac8ed5e69f4ea30f6d8478ae31b24bf046c5b59103cd; parent_hash: 0x67cf…dc66; extrinsics (1): [0xe2b9…d17c]]    
Dec 31 10:19:48.159  INFO   Pre-sealed block for proposal at 1. Hash now 0xe2093722a2dd957c93e9e112c541560f903e569bade04b31cd9ec03f75378e39, previously 0x4b0b94d2fbc5e23bb09fac8ed5e69f4ea30f6d8478ae31b24bf046c5b59103cd.    
Dec 31 10:19:48.160  INFO ✨ Imported #1 (0xe209…8e39)    
Dec 31 10:19:50.552  INFO   Idle (1 peers), best: #1 (0xe209…8e39), finalized #0 (0x67cf…dc66), ⬇ 1.0kiB/s ⬆ 1.0kiB/s    
Dec 31 10:19:54.037  INFO ✨ Imported #2 (0xcd1c…2eb2)    
Dec 31 10:19:55.553  INFO   Idle (1 peers), best: #2 (0xcd1c…2eb2), finalized #0 (0x67cf…dc66), ⬇ 0.7kiB/s ⬆ 0.6kiB/s    
Dec 31 10:20:00.007  INFO   Starting consensus session on top of parent 0xcd1c76cbfc68aa36610a7be76d8619581866b06aad90135b1befcf91da952eb2    
Dec 31 10:20:00.014  INFO   Prepared block for proposing at 3 [hash: 0x3db32650e4de15c7cd3464f52f0848505f0f1f8c596b29841ae581fd09e25de1; parent_hash: 0xcd1c…2eb2; extrinsics (1): [0x1fab…ddf1]]    
Dec 31 10:20:00.020  INFO   Pre-sealed block for proposal at 3. Hash now 0x2abd02122de9ed1d69f26d49413fb7919be2ca5f5b5a98f3126a4eb2ee7e851f, previously 0x3db32650e4de15c7cd3464f52f0848505f0f1f8c596b29841ae581fd09e25de1.    
Dec 31 10:20:00.023  INFO ✨ Imported #3 (0x2abd…851f)    
Dec 31 10:20:00.554  INFO   Idle (1 peers), best: #3 (0x2abd…851f), finalized #0 (0x67cf…dc66), ⬇ 0.7kiB/s ⬆ 0.7kiB/s    
Dec 31 10:20:05.555  INFO   Idle (1 peers), best: #3 (0x2abd…851f), finalized #1 (0xe209…8e39), ⬇ 1.0kiB/s ⬆ 1.0kiB/s    
Dec 31 10:20:06.073  INFO ✨ Imported #4 (0x9999…9ead)    
Dec 31 10:20:10.556  INFO   Idle (1 peers), best: #4 (0x9999…9ead), finalized #2 (0xcd1c…2eb2), ⬇ 1.0kiB/s ⬆ 0.9kiB/s    
Dec 31 10:20:12.012  INFO   Starting consensus session on top of parent 0x999952111675724c17472c1abce528f2e5b67b7a27a5c29ac26d9993407a9ead    
Dec 31 10:20:12.030  INFO   Prepared block for proposing at 5 [hash: 0xb0f8c3b7c298dc923ac53902d8d2c047ffece5cdd737389229377192f1e47a23; parent_hash: 0x9999…9ead; extrinsics (1): [0xfa35…2f8c]]    
Dec 31 10:20:12.048  INFO   Pre-sealed block for proposal at 5. Hash now 0x64c2fa010acea784e56870fdeae0ef326b66646d7c92d7c4f6c9a853075988ab, previously 0xb0f8c3b7c298dc923ac53902d8d2c047ffece5cdd737389229377192f1e47a23. 

在启动Bob节点的窗口中,也可看到类似的内容:

Dec 31 10:19:44.180  INFO Substrate Node    
Dec 31 10:19:44.180  INFO ✌️  version 2.0.0-655bfdc-x86_64-linux-gnu    
Dec 31 10:19:44.180  INFO ❤️  by Substrate DevHub <https://github.com/substrate-developer-hub>, 2017-2020    
Dec 31 10:19:44.180  INFO   Chain specification: Local Testnet    
Dec 31 10:19:44.180  INFO    Node name: Bob    
Dec 31 10:19:44.180  INFO   Role: AUTHORITY    
Dec 31 10:19:44.198  INFO   Database: RocksDb at /tmp/bob/chains/local_testnet/db    
Dec 31 10:19:44.198  INFO ⛓  Native runtime: node-template-1 (node-template-1.tx1.au1)    
Dec 31 10:19:44.673  INFO   Initializing Genesis block/state (state: 0x2751…2e34, header-hash: 0x67cf…dc66)    
Dec 31 10:19:44.699  INFO   Loading GRANDPA authority set from genesis on what appears to be first startup.    
Dec 31 10:19:44.859  INFO ⏱  Loaded block-time = 6000 milliseconds from genesis on first-launch    
Dec 31 10:19:44.859  WARN Using default protocol ID "sup" because none is configured in the chain specs    
Dec 31 10:19:44.882  INFO    Local node identity is: 12D3KooWGH5WggsCgqMc2Ko6edTrdS48iaofkU39s8M5bZ6QzSjL (legacy representation: 12D3KooWGH5WggsCgqMc2Ko6edTrdS48iaofkU39s8M5bZ6QzSjL)    
Dec 31 10:19:45.126  INFO   Highest known block at #0    
Dec 31 10:19:45.129  INFO Listening for new connections on 127.0.0.1:9946.    
Dec 31 10:19:45.648  INFO   Discovered new external address for our node: /ip4/127.0.0.1/tcp/30334/p2p/12D3KooWGH5WggsCgqMc2Ko6edTrdS48iaofkU39s8M5bZ6QzSjL    
Dec 31 10:19:45.713  INFO   Discovered new external address for our node: /ip4/192.168.112.129/tcp/30334/p2p/12D3KooWGH5WggsCgqMc2Ko6edTrdS48iaofkU39s8M5bZ6QzSjL    
Dec 31 10:19:48.189  INFO ✨ Imported #1 (0xe209…8e39)    
Dec 31 10:19:50.131  INFO   Idle (1 peers), best: #1 (0xe209…8e39), finalized #0 (0x67cf…dc66), ⬇ 1.7kiB/s ⬆ 1.7kiB/s    
Dec 31 10:19:54.007  INFO   Starting consensus session on top of parent 0xe2093722a2dd957c93e9e112c541560f903e569bade04b31cd9ec03f75378e39    
Dec 31 10:19:54.014  INFO   Prepared block for proposing at 2 [hash: 0x670067dcd5af9a627db98ab749da641fb8b42c3e2a32fb60766f3e73d7c91df0; parent_hash: 0xe209…8e39; extrinsics (1): [0xf843…8809]]    
Dec 31 10:19:54.022  INFO   Pre-sealed block for proposal at 2. Hash now 0xcd1c76cbfc68aa36610a7be76d8619581866b06aad90135b1befcf91da952eb2, previously 0x670067dcd5af9a627db98ab749da641fb8b42c3e2a32fb60766f3e73d7c91df0.    
Dec 31 10:19:54.023  INFO ✨ Imported #2 (0xcd1c…2eb2)    
Dec 31 10:19:55.132  INFO   Idle (1 peers), best: #2 (0xcd1c…2eb2), finalized #0 (0x67cf…dc66), ⬇ 0.6kiB/s ⬆ 0.7kiB/s    
Dec 31 10:20:00.069  INFO ✨ Imported #3 (0x2abd…851f)    
Dec 31 10:20:00.133  INFO   Idle (1 peers), best: #3 (0x2abd…851f), finalized #0 (0x67cf…dc66), ⬇ 0.7kiB/s ⬆ 0.7kiB/s    
Dec 31 10:20:05.134  INFO   Idle (1 peers), best: #3 (0x2abd…851f), finalized #1 (0xe209…8e39), ⬇ 1.0kiB/s ⬆ 0.9kiB/s    
Dec 31 10:20:06.006  INFO   Starting consensus session on top of parent 0x2abd02122de9ed1d69f26d49413fb7919be2ca5f5b5a98f3126a4eb2ee7e851f    
Dec 31 10:20:06.013  INFO   Prepared block for proposing at 4 [hash: 0x462ae509e11577a31fa92fc5cb974925e42da123b1ce8c63b3d4e2b666cd4599; parent_hash: 0x2abd…851f; extrinsics (1): [0x0608…9a0c]]    
Dec 31 10:20:06.020  INFO   Pre-sealed block for proposal at 4. Hash now 0x999952111675724c17472c1abce528f2e5b67b7a27a5c29ac26d9993407a9ead, previously 0x462ae509e11577a31fa92fc5cb974925e42da123b1ce8c63b3d4e2b666cd4599.

通过以上演示,我们快速地搭建了一个样板网络,了解了substrate区块链网络的基本原理和命令行选项,接下来轮到创建我们自己的区块链网络了,这里先将Alice和Bob节点都停掉(在节点窗口中ctrl+c即可)。

接下来依葫芦画瓢,定制并启动我们自己的区块链网络。

二、定制并启动我们自己的区块链网络

在本节中,主要需要修改两块内容:

  • 将Alice和Bob的密钥替换成我们自己的
  • 创建自定义的创世区块配置文件(chain spec文件)

规划网络

节点名称数据保存路径p2p端口ws端口rpc端口
MyNode01/tmp/node013033399459933
MyNode02/tmp/node023033499469934

实际上可以是任意节点个数,这里我们以两个为例,取代Alice和Bob。

生成密钥

先来生成自己的密钥,官方提供了两种方式:

  • 通过subkey工具生成
  • 通过Polkadot-JS Apps生成

分别来介绍一下。

1、通过subkey工具生成

我们需要先安装subkey:

cargo install --force subkey --git https://github.com/paritytech/substrate --version 2.0.0

编译成功后,就可以使用subkey来生成密钥了。想了解更多,可查看Substrate 帮助。

一个节点需要有两种不同类型的密钥: sr25519ed25519sr25519 密钥用于 Aura 生产区块, ed25519密钥用于 GRANDPA 达成区块的最终确定性。
换句话理解, 每个节点都需要添加两种类型的密钥:Aura 和 GRANDPA 密钥。 区块生成需要 Aura 密钥; 而区块达到最终性则需要 GRANDPA 密钥。

我们先来为MyNode01节点生成sr25519类型的密钥(本文是测试,就直接把密钥公开了):

subkey generate --scheme sr25519
//如下:
  Secret phrase `engine cube pioneer firm thought exhibit carbon dumb exotic pulse noodle ceiling` is account:
  Secret seed:      0x88eb6714e47c8ce4ef6017e92dcb4b9ae268de2ef8161127e7740dc3a53d5d98
  Public key (hex): 0x00301f5ae5f5e5f5067fb10728e963680704c96ee5472e30e370faf1e49d843e
  Account ID:       0x00301f5ae5f5e5f5067fb10728e963680704c96ee5472e30e370faf1e49d843e
  SS58 Address:     5C4x9oLkgS6fQfgnZ4dHAQ2riLFa5xN3TCXuzo9GZ6DeXM7B

再通过上面的助记词engine cube pioneer firm thought exhibit carbon dumb exotic pulse noodle ceiling查看ed25519密钥:

subkey inspect --scheme ed25519 "engine cube pioneer firm thought exhibit carbon dumb exotic pulse noodle ceiling"
//如下:
  Secret phrase `engine cube pioneer firm thought exhibit carbon dumb exotic pulse noodle ceiling` is account:
  Secret seed:      0x88eb6714e47c8ce4ef6017e92dcb4b9ae268de2ef8161127e7740dc3a53d5d98
  Public key (hex): 0x063f488785f1f63ecaf7dd74cce9b73a91904f3349ecfebb1e1dc0abf8f8b5dd
  Account ID:       0x063f488785f1f63ecaf7dd74cce9b73a91904f3349ecfebb1e1dc0abf8f8b5dd
  SS58 Address:     5CCtwgKn6b2MTuWWrwFcFEa5LpbcNtdfqhXXvmQzo6B4UCZM

将上述信息安全地记录下来,一个节点的密钥就生成完毕了,重复上面的操作为MyNode02生成密钥:

subkey generate --scheme sr25519

  Secret phrase `blind plug install hair scene profit drill scorpion clock spoon fence aware` is account:
  Secret seed:      0xc5806750ba7725af85ef9284881c41c81db1000a8d2c44e803ae3128512ba1ae
  Public key (hex): 0x66b8a5ed292cdc8c71d7c13818b7e25c3893ce12b8e85ac5ab426a258579d510
  Account ID:       0x66b8a5ed292cdc8c71d7c13818b7e25c3893ce12b8e85ac5ab426a258579d510
  SS58 Address:     5EPPbNJxMD3hAVr7zNmtyVfCKPEGc3iuhiUrj9M48yjULtHZ

subkey inspect --scheme ed25519 "blind plug install hair scene profit drill scorpion clock spoon fence aware"

  Secret phrase `blind plug install hair scene profit drill scorpion clock spoon fence aware` is account:
  Secret seed:      0xc5806750ba7725af85ef9284881c41c81db1000a8d2c44e803ae3128512ba1ae
  Public key (hex): 0xe8993b725606b8c1631b900ec25f10b6be8db74dece1a051fd3265cbdd1dee77
  Account ID:       0xe8993b725606b8c1631b900ec25f10b6be8db74dece1a051fd3265cbdd1dee77
  SS58 Address:     5HKgV8n5uU3PVzCqYSNLnaXsHQHnV4XttBvSpfzedc2yEcr7

2、通过Polkadot-JS Apps生成密钥

为了安全,使用Polkadot-JS Apps生成密钥时,建议断网。

这里简单介绍一下,在“ Accounts”选项栏上,点击"Add account"。如下图所示操作:

d21ea653950782588c9ba3600d5fce6b.png
注意妥善保管助记词,为了安全,不建议将此种方法生成的密钥用于生产环境。

创建自定义的创世区块配置文件

这个文件官方称之为Chain Spec文件,个人理解就是区块链的创世区块配置文件。这个文件不需要我们全新编写,只需要从现有项目中导出来做修改即可。

通过如下命令,将 chain spec 导出到一个名为 customSpec.json 的文件中:

cd substrate-node-template
./target/release/node-template build-spec --disable-default-bootnode --chain local > customSpec.json
Dec 30 16:41:56.554  INFO Building chain spec

在IDE中打开这个文件,我们可以找到如下部分的内容进行替换(参见注释内容):

{
  //-- snip --
  "genesis": {
    "runtime": {
      "frameSystem": {
        "changesTrieConfig": null
        //-- snip --
        "code":"..."
      },
      "palletAura": {
        "authorities": [
          "5C4x9oLkgS6fQfgnZ4dHAQ2riLFa5xN3TCXuzo9GZ6DeXM7B",  <=== 把这里替换成MyNode01的sr25519类型的SS58 Address
          "5EPPbNJxMD3hAVr7zNmtyVfCKPEGc3iuhiUrj9M48yjULtHZ" <=== 把这里替换成MyNode02的sr25519类型的SS58 Address
        ]
      },
      "palletGrandpa": {
        "authorities": [
          [
            "5CCtwgKn6b2MTuWWrwFcFEa5LpbcNtdfqhXXvmQzo6B4UCZM", <=== 把这里替换成MyNode01的ed25519类型的SS58 Address
            1  <=== 作为验证节点的权重值,了解下
          ],
          [
            "5HKgV8n5uU3PVzCqYSNLnaXsHQHnV4XttBvSpfzedc2yEcr7", <=== 把这里替换成MyNode02的ed25519类型的SS58 Address
            1  <=== 作为验证节点的权重值,了解下
          ]
        ]
      },
      //-- snip --
    }
  }
}

以上内容是已经替换好的效果。"palletAura" 字段显示,是用于创建区块的 Aura 权限;"palletGrandpa" 字段显示,用于最终确定区块的 GRANDPA 权限。另外,我们还可以看到code字段里有很多16进制数据, 就是 runtime 的 Wasm 二进制文件内容,它是之前运行 cargo build --release 命令时构建的。

将修改好的 customSpec.json 文件保存,我们使用命令将其转换为 "原生"的chain spec文件:

./target/release/node-template build-spec --chain=customSpec.json --raw --disable-default-bootnode > customSpecRaw.json

最后,将 customSpecRaw.json 与网络中的所有其他验证节点共享。

chain spec 应该由一人单独创建,并将生成的 customSpecRaw.json 文件共享给其他要加入网络的验证节点。因为 Rust -> Wasm 的优化构建并不 "可重现 ",所以每个人都会得到一个略有不同的 Wasm 二进制代码块,如果每个参与者都自己生成文件,将无法达成共识。

启动创世节点MyNode01

启动MyNode01节点 :

./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

命令和参数与启动Alice节点是类似的,但有不同之处,如下:

  • --alice 我们省略了该 flag,但很快我们就会通过 RPC 将自己的密钥加入密钥库中。
  • --chain 该 flag 选项已更改,以使用我们自定义的 chain spec。
  • --name 添加了该 flag,让我们可以在 telemetry 界面给该节点命名。
  • --rpc-methods Unsafe 加了这个可选的 flag。 顾名思义,在生产环境中使用该 flag 并不安全,生产环境该怎么使用等待我们探索。

MyNode01节点窗口中我们应该可以看到如下内容:

Dec 31 18:12:37.491  INFO Substrate Node    
Dec 31 18:12:37.517  INFO ✌️  version 2.0.0-655bfdc-x86_64-linux-gnu    
Dec 31 18:12:37.517  INFO ❤️  by Substrate DevHub <https://github.com/substrate-developer-hub>, 2017-2020    
Dec 31 18:12:37.517  INFO   Chain specification: Local Testnet    
Dec 31 18:12:37.517  INFO    Node name: MyNode01    
Dec 31 18:12:37.517  INFO   Role: AUTHORITY    
Dec 31 18:12:37.517  INFO   Database: RocksDb at /tmp/node01/chains/local_testnet/db    
Dec 31 18:12:37.517  INFO ⛓  Native runtime: node-template-1 (node-template-1.tx1.au1)    
Dec 31 18:12:38.711  INFO   Initializing Genesis block/state (state: 0x052a…8812, header-hash: 0x190a…e2d0)    
Dec 31 18:12:38.776  INFO   Loading GRANDPA authority set from genesis on what appears to be first startup.    
Dec 31 18:12:38.986  INFO ⏱  Loaded block-time = 6000 milliseconds from genesis on first-launch    
Dec 31 18:12:39.014  WARN Using default protocol ID "sup" because none is configured in the chain specs    
Dec 31 18:12:39.075  INFO    Local node identity is: 12D3KooWN967iQjeSWxxPuQTtmmM6woxRyJzPrNSxyHWhg9Y6jC1 (legacy representation: 12D3KooWN967iQjeSWxxPuQTtmmM6woxRyJzPrNSxyHWhg9Y6jC1)    
Dec 31 18:12:39.413  INFO   Highest known block at #0    
Dec 31 18:12:39.414  INFO 〽️ Prometheus server started at 127.0.0.1:9615    
Dec 31 18:12:39.471  INFO Listening for new connections on 127.0.0.1:9945.    
Dec 31 18:12:44.473  INFO   Idle (0 peers), best: #0 (0x190a…e2d0), finalized #0 (0x190a…e2d0), ⬇ 0 ⬆ 0    
Dec 31 18:12:49.474  INFO   Idle (0 peers), best: #0 (0x190a…e2d0), finalized #0 (0x190a…e2d0), ⬇ 0 ⬆ 0 

将密钥添加到密钥库

MyNode01节点开始运行,我们会再次发现没有区块生成。 此时,我们应该将节点的密钥加进密钥库里。 注意:我们需要在网络中的每一个节点都完成这些步骤,记得操作时切换不同节点的端口。

添加方式有两种可选:1、通过命令curl的方式;2、通过Apps界面的方式。分别来介绍一下。

选项一:通过curl的方式

先通过命令curl的方式操作,这也是官方推荐的方式,因为在生产环境安全性是最重要的,所以必须采取一切可能的预防措施。 这意味着在不要在任何地方留下密钥的痕迹,比如在终端的历史记录中。 创建一个文件,用于定义 curl 请求的内容:

{
  "jsonrpc":"2.0",
  "id":1, 
  "method":"author_insertKey",
  "params": [
    "填写aura或gran,必填",
    "填写生成密钥时的助记词,必填",
    "对应的公钥,必填"
  ]
}

这里笔者在当前目录下,创建了一个专门的目录mykey用于存储这些文件:

如:mykey/node01_aura.jsonmykey/node01_gran.json

内容分别为:

mykey/node01_aura.json文件内容:
{
  "jsonrpc":"2.0",
  "id":1,
  "method":"author_insertKey",
  "params": [
    "aura",
    "engine cube pioneer firm thought exhibit carbon dumb exotic pulse noodle ceiling",
    "0x00301f5ae5f5e5f5067fb10728e963680704c96ee5472e30e370faf1e49d843e"
  ]
}

mykey/node01_gran.json文件内容:
{
  "jsonrpc":"2.0",
  "id":1,
  "method":"author_insertKey",
  "params": [
    "gran",
    "engine cube pioneer firm thought exhibit carbon dumb exotic pulse noodle ceiling",
    "0x063f488785f1f63ecaf7dd74cce9b73a91904f3349ecfebb1e1dc0abf8f8b5dd"
  ]
}

分别执行如下命令,将MyNode01节点的密钥导入密钥库,这里的端口为MyNode01节点的rpc端口:

curl http://localhost:9933 -H "Content-Type:application/json;charset=utf-8" -d "@/home/simon/polkadot/substrate-node-template/mykey/node01_aura.json"
curl http://localhost:9933 -H "Content-Type:application/json;charset=utf-8" -d "@/home/simon/polkadot/substrate-node-template/mykey/node01_gran.json"

如果命令和参数输入正确,则节点将返回如下的 JSON 响应:

{ "jsonrpc": "2.0", "result": null, "id": 1 }

这样我们对MyNode01节点的密钥操作就完成了。

选项二:通过Apps界面的方式

a6b09818b814f395bbbf42a22907063f.png

4292b56628fc423454d20ab198e29c9d.png

a17714d1625cc413a9c0a1e754b11e63.png

重复以上步骤添加其他节点的密钥到密钥库。

启动其他节点MyNode02

./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/12D3KooWN967iQjeSWxxPuQTtmmM6woxRyJzPrNSxyHWhg9Y6jC1

和之前一样,我们指定了另一个 base-path 和不同端口,给它另一个 name 参数,并指定此节点为 validator。

接下来重复MyNode01使用curl方式导入密钥的操作,对MyNode02节点的密钥进行导入,但是这里操作不当就会有坑,重点强调一下:除了文件和内容都换成MyNode02节点之外,在执行curl命令时,记得切换rpc端口。

我们会注意到,即使在为第二个节点添加密钥之后,依然没有区块完成最终确定性 (finalized #0)。 Substrate节点在添加 GRANDPA 密钥后需要重启。 使用与之前相同的命令,关闭节点并重启他们,此时区块就可以达到最终确定性。

查看MyNode01节点,我们可以看到网络正常出块并确认区块了:

Dec 31 19:51:56.644  INFO Substrate Node    
Dec 31 19:51:56.644  INFO ✌️  version 2.0.0-655bfdc-x86_64-linux-gnu    
Dec 31 19:51:56.644  INFO ❤️  by Substrate DevHub <https://github.com/substrate-developer-hub>, 2017-2020    
Dec 31 19:51:56.644  INFO   Chain specification: Local Testnet    
Dec 31 19:51:56.644  INFO    Node name: MyNode01    
Dec 31 19:51:56.644  INFO   Role: AUTHORITY    
Dec 31 19:51:56.644  INFO   Database: RocksDb at /tmp/node01/chains/local_testnet/db    
Dec 31 19:51:56.644  INFO ⛓  Native runtime: node-template-1 (node-template-1.tx1.au1)    
Dec 31 19:51:57.090  WARN Using default protocol ID "sup" because none is configured in the chain specs    
Dec 31 19:51:57.126  INFO    Local node identity is: 12D3KooWN967iQjeSWxxPuQTtmmM6woxRyJzPrNSxyHWhg9Y6jC1 (legacy representation: 12D3KooWN967iQjeSWxxPuQTtmmM6woxRyJzPrNSxyHWhg9Y6jC1)    
Dec 31 19:51:57.128  INFO   Highest known block at #35    
Dec 31 19:51:57.131  INFO Listening for new connections on 127.0.0.1:9945.    
Dec 31 19:51:57.665  INFO   Discovered new external address for our node: /ip4/192.168.112.129/tcp/30333/p2p/12D3KooWN967iQjeSWxxPuQTtmmM6woxRyJzPrNSxyHWhg9Y6jC1    
Dec 31 19:52:00.027  INFO   Starting consensus session on top of parent 0xb89d8e723827f5f45e767f130a701a799a885f9165dd3ef99272b20a6db64c23    
Dec 31 19:52:00.539  WARN Timeout fired waiting for transaction pool at block #35. Proceeding with production.    
Dec 31 19:52:00.549  INFO   Prepared block for proposing at 36 [hash: 0xf86be25cc39a2f384eabce077ee3407a16c9254e594988c8d8de783aaa9de7e6; parent_hash: 0xb89d…4c23; extrinsics (1): [0x0cd8…9a43]]    
Dec 31 19:52:00.561  INFO   Pre-sealed block for proposal at 36. Hash now 0x5bd9428b7042eece65a7163313b6a035853b5ee18045cd91f3cc71a8d3faa804, previously 0xf86be25cc39a2f384eabce077ee3407a16c9254e594988c8d8de783aaa9de7e6.    
Dec 31 19:52:00.562  INFO ✨ Imported #36 (0x5bd9…a804)    
Dec 31 19:52:02.132  INFO   Idle (1 peers), best: #36 (0x5bd9…a804), finalized #33 (0xa869…8356), ⬇ 1.5kiB/s ⬆ 1.5kiB/s    
Dec 31 19:52:06.140  INFO ✨ Imported #37 (0xa0fc…b6ce)    
Dec 31 19:52:07.133  INFO   Idle (1 peers), best: #37 (0xa0fc…b6ce), finalized #34 (0x4a7d…2924), ⬇ 1.0kiB/s ⬆ 1.0kiB/s    
Dec 31 19:52:12.002  INFO   Starting consensus session on top of parent 0xa0fc3ee234c172933d314f5a7c03355d81fda692b228ab204a14f7f13cdeb6ce    
Dec 31 19:52:12.005  INFO   Prepared block for proposing at 38 [hash: 0x41137065ca473208f88e75f297da0de7b771be192df00c41df8c8a1f9e8a63f1; parent_hash: 0xa0fc…b6ce; extrinsics (1): [0x5052…8ef6]]    
Dec 31 19:52:12.008  INFO   Pre-sealed block for proposal at 38. Hash now 0x2b47d55f994bb91e5a1c5346f6403cfdcabb5785d4cba1209d4104051707cfd7, previously 0x41137065ca473208f88e75f297da0de7b771be192df00c41df8c8a1f9e8a63f1.

513c392d0e6b7f80eee3090da0bacec6.png

好了,到此就大功告成了!

小结

通过本文的学习,我们熟悉并掌握了怎样创建一个自己的区块链网络,包括学会了生成自己的账号密钥、导入密钥到密钥库,并创建一个使用该密钥对的自定义创世区块配置文件(chain spec),离“使用substrate创建的区块链网络用于生产环境”又更近了一步了。


参考:

Creating Your Private Network · Substrate Developer Hub

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值