当前位置: 首页 > news >正文

Substrate 基础教程(Tutorials) -- 模拟网络 添加可信节点

三、模拟网络

本教程基本介绍了如何使用一个私有验证器(validators)的授权集合来启动私有区块链网络。

Substrate节点模板使用授权共识模型(authority consensus model),该模型将块生产限制为授权帐户的旋转列表(rotating list)。授权帐户(authorities,授权机构)负责以循环方式创建块。

在本教程中,您将通过使用两个预定义的帐户作为允许节点生成块的权限,了解权限共识模型在实践中是如何工作的。在这个模拟网络中,两个节点使用不同的帐户和密钥启动,但运行在一台计算机上。

3.1 教程的目标

通过完成本教程,您将实现以下目标:

  • 使用预定义帐户启动区块链节点。
  • 了解用于启动节点的关键命令行选项。
  • 确定一个节点是否正在运行并生成块。
  • 将第二个节点连接到运行中的网络。
  • 验证对等计算机生成和完成块。

3.2 启动第一个区块链节点

在生成密钥以启动自己的专用Substrate网络之前,可以使用称为local的预定义网络规范学习基本原理,该规范在预定义用户帐户下运行。

本教程通过在一台本地计算机上使用命名为alicebob的预定义帐户运行两个Substrate节点来模拟专用网络。

启动区块链:

  1. 在计算机上打开一个终端。
  2. 切换到编译Substrate节点模板的根目录。
  3. 运行命令如下:清除旧链数据。
./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]:
  1. 输入y以确认要删除链数据。
    当你开始一个新的网络时,你应该总是删除旧的链数据。

  2. 以“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

在这里插入图片描述

检查命令行选项

在继续之前,看看如何使用以下选项启动节点。

OptionOption
–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-urlSpecifies 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托管的任何人都可以使用的服务器。
–validatorSpecifies 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帐户将另一个节点添加到网络中。因为您正在加入一个已经在运行的网络,所以您可以使用正在运行的节点来标识新节点要加入的网络。这些命令与您以前使用的命令类似,但有一些重要的区别。

向运行中的区块链添加节点:

  1. 在计算机上打开一个新的终端。
  2. 切换到编译Substrate节点模板的根目录。
  3. 使用实例清除旧链数据。
./target/release/node-template purge-chain --base-path /tmp/bob --chain local -y
  1. 以“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 验证块的生产和最终确定

启动第二个节点后,这些节点应该作为对等点相互连接,并开始生成块。

  1. 验证块正在完成:
    验证您在启动第一个节点的终端中看到类似于下面的行:
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)
  1. 验证在启动第二个节点的终端中是否看到类似的输出。
  2. 在终端shell中按Control-c关闭其中一个节点。
  3. 关闭节点后,您将看到剩下的节点现在没有对等点,并且已经停止生成块。例如:
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   
  1. 在终端shell中按Control-c关闭第二个节点。
    如果您想从模拟网络中删除链状态,可以在/tmp/bob/tmp/alice目录中使用带有--base-path命令行选项的purge-chain子命令。

四、添加可信节点

本教程演示如何使用一个私有验证器(validator)的 授权集启动一个小型的独立区块链网络。

正如你在区块链基础知识中所学到的,所有区块链都要求网络中的节点在任何特定的时间点对数据的状态达成一致,这种关于状态的一致被称为共识(consensus)。

Substrate节点模板使用授权证明共识模型(proof of authority consensus model),也称为authority roundAura共识。Aura共识协议将区块生产限制为授权帐户的轮询列表。授权帐户(authorities)以轮询方式创建块,通常被认为是网络中可信的参与者。

这个共识模型为有限数量的参与者提供了一个简单的方法来启动一个单独的区块链。在本教程中,您将了解如何生成授权节点参与网络所需的密钥,如何配置网络并与其他授权帐户共享有关网络的信息,以及如何使用一组经过批准的验证器启动网络。

4.1 教程的目标

通过完成本教程,您将实现以下目标:

  • 生成密钥对以作为网络授权使用。
  • 创建一个自定义链规范文件。
  • 启动私有双节点区块链网络。

4.2 生成您的帐户和密钥

