在Ubuntu中部署並測試HyperLedger Fabric 0.6

1、環境準備

1.1 安裝VirtualBox並在其中安裝好Ubuntu

這一步其實沒啥好說的,下載好最新版的VirtualBox,下載Ubuntu Server,我用的是16.10 X64。在安裝完Ubuntu後,須要保證apt source是國內的,否則若是是國外的話會很慢很慢的。具體作法是java

sudo vi /etc/apt/sources.list

打開這個apt源列表,若是其中看到是http://us.xxxxxx之類的,那麼就是外國的,若是看到是http://cn.xxxxx之類的,那麼就不用換的。個人是美國的源,因此須要作一下批量的替換。在命令模式下,輸入:node

:%s/us./cn./g

就能夠把全部的us.改成cn.了。而後輸入:wq便可保存退出。python

sudo apt-get update

更新一下源。git

而後安裝ssh,這樣接下來就能夠用putty或者SecureCRT之類的客戶端遠程鏈接Ubuntu了。github

sudo apt-get install ssh

1.2 安裝Docker

安裝Docker也會遇到外國網絡慢的問題,幸虧國內有很好的鏡像,推薦DaoClound,安裝Docker的命令是:web

curl -sSL https://get.daocloud.io/docker | sh
安裝完成後,運行如下腳本將當前用戶添加到Docker的組中
sudo usermod -aG docker studyzy
從新登陸當前用戶,接下來修改 Docker 服務配置( 文件)。/etc/default/docker
sudo vi /etc/default/docker
添加如下內容:
DOCKER_OPTS="$DOCKER_OPTS -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --api-cors-header='*'"
接下來就須要設置國內的Docker鏡像地址,須要註冊一個帳號,而後在加速器頁面提供了設置Docker鏡像的腳本,加速器頁面是:
https://www.daocloud.io/mirror 我提供的腳本是:
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://d4cc5789.m.daocloud.io
運行完腳本後,重啓Docker服務
sudo service docker restart

1.3 安裝docker-compose

Docker-compose是支持經過模板腳本批量建立Docker容器的一個組件。在安裝Docker-Compose以前,須要安裝Python-pip,運行腳本:docker

sudo apt-get install python-pip

安裝完成後,接下來從DaoClound安裝Docker-compose,運行腳本:json

curl -L https://get.daocloud.io/docker/compose/releases/download/1.10.1/docker-compose-`uname -s`-`uname -m` > ~/docker-compose 
sudo mv ~/docker-compose /usr/local/bin/docker-compose 
chmod +x /usr/local/bin/docker-compose

2、Fabric部署

2.1 下載Fabric鏡像

Fabric的Docker鏡像是在https://hub.docker.com/r/hyperledger/ 咱們要作實驗主要用到peer,baseimage,membersrvc,先如今Peer和membersrvc,這兩個鏡像提供了latest版本,因此直接pull下來便可。c#

docker pull hyperledger/fabric-peer
docker pull hyperledger/fabric-membersrvc

可是baseimage是沒有latest版本,因此咱們能夠下載一個新一點的版本,而後rename成latest。api

docker pull hyperledger/fabric-baseimage:x86_64-0.3.0
docker tag hyperledger/fabric-baseimage:x86_64-0.3.0 hyperledger/fabric-baseimage:latest

如今咱們運行docker images命令,能夠看到咱們準備好的鏡像:

REPOSITORY                      TAG                 IMAGE ID            CREATED             SIZE 
hyperledger/fabric-baseimage    latest              f4751a503f02        7 days ago          1.27 GB 
hyperledger/fabric-baseimage    x86_64-0.3.0        f4751a503f02        7 days ago          1.27 GB 
hyperledger/fabric-membersrvc   latest              b3654d32e4f9        3 months ago        1.42 GB 
hyperledger/fabric-peer         latest              21cb00fb27f4        3 months ago        1.42 GB

2.2 使用Git下載Docker-compose模板

若是沒有安裝Git,那麼須要先安裝Git,安裝Git很簡單:

sudo apt-get install git

感謝yeasy提供的很好的HyperLedger的模板,咱們先克隆到本地:

git clone https://github.com/yeasy/docker-compose-files

2.3 以PBFT模式啓動Fabric

先進入Git下載下來的Docker-compose目錄:

cd docker-compose-files/hyperledger/0.6/pbft/

