三、模拟网络
本教程基本介绍了如何使用一个私有验证器(validators
)的授权集合来启动私有区块链网络。
Substrate
节点模板使用授权共识模型(authority consensus model
),该模型将块生产限制为授权帐户的旋转列表(rotating list
)。授权帐户(authorities,授权机构)负责以循环方式创建块。
在本教程中,您将通过使用两个预定义的帐户作为允许节点生成块的权限,了解权限共识模型在实践中是如何工作的。在这个模拟网络中,两个节点使用不同的帐户和密钥启动,但运行在一台计算机上。
3.1 教程的目标
通过完成本教程,您将实现以下目标:
- 使用预定义帐户启动区块链节点。
- 了解用于启动节点的关键命令行选项。
- 确定一个节点是否正在运行并生成块。
- 将第二个节点连接到运行中的网络。
- 验证对等计算机生成和完成块。
3.2 启动第一个区块链节点
在生成密钥以启动自己的专用Substrate
网络之前,可以使用称为local
的预定义网络规范学习基本原理,该规范在预定义用户帐户下运行。
本教程通过在一台本地计算机上使用命名为alice
和bob
的预定义帐户运行两个Substrate
节点来模拟专用网络。
启动区块链:
- 在计算机上打开一个终端。
- 切换到编译Substrate节点模板的根目录。
- 运行命令如下:清除旧链数据。
./target/release/node-template purge-chain --base-path /tmp/alice --chain local
命令提示用户确认操作:
Are you sure to remove "/tmp/alice/chains/local_testnet/db"? [y/N]:
-
输入
y
以确认要删除链数据。
当你开始一个新的网络时,你应该总是删除旧的链数据。 -
以“
alice
”帐号启动本地区块链节点。
./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 --unsafe-ws-external
检查命令行选项
在继续之前,看看如何使用以下选项启动节点。
Option | Option |
---|---|
–base-path | 指定用于存储与此链相关的所有数据的目录 |
–chain local | 指定要使用的链规范。有效的预定义链规范包括local, development, 和staging. |
–alice | 将alice帐户的预定义密钥添加到节点的密钥存储库中。使用此设置,alice帐户将用于块生产和finalization。 |
–port 30333 | 指定侦听点对点(p2p)流量的端口。由于本教程使用在同一物理计算机上运行的两个节点来模拟网络,因此必须为至少一个帐户显式指定不同的端口。 |
–ws-port 9945 | 指定监听进入 WebSocket 流量的端口。默认端口号为9944。本教程使用自定义WebSocket 端口号(9945) |
–rpc-port 9933 | 指定侦听传入RPC通信的端口。默认端口号为9933。 |
–node-key | 指定用于libp2p网络的Ed25519秘密密钥。您应该只在开发和测试时使用此选项 |
–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.指定发送遥测数据的位置。在本教程中,您可以将遥测数据发送到Parity托管的任何人都可以使用的服务器。 |
–validator | Specifies that this node participates in block production and finalization for the network. 指定该节点参与网络的块生产和结束。 |
有关节点模板(node template)可用的命令行选项的更多信息,请参见运行以下命令的用法帮助:
./target/release/node-template --help
查看显示的节点消息
如果节点启动成功,终端显示网络操作信息。例如,你应该看到类似这样的输出:
特别地,您应该注意输出中的以下消息:
Initializing Genesis block/state (state: 0x4e1c…a8dc, header-hash: 0xbd60…2cb6)
:标识节点正在使用的初始块或起源块。当启动下一个节点时,验证这些值是否相同。
Local node identity is: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp
:指定唯一标识此节点的字符串。该字符串由--node-key
决定,该key用于使用alice帐户启动节点。在启动第二个节点时,可以使用此字符串标识要连接的节点。
Idle (0 peers), best: #0 (0xbd60…2cb6), finalized #0 (0xbd60…2cb6), ⬇ 0 ⬆ 0
:表示网络中没有其他节点,也没有正在生成的块。在区块开始生成之前,必须有另一个节点加入网络。
3.3 添加第二个节点到区块链网络
现在您使用alice
帐户密钥启动的节点正在运行,您可以使用bob
帐户将另一个节点添加到网络中。因为您正在加入一个已经在运行的网络,所以您可以使用正在运行的节点来标识新节点要加入的网络。这些命令与您以前使用的命令类似,但有一些重要的区别。
向运行中的区块链添加节点:
- 在计算机上打开一个新的终端。
- 切换到编译Substrate节点模板的根目录。
- 使用实例清除旧链数据。
./target/release/node-template purge-chain --base-path /tmp/bob --chain local -y
- 以“bob”帐号启动本地第二个区块链节点。
./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
注意此命令与上一个命令的区别如下:
因为两个节点运行在同一台物理计算机上,所以必须为--base-path
、--port
、--ws-port
和--rpc-port
选项指定不同的值。
该命令包括--bootnodes
选项,并指定一个引导节点,即由alice
启动的节点。
The --bootnodes
option specifies the following information:
ip4
表示节点IP地址为IPv4格式127.0.0.1
为运行节点的IP地址。在本例中,是localhost
的地址。- tcp指定使用tcp协议进行点对点通信。
30333
为点对点通信时使用的端口号。 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp
标识此网络中要与之通信的运行节点。在本例中,节点的标识符开始使用alice
帐户。
3.4 验证块的生产和最终确定
启动第二个节点后,这些节点应该作为对等点相互连接,并开始生成块。
- 验证块正在完成:
验证您在启动第一个节点的终端中看到类似于下面的行:
2023-03-01 11:08:13 Low open file descriptor limit configured for the process. Current value: 4096, recommended value: 10000.
2023-03-01 11:08:13 Substrate Node
2023-03-01 11:08:13 ✌️ version 4.0.0-dev-d79d8cef20b
2023-03-01 11:08:13 ❤️ by Substrate DevHub <https://github.com/substrate-developer-hub>, 2017-2023
2023-03-01 11:08:13 📋 Chain specification: Local Testnet
2023-03-01 11:08:13 🏷 Node name: Bob
2023-03-01 11:08:13 👤 Role: AUTHORITY
2023-03-01 11:08:13 💾 Database: RocksDb at /tmp/bob/chains/local_testnet/db/full
2023-03-01 11:08:13 ⛓ Native runtime: node-template-100 (node-template-1.tx1.au1)
2023-03-01 11:08:15 🔨 Initializing Genesis block/state (state: 0x4e1c…a8dc, header-hash: 0xbd60…2cb6)
2023-03-01 11:08:16 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.
2023-03-01 11:08:16 Using default protocol ID "sup" because none is configured in the chain specs
2023-03-01 11:08:16 🏷 Local node identity is: 12D3KooWGGyA4aXnaEkazB8hFYUt2Pf9mDN5nYEGeoDwV73UYG4v
2023-03-01 11:08:16 💻 Operating system: linux
2023-03-01 11:08:16 💻 CPU architecture: x86_64
2023-03-01 11:08:16 💻 Target environment: gnu
2023-03-01 11:08:16 💻 CPU: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz
2023-03-01 11:08:16 💻 CPU cores: 2
2023-03-01 11:08:16 💻 Memory: 1960MB
2023-03-01 11:08:16 💻 Kernel: 5.4.230-1.el7.elrepo.x86_64
2023-03-01 11:08:16 💻 Linux distribution: CentOS Linux 7 (Core)
2023-03-01 11:08:16 💻 Virtual machine: yes
2023-03-01 11:08:16 📦 Highest known block at #0
2023-03-01 11:08:16 Running JSON-RPC HTTP server: addr=127.0.0.1:9934, allowed origins=["http://localhost:*", "http://127.0.0.1:*", "https://localhost:*", "https://127.0.0.1:*", "https://polkadot.js.org"]
2023-03-01 11:08:16 Running JSON-RPC WS server: addr=127.0.0.1:9946, allowed origins=["http://localhost:*", "http://127.0.0.1:*", "https://localhost:*", "https://127.0.0.1:*", "https://polkadot.js.org"]
2023-03-01 11:08:16 discovered: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp /ip4/192.168.122.1/tcp/30333
2023-03-01 11:08:16 discovered: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp /ip4/172.18.0.1/tcp/30333
2023-03-01 11:08:16 discovered: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp /ip4/172.17.0.1/tcp/30333
2023-03-01 11:08:16 discovered: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp /ip4/192.168.159.128/tcp/30333
2023-03-01 11:08:18 🙌 Starting consensus session on top of parent 0xbd60aaeb57aeb6a7620f7450d5d7bc07410fe512591d0032979ff5ba65bf2cb6
2023-03-01 11:08:18 🎁 Prepared block for proposing at 1 (0 ms) [hash: 0xdb613010821ae195a3fa19fa051c6c9349322115930ad9a37d19f01d145d68a0; parent_hash: 0xbd60…2cb6; extrinsics (1): [0xcaad…5f79]]
2023-03-01 11:08:18 🔖 Pre-sealed block for proposal at 1. Hash now 0x8ace1e4b0545173d26b8dddef90c0b8e264ab38ca61c65a287707187f8139a48, previously 0xdb613010821ae195a3fa19fa051c6c9349322115930ad9a37d19f01d145d68a0.
2023-03-01 11:08:18 ✨ Imported #1 (0x8ace…9a48)
2023-03-01 11:08:21 💤 Idle (1 peers), best: #1 (0x8ace…9a48), finalized #0 (0xbd60…2cb6), ⬇ 1.8kiB/s ⬆ 1.9kiB/s
2023-03-01 11:15:39 💤 Idle (1 peers), best: #17 (0x6d18…12fe), finalized #15 (0x20ac…5747), ⬇ 0.7kiB/s ⬆ 0.6kiB/s
2023-03-01 11:15:42 🙌 Starting consensus session on top of parent 0x6d1894bbb824f7534cc9c1834722e2ffb38f1e72dcd71e0d21fdf992f84212fe
2023-03-01 11:15:42 🎁 Prepared block for proposing at 18 (0 ms) [hash: 0x409738e75bf5e80aee3a126d274dce1339b2924372e0c323e2f5312b391ff8b0; parent_hash: 0x6d18…12fe; extrinsics (1): [0xf57c…57da]]
2023-03-01 11:15:42 🔖 Pre-sealed block for proposal at 18. Hash now 0xa53d462295b3c84fb86f471a9ee666f7cc398218f65950462b6edcc6aa63a0df, previously 0x409738e75bf5e80aee3a126d274dce1339b2924372e0c323e2f5312b391ff8b0.
2023-03-01 11:15:42 ✨ Imported #18 (0xa53d…a0df)
2023-03-01 11:15:44 💤 Idle (1 peers), best: #18 (0xa53d…a0df), finalized #16 (0x0604…04af), ⬇ 0.6kiB/s ⬆ 0.8kiB/s
2023-03-01 11:15:48 ✨ Imported #19 (0x2370…cfe1)
2023-03-01 11:15:49 💤 Idle (1 peers), best: #19 (0x2370…cfe1), finalized #17 (0x6d18…12fe), ⬇ 0.7kiB/s ⬆ 0.6kiB/s
2023-03-01 11:15:54 🙌 Starting consensus session on top of parent 0x2370ab5a6ad0e4fd4a36cd18aa4d58dbb70a9be80e887d84cbaa8116945fcfe1
2023-03-01 11:15:54 🎁 Prepared block for proposing at 20 (6 ms) [hash: 0xf1f4369f6f8dc41adc0d6e7b5d96489d0dcedce232e5c075477a84db6157ab1c; parent_hash: 0x2370…cfe1; extrinsics (1): [0xa4fe…dbc3]]
2023-03-01 11:15:54 🔖 Pre-sealed block for proposal at 20. Hash now 0x7e307e4e16102a98a125c7c00fb697ceaa5b8db8f1b32b55419686c0c96cad5e, previously 0xf1f4369f6f8dc41adc0d6e7b5d96489d0dcedce232e5c075477a84db6157ab1c.
2023-03-01 11:15:54 ✨ Imported #20 (0x7e30…ad5e)
2023-03-01 11:15:54 💤 Idle (1 peers), best: #20 (0x7e30…ad5e), finalized #17 (0x6d18…12fe), ⬇ 0.6kiB/s ⬆ 0.7kiB/s
2023-03-01 11:15:59 💤 Idle (1 peers), best: #20 (0x7e30…ad5e), finalized #18 (0xa53d…a0df), ⬇ 0.6kiB/s ⬆ 0.6kiB/s
2023-03-01 11:16:00 ✨ Imported #21 (0x0470…7707)
在这些行中,您可以看到关于您的区块链的以下信息:
- 在网络上发现第二个节点标识
12D3KooWGGyA4aXnaEkazB8hFYUt2Pf9mDN5nYEGeoDwV73UYG4v
- The node has a one peer (1 peers).
- The nodes have produced some blocks
best: #20 (0x7e30…ad5e)
- 这些区块正在最后确定
finalized #17 (0x6d18…12fe)
- 验证在启动第二个节点的终端中是否看到类似的输出。
- 在终端shell中按Control-c关闭其中一个节点。
- 关闭节点后,您将看到剩下的节点现在没有对等点,并且已经停止生成块。例如:
2023-03-01 11:16:03 💤 Idle (1 peers), best: #21 (0x0470…7707), finalized #19 (0x2370…cfe1), ⬇ 0.7kiB/s ⬆ 0.8kiB/s
2023-03-01 11:16:06 ✨ Imported #22 (0x6481…152b)
2023-03-01 11:16:08 💤 Idle (0 peers), best: #22 (0x6481…152b), finalized #19 (0x2370…cfe1), ⬇ 0.6kiB/s ⬆ 0.5kiB/s
- 在终端shell中按Control-c关闭第二个节点。
如果您想从模拟网络中删除链状态,可以在/tmp/bob
和/tmp/alice
目录中使用带有--base-path
命令行选项的purge-chain
子命令。
四、添加可信节点
本教程演示如何使用一个私有验证器(validator
)的 授权集启动一个小型的独立区块链网络。
正如你在区块链基础知识中所学到的,所有区块链都要求网络中的节点在任何特定的时间点对数据的状态达成一致,这种关于状态的一致被称为共识(consensus
)。
Substrate
节点模板使用授权证明共识模型(proof of authority consensus model
),也称为authority round
或Aura
共识。Aura
共识协议将区块生产限制为授权帐户的轮询列表。授权帐户(authorities)以轮询方式创建块,通常被认为是网络中可信的参与者。
这个共识模型为有限数量的参与者提供了一个简单的方法来启动一个单独的区块链。在本教程中,您将了解如何生成授权节点参与网络所需的密钥,如何配置网络并与其他授权帐户共享有关网络的信息,以及如何使用一组经过批准的验证器启动网络。
4.1 教程的目标
通过完成本教程,您将实现以下目标:
- 生成密钥对以作为网络授权使用。
- 创建一个自定义链规范文件。
- 启动私有双节点区块链网络。
4.2 生成您的帐户和密钥
在模拟网络中,使用预定义的帐户和密钥启动对等节点。对于本教程,您将为网络中的验证器节点生成自己的密钥。重要的是要记住,区块链网络中的每个参与者都负责生成唯一密钥。
key 生成选项
有几种生成密钥的方法。例如,您可以使用node-template
子命令、独立subkey命令行程序、Polkadot-JS
应用程序或第三方密钥生成实用程序生成密钥对。
虽然您可以使用预定义的键对来完成本教程,但您绝不会在生产环境中使用这些键。本教程没有使用预定义的密钥或更安全的subkey
程序,而是说明如何使用Substrate
节点模板和key
子命令生成密钥。
使用节点模板生成本地密钥
作为最佳实践,在为生产区块链(production blockchain)生成密钥时,应该使用从未连接到internet的air-gapped计算机。至少,在生成任何密钥用于不受您控制的公共或私有区块链之前,您应该断开与互联网的连接。
但是,对于本教程,您可以使用node-template
命令行选项在本地生成随机键,同时保持与互联网的连接。
- 运行如下命令生成一个随机的秘密短语和密钥:
./target/release/node-template key generate --scheme Sr25519 --password-interactive
你现在有了Sr25519 key,可以在一个节点上使用aura
生成区块。在此例中,帐号的Sr25519
公钥为5Esh9DFdgPTsoBYNWCBRy5z91WkPhE35yskGivwvapqi2DNd
。
- 对刚刚生成的帐户使用
secret phrase
,以使用Ed25519
签名方案派生密钥。
./target/release/node-template key inspect --password-interactive --scheme Ed25519 "reduce nerve siren ramp pride wrist main cry dolphin immune car group"
- 输入用于生成密钥的密码。
[root@localhost substrate-node-template]# ./target/release/node-template key inspect --password-interactive --scheme Ed25519 "reduce nerve siren ramp pride wrist main cry dolphin immune car group"
Key password:
Secret phrase: reduce nerve siren ramp pride wrist main cry dolphin immune car group
Network ID: substrate
Secret seed: 0x157b8dec08acbcf1abbdff5256586cce1f6d096959d0b6e9c90e3a244c1e1831
Public key (hex): 0x03424a4a780766de57469c422d771c44e24e0fc97ccdc28e9f92a4e107b443f2
Account ID: 0x03424a4a780766de57469c422d771c44e24e0fc97ccdc28e9f92a4e107b443f2
Public key (SS58): 5C8yh9u4rwY3VrQW6pDdScnP6WTx7xJfQSn53K44Uw1ShCuw
SS58 Address: 5C8yh9u4rwY3VrQW6pDdScnP6WTx7xJfQSn53K44Uw1ShCuw
现在您有了Ed25519 key,用于对一个节点使用grandpa
来确认块。在此例中,帐号的Ed25519公钥为5C8yh9u4rwY3VrQW6pDdScnP6WTx7xJfQSn53K44Uw1ShCuw
。
生成第二组密钥
对于本教程,专用网络仅由两个节点组成,因此需要两组密钥。你有几个选项来继续本教程:
- 您可以对预定义帐户之一使用密钥。
- 您可以在本地计算机上使用不同的标识重复上一节中的步骤,以生成第二个密钥对。
- 您可以派生子密钥对来模拟本地计算机上的第二个标识。
- 您可以招募其他参与者来生成加入您的私有网络所需的密钥。
[root@localhost substrate-node-template]# ./target/release/node-template key generate --scheme Sr25519 --password-interactive
Key password:
Secret phrase: zoo trip idle enable gaze betray shy caught harvest crash warm pudding
Network ID: substrate
Secret seed: 0x0364437d6f1ff68042d0f05e98c63a2e56a691b9ed5474af8048b63696d78a8f
Public key (hex): 0x065ccea9171c88a1a1098c4d21576b9b54b334c23ccc06c427164fa37bc7324c
Account ID: 0x065ccea9171c88a1a1098c4d21576b9b54b334c23ccc06c427164fa37bc7324c
Public key (SS58): 5CD3iN6qxUUvay2hVMBSgTJAXHXZgFPJU4i3jkNVBMAqUB24
SS58 Address: 5CD3iN6qxUUvay2hVMBSgTJAXHXZgFPJU4i3jkNVBMAqUB24
[root@localhost substrate-node-template]# ./target/release/node-template key inspect --password-interactive --scheme Ed25519 'zoo trip idle enable gaze betray shy caught harvest crash warm pudding'
Key password:
Secret phrase: zoo trip idle enable gaze betray shy caught harvest crash warm pudding
Network ID: substrate
Secret seed: 0x0364437d6f1ff68042d0f05e98c63a2e56a691b9ed5474af8048b63696d78a8f
Public key (hex): 0x19b6e3e347b28fd5bee94cb57945d9cb116f81741e35f5e0731c3cec019b741b
Account ID: 0x19b6e3e347b28fd5bee94cb57945d9cb116f81741e35f5e0731c3cec019b741b
Public key (SS58): 5CeRPE4xNPqrUCRChmSGG2KZ4jDcVsBdj64BRfeVeC3xa4FS
SS58 Address: 5CeRPE4xNPqrUCRChmSGG2KZ4jDcVsBdj64BRfeVeC3xa4FS
4.3 创建自定义链规范
生成用于区块链的密钥后,就可以使用这些密钥对创建自定义链规范,然后与称为验证者(validators)的可信网络参与者共享自定义链规范。
要使其他人能够参与您的区块链网络,请确保他们生成自己的密钥。收集网络参与者的密钥后,可以创建自定义链规范来替换local
链规范。
为简单起见,在本教程中创建的自定义链规范是local
链规范的修改版本,该规范演示了如何创建双节点网络。如果您拥有所需的密钥,可以按照相同的步骤向网络添加更多节点。
修改local 链规格
您可以修改预定义的local
链规范,而不是编写一个全新的链规范。
基于本地规范创建一个新的链规范:
- 将本地链规范导出到名为
customSpec.json
的文件中。通过执行以下命令查看:
./target/release/node-template build-spec --disable-default-bootnode --chain local > customSpec.json
如果您打开customSpec.json
文件在文本编辑器中,您将看到它包含几个字段。其中一个字段是使用cargo build --release
命令构建的运行时的WebAssembly (Wasm)二进制文件。因为WebAssembly (Wasm)二进制文件是一个大的blob,您可以预览第一行和最后几行,以查看需要更改的字段。
- 预览
customSpec.json
中的前几个字段。执行以下命令:
head customSpec.json
3. 预览customSpec.json
中的最后几行:
tail -n 80 customSpec.json
该命令显示Wasm二进制字段后面的最后部分,包括运行时中使用的几个pallet
盘(如sudo
和balanced
托盘)的详细信息。
- 修改
name
字段,将此链规范标识为自定义链规范。
"name": "My Custom Testnet",
-
修改
aura
字段,为每个网络参与者添加Sr25519 SS58地址密钥,指定有权限创建块的节点。 -
修改
grandpa
字段,通过为每个网络参与者添加Ed25519 SS58地址密钥,指定具有完成块的权限的节点。
"aura": {
"authorities": [
"5Esh9DFdgPTsoBYNWCBRy5z91WkPhE35yskGivwvapqi2DNd",
"5CD3iN6qxUUvay2hVMBSgTJAXHXZgFPJU4i3jkNVBMAqUB24"
]
},
"grandpa": {
"authorities": [
[
"5C8yh9u4rwY3VrQW6pDdScnP6WTx7xJfQSn53K44Uw1ShCuw",
1
],
[
"5CeRPE4xNPqrUCRChmSGG2KZ4jDcVsBdj64BRfeVeC3xa4FS",
1
]
]
},
请注意,grandpa
部分中的authorities
字段有两个数据值。第一个值是地址key。第二个值用于支持加权投票(weighted votes)。在本例中,每个验证器的权重为1票。
- 添加验证器
正如您刚才看到的,您可以通过修改aura
和grandpa
部分来添加和更改链规范中的授权地址(authority addresses)。您可以使用此技术添加任意数量的验证器。
To add validators:
- Modify the
aura
section to include Sr25519 addresses. - Modify the
grandpa
section to include Ed25519 addresses and a voting weight.
有关使用密钥对和签名的更多信息,请参见 Public-Key cryptography
4.4 将链规范转换为原始格式
在准备了带有验证器信息的链规范之后,必须在使用它之前将其转换为原始规范格式(raw specification format)。原始链规范包含与未转换的规范相同的信息。但是,原始链规范还包含编码的存储键,节点使用这些存储键引用本地存储中的数据。分发原始链规范可确保每个节点使用适当的存储密钥存储数据。
将一个链规范转换为使用原始格式:
用文件名customSpecRaw.json
转换customSpec_my.json
链规范到原始格式。
./target/release/node-template build-spec --chain=customSpec_my.json --raw --disable-default-bootnode > customSpecRaw.json
4.5 准备启动私有网络
将自定义链规范分发给所有网络参与者之后,就可以启动自己的私有区块链了。步骤与启动第一个区块链节点中所遵循的步骤类似。但是,如果您遵循本教程中的步骤,您将能够将多台计算机添加到网络中。
要继续,请验证以下内容:
- 您已经生成或收集了至少两个权限帐户的帐户密钥。
- 您已经更新了自定义链规范,以包括区块生产(aura)和区块终结(grandpa)的键。
- 您已经将自定义链规范转换为原始格式,并将原始链规范分发到参与私有网络的节点。
4.6 启动第一个节点
作为私有区块链网络中的第一个参与者,您负责启动称为引导节点(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 \
--password-interactive \
--unsafe-ws-external
请注意以下命令行选项,您正在使用来启动节点:
- The
--validator
command-line option indicates that this node is an authority for the chain. - The
--rpc-methods Unsafe
command-line option allows you to continue the tutorial using an unsafe communication mode because your blockchain is not being used in a production setting. - The
--name
command-line option enables you to give your node a human-readable name in the telemetry UI.
该命令还使用您自己的密钥而不是预定义的帐户启动节点。因为您没有使用具有已知密钥的预定义帐户,所以需要在单独的步骤中将密钥添加到密钥存储库中。
4.7 查看节点操作信息
2023-03-01 14:34:58 Low open file descriptor limit configured for the process. Current value: 4096, recommended value: 10000.
2023-03-01 14:34:58 Substrate Node
2023-03-01 14:34:58 ✌️ version 4.0.0-dev-d79d8cef20b
2023-03-01 14:34:58 ❤️ by Substrate DevHub <https://github.com/substrate-developer-hub>, 2017-2023
2023-03-01 14:34:58 📋 Chain specification: My Custom Testnet
2023-03-01 14:34:58 🏷 Node name: MyNode01
2023-03-01 14:34:58 👤 Role: AUTHORITY
2023-03-01 14:34:58 💾 Database: RocksDb at /tmp/node01/chains/local_testnet/db/full
2023-03-01 14:34:58 ⛓ Native runtime: node-template-100 (node-template-1.tx1.au1)
2023-03-01 14:34:58 🔨 Initializing Genesis block/state (state: 0x972a…636b, header-hash: 0x7633…9642)
2023-03-01 14:34:58 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.
2023-03-01 14:34:59 Using default protocol ID "sup" because none is configured in the chain specs
2023-03-01 14:34:59 🏷 Local node identity is: 12D3KooWAecWYYGnLz6iUsQgU1kmTcVPyNunbwQaV14oeaW31jmB
2023-03-01 14:34:59 💻 Operating system: linux
2023-03-01 14:34:59 💻 CPU architecture: x86_64
2023-03-01 14:34:59 💻 Target environment: gnu
2023-03-01 14:34:59 💻 CPU: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz
2023-03-01 14:34:59 💻 CPU cores: 2
2023-03-01 14:34:59 💻 Memory: 1960MB
2023-03-01 14:34:59 💻 Kernel: 5.4.230-1.el7.elrepo.x86_64
2023-03-01 14:34:59 💻 Linux distribution: CentOS Linux 7 (Core)
2023-03-01 14:34:59 💻 Virtual machine: yes
2023-03-01 14:34:59 📦 Highest known block at #0
2023-03-01 14:34:59 〽️ Prometheus exporter started at 127.0.0.1:9615
2023-03-01 14:34:59 Running JSON-RPC HTTP server: addr=127.0.0.1:9933, allowed origins=["http://localhost:*", "http://127.0.0.1:*", "https://localhost:*", "https://127.0.0.1:*", "https://polkadot.js.org"]
2023-03-01 14:34:59 Running JSON-RPC WS server: addr=0.0.0.0:9945, allowed origins=["http://localhost:*", "http://127.0.0.1:*", "https://localhost:*", "https://127.0.0.1:*", "https://polkadot.js.org"]
2023-03-01 14:35:04 💤 Idle (0 peers), best: #0 (0x7633…9642), finalized #0 (0x7633…9642), ⬇ 0 ⬆ 0
2023-03-01 14:35:09 💤 Idle (0 peers), best: #0 (0x7633…9642), finalized #0 (0x7633…9642), ⬇ 0 ⬆ 0
请注意以下信息:
- 输出表明正在使用的链规范是使用
--chain
命令行选项创建和指定的自定义链规范。 - 输出表明该节点是一个authority 节点,因为您使用
--validator
命令行选项启动了该节点。 - 输出显示了用块哈希
(state: 0x972a…636b, header-hash: 0x7633…9642)
初始化的创世块 - 输出为您的节点指定Local节点标识。在本例中,节点标识为
12D3KooWAecWYYGnLz6iUsQgU1kmTcVPyNunbwQaV14oeaW31jmB
。 - 说明节点使用的IP地址为本地主机
127.0.0.1
。
这些值是针对这个特定的教程示例的。输出中的值将特定于您的节点,您必须将节点的值提供给其他网络参与者以连接到引导节点。
现在您已经成功地使用自己的 key 启动了验证器节点,并记录了节点标识,可以继续下一步。但是,在将密钥添加到密钥存储库之前,请通过按Control-c停止节点。
4.8 向密钥存储库添加密钥
在启动第一个节点之后,还没有生成任何块。下一步是为网络中的每个节点向密钥存储库添加两种类型的密钥。
对于每个节点:
- 添加
aura
授权密钥以启用块生产。 - 添加
grandpa
授权密钥以启用块结束。
有几种方法可以将密钥插入密钥存储库。对于本教程,您可以使用key
子命令插入本地生成的密钥。
- 执行如下命令插入
key
子命令生成的aura
secret key:
./target/release/node-template key insert --base-path /tmp/node01 \
--chain customSpecRaw.json \
--scheme Sr25519 \
--suri <your-secret-seed> \
--password-interactive \
--key-type aura
将<your-secret-seed>
替换为您在“使用节点模板生成本地密钥”中生成的第一个密钥对的秘密短语或秘密种子。
在本教程中,秘密短语是reduce nerve siren ramp pride wrist main cry dolphin immune car group
,因此--suri
命令行选项指定将密钥插入密钥库的字符串。
--suri "reduce nerve siren ramp pride wrist main cry dolphin immune car group"
- 还可以从指定的文件位置插入密钥。查看可用的命令行选项信息,执行以下命令:
./target/release/node-template key insert --help
- 输入用于生成密钥的密码。
- 执行如下命令插入key子命令生成的
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
<your-secret-seed>
同上
- 通过运行以下命令,验证您的密钥位于
node01
的密钥存储库中:
ls /tmp/node01/chains/local_testnet/keystore
4.9 允许其他与会者加入
现在可以使用--bootnodes
和-validator
命令行选项允许其他验证器加入网络。
向私有网络添加第二个验证器:
- 以如下命令启动第二个区块链节点:
./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/12D3KooWAecWYYGnLz6iUsQgU1kmTcVPyNunbwQaV14oeaW31jmB\
--password-interactive
该命令使用base-path
、name
和validator
命令行选项将该节点标识为私有网络的第二个验证器。--chain
命令行选项指定要使用的链规范文件。该文件对于网络中的所有验证器必须相同。确保为--bootnodes
命令行选项设置了正确的信息。特别是,确保您已经从网络中的第一个节点指定了本地节点标识符。如果你没有设置正确的引导节点标识符,你会看到这样的错误:
The bootnode you want to connect to at ... provided a different peer ID than the one you expect: ...
- 执行如下命令添加
key
子命令生成的aura
secret key:
./target/release/node-template key insert --base-path /tmp/node02 \
--chain customSpecRaw.json \
--scheme Sr25519 \
--suri <second-participant-secret-seed> \
--password-interactive \
--key-type gran
将<second-participant-secret-seed>
替换为您在生成第二个密钥对中生成的短语或种子。aura
密钥类型是启用块生产所必需的。
- 运行如下命令,将key子命令生成的爷爷密钥添加到本地密钥存储库中:
./target/release/node-template key insert --base-path /tmp/node02 \
--chain customSpecRaw.json \
--scheme Ed25519 --suri <second-participant-secret-seed> \
--password-interactive \
--key-type gran
<second-participant-secret-seed>
同上
块结束(Block finalization )需要至少三分之二的验证器将它们的密钥添加到各自的密钥存储库中。因为这个网络在链规范中配置了两个验证器,所以区块终结只能在第二个节点添加了它的密钥之后开始。
- 通过运行以下命令,验证您的密钥位于
node02
的密钥存储库中:
ls /tmp/node02/chains/local_testnet/keystore
Substrate 节点在插入grandpa
key 后需要重新启动,因此必须在看到块最终完成之前关闭并重新启动节点。
在两个节点将它们的密钥添加到各自的密钥存储库(位于/tmp/node01
和/tmp/node02
下)并重新启动之后,您应该会看到相同的起源块和状态根散列。
您还应该看到每个节点都有一个对等体(1 peers
),并且它们已经生成了一个块提议(best: #2 (0xe111…c084)
)。几秒钟后,您应该看到两个节点上都完成了新的块。
Accounts, addresses, and keys
Chain specification
subkey
Cryptography