Hyperledger Fabric 2.0最近已經發布,其中最引人關注的一點是鏈碼操做。官方文檔雖然對此提供了詳細的說明,但本文將經過與Hyperledger Fabric前一個版本中鏈碼操做的對比,來幫助你更好的理解新版本中鏈碼操做的不一樣之處以及幕後的一些技術細節。git
咱們將首先快速介紹在HF 1.4和HF 2.0中的整個鏈碼操做過程。docker
鏈碼操做指的是在Hyperledger fabric網絡通道上部署鏈碼的操做,這樣區塊鏈以外的應用能夠調用或查詢鏈碼方法。在鏈碼開發完成並測試後,首先須要將Fabric鏈碼安裝到指定的peer節點。在這個階段鏈碼還不能使用,直到鏈碼被提交(Fabric 2.0中的術語)到通道中或在通道上實例化(Fabric 1.4中的術語),這樣鏈碼就能夠被受權用戶訪問了。json
下面是兩個版本的Hyperledger Fabric中鏈碼操做流程的對比圖:網絡
在Hyperledger Fabric 1.4中,鏈碼操做過程包含如下步驟:打包、安裝、實例化。若是鏈碼屬於多個參與方,那麼就須要打包這一環節。若是不存在多方屬主的問題,那麼直接安裝鏈碼就能夠(其中隱含了打包環節)。在Fabric鏈碼安裝時須要指定要安裝鏈碼的目標節點。app
在這個階段,安裝好的Fabric鏈碼還不能使用,由於它尚未在通道上實例化。當Fabric鏈碼包被安裝在指定的節點上以後,咱們就能夠執行鏈碼實例化操做,從而讓鏈碼在通道上可用。技術上來講,鏈碼實例化實際上就是調用LSCC系統鏈碼的方法來初始化通道上的一個鏈碼。區塊鏈
Fabric鏈碼實例化以後就可使用了,能夠接受通道上的調用或查詢請求。測試
下面咱們看在Hyperledger Fabric 2.0中的鏈碼操做步驟有何區別。ui
寬泛地來說,在Fabric 2.0中鏈碼操做基本遵循一樣的流程,可是在命令和某些後臺處理中作了一些調整。總體的流程能夠分爲四個步驟:打包、安裝、機構審批、鏈碼提交。大體能夠認爲前兩個環節對應於Fabric 1.4中的鏈碼安裝,後面兩個環節對應於Fabric 1.4中的鏈碼實例化,可是實例化(instantiation)這個詞再也不用了。3d
鏈碼打包這一步是建立一個打包文件(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方法。
在批准機構達到指定數量後,鏈碼就能夠提交了。咱們如今就進入了最後一個步驟:鏈碼提交。
鏈碼提交能夠由任何機構發起。該流程首先須要批准機構的背書,而後交易提交到排序服務並生成新的區塊,最後全部的對等節點在帳本中提交該區塊。
如今鏈碼就可使用了。
出於完整性考慮,下面給出關於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中鏈碼操做的不一樣了。
咱們首先以無鏈碼方式(使用-n選項)啓動First Network,而後咱們再加載SACC鏈碼以便聚焦鏈碼的生命週期。
下面是演示步驟:
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用於鏈碼操做。
如今咱們能夠開始鏈碼部署操做。
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/Admin@org2.example.com/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
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')"
若是如今看看peer節點的日誌,咱們能夠看到出了新區塊#3。
在鏈碼實例化以後,咱們能夠查詢:
docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'
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/Admin@org2.example.com/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"]}'
相似的,在Fairc 2.0.0中,咱們也先以無鏈碼方式啓動First Network,而後再啓動SACC鏈碼以便聚焦鏈碼的生命週期。
下面是演示步驟:
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,不過使用其餘排序節點也是同樣的。
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:
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/Admin@org2.example.com/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
咱們會收到鏈碼包的標識符,在下面的鏈碼審批階段會用到。咱們收到的鏈碼標識符爲: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/Admin@org2.example.com/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}
若是咱們如今看下peer節點的日誌,能夠看到出了新塊#3。
相似的,咱們讓Org2批准鏈碼:
docker exec \ -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/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}
不出意外,能夠看到出了新塊block#4:
注意咱們在approval命令中指定了init相關的參數,以便向SACC鏈碼的Init方法傳入所需的參數。
能夠隨時使用以下命令查看鏈碼的提交狀態:
docker exec cli peer lifecycle chaincode checkcommitreadiness \ --channelID mychannel --name mycc --version 1 --sequence 1 --output json
兩個機構都已經批准了鏈碼,如今能夠提交了。
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
能夠看到出了新塊#5:
注意咱們在commit命令中已經包含了init所需的參數。
一樣,咱們可使用querycommited命令來查看鏈碼的提交狀態:
docker exec cli peer lifecycle chaincode querycommitted --channelID mychannel --name mycc
在鏈碼提交到通道以後,鏈碼的生命週期就完成了,鏈碼已經能夠訪問。如今咱們回到鏈碼的調用和查詢,這和以前的版本是一致的。
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"]}'
如今能夠查詢 鏈碼:
docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'
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/Admin@org2.example.com/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"]}'
一切正常。