這裏提供了多種模式的啓動方案,一種是啓動4個節點的Peer,沒有權限認證:4-peers.yml 另外一種是在4節點Peer的基礎上,再加上MembershipService節點,也就是須要權限認證的:4-peers-with-membersrvc.yml 另外還有再進一步,提供了web的Explorer的:4-peers-with-membersrvc-explorer.yml

這裏咱們就簡單點,直接忽略掉MembershipService和Explorer,只啓用4個節點的PBFT:

docker-compose -f 4-peers.yml up

系統會打印出啓動的日誌:

Creating network "pbft_default" with the default driver 
Creating pbft_vp0_1 
Creating pbft_vp3_1 
Creating pbft_vp2_1 
Creating pbft_vp1_1
……

至此,咱們的環境搭建完畢,接下來咱們就能夠在上面跑鏈上代碼了。

3、測試Fabric

3.1 在CLI中測試Example02

咱們前面建立了4個容器,開啓另一個命令行窗口,輸入docker ps命令,能夠看到當前容器的狀態: 
CONTAINER ID        IMAGE                            COMMAND             CREATED             STATUS              PORTS                                   NAMES 
2131cede4ade        hyperledger/fabric-peer:latest   "peer node start"   3 minutes ago       Up 3 minutes        7050-7059/tcp                           pbft_vp1_1 
5acea88f21bc        hyperledger/fabric-peer:latest   "peer node start"   3 minutes ago       Up 3 minutes        7050-7059/tcp                           pbft_vp2_1 
546b103d904d        hyperledger/fabric-peer:latest   "peer node start"   3 minutes ago       Up 3 minutes        7050-7059/tcp                           pbft_vp3_1 
327ab874b2e3        hyperledger/fabric-peer:latest   "peer node start"   3 minutes ago       Up 3 minutes        0.0.0.0:7050->7050/tcp, 7051-7059/tcp   pbft_vp0_1

這裏咱們能夠看到,最後一個容器pbft_vp0_1其啓用了端口映射的,容器上面的7050端口會映射到Ubuntu的7050端口上。咱們要執行命令行代碼,須要先鏈接到這個容器內部:

docker exec -it pbft_vp0_1 bash

進入容器後,命令行會變爲:root@vp0:/opt/gopath/src/github.com/hyperledger/fabric#

這裏的容器已經幫咱們把測試代碼都放在了容器裏面,因此咱們不須要再下載測試代碼。

3.1.1部署Go語言的ChainCode並初始化

下面咱們部署Example02到Fabric上:

peer chaincode deploy -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Function":"init", "Args": ["a","100", "b", "200"]}'

這個示例是初始化兩個帳戶a和b,a有餘額100元,b有餘額200元,這是運行結果:

複製代碼
root@vp0:/opt/gopath/src/github.com/hyperledger/fabric# peer chaincode deploy -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Function":"init", "Args": ["a","100", "b", "200"]}' 
08:37:12.187 [chaincodeCmd] chaincodeDeploy -> INFO 001 Deploy result: type:GOLANG chaincodeID:<path:"github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"init" args:"a" args:"100" args:"b" args:"200" > 
Deploy chaincode: ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539 
08:37:12.188 [main] main -> INFO 002 Exiting.....
複製代碼

 

這裏咱們能夠看到已經部署成功,並返回了ChainCode的ID:ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539

3.1.2查詢ChainCode

下面咱們把這個ID放入一個變量中:

CC_ID="ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539"

下面咱們來查詢一下a帳戶的餘額:

peer chaincode query -n ${CC_ID} -c '{"Function": "query", "Args": ["a"]}'

這是運行結果:

root@vp0:/opt/gopath/src/github.com/hyperledger/fabric# peer chaincode query -n ${CC_ID} -c '{"Function": "query", "Args": ["a"]}' 
08:41:17.780 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Successfully queried transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"query" args:"a" > > 
Query Result: 100 
08:41:17.781 [main] main -> INFO 002 Exiting.....

能夠看到查詢結果是100元。

注意:這裏若是遇到了拋出異常:

LedgerError - ResourceNotFound: ledger: resource not found

那麼就得看log,究竟是什麼地方錯了,咱們能夠切換回docker-compose的那個窗口,那個窗口會打印錯誤日誌,或者咱們再打開一個窗口,運行命令:

docker logs -f pbft_vp0_1

