Substrate 基础教程(Tutorials) -- 模拟网络 添加可信节点
三、模拟网络
本教程基本介绍了如何使用一个私有验证器(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 groupNetwork ID: substrateSecret seed: 0x157b8dec08acbcf1abbdff5256586cce1f6d096959d0b6e9c90e3a244c1e1831Public key (hex): 0x03424a4a780766de57469c422d771c44e24e0fc97ccdc28e9f92a4e107b443f2Account ID: 0x03424a4a780766de57469c422d771c44e24e0fc97ccdc28e9f92a4e107b443f2Public key (SS58): 5C8yh9u4rwY3VrQW6pDdScnP6WTx7xJfQSn53K44Uw1ShCuwSS58 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 puddingNetwork ID: substrateSecret seed: 0x0364437d6f1ff68042d0f05e98c63a2e56a691b9ed5474af8048b63696d78a8fPublic key (hex): 0x065ccea9171c88a1a1098c4d21576b9b54b334c23ccc06c427164fa37bc7324cAccount ID: 0x065ccea9171c88a1a1098c4d21576b9b54b334c23ccc06c427164fa37bc7324cPublic key (SS58): 5CD3iN6qxUUvay2hVMBSgTJAXHXZgFPJU4i3jkNVBMAqUB24SS58 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 puddingNetwork ID: substrateSecret seed: 0x0364437d6f1ff68042d0f05e98c63a2e56a691b9ed5474af8048b63696d78a8fPublic key (hex): 0x19b6e3e347b28fd5bee94cb57945d9cb116f81741e35f5e0731c3cec019b741bAccount ID: 0x19b6e3e347b28fd5bee94cb57945d9cb116f81741e35f5e0731c3cec019b741bPublic key (SS58): 5CeRPE4xNPqrUCRChmSGG2KZ4jDcVsBdj64BRfeVeC3xa4FSSS58 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
相关文章:

Substrate 基础教程(Tutorials) -- 模拟网络 添加可信节点
三、模拟网络 本教程基本介绍了如何使用一个私有验证器(validators)的授权集合来启动私有区块链网络。 Substrate节点模板使用授权共识模型(authority consensus model),该模型将块生产限制为授权帐户的旋转列表(rotating list)。授权帐户(…...
SAP 设置无物料号的费用采购
现在还是以外购电来说一下ERP中费用采购单的使用步骤: (1).Tcode:OMSF定义物料组D1,如下图。 (2).到配置路径IMG Path:物料管理->采购->帐户分配(或直接SE16:V_T163K)定义一科目分配类别,默认的K就是费用采购科目分配类型,如果可能可以复制一个,如下图,注意下…...

k8s ConfigMap 中 subPath 字段和 items 字段
Kubernetes中什么是subPath 有时,在单个 Pod 中共享卷以供多方使用是很有用的。volumeMounts.subPath 属性可用于指定所引用的卷内的子路径,而不是其根路径。 这句话理解了,基本就懂subPath怎么用了,比如我们要替换nginx.cnf, 挂…...

UML建模
主要记录UML中的相关知识,包括类、对象、接口、方法、用例、活动、状态、组件和部署图,详细介绍类之间关系与类图的绘制 文章目录一、UML介绍二、类图类之间的关系依赖关系继承关系实现关系关联关系组合关系聚合关系正文内容: 一、UML介绍 …...
JavaScript常见面试题(更新中)
介绍js的基本数据类型 js一共有五种数据类型 分别是undefined null boolean number string 还有ES6中新增的symbol和ES10的bigInt symbol代表创建后独一无二的不可变的数据类型,他的出现我认为是为了解决可能出现的全局变量冲突的问题 BigInt是一种数字类型的数据 …...

TCP/IP协议
✏️作者:银河罐头 📋系列专栏:JavaEE 🌲“种一棵树最好的时间是十年前,其次是现在” 目录TCP/IP协议应用层协议自定义应用层协议DNS传输层协议端口号UDP协议UDP协议端格式TCP协议TCP协议段格式TCP工作机制确认应答(安…...

Python使用异步线程池实现异步TCP服务器交互
背景: 实现客户端与服务端交互,由于效率原因,要发送与接收异步,提高效率。 需要多线程,本文用线程池管理。 common代码: import pickle import struct import timedef send_msg(conn, data):time.sleep(…...

matplotlib常用操作
文章目录1 matplotlib绘图1.1 绘图步骤2 matplotlib基本元素2.1 matplotlib 画布2.2 设置坐标轴长度和范围2.3 设置图形的线型和颜色2.4 设置图形刻度范围、刻度标签和坐标轴标签等2.4.1 设置刻度范围2.4.2 设置坐标轴刻度2.5 文本标签图例3 matplotlib的ax对象绘图4 绘制子图5…...

二分算法题
文章目录一、在排序数组中查找数字二、0~n-1中缺失的数字三、旋转数组的最小数字四、二维数组中的查找一、在排序数组中查找数字 题目传送门 法一:暴力解 直接遍历然后计数 法二:二分法求边界 看到关键字排序数组、有序数组,一定要想到二分…...

Vue+ElementUI+SpringBoot项目配合分页插件快速实现分页(简单暴力)
首先需要在项目中引入Element-UI的组件库,使用以下命令,不会引入的请自行百度。 npm i element-ui -S Element官网地址:https://element.eleme.cn/#/zh-CN/component/changelog 去Element-UI官网组件库找到合适的分页插件,并把他引…...
【回眸】牛客网刷刷刷!嵌入式软件中也会遇到的嵌入式硬件,通讯,通讯协议专题(一)
前言 最近继续刷题,看看嵌入式软件还需要了解一些嵌入式硬件中的通讯协议和常用接口协议 比如说SPI CAN I2C 通讯协议专题 1.波特率 波特率 每秒传送的字符数 * 字符位数。串口的工作模式为1个起始位,7个数据位,1个校验位,1个…...

使用Vue展示数据(动态查询)
学习内容来源:视频P4 本篇文章进度接着之前的文章进行续写 精简前后端分离项目搭建 Vue基础容器使用 目录选择组件修改表格组件修改分页组件增加后端接口前端请求数据接口页面初始化请求数据点击页码请求数据选择组件 在官方文档中选择现成的组件,放在页…...
构建数据库测试数据——mysql
建表脚本 -- 建表 CREATE TABLE test_table (id INT(11) NOT NULL AUTO_INCREMENT,varchar_col VARCHAR(50),char_col CHAR(10),text_col TEXT,tinyint_col TINYINT(4),smallint_col SMALLINT(6),mediumint_col MEDIUMINT(9),int_col INT(11),bigint_col BIGINT(20),float_col…...

你想要的Android性能优化系列:启动优化 !
App启动优化为什么要做App的启动优化?网页端存在的一个定律叫8秒定律:即指用户访问一个网站时,如果等待打开的时间超过8秒,超过70%的用户将会放弃等待。同样的,移动端也有一个8秒定律:如果一个App的启动时间…...
python3的基础入门3:基本数据类型
基本数据类型 python 中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。 在 Python 中,变量就是变量,它没有类型,我们所说的"类型"是变量所指的内存中对象的类型。 等号(&…...

消息队列原理与实战-学习笔记
消息队列:保存消息的一个容器,本质是个队列,但是需要支持高吞吐、高并发、高可用。 1 前世今生 1.1 业界消息队列对比 Kafka:分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥较为出色RocketMQ:低延迟、强一致、高性…...

Linux权限相关知识(大量图文展示,及详细操作)
Linux权限相关概念 Linux下有两种用户:一种是超级用户(root)、一种是普通用户。 超级用户:可以在linux系统下做任何事情,不受限制 普通用户:在linux下做有限的事情。 超级用户的命令提示符是“#”…...

Ep_操作系统面试题-什么是协程
协程 是一种 比线程更加轻量级的存 在,一个线程可以拥有多个协程。是一个特殊的 函数 ,这个函数可以在某个地方挂起,并且可以重新在挂起处外继续运行。协程 不是被操作系统内核所管理 , 而完全是由程序所控制(也就是在…...

在C#中使用互斥量解决多线程访问共享资源的冲突问题
在阿里云上对互斥量的概述:互斥量的获取是完全互斥的,即同一时刻,互斥量只能被一个任务获取。而信号量按照起始的计数值的配置,可以存在多个任务获取同一信号量的情况,直到计数值减为0,则后续任务无法再获取…...

JavaEE进阶第六课:SpringBoot配置文件
上篇文章介绍了SpringBoot的创建和使用,这篇文章我们将会介绍SpringBoot配置文件 目录1.配置文件的作用2.配置文件的格式2.1 .properties语法2.1.1.properties的缺点2.2 .yml语法2.2.1优点分析2.2.2配置与读取对象2.2.3配置与读取集合2.2.4补充说明3.设置不同环境的…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...

MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...