Hyperledger Fabric 2.2 學習筆記:測試網路test-network

語言: CN / TW / HK

寫在前面

最近被Hyperledger Fabric折磨,歸根結底還是因為自己太菜了qwq。學習路漫漫,筆記不能少。下面的步驟均是基於已經成功搭建了Fabric2.2環境,並且拉取fabric-samples檔案夾了。

一、啟動測試網路

開啟終端進入test-network目錄下。我的具體目錄是: /workspace/fabric-samples/test-network,因此有命令:

cd /workspace/fabric-samples/test-network

在使用./network.sh命令前,可以先檢視選項說明。

./network.sh -h

要是不想看問題也不大,跟著我走就好。(๑>ڡ<)☆

下面正式開始!

首先啟動網路。注意下面這個命令只是啟動網路並沒有建立通道。

./network.sh up

啟動網路後,接著建立通道。由於這裡並沒有指定通道的名字,此時預設為mychannel.

./network.sh createChannel

其實上述兩步可以用一條命令實現,那就是:

./network.sh up createChannel

之後,將bin目錄中二進位制檔案新增到 CLI 路徑。

export PATH=${PWD}/../bin:$PATH

設定FABRIC_CFG_PATH為指向fabric-samples中的core.yaml檔案。

export FABRIC_CFG_PATH=$PWD/../config/

二、安裝鏈碼

根據官方文件可以知道,Fabric鏈碼生命週期需要組織同意定義一個鏈碼的引數,比如說名稱、版本以及鏈碼背書策略。通道成員通過 以下四步 達成共識。不是通道上的每一個組織都需要完成每一步。

1. 打包鏈碼。 這一步可以被一個或者每一個組織完成。

2. 安裝鏈碼在你的peer節點上。 每一個用鏈碼的組織都需要完成。

3. 為你的組織批准鏈碼定義。 使用鏈碼的每一個組織都需要完成這一步。鏈碼能夠在通道上執行之前,鏈碼定義需要被足夠多的組織批准來滿足通道的生命週期背書(LifecycleEndorsement)策略(預設為大多陣列織)。

4. 提交鏈碼定義到鏈上。 一旦通道所需數量的組織已經同意,提交交易需要被提交。提交者首先從已同意組織中的足夠的peer節點中收集背書,然後通過提交鏈碼宣告。

顯然,下面要進行的第一步是打包鏈碼。鏈碼需要被打包成一個tar檔案。

1.打包鏈碼

下面使用peer lifecycle chaincode package命令建立鏈碼包

peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/go/ --lang golang --label fabcar_1

說明:① 命令中--path指的是 將指定目錄(../chaincode/fabcar/go/)的原始碼打包成fabcar.tar.gz.

② --label 後面是標籤,當日後鏈碼包升級的時候,可以設定不同的標籤。

2.安裝鏈碼

此時網路有兩個組織,所以需要先後在Org1、Org2的peer節點上安裝鏈碼。

(1) Org1 peer節點安裝鏈碼

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode install fabcar.tar.gz

當看到status:200即為成功。具體成功返回如下:

2022-04-20 10:03:14.293 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nIfabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506\022\010fabcar_1" >
2022-04-20 10:03:14.294 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506

但過程總是曲折的,顯然我沒有那麼順利成功。在安轉鏈碼的時候,我得到如下返回:

Error: chaincode install failed with status: 500 - failed to invoke backing implementation of 'InstallChaincode': could
not build chaincode: docker build failed: docker image build failed: docker build failed: Error returned from build: 1
"go: github.com/hyperledger/[email protected]: Get "https://proxy.golang.org/github.com/hyperledger
/fabric-contract-api-go/@v/v1.1.0.mod": dial tcp: lookup proxy.golang.org on 172.20.10.1:53: read udp 172.17.0.2:53395
->172.20.10.1:53: i/o timeout “

解決方案如下:

到../chaincode/fabcar/go/目錄下開啟終端執行命令。

go env -w GOPROXY=https://goproxy.io,direct
go env -w GO111MODULE=on
go mod vendor

之後重新執行peer lifecycle chaincode install fabcar.tar.gz即可成功。

(2)Org2 peer節點安裝鏈碼

export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:9051
peer lifecycle chaincode install fabcar.tar.gz

3.批准鏈碼定義

下面需要把鏈碼釋出到通道上去。首先 查詢鏈碼包ID

peer lifecycle chaincode queryinstalled

得到返回如下:

Installed chaincodes on peer:
Package ID: fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506, Label: fabcar_1

因此我的包ID為:

fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506.

通過鏈碼時,我們將使用包ID,因此,將包ID儲存為環境變數。將返回的包ID貼上到下面的命令中。

export CC_PACKAGE_ID=

在這裡就是:

export CC_PACKAGE_ID=fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506

之後,Org2通過鏈碼定義

peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --waitForEvent

返回如下即為成功。

