本文将介绍在本地部署 EOS 的多节点私链的方案。
1. 创建三个数据文件夹 用来存储相关的数据,每个文件夹下包括创世文件 genesis.json
和配置文件 config.ini
。
1 mkdir -p eostest1 eostest2 eostest3
三个节点的 genesis.json 都相同,内容为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 vim eostest1/genesis.json { "initial_timestamp": "2018-03-01T12:00:00.000", "initial_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", "initial_configuration": { "base_per_transaction_net_usage": 100, "base_per_transaction_cpu_usage": 500, "base_per_action_cpu_usage": 1000, "base_setcode_cpu_usage": 2097152, "per_signature_cpu_usage": 100000, "per_lock_net_usage": 32, "context_free_discount_cpu_usage_num": 20, "context_free_discount_cpu_usage_den": 100, "max_transaction_cpu_usage": 10485760, "max_transaction_net_usage": 104857, "max_block_cpu_usage": 104857600, "target_block_cpu_usage_pct": 1000, "max_block_net_usage": 1048576, "target_block_net_usage_pct": 1000, "max_transaction_lifetime": 3600, "max_transaction_exec_time": 0, "max_authority_depth": 6, "max_inline_depth": 4, "max_inline_action_size": 4096, "max_generated_transaction_count": 16 }, "initial_chain_id": "0000000000000000000000000000000000000000000000000000000000000000" }
2. 启动节点 (1) 节点 1 的 config.ini 文件内容为:
1 2 3 4 5 6 7 8 9 10 11 12 13 blocks-dir = "blocks" bnet-endpoint = 0.0.0.0:4321 http-server-address = 0.0.0.0:8888 p2p-listen-endpoint = 0.0.0.0:9876 p2p-server-address = localhost:9876 allowed-connection = any signature-provider = EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV=KEY:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3 producer-name = eosio plugin = eosio::producer_plugin plugin = eosio::chain_api_plugin plugin = eosio::history_api_plugin plugin = eosio::http_plugin enable-stale-production = true
配置选项如下:
http-server-address = 0.0.0.0:8888,这里设置四个 0 代表本地可以通过 localhost 或者 127.0.0.1 调用 http 接口,同时外部可以通过本机固定 ip 访问。
p2p-listen-endpoint = 0.0.0.0:9876,p2p 网络本机监听端口,监听外部接入的 p2p 节点,这里的四个 0 的 ip 配置意义同上。
bnet-endpoint = 0.0.0.0:4321,bnet 是使用一个非常简单的算法来同步两条区块链。主要工作是两条链上的确权,共识,广播,同步区块,保持默认配置即可。
p2p-peer-address = ip:port,对端 p2p 节点地址,可以设置多个。
producer-name = eosio,配置出块的账户采用 eosio
enable-stale-production = true,意思是可以不经过确权直接出块,单节点时要配置为 true,多节点出块由于需要各方确权共识,要配置为 false。
signature-provider = EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV=KEY:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3 ,密钥对,公钥加私钥,对应 eosio 账户,这对秘钥是写死的,不可改变。
然后启动节点 (1) 并让它出块:
1 2 3 4 5 6 7 8 9 cd eostest1 nodeos --data-dir ./ --config-dir ./ info 2019-01-10T07:03:41.501 thread-0 producer_plugin.cpp:1494 produce_block ] Produced block 000019a5cf1b561c... #6565 @ 2019-01-10T07:03:41.500 signed by eosio [trxs: 0, lib: 6541, confirmed: 0] info 2019-01-10T07:03:42.006 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block d7cee8be773b4185... #6566 @ 2019-01-10T07:03:42.000 signed by eosio [trxs: 0, lib: 6553, conf: 12, latency: 6 ms] info 2019-01-10T07:03:42.502 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block 25b680065172a2af... #6567 @ 2019-01-10T07:03:42.500 signed by eosio [trxs: 0, lib: 6553, conf: 0, latency: 2 ms] info 2019-01-10T07:03:43.003 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block 1e5a1ab3b45cb800... #6568 @ 2019-01-10T07:03:43.000 signed by eosio [trxs: 0, lib: 6553, conf: 0, latency: 3 ms] info 2019-01-10T07:03:43.507 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block 3d71245b32785815... #6569 @ 2019-01-10T07:03:43.500 signed by eosio [trxs: 0, lib: 6553, conf: 0, latency: 7 ms] info 2019-01-10T07:03:44.005 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block 31df4883ad685708... #6570 @ 2019-01-10T07:03:44.000 signed by eosio [trxs: 0, lib: 6553, conf: 0, latency: 5 ms]
3. 创建账户用来启动节点 (2) 和 (3) 创建默认钱包 default
1 2 3 👍 cleos wallet create --to-console Error 3120001: Wallet already exists Try to use different wallet name.
如果创建过,进行解锁:
1 2 cleos wallet unlock password: Unlocked: default
将创建节点 1 的私钥密钥导入钱包
1 2 cleos wallet import --private-key 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3 imported private key for: EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
然后发布 eosio.bios 合约:
1 2 3 4 5 6 7 cleos set contract eosio build/contracts/eosio.bios/ Reading WASM from /wwwroot/block_chain/eos/build/contracts/eosio.bios/eosio.bios.wasm... Publishing contract... executed transaction: 9eca4b74c8608974da726a1d96f972537e9bf7359d41442b6a083c2410a65847 4352 bytes 12020 us # eosio <= eosio::setcode {"account":"eosio","vmtype":0,"vmversion":0,"code":"0061736d0100000001621260037f7e7f0060057f7e7e7e7e... # eosio <= eosio::setabi {"account":"eosio","abi":"0e656f73696f3a3a6162692f312e30050c6163636f756e745f6e616d65046e616d650f7065... warning: transaction executed locally, but may not be confirmed by the network yet ]
然后再创建 inita、initb 两个账户:
1 2 3 4 5 6 7 8 9 $ cleos create account eosio inita EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV executed transaction: c9d76cd299a701c516c46406cd9054b07b8dacfb5dd1cd682c5c8f248577f2ad 200 bytes 4800 us # eosio <= eosio::newaccount {"creator":"eosio","name":"inita","owner":{"threshold":1,"keys":[{"key":"EOS6MRyAjQq8ud7hVNYcfnVPJqc... warning: transaction executed locally, but may not be confirmed by the network yet ] $ cleos create account eosio initb EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV executed transaction: e5492b4d415345bff1bc66adf636b6854231aa78977c447c86b6953101d6f42d 200 bytes 194 us # eosio <= eosio::newaccount {"creator":"eosio","name":"initb","owner":{"threshold":1,"keys":[{"key":"EOS6MRyAjQq8ud7hVNYcfnVPJqc... warning: transaction executed locally, but may not be confirmed by the network yet ]
4. 启动节点 (2) 节点 2 的 config.ini 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 blocks-dir = "blocks" bnet-endpoint = 0.0.0.0:4321 http-server-address = 0.0.0.0:8889 p2p-listen-endpoint = 0.0.0.0:9877 p2p-server-address = localhost:9877 allowed-connection = any p2p-peer-address = localhost:9876 signature-provider = EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV=KEY:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3 producer-name = inita plugin = eosio::producer_plugin plugin = eosio::chain_api_plugin plugin = eosio::history_api_plugin plugin = eosio::http_plugin
注意修改以下几项代表了该节点的信息:
p2p-peer-address = localhost:9876 节点 (1) 的 p2p 服务地址,通过该配置项使节点 (2) 链接上节点 (1)
producer-name = inita,节点 2 的出块账户设置为 inita
enable-stale-production = false 不允许节点 2 在不经确认直接出块的功能
http-server-address = 0.0.0.0:8889 该节点的 server 端口
p2p-listen-endpoint = 0.0.0.0:9877 p2p 网络本机监听端口,监听外部接入的 p2p 节点
p2p-server-address = 0.0.0.0:9877 p2p 网络服务节点端口
启动节点 2:
1 2 cd eostest2 nodeos --data-dir ./ --config-dir ./
可以看到节点 2 连上了节点 1 并进行了同步,此时节点 2 还不能出块。
1 2 3 info 2019-01-10T07:20:22.004 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block c8ae236b27e648d3... #8533 @ 2019-01-10T07:20:22.000 signed by inita [trxs: 0, lib: 8464, conf: 0, latency: 4 ms] info 2019-01-10T07:20:22.505 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block 76331985072c44a1... #8534 @ 2019-01-10T07:20:22.500 signed by inita [trxs: 0, lib: 8464, conf: 0, latency: 5 ms] info 2019-01-10T07:20:23.003 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block 4efe78f29187c469... #8535 @ 2019-01-10T07:20:23.000 signed by inita [trxs: 0, lib: 8464, conf: 0, latency: 3 ms]
配置节点 (2) 可以出块,在节点 (1) 上执行命令:
1 2 3 4 5 $ cleos push action eosio setprods '{"schedule":[{"producer_name":"inita","block_signing_key":"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"}]}' -p eosio info 2019-01-10T07:20:52.005 thread-0 producer_plugin.cpp:1494 produce_block ] Produced block 000021919d63255e... #8593 @ 2019-01-10T07:20:52.000 signed by inita [trxs: 0, lib: 8572, confirmed: 0] info 2019-01-10T07:20:52.502 thread-0 producer_plugin.cpp:1494 produce_block ] Produced block 00002192f489e43e... #8594 @ 2019-01-10T07:20:52.500 signed by inita [trxs: 0, lib: 8572, confirmed: 0] info 2019-01-10T07:20:53.003 thread-0 producer_plugin.cpp:1494 produce_block ] Produced block 000021934874223f... #8595 @ 2019-01-10T07:20:53.000 signed by inita [trxs: 0, lib: 8572, confirmed: 0]
而节点 1 由出块者变成了同步者:
1 2 3 info 2019-01-10T07:26:55.004 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block c6c6536853f2ee5c... #9319 @ 2019-01-10T07:26:55.000 signed by initb [trxs: 0, lib: 9304, conf: 0, latency: 4 ms] info 2019-01-10T07:26:55.506 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block 8676c0cdc18d2d55... #9320 @ 2019-01-10T07:26:55.500 signed by initb [trxs: 0, lib: 9304, conf: 0, latency: 6 ms] info 2019-01-10T07:26:56.005 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block 2c795666435af362... #9321 @ 2019-01-10T07:26:56.000 signed by initb [trxs: 0, lib: 9304, conf: 0, latency: 5 ms]
5. 启动节点 (3) 节点 3 的 config.ini 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 blocks-dir = "blocks" bnet-endpoint = 0.0.0.0:4321 http-server-address = 0.0.0.0:8890 p2p-listen-endpoint = 0.0.0.0:9878 p2p-server-address = localhost:9878 allowed-connection = any p2p-peer-address = localhost:9877 signature-provider = EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV=KEY:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3 producer-name = initb plugin = eosio::producer_plugin plugin = eosio::chain_api_plugin plugin = eosio::history_api_plugin plugin = eosio::http_plugin
节点 (3) 的出块账户设置为 initb,另外要注意的是节点 (3) 的 p2p 连接节点不能设置为节点 (1),因为此时节点 (1) 已经不是生产者了。节点 (3) 的连接节点应该设置为节点 (2) 的地址 p2p-peer-address = localhost:9877
。
启动节点 3:
1 2 3 4 5 6 $ cd eostest3 $ nodeos --data-dir ./ --config-dir ./ info 2019-01-10T07:30:49.003 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block e745e7582cef727e... #9787 @ 2019-01-10T07:30:49.000 signed by inita [trxs: 0, lib: 9772, conf: 0, latency: 3 ms] info 2019-01-10T07:30:49.502 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block 9fae21e7f5376742... #9788 @ 2019-01-10T07:30:49.500 signed by inita [trxs: 0, lib: 9772, conf: 0, latency: 2 ms] info 2019-01-10T07:30:50.007 thread-0 producer_plugin.cpp:341 on_incoming_block ] Received block 0e4320dbc2ac5f73... #9789 @ 2019-01-10T07:30:50.000 signed by inita [trxs: 0, lib: 9772, conf: 0, latency: 7 ms]
为了让节点 3 成为出块者,需要执行命令:
1 2 3 4 5 $ cleos push action eosio setprods '{"schedule":[{"producer_name":"inita","block_signing_key":"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"},{"producer_name":"initb","block_signing_key":"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"}]}' -p eosio info 2019-01-10T07:34:42.501 thread-0 producer_plugin.cpp:1494 produce_block ] Produced block 0000280e93eaf396... #10254 @ 2019-01-10T07:34:42.500 signed by initb [trxs: 0, lib: 10240, confirmed: 0] info 2019-01-10T07:34:43.003 thread-0 producer_plugin.cpp:1494 produce_block ] Produced block 0000280f2c03ef11... #10255 @ 2019-01-10T07:34:43.000 signed by initb [trxs: 0, lib: 10240, confirmed: 0] info 2019-01-10T07:34:43.504 thread-0 producer_plugin.cpp:1494 produce_block ] Produced block 0000281013ed3c65... #10256 @ 2019-01-10T07:34:43.500 signed by initb [trxs: 0, lib: 10240, confirmed: 0]
可以看到此时节点 1 和节点 2 交替出块了,每个节点在轮到它出块时连续生产了 12 个块。