天天看點

實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

Hyperledger Fabric 2.0最近已經釋出,其中最引人關注的一點是鍊碼操作。官方文檔雖然對此提供了詳細的說明,但本文将通過與Hyperledger Fabric前一個版本中鍊碼操作的對比,來幫助你更好的了解新版本中鍊碼操作的不同之處以及幕後的一些技術細節。

Hyperledger Fabric區塊鍊開發教程: Node.js | Java Golang

1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

我們将首先快速介紹在HF 1.4和HF 2.0中的整個鍊碼操作過程。

鍊碼操作指的是在Hyperledger fabric網絡通道上部署鍊碼的操作,這樣區塊鍊之外的應用可以調用或查詢鍊碼方法。在鍊碼開發完成并測試後,首先需要将Fabric鍊碼安裝到指定的peer節點。在這個階段鍊碼還不能使用,直到鍊碼被送出(Fabric 2.0中的術語)到通道中或在通道上執行個體化(Fabric 1.4中的術語),這樣鍊碼就可以被授權使用者通路了。

下面是兩個版本的Hyperledger Fabric中鍊碼操作流程的對比圖:

實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

在Hyperledger Fabric 1.4中,鍊碼操作過程包含以下步驟:打包、安裝、執行個體化。如果鍊碼屬于多個參與方,那麼就需要打包這一環節。如果不存在多方屬主的問題,那麼直接安裝鍊碼就可以(其中隐含了打包環節)。在Fabric鍊碼安裝時需要指定要安裝鍊碼的目标節點。

在這個階段,安裝好的Fabric鍊碼還不能使用,因為它還沒有在通道上執行個體化。當Fabric鍊碼包被安裝在指定的節點上之後,我們就可以執行鍊碼執行個體化操作,進而讓鍊碼在通道上可用。技術上來說,鍊碼執行個體化實際上就是調用LSCC系統鍊碼的方法來初始化通道上的一個鍊碼。

Fabric鍊碼執行個體化之後就可以使用了,可以接受通道上的調用或查詢請求。

下面我們看在Hyperledger Fabric 2.0中的鍊碼操作步驟有何差別。

寬泛地來講,在Fabric 2.0中鍊碼操作基本遵循同樣的流程,但是在指令和某些背景進行中做了一些調整。整體的流程可以分為四個步驟:打包、安裝、機構審批、鍊碼送出。大緻可以認為前兩個環節對應于Fabric 1.4中的鍊碼安裝,後面兩個環節對應于Fabric 1.4中的鍊碼執行個體化,但是執行個體化(instantiation)這個詞不再用了。

鍊碼打包這一步是建立一個打封包件(tar格式),其中包含Fabric鍊碼以及一些中繼資料。雖然不同的機構可以分别進行打包處理,更常見是由一個機構打包然後分發給其他機構以便確定所有的機構使用相同的鍊碼。

安裝步驟是将打包的Fabric鍊碼檔案安裝在指定的peer節點上。和之前的版本一樣,隻有需要接受鍊碼調用的節點才需要安裝鍊碼。在這個節點,Fabric鍊碼還不可用,因為還沒有送出到通道中。鍊碼安裝的結果是得到一個包辨別符,其格式為

<label>.<hash>

機構審批是在Hyperledger Fabric 2.0中增加的步驟。在之前的版本中我們可以讓一個機構執行個體化鍊碼。在Fabric 2.0中,需要機構顯式地審批鍊碼。需要多少機構審批則是由生命周期背書政策來決定,預設情況下設定為需要大多數機構(超過半數)。如果Fabric網絡中包含兩個機構,那麼就需要這兩個機構同時準許。在審批過程中需要排序節點的參與,因為每次審批都會生成一個新的區塊,這意味着所有的peer節點都了解審批的狀态。

當審批環節完成後,我們就需要指定要在哪個通道上部署鍊碼。這需要送出一些資訊,例如背書政策、是否需要執行Init代碼等等。在這裡也有些與Fabric 1.4不同的地方:在Fabric 1.4中,當鍊碼執行個體化時會自動調用鍊碼的Init方法,然而在Fabric 2.0中,需要在送出鍊碼後顯式地調用Init方法。

在準許機構達到指定數量後,鍊碼就可以送出了。我們現在就進入了最後一個步驟:鍊碼送出。

鍊碼送出可以由任何機構發起。該流程首先需要準許機構的背書,然後交易送出到排序服務并生成新的區塊,最後所有的對等節點在賬本中送出該區塊。

現在鍊碼就可以使用了。

2、First Network和SACC鍊碼簡介

出于完整性考慮,下面給出關于First Network和SACC鍊碼的一些資訊,這些内容都來自fabric-samples倉庫。

First Network是一個雙機構設定,每個機構中包含兩個peer節點。通道mychannel建立後加入所有的4個peer節點。在byfn.sh中完整的實作了First Network的部署,并包含一些可選的參數。在下面的示範中,我們不使用預設的鍊碼(在Fabric 1.4中式chaincode_example02,在Fabric 2.0中式abstore),而是使用SACC鍊碼。

SACC式Simple Asset ChainCode的縮寫,表示簡單資産鍊碼。它在賬本中模拟一個鍵/值存儲。當初次部署後,需要一個初始的鍵/值對。SACC鍊碼定義了兩個方法:

Set()

Get()

,分别用來設定或讀取某個鍵的值。

好了,現在我們可以開始示範Fabric 1.4和Fabric 2.0中鍊碼操作的不同了。

3、Fabric 1.4.4鍊碼操作示範

我們首先以無鍊碼方式(使用-n選項)啟動First Network,然後我們再加載SACC鍊碼以便聚焦鍊碼的生命周期。

下面是示範步驟:

  • 無鍊碼方式啟動First Network
  • 在指定的peer節點上安裝SACC鍊碼
  • 在mychannel通道上執行個體化SACC鍊碼并查詢結果
  • 調用set()設定新值并從另一個peer節點查詢結果

STEP 1:首先啟動First Network:

cd fabric-samples/first-network
./byfn.sh up -n           

上面的指令會啟動First Network、建立通道mychannel并将所有的peer節點加入該通道。注意在Fabric 1.4.4中,First Network使用solo排序服務實作,隻有一個排序節點。另外,我們看到有4個對等節點在運作,以及一個CLI用于鍊碼操作。

實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

現在我們可以開始鍊碼部署操作。

STEP 2:在指定peer節點上安裝鍊碼

這裡我們跳過打包環節,直接在目标節點peer.org1和peer0.org2上安裝鍊碼,因為在這個示範中我們隻需要這兩個節點進行鍊碼調用和查詢。

# peer0.org1
docker exec cli peer chaincode install -n mycc -v 1 \
  -p github.com/chaincode/sacc
  
# peer0.org2  
docker exec \
  -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
  -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 -e CORE_PEER_LOCALMSPID="Org2MSP" \
  -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  cli peer chaincode install -n mycc -v 1 -p github.com/chaincode/sacc           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

STEP 3:在通道mychannel上執行個體化鍊碼并查詢

注意在sacc鍊碼中有Init()代碼。當我們執行個體化鍊碼時,我們需要提供Init()所需的參數:

docker exec cli peer chaincode instantiate -o orderer.example.com:7050 --tls \
  --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  -C mychannel -n mycc -v 1 -c '{"Args":["name","kc"]}' \
  -P "AND ('Org1MSP.peer','Org2MSP.peer')"           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

如果現在看看peer節點的日志,我們可以看到出了新區塊#3。

實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

在鍊碼執行個體化之後,我們可以查詢:

docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

STEP 4:調用set()設定新值并從另一個節點查詢

出于示範目的,我們在peer0.org1上調用

set()

,然後在peer0.org2上調用

get()

,以此說明鍊碼是否工作正常。

# peer0.org1
docker exec cli peer chaincode invoke -o orderer.example.com:7050 --tls \
  --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  --peerAddresses peer0.org1.example.com:7051 \
  --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
  --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  -C mychannel -n mycc -c '{"Args":["set","name","Peter"]}'
  
  # peer0.org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
  -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \
  -e CORE_PEER_LOCALMSPID="Org2MSP" \
  -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

4、Fabric 2.0鍊碼操作示範

類似的,在Fairc 2.0.0中,我們也先以無鍊碼方式啟動First Network,然後再啟動SACC鍊碼以便聚焦鍊碼的生命周期。

  • 打包SACC鍊碼
  • 在指定peer節點上安裝SACC鍊碼包
  • 機構審批鍊碼
  • 在mychannel通道上送出鍊碼
  • 調用SACC鍊碼的Init方法
  • 調用SACC鍊碼的set方法并從另一個peer節點查詢結果

STEP 1:以無鍊碼方式啟動First Network:

cd fabric-samples/first-network
./byfn.sh up -n           

現在First Network已經啟動,通道mychannel已經建立并且所有peer節點已經加入mychannel通道。注意在Fabric 2.0.0中,First Network使用Raft作為排序服務,所有5個排序節點都在運作。在這個示範中,我們隻使用orderer.example.com,不過使用其他排序節點也是一樣的。

實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

STEP 2:打包SACC鍊碼

首先我們處理依賴問題:

cd fabric-sample/chaincode/sacc
GO111MODULE=on go mod vendor
cd fabric-sample/first-network           

然後打包鍊碼:

docker exec cli peer lifecycle chaincode package sacc.tar.gz \
  --path github.com/hyperledger/fabric-samples/chaincode/sacc/ \
  --label sacc_1           

在CLI容器内可以看到生成了新的檔案sacc.tar.gz:

實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

STEP 3:在指定peer節點上安裝SACC鍊碼包

現在我們在peer0.org1和peer0.org2上安裝SACC練馬報,因為在這個示範中我們隻需要使用這兩個節點進行鍊碼調用和查詢。

# peer0.org1
docker exec cli peer lifecycle chaincode install sacc.tar.gz

# peer0.org2
docker exec \
  -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
  -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \
  -e CORE_PEER_LOCALMSPID="Org2MSP" \
  -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  cli peer lifecycle chaincode install sacc.tar.gz           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

我們會收到鍊碼包的辨別符,在下面的鍊碼審批階段會用到。我們收到的鍊碼辨別符為:

sacc_1:bf57…6399

我們可以使用

peer lifecycle chaincode queryinstalled

指令随時檢查節點上的鍊碼安裝情況,如果我們需要找對外連結碼包的辨別ID,這個指令會很有用。

# peer0.org1
docker exec cli peer lifecycle chaincode queryinstalled

# peer0.org2
docker exec \
  -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
  -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \
  -e CORE_PEER_LOCALMSPID="Org2MSP" \
  -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  cli peer lifecycle chaincode queryinstalled           

STEP 4:審批鍊碼

根據預設政策,需要超過半數的機構審批鍊碼後才能向通道送出鍊碼,具體可參考configtx.yaml中的

Application/Policies/LifecycleEndorsement

部分。目前的設定中包含兩個機構,是以需要兩個機構同時準許鍊碼。

首先是Org1準許鍊碼:

docker exec cli peer lifecycle chaincode approveformyorg \
  --tls \
  --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  --channelID mychannel --name mycc --version 1 \
  --init-required --sequence 1 --waitForEvent --package-id ${PACKAGE_ID}           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

如果我們現在看下peer節點的日志,可以看到出了新塊#3。

實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

類似的,我們讓Org2準許鍊碼:

docker exec \
  -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
  -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \
  -e CORE_PEER_LOCALMSPID="Org2MSP" \
  -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  cli peer lifecycle chaincode approveformyorg \
  --tls \
  --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  --channelID mychannel --name mycc --version 1 --init-required \
  --sequence 1 --waitForEvent --package-id ${PACKAGE_ID}           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

不出意外,可以看到出了新塊block#4:

實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

注意我們在approval指令中指定了init相關的參數,以便向SACC鍊碼的Init方法傳入所需的參數。

可以随時使用如下指令檢視鍊碼的送出狀态:

docker exec cli peer lifecycle chaincode checkcommitreadiness \
  --channelID mychannel --name mycc --version 1 --sequence 1 --output json           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

兩個機構都已經準許了鍊碼,現在可以送出了。

STEP 5:向通道mychannel送出鍊碼

鍊碼送出可以在一個peer節點上完成:

docker exec cli peer lifecycle chaincode commit -o orderer.example.com:7050 \
  --tls \
  --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  --peerAddresses peer0.org1.example.com:7051 \
  --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
  --peerAddresses peer0.org2.example.com:9051 \
  --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  --channelID mychannel --name mycc --version 1 --sequence 1 --init-required           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

可以看到出了新塊#5:

實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

注意我們在commit指令中已經包含了init所需的參數。

同樣,我們可以使用querycommited指令來檢視鍊碼的送出狀态:

docker exec cli peer lifecycle chaincode querycommitted --channelID mychannel --name mycc           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

在鍊碼送出到通道之後,鍊碼的生命周期就完成了,鍊碼已經可以通路。現在我們回到鍊碼的調用和查詢,這和之前的版本是一緻的。

STEP 6:調用鍊碼的Init方法

SACC鍊碼的Init方法需要首先調用。

docker exec cli peer chaincode invoke -o orderer.example.com:7050 \
  --tls \
  --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  --peerAddresses peer0.org1.example.com:7051 \
  --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
  --peerAddresses peer0.org2.example.com:9051 \
  --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  -C mychannel -n mycc --isInit -c '{"Args":["name","kc"]}'           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

現在可以查詢 鍊碼:

docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

STEP 7:調用鍊碼的set()方法并從另一個peer節點查詢

和之前一樣,我們在peer0.org1上調用鍊碼的

set()

方法,在peer0.org2上進行查詢:

# peer0.org1
docker exec cli peer chaincode invoke \
  -o orderer.example.com:7050 \
  --tls \
  --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  --peerAddresses peer0.org1.example.com:7051 \
  --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
  --peerAddresses peer0.org2.example.com:9051 \
  --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  -C mychannel -n mycc -c '{"Args":["set","name","Peter"]}'
  
  # peer0.org2
docker exec \
  -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
  -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \
  -e CORE_PEER_LOCALMSPID="Org2MSP" \
  -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'           
實戰Fabric 2.0 鍊碼操作1、鍊碼操作:Fabric 1.4 vs Fabric 2.0

一切正常。

原文連結:

Hyperledger Fabric 2.0鍊碼操作詳解 — 彙智網