2022-04-20 10:20:59.307 CST [chaincodeCmd] ClientWait -> INFO 001 txid [f688ddff60056af56e96784d253695e9fbb056e5244058fb30b2d05977214c1c] committed with status (VALID) at localhost:9051

設定以下環境變數以Org1管理員身份執行:

Org1通過鏈碼定義

export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --waitForEvent

返回:

2022-04-20 10:25:23.828 CST [chaincodeCmd] ClientWait -> INFO 001 txid [9178a978646d4b010a61677488532af88b7393ba898341168fc627c0953a9884] committed with status (VALID) at localhost:7051

使用 peer lifecycle chaincode checkcommitreadiness 命令來檢查通道成員是否已批准相同的鏈碼定義:

peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json

返回:

{
    "approvals": {
        "Org1MSP": true,
        "Org2MSP": true
    }
}

返回的結果說明這兩個節點批准了這個鏈碼的定義。

4.將鏈碼提交到通道

使用 peer lifecycle chaincode commit 命令將鏈碼定義提交到通道。commit命令還需要由組織管理員提交。

peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt

返回:

2022-04-20 10:45:05.973 CST [chaincodeCmd] ClientWait -> INFO 001 txid [c93e2e79e2da09f04654d30630959d9e80d2576aefdf4be16e3b281d48a011a4] committed with status (VALID) at localhost:7051
2022-04-20 10:45:06.019 CST [chaincodeCmd] ClientWait -> INFO 002 txid [c93e2e79e2da09f04654d30630959d9e80d2576aefdf4be16e3b281d48a011a4] committed with status (VALID) at localhost:9051

使用 peer lifecycle chaincode querycommitted 命令來確認鏈碼定義已經提交給通道。

peer lifecycle chaincode querycommitted --channelID mychannel --name fabcar --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

返回:

Committed chaincode definition for chaincode 'fabcar' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]

看到此返回資訊後可以知道我們提交的鏈碼已經提交到通道myChannel中。

三、呼叫鏈碼

① 呼叫鏈碼

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n fabcar  --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"initLedger","Args":[]}'

返回如下即為成功。

2022-04-20 15:49:24.590 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200

顯然,我並沒有一下就成功。我得到如下返回:

Error: endorsement failure during invoke. response: status:500 message:"error in simulation:failed to execute transaction 5e72e85cea510ecc198412f2f7df406b8fbcff8adf97d052d6b165413ed85854:
could not launch chaincode fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506:error starting container: error starting container: API error (404): network _test not found"

錯誤原因:

fabric-samples/test-network/docker/docker-compose-test-net.yaml的配置檔案中有一個

- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE= ${COMPOSE_PROJECT_NAME} _test

${COMPOSE_PROJECT_NAME}在智慧合約啟動時,此值獲取到的會是空值,從而導致標題的錯誤提示。這個也被官方收錄進issue中,並在fabric-samples的main分支中已經改為固定值,如下:

- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE= fabric _test

需要注意的是使用docker-compse啟動時,建立的network名字會在前邊加上當前docker-compse檔案的目錄名字。所以如果我們在使用老版本的fabric-sample時,自己可修改${COMPOSE_PROJECT_NAME}值為當前你存放compose檔案的資料夾名稱。

檢視建立的docker network可以使用docker network ls檢視。

此時檢視到名字是:docker_test

因此將檔案中的

- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE= ${COMPOSE_PROJECT_NAME} _test

改為

- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE= docker _test

注意檔案有 兩處 需要改。

②呼叫鏈碼

peer chaincode query --channelID mychannel --name fabcar -c '{"Args":["queryAllCars"]}'

得到返回:

[{"Key":"CAR0","Record":{"make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}},{"Key":"CAR1","Record":{"make":"Ford","model":"Mustang","colour":"red","owner":"Brad"}},{"Key":"CAR10","Record":{"make":"VW","model":"Polo","colour":"Grey","owner":"Archie"}},{"Key":"CAR2","Record":{"make":"Hyundai","model":"Tucson","colour":"green","owner":"Jin Soo"}},{"Key":"CAR3","Record":{"make":"Volkswagen","model":"Passat","colour":"yellow","owner":"Max"}},{"Key":"CAR4","Record":{"make":"Tesla","model":"S","colour":"black","owner":"Adriana"}},{"Key":"CAR5","Record":{"make":"Peugeot","model":"205","colour":"purple","owner":"Michel"}},{"Key":"CAR6","Record":{"make":"Chery","model":"S22L","colour":"white","owner":"Aarav"}},{"Key":"CAR7","Record":{"make":"Fiat","model":"Punto","colour":"violet","owner":"Pari"}},{"Key":"CAR8","Record":{"make":"Tata","model":"Nano","colour":"indigo","owner":"Valeria"}},{"Key":"CAR9","Record":{"make":"Holden","model":"Barina","colour":"brown","owner":"Shotaro"}}]

到這測試網路也就跑通了。(๑╹◡╹)ノ"""

參考

[1]