在模拟网络中,使用预定义的帐户和密钥启动对等节点。对于本教程,您将为网络中的验证器节点生成自己的密钥。重要的是要记住,区块链网络中的每个参与者都负责生成唯一密钥

key 生成选项

有几种生成密钥的方法。例如,您可以使用node-template子命令、独立subkey命令行程序、Polkadot-JS应用程序或第三方密钥生成实用程序生成密钥对。

虽然您可以使用预定义的键对来完成本教程,但您绝不会在生产环境中使用这些键。本教程没有使用预定义的密钥或更安全的subkey 程序,而是说明如何使用Substrate节点模板和key子命令生成密钥。

使用节点模板生成本地密钥

作为最佳实践,在为生产区块链(production blockchain)生成密钥时,应该使用从未连接到internet的air-gapped计算机。至少,在生成任何密钥用于不受您控制的公共或私有区块链之前,您应该断开与互联网的连接。

但是,对于本教程,您可以使用node-template命令行选项在本地生成随机键,同时保持与互联网的连接。

  1. 运行如下命令生成一个随机的秘密短语和密钥:
./target/release/node-template key generate --scheme Sr25519 --password-interactive

在这里插入图片描述

你现在有了Sr25519 key,可以在一个节点上使用aura生成区块。在此例中,帐号的Sr25519公钥为5Esh9DFdgPTsoBYNWCBRy5z91WkPhE35yskGivwvapqi2DNd

  1. 对刚刚生成的帐户使用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"
  1. 输入用于生成密钥的密码。
[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 链规范,而不是编写一个全新的链规范。

基于本地规范创建一个新的链规范:

  1. 将本地链规范导出到名为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,您可以预览第一行和最后几行,以查看需要更改的字段。

  1. 预览customSpec.json中的前几个字段。执行以下命令:
head customSpec.json

在这里插入图片描述
3. 预览customSpec.json中的最后几行:

tail -n 80 customSpec.json

该命令显示Wasm二进制字段后面的最后部分,包括运行时中使用的几个pallet盘(如sudobalanced托盘)的详细信息。

  1. 修改name字段,将此链规范标识为自定义链规范。
"name": "My Custom Testnet",
  1. 修改aura字段,为每个网络参与者添加Sr25519 SS58地址密钥,指定有权限创建块的节点。

  2. 修改grandpa 字段,通过为每个网络参与者添加Ed25519 SS58地址密钥,指定具有完成块的权限的节点。

"aura": {"authorities": ["5Esh9DFdgPTsoBYNWCBRy5z91WkPhE35yskGivwvapqi2DNd","5CD3iN6qxUUvay2hVMBSgTJAXHXZgFPJU4i3jkNVBMAqUB24"]},"grandpa": {"authorities": [["5C8yh9u4rwY3VrQW6pDdScnP6WTx7xJfQSn53K44Uw1ShCuw",1],["5CeRPE4xNPqrUCRChmSGG2KZ4jDcVsBdj64BRfeVeC3xa4FS",1]]},

请注意,grandpa 部分中的authorities 字段有两个数据值。第一个值是地址key。第二个值用于支持加权投票(weighted votes)。在本例中,每个验证器的权重为1票。

  1. 添加验证器
    正如您刚才看到的,您可以通过修改auragrandpa部分来添加和更改链规范中的授权地址(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子命令插入本地生成的密钥。

  1. 执行如下命令插入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"
  1. 还可以从指定的文件位置插入密钥。查看可用的命令行选项信息,执行以下命令:
./target/release/node-template key insert --help
  1. 输入用于生成密钥的密码。
  2. 执行如下命令插入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>同上

  1. 通过运行以下命令,验证您的密钥位于node01的密钥存储库中:
ls /tmp/node01/chains/local_testnet/keystore

在这里插入图片描述

4.9 允许其他与会者加入

现在可以使用--bootnodes-validator命令行选项允许其他验证器加入网络。

向私有网络添加第二个验证器:

  1. 以如下命令启动第二个区块链节点:
./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-pathnamevalidator命令行选项将该节点标识为私有网络的第二个验证器。--chain命令行选项指定要使用的链规范文件。该文件对于网络中的所有验证器必须相同。确保为--bootnodes命令行选项设置了正确的信息。特别是,确保您已经从网络中的第一个节点指定了本地节点标识符。如果你没有设置正确的引导节点标识符,你会看到这样的错误:

The bootnode you want to connect to at ... provided a different peer ID than the one you expect: ...
  1. 执行如下命令添加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密钥类型是启用块生产所必需的。

  1. 运行如下命令,将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 )需要至少三分之二的验证器将它们的密钥添加到各自的密钥存储库中。因为这个网络在链规范中配置了两个验证器,所以区块终结只能在第二个节点添加了它的密钥之后开始。

  1. 通过运行以下命令,验证您的密钥位于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) -- 模拟网络 添加可信节点

