天天看點

quorum examples初探

文章目錄

    • 環境
    • 引言
    • 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. 檢查網絡

  • 運作

    docker ps

    檢查所有的容器是否正常運作(7個節點、7個TX管理器、一個cakeshop:Quorum的內建開發環境和SDK)
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

繼續閱讀