文章目錄
-
- 環境
- 引言
- 1. 安裝docker
- 2. 安裝docker-compose
- 3. 啟動quorum網絡
- 4. 檢查網絡
- 5. 隐私交易測試
-
-
- 5.1 發送隐私交易
- 5.1 檢查quorum node
- 5.3 檢查合約狀态
- 5.3 更新合約狀态
-
- 6. 節點許可測試
-
-
- 6.1 檢視已經連接配接的節點
- 6.2 節點許可配置
- 6.3 禁用其中一個節點
-
- 7. cakeshop dashboard
- 8. 停止(關閉)quorum網絡
- 問題
- 參考
環境
- Ubuntu18.04
- Docker Engine 18.02.0
- Docker Compose 1.21+
引言
quorum examples
包含Quorum平台的安裝示例,啟動由7個獨立節點組成的功能齊全的Quorum環境,從這個例子中可以測試以太坊平台的共識、隐私和所有預期功能。
1. 安裝docker
參考ubuntu安裝、更新docker社群版
2. 安裝docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
3. 啟動quorum網絡
git clone https://github.com/jpmorganchase/quorum-examples
cd quorum-examples
docker-compose up -d
預設使用Tessera隐私管理器和Istanbul BFT共識,如果要使用raft共識,請設定
QUORUM_CONSENSUS=raft
,啟動沒有關聯的隐私事務管理器,請設定
PRIVATE_CONFIG=ignore
,兩者可以一同實用。
PRIVATE_CONFIG=ignore QUORUM_CONSENSUS=raft docker-compose up -d
4. 檢查網絡
- 運作
檢查所有的容器是否正常運作(7個節點、7個TX管理器、一個cakeshop:Quorum的內建開發環境和SDK)docker ps
IMAGE PORTS
quorumengineering/quorum:2.5.0 8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22005->8545/tcp
quorumengineering/quorum:2.5.0 8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22006->8545/tcp
quorumengineering/quorum:2.5.0 8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22004->8545/tcp
quorumengineering/quorum:2.5.0 8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22000->8545/tcp
quorumengineering/quorum:2.5.0 8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22001->8545/tcp
quorumengineering/quorum:2.5.0 8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22002->8545/tcp
quorumengineering/quorum:2.5.0 8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22003->8545/tcp
quorumengineering/tessera:0.10.4 9000/tcp, 0.0.0.0:9082->9080/tcp
quorumengineering/tessera:0.10.4 9000/tcp, 0.0.0.0:9087->9080/tcp
quorumengineering/tessera:0.10.4 9000/tcp, 0.0.0.0:9083->9080/tcp
quorumengineering/tessera:0.10.4 9000/tcp, 0.0.0.0:9084->9080/tcp
quorumengineering/tessera:0.10.4 9000/tcp, 0.0.0.0:9081->9080/tcp
quorumengineering/tessera:0.10.4 9000/tcp, 0.0.0.0:9085->9080/tcp
quorumengineering/cakeshop:0.11.0 8080/tcp, 8102/tcp, 0.0.0.0:8999->8999/tcp
quorumengineering/tessera:0.10.4 9000/tcp, 0.0.0.0:9086->9080/tcp
- docker logs -f 檢視特定容器的日志
5. 隐私交易測試
這裡我們将做以下實驗測試交易:
- 在node1和node7之間發送隐私交易
- 證明隻有node1和node7可以檢視合約的初始狀态
- node1更新合約的狀态,并且一旦包含更新交易的區塊被網絡驗證,再次驗證隻有node1和node7能夠看到合約的更新狀态
5.1 發送隐私交易
連接配接node1
docker exec -it quorum-examples_node1_1 geth attach /qdata/dd/geth.ipc
發送一筆私有交易
Contract transaction send: TransactionHash: 0x88103cbf9b6e4823e214af0e50e21941ff416cc81320d20049f4d324627bcfcb waiting to be mined...
true
> Contract mined! Address: 0x1932c48b2bf8102ba33b4a6b545c32236e342f34
[object Object]
記錄下
TransactionHash
的值。
private-contract.js
内容如下:
a = eth.accounts[0]
web3.eth.defaultAccount = a;
// abi and bytecode generated from simplestorage.sol:
// > solcjs --bin --abi simplestorage.sol
var abi = [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initVal","type":"uint256"}],"payable":false,"type":"constructor"}];
var bytecode = "0x6060604052341561000f57600080fd5b604051602080610149833981016040528080519060200190919050505b806000819055505b505b610104806100456000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632a1afcd914605157806360fe47b11460775780636d4ce63c146097575b600080fd5b3415605b57600080fd5b606160bd565b6040518082815260200191505060405180910390f35b3415608157600080fd5b6095600480803590602001909190505060c3565b005b341560a157600080fd5b60a760ce565b6040518082815260200191505060405180910390f35b60005481565b806000819055505b50565b6000805490505b905600a165627a7a72305820d5851baab720bba574474de3d09dbeaabc674a15f4dd93b974908476542c23f00029";
var simpleContract = web3.eth.contract(abi);
var simple = simpleContract.new(42, {from:web3.eth.accounts[0], data: bytecode, gas: 0x47b760, privateFor: ["ROAZBWtSacxXQrOe3FGAqJDyJjFePR5ce4TSIzmJ0Bc="]}, function(e, contract) {
if (e) {
console.log("err creating contract", e);
} else {
if (!contract.address) {
console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");
} else {
console.log("Contract mined! Address: " + contract.address);
console.log(contract);
}
}
});
privateFor: ["ROAZBWtSacxXQrOe3FGAqJDyJjFePR5ce4TSIzmJ0Bc="]
為node7的公鑰。
5.1 檢查quorum node
通過geth attach打開Geth JavaScript控制台,這裡我們檢查node1、node4、node7.
打開三個終端:
docker exec -it quorum-examples_node1_1 geth attach /qdata/dd/geth.ipc
docker exec -it quorum-examples_node4_1 geth attach /qdata/dd/geth.ipc
docker exec -it quorum-examples_node7_1 geth attach /qdata/dd/geth.ipc
在其中一個終端執行以下指令(參數為上一步的
TransactionHash
):
{
blockHash: "0x57766df2f6eee01b9babacbb1978ad5d60d2fbcbe117f8ba0d7f68052edb4cac",
blockNumber: 516,
from: "0xed9d02e382b34818e88b88a309c7fe71e65f419d",
gas: 4700000,
gasPrice: 0,
hash: "0x88103cbf9b6e4823e214af0e50e21941ff416cc81320d20049f4d324627bcfcb",
input: "0x7958c99b76a16c71637b9fa1f7e8728fcdb93c656c18e705ec8daf9b2c7221b7eae9afcb67961dc0bcbac0cc35aa3e51f21c5d7f11a465db6b8d3fe4b96e7426",
nonce: 0,
r: "0x3323ee2c9c4df841b1ac049a048a0e27a09b203c630e92a7e9daa7075e43ef52",
s: "0xe09387feecaf051f4a7fe6cebdc00d5395b2dee56913bddecbc28de0da59398",
to: null,
transactionIndex: 0,
v: "0x25",
value: 0
}
請注意或的v字段值是 “0x25” or “0x26”(十進制為37或38),它标示交易(事務)是是隐私交易。
5.3 檢查合約狀态
可以通過以下指令得到合約位址(在5.1中也發送交易後也列印了)
在三個終端運作以下指令:
定義合約位址
定義abi
調用合約
- 終端視窗1(node1):
> private.get() 42
- 終端視窗2(node4):
> private.get() 0
- 終端視窗3(node4):
> private.get() 42
是以,我們可以看到node1和node7能夠讀取隐私合約的狀态,并且其初始值為42。如果您進行檢視private-contract.js您将看到這是建立合同時設定的值。而node4無法讀取狀态。
5.3 更新合約狀态
接下來我們在node1上将合約的狀态值更新為
4
,并在node4和node7上檢視最新的狀态。
終端視窗1(node1):
> private.set(4,{from:"0xed9d02e382b34818e88b88a309c7fe71e65f419d",privateFor:["ROAZBWtSacxXQrOe3FGAqJDyJjFePR5ce4TSIzmJ0Bc="]});
"0x4a5618b41019161f710b16f3c749f88de605ddbb9b3c495809f461d64b30b76e"
- 終端視窗1(node1):
> private.get() 4
- 終端視窗2(node4):
> private.get() 0
- 終端視窗3(node4):
> private.get() 4
所有7個節點都在驗證相同的交易區塊鍊,隐私交易僅包含512位哈希值來代替交易資料,并且隻有隐私交易的參與方才能檢視和更新隐私合約狀态。
6. 節點許可測試
節點許可是Quorum中的一項功能,它僅允許一組預定義的節點連接配接到許可的網絡。
在此示範中,我們将:
- 檢視目前節點已連接配接的peer
- 看一下permissioned-nodes.json檔案的細節
-
證明隻有permissioned-nodes.json中指定的節點才能連接配接到網絡
單個節點可以通過傳遞-permissioned指令行标志來啟用/禁用。如果啟用,則隻有其中的節點/permissioned-nodes.json可以連接配接到它。
6.1 檢視已經連接配接的節點
進入node1的JavaScript控制台
docker exec -it quorum-examples_node1_1 geth attach /qdata/dd/geth.ipc
檢視已連接配接的peer
> admin.peers
[{
caps: ["istanbul/64"],
enode: "enode://239c1f044a2b03b6c4713109af036b775c5418fe4ca63b04b1ce00124af00ddab7cc088fc46020cdc783b6207efe624551be4c06a994993d8d7[email protected]:21000?discport=0&raftport=50400",
id: "3cb4aaea0f49f73c9de4a34db131288f355bc27090e542ae0be213c20350b767",
name: "Geth/node7-istanbul/v1.8.18-stable-685f59fb(quorum-v2.5.0)/linux-amd64/go1.11.13",
network: {
inbound: false,
localAddress: "172.16.239.11:48834",
remoteAddress: "172.16.239.17:21000",
static: true,
trusted: false
},
protocols: {
istanbul: {
difficulty: 36998,
head: "0xeb173a1f54a705a880fa8f7ee65ee8e8214563713e6a3ca64146d73f5e97f6ac",
version: 64
}
}
}, {
caps: ["istanbul/64"],
enode: "enode://0ba6b9f606a43a95edc6247cdb1c1e105145817be7bcafd6b2c0ba15d58145f0dc1a194f70ba73cd6f4cd[email protected]:43910",
id: "995dbe18829f1affb75402e66571d97f340c8495b661a823f2c2145ca47d63c2",
name: "Geth/node2-istanbul/v1.8.18-stable-685f59fb(quorum-v2.5.0)/linux-amd64/go1.11.13",
network: {
inbound: true,
localAddress: "172.16.239.11:21000",
remoteAddress: "172.16.239.12:43910",
static: false,
trusted: false
},
protocols: {
istanbul: {
difficulty: 36998,
head: "0xeb173a1f54a705a880fa8f7ee65ee8e8214563713e6a3ca64146d73f5e97f6ac",
version: 64
}
}
}, {
caps: ["istanbul/64"],
enode: "enode://eacaa74c4b0e7a9e12d2fe5fee6595eda841d6d992c35dbbcc50fcee4aa86dfbbdeff7dc7e72c2305d5a6[email protected]:52748",
id: "ab62dd7df5863a5f3bb61f458157d4437104e3b8df4451a85f7b2438ef6699ff",
name: "Geth/node6-istanbul/v1.8.18-stable-685f59fb(quorum-v2.5.0)/linux-amd64/go1.11.13",
network: {
inbound: true,
localAddress: "172.16.239.11:21000",
remoteAddress: "172.16.239.16:52748",
static: false,
trusted: false
},
protocols: {
istanbul: {
difficulty: 36997,
head: "0xfe5892fc865d7c3c759d559e5ca0fe4f52ba30ad38021ddf72e320c5a4b9e6b8",
version: 64
}
}
}, {
caps: ["istanbul/64"],
enode: "enode://579f786d4e2830bbcc02815a27e8a9bacccc9605df4dc6f20bcc1a6eb391e7225fff7cb83e5b4ecd1f3a9[email protected]:49578",
id: "c39143f98d04e97bd9e31ac1e36cbeb565b061217930767886474e3cde903ac5",
name: "Geth/node3-istanbul/v1.8.18-stable-685f59fb(quorum-v2.5.0)/linux-amd64/go1.11.13",
network: {
inbound: true,
localAddress: "172.16.239.11:21000",
remoteAddress: "172.16.239.13:49578",
static: false,
trusted: false
},
protocols: {
istanbul: {
difficulty: 36997,
head: "0xfe5892fc865d7c3c759d559e5ca0fe4f52ba30ad38021ddf72e320c5a4b9e6b8",
version: 64
}
}
}, {
caps: ["istanbul/64"],
enode: "enode://3d9ca5956b38557aba991e31cf510d4df641dce9cc26bfeb7de082f0c07abb6ede3a58410c8f249dabeec[email protected]:37980",
id: "c75f7dcb9fd6063f0ada0998f512a992f3fb749857d758ffda1330e590fa915e",
name: "Geth/node4-istanbul/v1.8.18-stable-685f59fb(quorum-v2.5.0)/linux-amd64/go1.11.13",
network: {
inbound: true,
localAddress: "172.16.239.11:21000",
remoteAddress: "172.16.239.14:37980",
static: false,
trusted: false
},
protocols: {
istanbul: {
difficulty: 36998,
head: "0xeb173a1f54a705a880fa8f7ee65ee8e8214563713e6a3ca64146d73f5e97f6ac",
version: 64
}
}
}, {
caps: ["istanbul/64"],
enode: "enode://3701f007bfa4cb26512d7df18e6bbd202e8484a6e11d387af6e482b525fa25542d46ff9c99db87bd419b980c24a086117a397f6d8f88e74351b[email protected]:21000?discport=0&raftport=50400",
id: "f06c06f1e958cb2edf90d8bfb912de287f9b047b4228436e94b5b78e3ee16171",
name: "Geth/node5-istanbul/v1.8.18-stable-685f59fb(quorum-v2.5.0)/linux-amd64/go1.11.13",
network: {
inbound: false,
localAddress: "172.16.239.11:51332",
remoteAddress: "172.16.239.15:21000",
static: true,
trusted: false
},
protocols: {
istanbul: {
difficulty: 36998,
head: "0xeb173a1f54a705a880fa8f7ee65ee8e8214563713e6a3ca64146d73f5e97f6ac",
version: 64
}
}
}]
6.2 節點許可配置
配置在examples/7nodes/permissioned-nodes.json:
[
"enode://ac6b1096ca56b9f6d004b779ae3728bf83f8e22453404cc3cef16a3d9b96608bc67c4b30db88e0a5a6c6390213f7acbe1153ff6d23ce57380104288ae19373ef@127.0.0.1:21000?discport=0&raftport=50401",
"enode://0ba6b9f606a43a95edc6247cdb1c1e105145817be7bcafd6b2c0ba15d58145f0dc1a194f70ba73cd6f4cdd6864edc7687f311254c7555cc32e4d45aeb1b80416@127.0.0.1:21001?discport=0&raftport=50402",
"enode://579f786d4e2830bbcc02815a27e8a9bacccc9605df4dc6f20bcc1a6eb391e7225fff7cb83e5b4ecd1f3a94d8b733803f2f66b7e871961e7b029e22c155c3a778@127.0.0.1:21002?discport=0&raftport=50403",
"enode://3d9ca5956b38557aba991e31cf510d4df641dce9cc26bfeb7de082f0c07abb6ede3a58410c8f249dabeecee4ad3979929ac4c7c496ad20b8cfdd061b7401b4f5@127.0.0.1:21003?discport=0&raftport=50404",
"enode://3701f007bfa4cb26512d7df18e6bbd202e8484a6e11d387af6e482b525fa25542d46ff9c99db87bd419b980c24a086117a397f6d8f88e74351b41693880ea0cb@127.0.0.1:21004?discport=0&raftport=50405",
"enode://eacaa74c4b0e7a9e12d2fe5fee6595eda841d6d992c35dbbcc50fcee4aa86dfbbdeff7dc7e72c2305d5a62257f82737a8cffc80474c15c611c037f52db1a3a7b@127.0.0.1:21005?discport=0&raftport=50406",
"enode://239c1f044a2b03b6c4713109af036b775c5418fe4ca63b04b1ce00124af00ddab7cc088fc46020cdc783b6207efe624551be4c06a994993d8d[email protected]:21006?discport=0&raftport=50407"
]
6.3 禁用其中一個節點
删掉permissioned-nodes.json中的一個node6
vi examples/7nodes/permissioned-nodes.json
重新開機網絡
docker-compose restart
連接配接到node1
docker exec -it quorum-examples_node1_1 geth attach /qdata/dd/geth.ipc
檢視peer
>admin.peers
可以觀察,比原來少了一個peer,也可以在
cakeshop dashboard
中檢視,切換到node6 可以發現peer數量為0
7. cakeshop dashboard
cakeshop是一個內建開發環境,提供管理控制ui,包含節點管理、合約管理、編譯沙箱環境、區塊浏覽器、錢包管理、peer管理。
打開 http://yourip:8999,觀察節點是否正常。
8. 停止(關閉)quorum網絡
docker-compose down
docker-compose rm
問題
cakeshop容器報錯,不能解析
host.docker.internal
解決辦法:修改docker-compose.yaml,在啟動cakeshop的時候将ip位址寫入 /etc/hosts
x-cakeshop-def:
&cakeshop-def
image: "${CAKESHOP_DOCKER_IMAGE:-quorumengineering/cakeshop:0.11.0}"
expose:
- "8999"
restart: "no"
healthcheck:
test: ["CMD", "wget", "--spider", "--proxy=off", "http://localhost:8999/actuator/health"]
interval: 5s
timeout: 5s
retries: 20
start_period: 5s
entrypoint:
- /bin/sh
- -c
- |
ip -4 route list match 0/0 | awk '{print $$3" host.docker.internal"}' >> /etc/hosts
DDIR=/qdata/cakeshop/local
rm -rf $${DDIR}
mkdir -p $${DDIR}
DOCKER_IMAGE="${CAKESHOP_DOCKER_IMAGE:-quorumengineering/cakeshop:0.11.0}"
cp /examples/cakeshop/application.properties.template $${DDIR}/application.properties
cp /examples/cakeshop/7nodes_docker.json $${DDIR}/7nodes.json
java -Xms128M -Xmx128M -Dcakeshop.config.dir=/qdata/cakeshop -Dlogging.path=/qdata/logs/cakeshop -jar /opt/cakeshop/cakeshop.war
;;
參考
https://github.com/jpmorganchase/quorum-examples
https://github.com/docker/for-linux/issues/264