三、模拟网络 本教程基本介绍了如何使用一个私有验证器&#xff08;validators&#xff09;的授权集合来启动私有区块链网络。 Substrate节点模板使用授权共识模型(authority consensus model)&#xff0c;该模型将块生产限制为授权帐户的旋转列表(rotating list)。授权帐户(…...

SAP 设置无物料号的费用采购

现在还是以外购电来说一下ERP中费用采购单的使用步骤&#xff1a; (1).Tcode:OMSF定义物料组D1,如下图。 (2).到配置路径IMG Path:物料管理->采购->帐户分配(或直接SE16:V_T163K)定义一科目分配类别,默认的K就是费用采购科目分配类型,如果可能可以复制一个,如下图,注意下…...

k8s ConfigMap 中 subPath 字段和 items 字段

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

UML建模

主要记录UML中的相关知识&#xff0c;包括类、对象、接口、方法、用例、活动、状态、组件和部署图&#xff0c;详细介绍类之间关系与类图的绘制 文章目录一、UML介绍二、类图类之间的关系依赖关系继承关系实现关系关联关系组合关系聚合关系正文内容&#xff1a; 一、UML介绍 …...

JavaScript常见面试题(更新中)

介绍js的基本数据类型 js一共有五种数据类型 分别是undefined null boolean number string 还有ES6中新增的symbol和ES10的bigInt symbol代表创建后独一无二的不可变的数据类型&#xff0c;他的出现我认为是为了解决可能出现的全局变量冲突的问题 BigInt是一种数字类型的数据 …...

TCP/IP协议

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

Python使用异步线程池实现异步TCP服务器交互

背景&#xff1a; 实现客户端与服务端交互&#xff0c;由于效率原因&#xff0c;要发送与接收异步&#xff0c;提高效率。 需要多线程&#xff0c;本文用线程池管理。 common代码&#xff1a; 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中缺失的数字三、旋转数组的最小数字四、二维数组中的查找一、在排序数组中查找数字 题目传送门 法一&#xff1a;暴力解 直接遍历然后计数 法二&#xff1a;二分法求边界 看到关键字排序数组、有序数组&#xff0c;一定要想到二分…...

Vue+ElementUI+SpringBoot项目配合分页插件快速实现分页(简单暴力)

首先需要在项目中引入Element-UI的组件库&#xff0c;使用以下命令&#xff0c;不会引入的请自行百度。 npm i element-ui -S Element官网地址&#xff1a;https://element.eleme.cn/#/zh-CN/component/changelog 去Element-UI官网组件库找到合适的分页插件&#xff0c;并把他引…...

【回眸】牛客网刷刷刷!嵌入式软件中也会遇到的嵌入式硬件,通讯,通讯协议专题(一)

前言 最近继续刷题&#xff0c;看看嵌入式软件还需要了解一些嵌入式硬件中的通讯协议和常用接口协议 比如说SPI CAN I2C 通讯协议专题 1.波特率 波特率 每秒传送的字符数 * 字符位数。串口的工作模式为1个起始位&#xff0c;7个数据位&#xff0c;1个校验位&#xff0c;1个…...

使用Vue展示数据(动态查询)

学习内容来源&#xff1a;视频P4 本篇文章进度接着之前的文章进行续写 精简前后端分离项目搭建 Vue基础容器使用 目录选择组件修改表格组件修改分页组件增加后端接口前端请求数据接口页面初始化请求数据点击页码请求数据选择组件 在官方文档中选择现成的组件&#xff0c;放在页…...

构建数据库测试数据——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的启动优化&#xff1f;网页端存在的一个定律叫8秒定律&#xff1a;即指用户访问一个网站时&#xff0c;如果等待打开的时间超过8秒&#xff0c;超过70%的用户将会放弃等待。同样的&#xff0c;移动端也有一个8秒定律&#xff1a;如果一个App的启动时间…...

python3的基础入门3:基本数据类型

基本数据类型 python 中的变量不需要声明。每个变量在使用前都必须赋值&#xff0c;变量赋值以后该变量才会被创建。 在 Python 中&#xff0c;变量就是变量&#xff0c;它没有类型&#xff0c;我们所说的"类型"是变量所指的内存中对象的类型。 等号&#xff08;&…...

消息队列原理与实战-学习笔记

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

Linux权限相关知识(大量图文展示,及详细操作)

Linux权限相关概念 Linux下有两种用户&#xff1a;一种是超级用户&#xff08;root&#xff09;、一种是普通用户。 超级用户&#xff1a;可以在linux系统下做任何事情&#xff0c;不受限制 普通用户&#xff1a;在linux下做有限的事情。 超级用户的命令提示符是“#”&#xf…...

Ep_操作系统面试题-什么是协程

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

在C#中使用互斥量解决多线程访问共享资源的冲突问题

在阿里云上对互斥量的概述&#xff1a;互斥量的获取是完全互斥的&#xff0c;即同一时刻&#xff0c;互斥量只能被一个任务获取。而信号量按照起始的计数值的配置&#xff0c;可以存在多个任务获取同一信号量的情况&#xff0c;直到计数值减为0&#xff0c;则后续任务无法再获取…...

JavaEE进阶第六课:SpringBoot配置文件

上篇文章介绍了SpringBoot的创建和使用&#xff0c;这篇文章我们将会介绍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.设置不同环境的…...

MySQL基础(一)SQL分类、导入、SELECT语句,运算符

目录 MySQL安装以及相关工具 SQL分类 导入数据 最基本的SELECT语句 SELECT FROM 列的别名 去除重复行 着重号 查询常数 描述表结构 过滤数据&#xff08;重要&#xff09; 运算符 算数运算符 比较运算符 符号运算符 非符号运算符 逻辑运算符 位运算符 MySQL安…...

反激与正激的区别

之前学习了正激开关电源&#xff0c;但是对于正激和反激一直不是很清楚&#xff0c;网上找了一篇&#xff0c;觉得感觉该可以&#xff0c;以此记录。正激和反激是两种不同的开关电源技术一、正激&#xff08;1&#xff09;概述正激式开关电源是指使用正激高频变压器隔离耦合能量…...

王道操作系统课代表 - 考研计算机 第四章 文件管理 究极精华总结笔记

本篇博客是考研期间学习王道课程 传送门 的笔记&#xff0c;以及一整年里对 操作系统 知识点的理解的总结。希望对新一届的计算机考研人提供帮助&#xff01;&#xff01;&#xff01; 关于对 “文件管理” 章节知识点总结的十分全面&#xff0c;涵括了《操作系统》课程里的全部…...

前端开发规范,你真的了解吗?一起来学习一下前端开发规范,让你的代码高级起来!

代码规范 1 编码风格规范 1.1 使用ES6风格编码源码 定义变量使用let ,定义常量使用const 使用export &#xff0c;import 模块化 1.2 组件 props 原子化 提供默认值 使用 type 属性校验类型 使用 props 之前先检查该 prop 是否存在 1.3 避免 this.$parent 1.4 谨慎使用 …...

Licode—基于webrtc的SFU/MCU实现

1. webrtc浅析webrtc的前世今生、编译方法、行业应用、最佳实践等技术与产业类的文章在网上卷帙浩繁&#xff0c;重复的内容我不再赘述。对我来讲&#xff0c;webrtc的概念可以有三个角度去解释&#xff1a;&#xff08;1&#xff09;.一个W3C和IETF制定的标准&#xff0c;约定…...

开发运维工具推荐 --- 解决远程访问局域网服务的问题。开发调试推荐