查看peer日誌,找到緣由。我以前一直遇到這個異常,後來發現是baseimage沒有latest版的形成的,因此2.1步驟不能出錯。

3.1.3調用ChainCode

接下來,咱們讓a給b轉帳10元,運行命令:

peer chaincode invoke -n ${CC_ID} -c '{"Function": "invoke", "Args": ["a", "b", "10"]}'

這是調用後的結果:

root@vp0:/opt/gopath/src/github.com/hyperledger/fabric# peer chaincode invoke -n ${CC_ID} -c '{"Function": "invoke", "Args": ["a", "b", "10"]}' 
08:44:19.903 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Successfully invoked transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"invoke" args:"a" args:"b" args:"10" > > (94c9cbd9-ea04-436f-9cf8-3436303554d2) 
08:44:19.904 [main] main -> INFO 002 Exiting.....

3.1.4檢查調用ChainCode後的結果

如今已經轉帳完畢,咱們再來查詢一下a帳戶的餘額:

peer chaincode query -n ${CC_ID} -c '{"Function": "query", "Args": ["a"]}'

查詢結果:

複製代碼
root@vp0:/opt/gopath/src/github.com/hyperledger/fabric# peer chaincode query -n ${CC_ID} -c '{"Function": "query", "Args": ["a"]}'             
08:45:33.937 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Successfully queried transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"query" args:"a" > > 
Query Result: 90 
08:45:33.937 [main] main -> INFO 002 Exiting.....
複製代碼

能夠看到,a帳戶變成90元了。

3.2 在REST API中測試Example02

前面咱們已經說到,容器的7050端口會映射成Ubuntu的7050端口,咱們在Ubuntu下,運行ifconfig,能夠看到Ubuntu的IP,而後咱們回到Windows,就能夠經過REST的Client來測試,這裏我喜歡用Chrome的插件DHC,很好用,強烈推薦!不過要FQ才能裝。

DHC

這裏我Ubuntu的IP是192.168.100.129,下面就用DHC進行REST API的Example02部署。

3.2.1經過REST API部署GO語言的ChainCode

POST 192.168.100.129:7050/chaincode

Body是:

複製代碼
{ 
  "jsonrpc": "2.0", 
  "method": "deploy", 
  "params": { 
    "type": 1, 
    "chaincodeID":{ 
        "path":"github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" 
    }, 
    "ctorMsg": { 
        "function":"init", 
        "args":["a", "1000", "b", "2000"] 
    } 
  }, 
  "id": 1 
}
複製代碼

這裏爲了區別,咱們把a帳戶初始化1000元,b帳戶初始化2000元。返回的結果是:

複製代碼
{
"jsonrpc": "2.0",
"result":{
"status": "OK",
"message": "04233c6dd8364b9f0749882eb6d1b50992b942aa0a664182946f411ab46802a88574932ccd75f8c75e780036e363d52dd56ccadc2bfde95709fc39148d76f050"
},
"id": 1
}
複製代碼

這裏04233c6dd8364b9f0749882eb6d1b50992b942aa0a664182946f411ab46802a88574932ccd75f8c75e780036e363d52dd56ccadc2bfde95709fc39148d76f050就是部署後的ChainCodeID。

3.2.2經過REST API查詢ChainCode

POST 192.168.100.129:7050/chaincode

Body內容是:

複製代碼
{ 
  "jsonrpc": "2.0", 
  "method": "query", 
  "params": { 
      "type": 1, 
      "chaincodeID":{ 
          "name":"04233c6dd8364b9f0749882eb6d1b50992b942aa0a664182946f411ab46802a88574932ccd75f8c75e780036e363d52dd56ccadc2bfde95709fc39148d76f050" 
      }, 
      "ctorMsg": { 
         "function":"query", 
         "args":["a"] 
      } 
  }, 
  "id": 2 
}
複製代碼

系統返回的結果是:

複製代碼
{
"jsonrpc": "2.0",
"result":{
"status": "OK",
"message": "1000"
},
"id": 2
}
複製代碼

一切正常,返回a帳戶的1000元。

3.2.3經過REST API調用ChainCode

咱們試着從a向b轉帳100元:

POST 192.168.100.129:7050/chaincode

Body內容是:

複製代碼
{ 
  "jsonrpc": "2.0", 
  "method": "invoke", 
  "params": { 
      "type": 1, 
      "chaincodeID":{ 
          "name":"04233c6dd8364b9f0749882eb6d1b50992b942aa0a664182946f411ab46802a88574932ccd75f8c75e780036e363d52dd56ccadc2bfde95709fc39148d76f050" 
      }, 
      "ctorMsg": { 
         "function":"invoke", 
         "args":["a", "b", "100"] 
      } 
  }, 
  "id": 3 
}
複製代碼

返回的結果:

複製代碼
{
"jsonrpc": "2.0",
"result":{
"status": "OK",
"message": "2ac78b5f-6d35-400d-b7c4-75ef81e14d3e"
},
"id": 3
}
複製代碼

3.2.4經過REST API檢查調用ChainCode後的結果

這裏咱們來查詢一下b帳戶。

POST 192.168.100.129:7050/chaincode

Body內容改成:

複製代碼
{ 
  "jsonrpc": "2.0", 
  "method": "query", 
  "params": { 
      "type": 1, 
      "chaincodeID":{ 
          "name":"04233c6dd8364b9f0749882eb6d1b50992b942aa0a664182946f411ab46802a88574932ccd75f8c75e780036e363d52dd56ccadc2bfde95709fc39148d76f050" 
      }, 
      "ctorMsg": { 
         "function":"query", 
         "args":["b"] 
      } 
  }, 
  "id": 4 
}
複製代碼

返回結果:

複製代碼
{
"jsonrpc": "2.0",
"result":{
"status": "OK",
"message": "2100"
},
"id": 4
}
複製代碼

一切正常,b帳戶果真真假了100元。

關於更多的REST API,咱們能夠參考這裏:https://github.com/hyperledger-archives/fabric/blob/master/docs/API/CoreAPI.md#rest-api

3.3測試Java版Chain Code

Fabric除了支持自己的Go語言的ChainCode,也能夠支持其餘語言,好比最經常使用的Java語言。Fabric的源代碼中也提供了Java示例,這裏咱們就用SimpleSample這個示例:

https://github.com/hyperledger/fabric/tree/master/examples/chaincode/java/SimpleSample

3.3.1在CLI中部署該Java代碼的ChainCode到Fabric

命令是:

peer chaincode deploy -l java -p /opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/java/SimpleSample -c '{"Function":"init", "Args": ["a","100", "b", "200"]}'

運行結果爲:

複製代碼
root@vp0:/opt/gopath/src/github.com/hyperledger/fabric# peer chaincode deploy -l java -p /opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/java/SimpleSample -c '{"Function":"init", "Args": ["a","100", "b", "200"]}' 
09:20:16.857 [chaincodeCmd] chaincodeDeploy -> INFO 001 Deploy result: type:JAVA chaincodeID:<path:"/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/java/SimpleSample" name:"0f5b1d65041bc6d500bd0f1cab50eb6154c291ef0f4596d64b6797e8ef8f7c34a179b5a2cea82253ff3d74e768512fe0481503eadcf13d18f9761bbb8133efd0" > ctorMsg:<args:"init" args:"a" args:"100" args:"b" args:"200" > 
Deploy chaincode: 0f5b1d65041bc6d500bd0f1cab50eb6154c291ef0f4596d64b6797e8ef8f7c34a179b5a2cea82253ff3d74e768512fe0481503eadcf13d18f9761bbb8133efd0 
09:20:16.857 [main] main -> INFO 002 Exiting.....
複製代碼

接下來的各類查詢,調用都是差很少的,我就再也不累述了。

3.3.2經過REST API部署Java ChainCode到Fabric

POST 192.168.100.129:7050/chaincode

Body爲

複製代碼
{ 
  "jsonrpc": "2.0", 
  "method": "deploy", 
  "params": { 
   "type": 4, 
    "chaincodeID":{ 
        "path":"/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/java/SimpleSample" 
    }, 
    "ctorMsg": { 
        "function":"init", 
        "args":["a", "1000", "b", "2000"] 
    } 
  }, 
  "id": 1 
}
複製代碼

系統返回的結果爲:

複製代碼
{
"jsonrpc": "2.0",
"result":{
"status": "OK",
"message": "27cb2925013a5e8f27b41be748e6767c3fbc7bfdfe2453c2640f9069e75c4db38735fa3b6b8cac78e212a1c97193f3bfb2f9b810ce0a11f437a96b330d508fbd"
},
"id": 1
}
複製代碼
相關文章
相關標籤/搜索