Sub Dev 分享 | Substrate Based区块链上线实战经验

《从0到1学会Substrate区块链应用开发》是由Parity 和一块+ 联合出品的全球首个Parity 官方合作课程。

 

每周日晚8点,作为课程内容知识拓展——助教技术分享会,由各位第一期的助教们自发轮流在线上进行分享,为学员们详细解读一个 Substrate 技术相关内容。

 

 

上周日晚,由RIODEFI INC.   CTO ——程剑宇在直播间为大家带来第一讲「基于Substrate的常见运维操作」,内容复盘如下。

 

当我们使用Substrate开发区块链时,从开发到生产环境上线一条区块链,中间会有哪些额外的步骤和实际的需要注意的地方(坑)?

 

基于我自己过去一段时间的研究和RioChain Beta(https://www.riochain.io/,由RioDefi开发的Substrate Based区块链)上线两个月以来实际的运维经验,为大家分享一些我们所积累的实际操作经验。

 

 

.01

多节点配置

 

线上环境的多节点配置上是大家非常关心的内容,一般开发的时候,根据教程我们会使用--dev来运行一条开发环境的区块链,或者根据--chain local来运行一条本地测试网络。

 

配置 Chain spec

这两条都是内置的测试网络,实际是在chain spec中配置的。需要注意的是,这两条都是仅能用于测试的网络,到生产环境的话,需要增加自己的网络。这就需要修改对应的chain spec的代码了。

 

chain spec是Substrate的区块链初始配置,类似于其他区块链的genesis。具体的实现一般放在chain_spec.rs中,具体的位置根据节点的目录结构而有所不同,在node template下是在node/src/chain_spec.rs中。

 

最核心的原因,是因为dev 和 local testnet 使用的出块密钥都是well-known keys,也就是一些约定俗成的密钥,像是Alice,Bob。而在生产环境,我们需要添加网络将其修改为我们自己私底下生成的节点的密钥,并且只将公钥放到上面。

 

观察chain_spec.rs文件,我们可以找到 dev 网络的出块节点配置,一般来说是像下面这个样子

testnet_genesis(  // initial_authorities  vec![   authority_keys_from_seed("Alice"),  ],  // root_key  get_account_id_from_seed::<sr25519::Public>("Alice"),  // endowed_accounts  vec![   get_account_id_from_seed::<sr25519::Public>("Alice"),   get_account_id_from_seed::<sr25519::Public>("Bob"),   get_account_id_from_seed::<sr25519::Public>("Alice//stash"),   get_account_id_from_seed::<sr25519::Public>("Bob//stash"),  ],  true, )

 

 

其中,testnet_genesis的第一个参数就是初始的出块节点,第二个参数是root key,第三个参数是初始的活跃账户,第四个参数这里不需要管。

 

其中有两个方法值得注意,第一个是其中authority_keys_from_seed,第二个是get_account_id_from_seed,这两个函数都是从seed生成对应所需要的公钥的函数。其中authority_keys_from_seed稍微复杂一点,由多组密钥组成。

 

修改过后的配置文件,应该是类似于下面这个样子。

beta_genesis(    // initial_authorities    vec![(        // 5FBod7BC86ahPWt6U1sxqEozt1MF8m48soYEJkvWTLkAQBje        hex!["8a1ed431fa78b83f195e228c47777cc4661916fd8b1571ac4e9801ae56560952"].unchecked_into(),        // 5FR2ttJ17Nn7KivDHMJsU7fadgSmCHgHvnZ3F9hqv3K6eygH        hex!["9435b260b98343ac8f42cdb0047e54d6c7229b3d6d24667bdf48a9a4e2f83aae"].unchecked_into(),    ), (        // 5FEyMs3XyiUq87iC7RVB1gUX1vBhpL2n6UdaCsm6RyuJsVBn        hex!["8c8957e6c33e1faef273f27283c0d2567f776d1fa487f8c310e7d88305f03b27"].unchecked_into(),        // 5DDw6Z8ZgFWYU2rpVqkSLjP8GPRR7K8vSqXWKohMF7EyKLoa        hex!["3346028b09c81cadd77853fc363f23a9dcdfe20132229a3298073f7c5c3fa45b"].unchecked_into(),    )],    // root_key    hex!["20cd1afa4f95b59b7f61a97360e8bc74a26a6fc13712e6f2eef3a1e020bbcd68"].into(), // 5CoiKRg4hQopwaHxvjdk7C2Gq1pbdvJhsLiYrVHAcsHNkV8m    // endowed_accounts    vec![        // 5Ca8HLb1EkJgsDMSpifh33rprTCn9m1DpRkjXNTe7czU1UA5        hex!["167056fa07ae7bc1d36da5520dd8c4c06cb5a5db557986f0c6ae2af0030d4c44"].into(),        // 5G9xD8Bn32KALTZWafYP97e9TwnnzqacwUgSNdLB8mvbvRt1        hex!["b4f179ee3e5e2498eb6d59d1d899bcb0157a917f9cfd8523101e4f78c8a52050"].into()    ],    true,)

 

请注意,这里将authority_keys_from_seed变成了由两组密钥组成的元组,原因是因为本身authority_keys_from_seed就是根据session keys的格式组装出来的,有可能由2个key组成,也有可能由其他数量的key组成,具体需要参照runtime中session keys的定义。

 

在这里,session keys是由aura和grandpa的密钥组成,分别由sr25519 和 ed25519进行加密。因此在上面的一个元组中,第一个元素为AuraId的公钥,第二个元素为grandpa的公钥。

 

一般我们可以通过subkey或者polkadot.js或者更安全的工具来生成Substrate相关的密钥,根据需求需要提前生成sr25519或者ed25519的密钥。

 

在上述代码中,还使用了hex!这个宏将相应代码转化为十六进制的格式,因此我们需要注意去掉所生成密钥的公钥开头的0x。hex!引用自hex_literal,所以还需要在文件最上方加上

use hex_literal::hex;

 

并且添加相关的Cargo依赖。这样,我们就为一个网络添加了指定的出块节点的密钥。

 

接下来要做的一件事情,就是将节点密钥与运行中的节点进行绑定了,这样链上才知道当前正在运行的节点,是什么样的身份。而在做到这一点之前,我们需要了解一个概念- Session Keys

 

Seesion Keys

简单来说,Session Keys 用于验证节点签名共识相关的消息。Session Keys 由多个Key组成,具体定义在runtime中可以看到。不同类型的Key可能由不同的算法实现,比如sr25519 或 ed25519。为了安全,Session Keys记得进行定时更换。

 

一般生成Session Keys有两种方式:

  • 从节点RPC接口去插入对应的keys

  • 从节点RPC接口生成Session Keys

 

前者的做法,适用于需要指定相关的密钥的区块,一般是搭建初始的出块节点或提前生成好相关的密钥的区块。后者的情况,则更适用与转入POS后搭建新的节点的区块,因为还需要额外发起一个链上交易,来绑定节点的密钥。

 

前者的实现主要是调用RPC接口中的author_rotateKeys,其可参考的cURL代码如下:

curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "method":"author_rotateKeys", "id":1 }' http://localhost:9933

 

调用完成后,系统会返回一串json,其中包含的就是Session Keys。

 

前者的实现主要是调用RPC接口中的author_insertKey的方法,,后者的可参考cURL实现如下:

curl http://localhost:9933 -H "Content-Type:application/json;charset=utf-8" -d \'{"jsonrpc":"2.0","id":1, "method":"author_insertKey", "params": [      "<aura/gran>",      "<mnemonic phrase>",      "<public key>"] }'

 

在做完该项绑定后,应该正常区块下会开始出块。

 

Node key

大家运行node-template --help的话,一般会出现一条关于node-key的信息。libp2p是由ipfs主导开发的一个p2p的网络模块,这里的Node key,主要是p2plib在直接使用。

 

一般需要注意的是,种子节点需要指定固定的Node key,以防止identity发生变化,导致外部无法连接。

 

 

.02

出块节点和数据同步节点

 

这里给出一个参照的运行命令。需要注意的主要有,--pool-limit是交易池的大小,可以适当调整大。--ws-max-connections是提升websocket的可连接数。

 

出块节点的参考命令

node-template —-chain local --node-key b6800b71239ae4a7b1792f3f19239eb65229b6277d2453a2890639cc91e499f2 --name substrate-n1--base-path /home/node/data/--pruning=archive --validator--telemetry-url ws://172.31.200.11:8000/submit--pool-limit 10000—execution=NativeElseWasm

 

 

数据同步节点的参照命令

node-template —-chain local--name substrate-data-node-0--port 30333--node-key 7cec6023c2e8e7d70354d413b4361634dbb87eecec0b05bd114a6bdc669c23bd --base-path /home/node/data/--rpc-external--ws-external--rpc-cors=all--pruning=archive--bootnodes /ip4/172.31.200.5/tcp/30333/p2p/QmYgcaAUKXAnX9CpyEDWaVbjWmhZVwzTCA7D22fNb6aV8t -- telemetry-url ws://172.31.200.11:8000/submit--ws-max-connections 2048 --pool-limit 10000

 

使用pm2来运行节点

pm2 --name n1 start -x ‘./bin/node-template' -- --chain local --node-key b6800b71239ae4a7b1792f3f19239eb65229b6277d2453a2890639cc91e499f2 --name substrate-n1--base-path /home/node/data/--pruning=archive --validator--telemetry-url ws://172.31.200.11:8000/submit --pool-limit 10000—execution=NativeElseWasm

 

使用systemd来运行节点

可参照官网的教程

https://wiki.polkadot.network/docs/en/maintain-guides-how-to-systemd

 

负载优化

RPC比WebSocket更方便实际的缓存与优化,在海量用户访问中尤其明显。但在Polkadot Js中,对RPC的支持不够完善,因此我们想了一个相对hack的方式,自己组装Storage Key来调用相关的接口。具体代码请参照

https://github.com/RioDefi/rpc_example/blob/master/index.js

 

 

.03

链上升级

 

在这里,为大家提供一个可参考的链上升级流程。

1、请先确保在staging环境测试升级

2、修改runtime module业务代码

3、修改runtime/lib.rs中的version,这个主要是一个参考的作用,

4、执行cargo build --release

5、输出的wasm默认在:

./target/release/wbuild/node-template-runtime/node- template_runtime.compact.wasm

6、打开polkadot ui中通过sudo,打开system模块的setCode方法,上传刚才编译的wasm文件,提交交易 交易打包执行成功后,应该可以观察到version已经更新到相应的版本。

 

需要注意的是,链上升级时注意不要修改到Chain Spec,否则可能会影响genesis hash,造成节点间无法互联。

 

但我觉得区块链运维,最终还是要对整体区块链有足够了解,才能在关键时候作出正确的选择。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值