一、FastNat 可为您解决的问题1. 没公网服务器&#xff0c;需要发布本地的站点或网络程序到公网上&#xff0c;供他人访问&#xff1b;此项功能大大方面开发人员进行远程调试&#xff0c;微信小程序等开发工作进行。2. 需要远程到在其他网络中的设备&#xff0c;但两处的网络不…...

【华为OD机试 】单词倒序(C++ Java JS Python)

文章目录 题目描述输入描述输出描述备注用例题目解析C++ 解法JavaScript算法源码Java算法源码Python解法题目描述 输入单行英文句子,里面包含英文字母,空格以及,.?三种标点符号,请将句子内每个单词进行倒序,并输出倒序后的语句。 输入描述 输入字符串S,S的长度 1 ≤ N…...

PLC 诊断故障的基本原理

(1)东欢坨选煤厂机电设备故障信号主要取自开关量信号,PLC 通过开关量的通和断对设备进行故障诊断。PLC 对开关量的识别是通过输入模块来实现的。PLC 控制设备运行时,设备中的温度、压力、急停、跑偏、速度、过热以及各种按钮和行程开关的传感器与 PLC 输入模块相连接,输入模块的…...

QT打开外部程序并嵌入Qt子窗口的缺点

首先可以参考如下文章&#xff1a; QT打开外部程序并嵌入Qt界面_qt界面嵌入外部应用程序_初学小白Lu的博客-CSDN博客 Qt嵌入外部程序界面初探_qt嵌入其他程序窗口_liming4675的博客-CSDN博客 QT 如何把外部程序嵌入到QT界面_qt嵌入其他程序窗口_hellokandy的博客-CSDN博客 Qt界…...

如何系统地学习 C++ 语言?

C作为具有广泛适用性的编程语言&#xff0c;学习C的人越来越多&#xff0c;但是如何系统地学习C还是个问题&#xff0c;下面我们一起来看一下C学习的方法有哪些吧。 首先&#xff0c;要学习C&#xff0c;最重要的就是掌握C的基础知识。 比如数据结构、算法、微积分等。这些都是…...

英国T4学生签证 可以做网站吗/个人优秀网页设计

树莓派zero系统里不知道为什么没有pip3 手动安装很麻烦 运行以下指令 可以快速完成安装 sudo apt-get install python3-pip...

wordpress恢复小工具/seo关键词排名优化教程

Python模块化编程 包 模块 模块是一个包含所有你定义的函数和变量的文件&#xff0c;其后缀为.py&#xff08;就如我们编写的程序就是一个模块&#xff09;&#xff0c;可被其他程序引入。以使用该模块的函数等功能 模块分为三种&#xff1a; 1.内置模块&#xff1a;sys,os,sub…...

公司网站建设工作重点/提高网站搜索排名

问题描述 今天在设计python串口代码时遇见一个问题&#xff0c;接收到的数据打印出来&#xff0c;一直都是两三组连在一起&#xff0c;即我的目标数据是&#xff1a; 7e307d02087d01557e 但是我把接收到的数据经过处理打印出来后是&#xff1a;7e307d02087d01557e7e307d02087d…...

宁波建设银行网站分部/培训学校加盟费用

哪里有macOS常用的压缩解压软件&#xff1f;小编今天为大家推荐的是解压专家 mac版下载&#xff0c;解压专家mac中文版是一个小巧易用的程序&#xff0c;可以压缩或解压许多不同类型的压缩文件。使用FileZip&#xff0c;您可以根据需要压缩任意数量的文件。您也可以使用密码保护…...

做系统之前的网站收藏在哪/360优化大师官方最新

package org.rui.pattern;import junit.framework.*;/*** 为了使同一个方法调用能够产生不同的行为&#xff0c;State 模式在代理&#xff08;surrogate&#xff09;的* 生命周期内切换它所相应的实现&#xff08;implementation&#xff09;。当你发现&#xff0c;在决定怎样实…...

上海专业网站建设哪家好/seo计费系统

Python2的字符串有两种&#xff1a;str 和 unicode&#xff1b;Python3的字符串也有两种&#xff1a;str 和 bytes。bytes可以是任何二进制数据&#xff0c;文本/图片/视频/音频等等。str就是文本。str与bytes互转b b"example" # bytes objects "example"…...