首先说明,本次的Quorum部署是在一台Ubuntu服务器上的,实际生产环境建议一个节点一台服务器。一台服务器上部署多个节点的流程跟多个服务器部署多个节点的流程其实是一样的。
并且,经过我的亲身测试,Quorum链4个节点就能够正常运行起来。
我的演示系统环境时 Ubuntu 18.04 LTS
环境要求:
golang (ubuntu建议安装方法:sudo apt install golang)
步骤1:
要部署Quorum链,首先编译源代码得到可运行的Quorum可执行文件。在github上获取源码,并编译
git clone https://github.com/jpmorganchase/quorum.git
cd quorum
make all
编译完成开始设置环境变量,指向/quorum/build/bin。
因为我是一台服务器搭建4个节点,所以我需要把不同节点的数据分开存放在不同的文件夹内,我是要把所有的数据都存在/mnt/volume_nyc1_02目录下。
mkdir node1
mkdir node2
mkdir node3
mkdir node4
步骤2:
接下来我们就可以针对每一个节点进行初始化。
geth --datadir node1 account new //这段命令是node1在创建账户
控制台会有返回信息
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase: //第一次输入密码
Repeat passphrase: //再次输入密码
Address: {bb9ef512675df6********4c259143d9e660ce2d} //创建成功返回的账户地址
步骤3:
重复刚才的命令操作,把node1分别换成node2,node3,node4,确保每个节点下都有一个可操作账户,方便后面测试操作。接下来创建一个公用的genesis.json(仅适用于 quorum 2.5.0 以前的版本,quorum 2.5.0引入了新版本的go-ethereum包,所以genesis.json文件也发生了变化,新版本genesis.json文件可以点击这个链接查看),因为是公用的, 所以我们把genesis.json放在volume_nyc1_02目录下。
{
"alloc": {
"0xbb9ef512675df6d**********59143d9e660ce2d": { //替换上node1刚刚产生的账户地址
"balance": "10000000000000000000000" //这里是设置该账户初始化余额
},
"0xf4674808becfbe***********0cfe5c154394ecc": { //替换上node2产生的账户地址
"balance": "10000000000000000000000"
},
"0x0ba0306e5fe478***************9e1e783bade": { //替换上node3......
"balance": "10000000000000000000000"
},
"0x26**************b41a99a6d19b87347992f7e2": { //替换上node4......
"balance": "10000000000000000000000"
}
},
"coinbase": "0x0000000000000000000000000000000000000000",
"config": {
"homesteadBlock": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"chainId": 10,
"eip150Block": 0,
"eip155Block": 0,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip158Block": 0,
"maxCodeSize": 35,
"maxCodeSizeChangeBlock" : 0,
"isQuorum": true
},
"difficulty": "0x0",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0xE0000000",
"mixhash": "0x00000000000000000000000000000000000000647572616c65787365646c6578",
"nonce": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x00"
}
保存文档退出。
步骤4:
接下来创建每个节点密钥的nodekey
bootnode --genkey=node1/nodekey // 创建节点1的nodekey
bootnode --genkey=node2/nodekey //节点2的nodekey
......
解析nodekey,显示节点ID,(这个节点ID很重要的)
bootnode --nodekey=node1/nodekey --writeaddress //解析节点1的nodekey
fa0a52153370170f8fb9e0bd3a324bd6f11ce4b8ef500baa8c38596d7c9bdc65629903fad30001a319c2b1603a177cc44ab4dc65b8107354e32da3985e272431 //解析出的结果,node id
bootnode --nodekey=node2/nodekey --writeaddress
.....
步骤5:
接下来就是分别对每个节点操作,首先从node1(节点1)开始
接下来的操作依旧是在我的/mnt/volume_nyc1_02目录下操作,创建static-nodes.json文件,该文件是展示链中节点连接信息
static-nodes.json文件主要存储的是节点的nodeid,ip,端口信息。如果是一台服务器搭建多个节点,ip可用127.0.0.1,如果是局域网可用本地IP(192.168.1.**)地址,如果节点在多台非局域网环境,那么就要填写公网IP
[
"enode://fa0a52153370170f8fb9e0bd3a324bd6f11ce4b8ef500baa8c38596d7c9bdc65629903fad30001a319c2b1603a177cc44ab4dc65b8107354e32da3985e272431@201.*.*.102:21001?discport=0&raftport=50001"
]
//这里的enode值就是刚刚获取的node id
//201.*.*.102:21001 是服务器地址+程序通讯端口号,因为我是一台服务器4个节点所以是21001,21002....
//raftport 是raft通讯端口号,跟上面一样,50001,50002.....
并且把当前static-nodes.json文件复制到node1目录下,是复制哦
cp static-nodes.json node1
步骤6:
节点初始化创世块
geth --datadir node1 init genesis.json
步骤7:
编写节点1启动脚本:startnode1.sh
PRIVATE_CONFIG=ignore nohup geth --datadir node1 --nodiscover --verbosity 5 --networkid 31337 --raft --raftport 50001 --rpc --rpcaddr 0.0.0.0 --rpcport 22001 --rpcapi admin,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,raft --emitcheckpoints --port 21001 >> node1.log 2>&1 &
//50001 22001 21001 就是几个对应的端口号
给startnode1.sh文件设置权限
chmod +x startnode1.sh
然后运行脚本启动节点,判断是否成功很简单,查看node1目录下是否有 geth.ipc 文件,如果有,就说明启动成功
打开geth控制台,并查看raft共识状态
geth attach node1/geth.ipc
> raft.cluster
因为当前节点是加入到链中的第一个节点,所以模式是以minter的角色存在的。至此一个基础节点部署完成了。隐私管理模块后面再部署。
接下来部署第二个节点。
步骤8:
先修改当前目录(我的目录:/mnt/volume_nyc1_02)下的static-nodes.json文件,把节点2的node id,ip,port信息添加上去
[
"enode://fa0a52153370170f8fb9e0bd3a324bd6f11ce4b8ef500baa8c38596d7c9bdc65629903fad30001a319c2b1603a177cc44ab4dc65b8107354e32da3985e272431@127.0.0.1:21001?discport=0&raftport=50001",
"enode://98e7cbbe32bf437a44bee225f33ffbe4ca6a575ce6ca26f8fa5e67af2b026030f1c9e84fa638a9d78684ed248f2b623d844eac4e11d3873e0dfe59e6b6334f23@127.0.0.1:21002?discport=0&raftport=50002"
]
然后复制到node2目录下
步骤9:
初始化节点2的创世块
geth --datadir node2 init genesis.json
步骤10:
然后打开节点1的控制台,通过控制台命令添加共识节点node2,raft.addPeer('这里直接把static-nodes中 node2的信息复制进来就行')
geth attach node1/geth.ipc
>raft.addPeer('enode://98e7cbbe32bf437a44bee225f33ffbe4ca6a575ce6ca26f8fa5e67af2b026030f1c9e84fa638a9d78684ed248f2b623d844eac4e11d3873e0dfe59e6b6334f23@127.0.0.1:21002?discport=0&raftport=50002')
执行raft.cluster命令查询节点状态,能够查到node2信息,说明添加成功,在我们输入raft.addPeer得到了一个值“2”,这个是我们节点的raft ID值,这个值很重要,在我们编辑节点2的startnode2.sh文件时这是个重要参数。
步骤11:
编写节点2启动脚本:startnode2.sh,并且给startnode.sh设置权限,然后运行该文件。这个时候上面的raft ID就用上了,startnode2.sh 中会多一个参数--raftjoinexisting 2
PRIVATE_CONFIG=ignore nohup geth --datadir node2 --nodiscover --verbosity 5 --networkid 31337 --raft --raftport 50002 --rpc --rpcaddr 0.0.0.0 --rpcport 22002 --rpcapi admin,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,raft --emitcheckpoints --raftjoinexisting 2 --port 21002 >> node2.log 2>&1 &
老规矩,查看geth.ipc是否在node2的目录下,如果有,说明运行成功
接下来的其他节点启动照着节点2的来就是了。其实就是从步骤8修改重复执行
这里只是节点启动起来了,但是隐私管理模块还没有部署,下一个文章联盟链Quorum(基于raft共识)部署流程(二)- 部署隐私模块Tessera,我会继续写Tessera隐私管理模块的部署。