golanghtml
nodejs:https://fabric-sdk-node.github.io/java
java:https://github.com/hyperledger/fabric-sdk-javanode
https://hyperledger-fabric.readthedocs.io/en/latest/chaincode4ade.htmlgit
Chaincode是一個用Go編寫的程序,後期也將支持Java中實現了一個規定的接口。github
鏈碼運行在與認可對等體進程隔離的安全Docker容器中。 Chaincode經過應用程序提交的交易來初始化和管理分類賬狀態。golang
鏈碼一般處理網絡成員所贊成的業務邏輯,所以可被視爲「智能合同」。 由鏈碼建立的狀態僅限於該鏈碼,不能被另外一個鏈碼直接訪問。 然而,在同一個網絡中,給定適當的權限,鏈碼能夠調用另外一個鏈碼來訪問其狀態。docker
咱們對鏈碼提供兩個不一樣的觀點。 一個,從應用程序開發人員的角度來看,開發一個名爲Chaincode for Developers的塊鏈應用程序/解決方案,另外一個是針對負責管理塊鏈網絡的塊鏈網絡運營商的運營商鏈碼,以及誰將利用Hyperledger Fabric API 鏈式代碼的安裝,實例化和升級,但可能不會涉及開發鏈碼應用程序。api
每一個鏈碼程序都必須實現Chaincode接口,其響應於接收到的事務調用其方法。 特別地,當鏈碼接收到instantiate
實例化或upgrade
升級事務時,調用Init方法,使得鏈碼能夠執行任何須要的初始化,包括應用程序狀態的初始化。 調用Invoke方法響應於接收到一個調用事務來處理事務提議。安全
初始化:http://godoc.org/github.com/hyperledger/fabric/core/chaincode/shim#Chaincodebash
chaincode「shim」API中的另外一個接口是ChaincodeStubInterface,用於訪問和修改分類賬,並在鏈碼之間進行調用。
api:http://godoc.org/github.com/hyperledger/fabric/core/chaincode/shim#ChaincodeStub
基本鍵值對鏈碼
安裝go,而且配置了環境變量
如今,要爲chaincode應用程序建立一個名爲$ GOPATH / src /的子目錄的目錄。 以及建立源文件
mkdir -p $GOPATH/src/sacc && cd $GOPATH/src/sacc
touch sacc.go
package main import ( "fmt" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/protos/peer" )
// Init is called during chaincode instantiation to initialize any data. func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response { }
注意,chaincode升級還會調用此功能。 當編寫一個將升級現有的鏈碼時,請確保適當地修改Init函數。 特別是,若是沒有「遷移」,或者沒有任何內容做爲升級的一部分進行初始化,請提供一個空的「Init」方法。
接下來,咱們將使用ChaincodeStubInterface.GetStringArgs函數檢索Init調用的參數,並檢查其有效性。在咱們的例子中,咱們期待着一個鍵值對。
接下來,如今咱們已經肯定了調用有效,咱們將把初始狀態存儲在分類賬中。爲此,咱們將使用鍵和值做爲參數傳遞給ChaincodeStubInterface.PutState。假設一切順利,返回一個指示初始化的peer.Response對象是成功的。
首先,咱們添加Invoke函數的簽名。
// Invoke is called per transaction on the chaincode. Each transaction is // either a 'get' or a 'set' on the asset created by Init function. The 'set' // method may create a new asset by specifying a new key-value pair. func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response { }
與上面的Init函數同樣,咱們須要從ChaincodeStubInterface中提取參數。
Invoke函數的參數將是要調用的chaincode應用程序函數的名稱。在例子中,咱們的應用程序將只有兩個函數:set和get,它容許設置一個資產的值或者檢索它的當前狀態。
咱們首先調用ChaincodeStubInterface.GetFunctionAndParameters來提取該代碼應用功能的函數名和參數。
// Invoke is called per transaction on the chaincode. Each transaction is // either a 'get' or a 'set' on the asset created by Init function. The Set // method may create a new asset by specifying a new key-value pair. func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response { // Extract the function and args from the transaction proposal fn, args := stub.GetFunctionAndParameters() }
接下來,咱們將函數名稱設置爲get或get,並調用這些鏈代碼應用程序函數,經過shim.Success或shim.Error函數返回一個適當的響應,該函數將響應序列化爲gRPC protobuf消息。
如上所述,咱們的chaincode應用程序實現了能夠經過Invoke函數調用的兩個函數。如今咱們來實現這些功能。請注意,如上所述,爲了進入分類賬狀態,咱們將利用chaincode shim API的ChaincodeStubInterface.PutState和ChaincodeStubInterface.GetState函數。
最後,咱們須要添加main函數,這將調用shim.Start函數。這是整個chaincode程序源碼。
go get -u --tags nopkcs11 github.com/hyperledger/fabric/core/chaincode/shim go build --tags nopkcs11
一般鏈式代碼由對等體啓動和維護。然而,在「開發模式」中,鏈碼由用戶構建和啓動。在快速代碼/構建/運行/調試周期週轉期間的鏈碼開發階段,此模式很是有用。
咱們經過利用樣例開發網絡的預生成的訂單和渠道工件來啓動「開發模式」。所以,用戶能夠當即跳入編譯鏈碼和調用的過程。
參看05/06中安裝https://hyperledger-fabric.readthedocs.io/en/latest/samples.html
轉到fabric-samples的chaincode-docker-devmode目錄:
cd chaincode-docker-devmode
咱們須要四個Docker圖像,以便「開發模式」針對提供的腳本運行。若是您安裝了fabric-samples repo克隆,並遵循下載指令 - 特定於二進制文件的說明,那麼您應該在本地安裝必要的Docker映像
如今打開三個終端,並導航到每一個的chaincode-docker-devmode目錄。
終端1、開啓網絡
docker-compose -f docker-compose-simple.yaml up
以上使用SingleSampleMSPSolo訂戶配置文件啓動網絡,並以「開發模式」啓動對等體。它還啓動兩個額外的容器 - 一個用於鏈碼環境和一個與鏈碼交互的CLI。用於建立和鏈接通道的命令嵌入在CLI容器中,所以咱們能夠當即跳轉到鏈碼調用。
終端2、構建並啓動鏈碼
docker exec -it chaincode bash
#後root@d2629980e76b:/opt/gopath/src/chaincode#
cd sacc
go build
運行鏈碼
CORE_PEER_ADDRESS=peer:7051 CORE_CHAINCODE_ID_NAME=mycc:0 ./sacc
鏈碼從對等體和鏈碼日誌開始,表示成功註冊對等體。請注意,在此階段,鏈碼與任何頻道都不相關。這在後續步驟中使用實例化命令完成。
終端3、使用鏈碼
即便您處於--peer-chaincodedev模式,您仍然必須安裝鏈碼,以便生命週期系統鏈碼能夠正常檢查。在-peer-chaincodedev模式下,此要求可能會被刪除。
咱們將利用CLI容器來驅動這些調用。
docker exec -it cli bash peer chaincode install -p chaincodedev/chaincode/sacc -n mycc -v 0 peer chaincode instantiate -n mycc -v 0 -c '{"Args":["a","10"]}' -C myc
使用
peer chaincode invoke -n mycc -c '{"Args":["set", "a", "20"]}' -C myc peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc