Quorum是一种基于以太坊的分布式分类账协议,具有交易/合同隐私和新的共识机制。
Quorum是go-ethereum的一个分支,并根据go-ethereum发布进行更新。
go-ethereum的关键改进:
- 隐私 - 仲裁通过公共/私有分离和利用Constellation支持私人交易和私人合同,Constellation是一种点对点加密消息交换,用于将私人数据定向传输给网络参与者
- 替代共识机制 - 在许可网络中不需要POW / POS,Quorum提供了多种更适合联盟链的共识机制:
- 基于Raft的共识 - 一种更快的阻塞时间,事务完成性和按需块创建的共识模型
- Istanbul BFT - 由AMIS提供的具有交易终结性的PBFT启发的一致性算法。
- 对等权限 - 使用智能合约进行节点/对等权限,确保只有已知方才能加入网络
- 更高的性能 - Quorum提供比公共geth更高的性能
1. 首先,从github上下载Quorum
git clone https://github.com/jpmorganchase/quorum.git
下载成功后进入quorum文件夹在进行编译
make all
编译完成后会在bulid/bin文件下发现abigen bootnode evm examples faucet geth p2psim puppeth rlpdump swarm wnode几个可执行文件 将它们添加到环境变量中即可 如export PATH=xxx/xxx/xxx/abigen:$PATH
注意:如果电脑中已经安装了geth 再将上面的geth加入环境变量的话会出现冲突 可以改改名称(如geth1)或者把文件拷到需要运行的目录,然后把geth改成./geth就行了
2. 下载constellation-node
wget https://github.com/jpmorganchase/constellation/releases/download/v0.3.1/constellation-0.3.1-ubuntu1604.tar.xz
我这里用的是0.3.1,版本不同可能会有一些不一样的地方,建议用我这个版本(用0.3.2之后的话不适用于本教程)
3. 下载用例教程
这是官方提供的样例,部署七个节点。
git clone https://github.com/jpmorganchase/quorum-examples
4.基于raft机制搭建联盟链
(1)首先进行初始化,可以找到raft-init.sh这个脚本
#!/bin/bash
set -u
set -e
echo "[*] Cleaning up temporary data directories"
rm -rf qdata
mkdir -p qdata/logs
echo "[*] Configuring node 1 (permissioned)"
mkdir -p qdata/dd1/{keystore,geth}
cp permissioned-nodes.json qdata/dd1/static-nodes.json
cp permissioned-nodes.json qdata/dd1/
cp keys/key1 qdata/dd1/keystore
cp raft/nodekey1 qdata/dd1/geth/nodekey
geth --datadir qdata/dd1 init genesis.json
echo "[*] Configuring node 2 (permissioned)"
mkdir -p qdata/dd2/{keystore,geth}
cp permissioned-nodes.json qdata/dd2/static-nodes.json
cp permissioned-nodes.json qdata/dd2/
cp keys/key2 qdata/dd2/keystore
cp raft/nodekey2 qdata/dd2/geth/nodekey
geth --datadir qdata/dd2 init genesis.json
echo "[*] Configuring node 3 (permissioned)"
mkdir -p qdata/dd3/{keystore,geth}
cp permissioned-nodes.json qdata/dd3/static-nodes.json
cp permissioned-nodes.json qdata/dd3/
cp keys/key6 qdata/dd3/keystore
cp keys/key3 qdata/dd3/keystore
cp raft/nodekey3 qdata/dd3/geth/nodekey
geth --datadir qdata/dd3 init genesis.json
echo "[*] Configuring node 4 (permissioned)"
mkdir -p qdata/dd4/{keystore,geth}
cp permissioned-nodes.json qdata/dd4/static-nodes.json
cp permissioned-nodes.json qdata/dd4/
cp keys/key4 qdata/dd4/keystore
cp raft/nodekey4 qdata/dd4/geth/nodekey
geth --datadir qdata/dd4 init genesis.json
echo "[*] Configuring node 5"
mkdir -p qdata/dd5/{keystore,geth}
cp permissioned-nodes.json qdata/dd5/static-nodes.json
cp keys/key5 qdata/dd5/keystore
cp raft/nodekey5 qdata/dd5/geth/nodekey
geth --datadir qdata/dd5 init genesis.json
echo "[*] Configuring node 6"
mkdir -p qdata/dd6/{keystore,geth}
cp permissioned-nodes.json qdata/dd6/static-nodes.json
cp raft/nodekey6 qdata/dd6/geth/nodekey
cp keys/key7 qdata/dd6/keystore
geth --datadir qdata/dd6 init genesis.json
echo "[*] Configuring node 7"
mkdir -p qdata/dd7/{keystore,geth}
cp permissioned-nodes.json qdata/dd7/static-nodes.json
cp raft/nodekey7 qdata/dd7/geth/nodekey
cp keys/key8 qdata/dd7/keystore
geth --datadir qdata/dd7 init genesis.json
这个脚本没啥坑 直接运行即可。
(2)启动联盟链,运行raft-start.sh这个脚本
#!/bin/bash
set -u
set -e
mkdir -p qdata/logs
echo "[*] Starting Constellation nodes"
./constellation-start.sh
echo "[*] Starting Ethereum nodes"
set -v
ARGS="--nodiscover --raft --rpc --rpcaddr 0.0.0.0 --rpcapi admin,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum --emitcheckpoints"
PRIVATE_CONFIG=qdata/c1/tm.ipc nohup geth --datadir qdata/dd1 $ARGS --permissioned --raftport 50401 --rpcport 22000 --port 21000 --unlock 0 --password passwords.txt 2>>qdata/logs/1.log &
PRIVATE_CONFIG=qdata/c2/tm.ipc nohup geth --datadir qdata/dd2 $ARGS --permissioned --raftport 50402 --rpcport 22001 --port 21001 --unlock 0 --password passwords.txt 2>>qdata/logs/2.log &
PRIVATE_CONFIG=qdata/c3/tm.ipc nohup geth --datadir qdata/dd3 $ARGS --permissioned --raftport 50403 --rpcport 22002 --port 21002 --unlock 0 --password passwords.txt 2>>qdata/logs/3.log &
PRIVATE_CONFIG=qdata/c4/tm.ipc nohup geth --datadir qdata/dd4 $ARGS --permissioned --raftport 50404 --rpcport 22003 --port 21003 --unlock 0 --password passwords.txt 2>>qdata/logs/4.log &
PRIVATE_CONFIG=qdata/c5/tm.ipc nohup geth --datadir qdata/dd5 $ARGS --raftport 50405 --rpcport 22004 --port 21004 --unlock 0 --password passwords.txt 2>>qdata/logs/5.log &
PRIVATE_CONFIG=qdata/c6/tm.ipc nohup geth --datadir qdata/dd6 $ARGS --raftport 50406 --rpcport 22005 --port 21005 --unlock 0 --password passwords.txt 2>>qdata/logs/6.log &
PRIVATE_CONFIG=qdata/c7/tm.ipc nohup geth --datadir qdata/dd7 $ARGS --raftport 50407 --rpcport 22006 --port 21006 --unlock 0 --password passwords.txt 2>>qdata/logs/7.log &
set +v
echo
echo "All nodes configured. See 'qdata/logs' for logs, and run e.g. 'geth attach qdata/dd1/geth.ipc' to attach to the first Geth node."
echo "To test sending a private transaction from Node 1 to Node 7, run './runscript.sh private-contract.js'"
注意到这个脚本中有constellation-start.sh这个脚本,不知道为什么我把constellation-node加入环境变量后也无法执行(可能是我电脑的原因?),如果你也遇到这个问题,就把之前下载的constellation-node拷到这个目录下,然后把下面脚本中的constellation-node改成./constellation-node就可以了。如果执行上面的raft-start.sh陷入死循环跳不出来的话,可以查看qdata/logs中的日志信息来寻找原因。正常执行成功的话是会输出最后那部分提示的(如下图)
constellation-start.sh:
#!/bin/bash
set -u
set -e
for i in {1..7}
do
DDIR="qdata/c$i"
mkdir -p $DDIR
mkdir -p qdata/logs
cp "keys/tm$i.pub" "$DDIR/tm.pub"
cp "keys/tm$i.key" "$DDIR/tm.key"
rm -f "$DDIR/tm.ipc"
CMD="constellation-node --url=https://127.0.0.$i:900$i/ --port=900$i --workdir=$DDIR --socket=tm.ipc --publickeys=tm.pub --privatekeys=tm.key --othernodes=https://127.0.0.1:9001/"
echo "$CMD >> qdata/logs/constellation$i.log 2>&1 &"
$CMD >> "qdata/logs/constellation$i.log" 2>&1 &
done
DOWN=true
while $DOWN; do
sleep 0.1
DOWN=false
for i in {1..7}
do
if [ ! -S "qdata/c$i/tm.ipc" ]; then
DOWN=true
fi
done
done
不出意外的话,到这里就基本上大功告成了,可以通过以下指令查看七个节点是否顺利运行,如果发现有七个进程在运行就证明已经成功了!只有一个的话就是失败了,得回去找问题。
ps -ef | grep constellation-node
ps -ef | grep geth
5.操作某个节点
geth attach qdata/dd1/geth.ipc
即可进入1号节点的控制台,基本操作跟geth是一样的,eth.accounts可以查看账号,钱包文件保存在7nodes/qdata/下的dd开头的七个文件夹中的keystore,然后再qdata/logs文件下会有1.log 到7.log ,1.log是主节点的挖矿信息,后面几个是1节点同步过去的信息,可以通过log来观察联盟链的事件。
至此,基本的七个节点就搭建起来了,下一节将结合具体项目来调用web3j!