日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hyperledger Fabric 1.0 实战开发系列 第三课 chaincode开发

發(fā)布時間:2025/3/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hyperledger Fabric 1.0 实战开发系列 第三课 chaincode开发 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

chaincode是由go語言寫的,實現(xiàn)了定義的接口。其他語言例如JAVA也是支持的。通過application體積的transaction,chaincode可以初始化并管理Ledger狀態(tài)。

一個chaincode創(chuàng)建的Ledger狀態(tài)是獨(dú)立的,不能被其他chaincode直接訪問。在合適的許可下,chaincode能夠調(diào)用在相同網(wǎng)絡(luò)下的其他chaincode用于訪問其Ledger狀態(tài)。

接下來,我們以chaincode開發(fā)者的視野來看看chaincode。下面我們以一個chaincode案例來看看chaincode Shim API的每一個方法。

1.Chaincode API

每一個chaincode需要實現(xiàn)Chaincode接口,其方法是用于響應(yīng)接收到的transaction。當(dāng)chaincode接收到instantiate或者upgrade transaction時Init方法被調(diào)用了,以便chaincode能夠執(zhí)行任何必要的初始化,包括application state的初始化。當(dāng)chaincode接收到invoke transaction時調(diào)用invoke方法,用于處理transaction proposal。

“shim”API中其他的接口是?ChaincodeStubInterface? 用于訪問及改變Ledger,以及在chaincode之間調(diào)用。

在本教程中,我們將通過實現(xiàn)簡單的chaincode應(yīng)用程序(管理簡單的“資產(chǎn)”)來演示這些API的使用。

2.簡單的資產(chǎn)chaincode

我們的application是一個基本的樣例chaincode,用于在Ledger上創(chuàng)建資產(chǎn)(鍵值對)。

推薦使用vscode進(jìn)行g(shù)o代碼編寫,

打開終端并運(yùn)行下面的命令:

sudo add-apt-repository ppa:ubuntu-desktop/ubuntu-make sudo apt-get update sudo apt-get install ubuntu-make 如果已經(jīng)安裝,運(yùn)行下面的命令:
umake web visual-studio-code

請注意,在安裝過程中, 你會問,給出路徑 insatllation 軟件包. 在那之后它會詢問提交您的權(quán)限,安裝 Visual Studio 代碼. 請按 ‘’ 若要安裝 (‘’ 表示接受條款和條件).


? ? ? 設(shè)置GOPATH

vscode安裝go插件時會提示GOPATH not set錯誤,則打開launch.json在里面env中設(shè)置?

安裝vscode go

在vscode應(yīng)用商店里面搜索go,點(diǎn)擊安裝即可。?

2.1 選擇代碼的位置

首選需要確定Go的環(huán)境被安裝以及被合適的配置。

為了簡單起見,我們使用以下命令:

mkdir -p $GOPATH/src/asset && cd $GOPATH/src/asset

接下來,我們創(chuàng)建源碼文件

touch asset.go

2.2 引入包

每一個chaincode都實現(xiàn)了Chaincode接口?<https://github.com/hyperledger/fabric/blob/master/core/chaincode/shim/interfaces.go#L28>,特別是Init以及Invoke函數(shù)。因此,我們引入

package mainimport ("fmt""github.com/hyperledger/fabric/core/chaincode/shim""github.com/hyperledger/fabric/protos/peer" )

2.3 初始化chaincode

我們的類名叫SimpleAsset

type SimpleAsset struct { }

接下來,我們事先Init函數(shù)

// Init is called during chaincode instantiation to initialize any data. func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {}

注:chaincode upgrade也調(diào)用這個函數(shù)。當(dāng)一個chaincode要升級時,確保合適修正Init函數(shù)。如果沒有需要遷移的東西,或者沒有需要在升級時初始化的東西,需要提供的空的init函數(shù)。

接下來,我們調(diào)用ChaincodeStubInterface.GetStringArgs方法獲取Init中需要的參數(shù),并檢查參數(shù)的有效性。我們期望獲取的參數(shù)是一個鍵值對。

// Init is called during chaincode instantiation to initialize any // data. Note that chaincode upgrade also calls this function to reset // or to migrate data, so be careful to avoid a scenario where you // inadvertently clobber your ledger's data! func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {// Get the args from the transaction proposalargs := stub.GetStringArgs()if len(args) != 2 {return shim.Error("Incorrect arguments. Expecting a key and a value")} }

接下來,由于我們的調(diào)用是有效的,我們將會在Ledger上存儲初始狀態(tài)。為了實現(xiàn)狀態(tài)的存儲,我們將會調(diào)用ChaincodeStubInterface.PutState方法,并把鍵值作為參數(shù)進(jìn)行輸入。假設(shè)一切都工作正常,則會返回一個peer.Response對象,表面初始化成功。


// Init is called during chaincode instantiation to initialize any // data. Note that chaincode upgrade also calls this function to reset // or to migrate data, so be careful to avoid a scenario where you // inadvertently clobber your ledger's data! func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {// Get the args from the transaction proposalargs := stub.GetStringArgs()if len(args) != 2 {return shim.Error("Incorrect arguments. Expecting a key and a value")}// Set up any variables or assets here by calling stub.PutState()// We store the key and the value on the ledgererr := stub.PutState(args[0], []byte(args[1]))if err != nil {return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))}return shim.Success(nil) }

2.4 調(diào)用chaincode

首先,添加Invoke函數(shù)簽名

// 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的函數(shù)那樣,我們需要通過ChaincodeStubInterface獲取參數(shù)。Invoke函數(shù)的參數(shù)就是需要調(diào)用chaincode應(yīng)用的名稱。在我們的例子中,我們的應(yīng)用有兩個簡單的函數(shù)set與get,允許asset的值被設(shè)定,同時允許獲取現(xiàn)在的狀態(tài)。我們首先調(diào)用ChaincodeStubInterface.GetFunctionAndParameters用來獲取chaincode應(yīng)用的函數(shù)名稱與參數(shù)。


// 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 proposalfn, args := stub.GetFunctionAndParameters()}

接著,我們設(shè)置set與get函數(shù)名稱,并調(diào)用這些chaincode應(yīng)用函數(shù),通過shim返回一個合適的響應(yīng)。Error函數(shù)將會把一個響應(yīng)序列化成gRPC protobuf消息。


// 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 proposalfn, args := stub.GetFunctionAndParameters()var result stringvar err errorif fn == "set" {result, err = set(stub, args)} else {result, err = get(stub, args)}if err != nil {return shim.Error(err.Error())}// Return the result as success payloadreturn shim.Success([]byte(result)) }

2.5 實現(xiàn)chaincode應(yīng)用

我們的chaincode應(yīng)用實現(xiàn)了兩個函數(shù),能夠通過Invoke進(jìn)行調(diào)用。接下來實現(xiàn)這些函數(shù)。就像我們上面所提到的,我使用chaincode shim API的ChaincodeStubInterface.PutState與ChaincodeStubInterface.GetState來訪問access的狀態(tài)。


// Set stores the asset (both key and value) on the ledger. If the key exists, // it will override the value with the new one func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {if len(args) != 2 {return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value")}err := stub.PutState(args[0], []byte(args[1]))if err != nil {return "", fmt.Errorf("Failed to set asset: %s", args[0])}return args[1], nil }// Get returns the value of the specified asset key func get(stub shim.ChaincodeStubInterface, args []string) (string, error) {if len(args) != 1 {return "", fmt.Errorf("Incorrect arguments. Expecting a key")}value, err := stub.GetState(args[0])if err != nil {return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err)}if value == nil {return "", fmt.Errorf("Asset not found: %s", args[0])}return string(value), nil }

2.6 合并上述代碼


package mainimport ("fmt""github.com/hyperledger/fabric/core/chaincode/shim""github.com/hyperledger/fabric/protos/peer" )// SimpleAsset implements a simple chaincode to manage an asset type SimpleAsset struct { }// Init is called during chaincode instantiation to initialize any // data. Note that chaincode upgrade also calls this function to reset // or to migrate data. func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {// Get the args from the transaction proposalargs := stub.GetStringArgs()if len(args) != 2 {return shim.Error("Incorrect arguments. Expecting a key and a value")}// Set up any variables or assets here by calling stub.PutState()// We store the key and the value on the ledgererr := stub.PutState(args[0], []byte(args[1]))if err != nil {return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))}return shim.Success(nil) }// 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 proposalfn, args := stub.GetFunctionAndParameters()var result stringvar err errorif fn == "set" {result, err = set(stub, args)} else { // assume 'get' even if fn is nilresult, err = get(stub, args)}if err != nil {return shim.Error(err.Error())}// Return the result as success payloadreturn shim.Success([]byte(result)) }// Set stores the asset (both key and value) on the ledger. If the key exists, // it will override the value with the new one func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {if len(args) != 2 {return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value")}err := stub.PutState(args[0], []byte(args[1]))if err != nil {return "", fmt.Errorf("Failed to set asset: %s", args[0])}return args[1], nil }// Get returns the value of the specified asset key func get(stub shim.ChaincodeStubInterface, args []string) (string, error) {if len(args) != 1 {return "", fmt.Errorf("Incorrect arguments. Expecting a key")}value, err := stub.GetState(args[0])if err != nil {return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err)}if value == nil {return "", fmt.Errorf("Asset not found: %s", args[0])}return string(value), nil }// main function starts up the chaincode in the container during instantiate func main() {if err := shim.Start(new(SimpleAsset)); err != nil {fmt.Printf("Error starting SimpleAsset chaincode: %s", err)} }

2.7 build chaincode

編譯chaincode

go get -u --tags nopkcs11 github.com/hyperledger/fabric/core/chaincode/shim go build --tags nopkcs11

接下來測試chaincode

2.8 使用dev模式測試

一般來說,peer啟動并持有chaincode。然而在開發(fā)模式下,chaincode由用戶build并啟動。在快速代碼/構(gòu)建/運(yùn)行/調(diào)試周期周轉(zhuǎn)期間的鏈碼開發(fā)階段,此模式非常有用。

我們通過為利用預(yù)先生成的order和channel artifacts來啟動一個簡單的開發(fā)網(wǎng)絡(luò)的“開發(fā)模式”。 因此,用戶可以立即編譯chaincode和調(diào)用函數(shù)。

3.安裝hyberLedger fabric 樣例

請先安裝hyberLedger fabric 樣例。

進(jìn)入fabric-samples以及chaincode-docker-devmode目錄

cd chaincode-docker-devmode

4.下載docker鏡像

我們需要四個Docker鏡像用于開發(fā)模式允許docker compose script.腳本,如果你已經(jīng)安裝了fabric-samples倉庫克隆,并且按照說明下載了platform-specific-binaries,接下來你應(yīng)該在本地按照Docker鏡像。輸入docker images命令去展示Docker鏡像。應(yīng)該能看到如下:


docker images REPOSITORY TAG IMAGE ID CREATED SIZE hyperledger/fabric-tools latest e09f38f8928d 4 hours ago 1.32 GB hyperledger/fabric-tools x86_64-1.0.0-rc1-snapshot-f20846c6 e09f38f8928d 4 hours ago 1.32 GB hyperledger/fabric-orderer latest 0df93ba35a25 4 hours ago 179 MB hyperledger/fabric-orderer x86_64-1.0.0-rc1-snapshot-f20846c6 0df93ba35a25 4 hours ago 179 MB hyperledger/fabric-peer latest 533aec3f5a01 4 hours ago 182 MB hyperledger/fabric-peer x86_64-1.0.0-rc1-snapshot-f20846c6 533aec3f5a01 4 hours ago 182 MB hyperledger/fabric-ccenv latest 4b70698a71d3 4 hours ago 1.29 GB hyperledger/fabric-ccenv x86_64-1.0.0-rc1-snapshot-f20846c6 4b70698a71d3 4 hours ago 1.29 GB

5.啟動網(wǎng)絡(luò)

docker-compose -f docker-compose-simple.yaml up

上述代碼啟動了包括SingleSampleMSPSolo?orderer profile的網(wǎng)絡(luò),同時啟動開發(fā)模式的peer。這個啟動了另外兩個容器,一個是chaincode的環(huán)境以及與chaincode交互的CLI。在CLI容器中進(jìn)行創(chuàng)建與加入channel的命令,因此我們可以開始chaincode的調(diào)用。

6.build與啟動chaincode

docker exec -it chaincode bash

進(jìn)入容器,

root@d2629980e76b:/opt/gopath/src/chaincode#

接下來,編譯chaincode

cd asset go build

現(xiàn)在運(yùn)行chaincode:

CORE_PEER_ADDRESS=peer:7051 CORE_CHAINCODE_ID_NAME=mycc:0 ./asset

peer啟動了chaincode,以及chaincode日志表明peer成功注冊了chaincode。該階段chaincode沒有與任何channel產(chǎn)生關(guān)聯(lián)。這在使用實例化命令的后續(xù)步驟中完成。

7.使用chaincode

即使現(xiàn)在在--peer-chaincodedev模式下,仍然需要安裝chaincode,以便生命周期的chaincode能夠正常檢查。

我們利用CLI容器去調(diào)用這些方法

docker exec -it cli bashpeer chaincode install -p chaincodedev/chaincode/asset -n mycc -v 0 peer chaincode instantiate -n mycc -v 0 -c '{"Args":["a","10"]}' -C myc

接下來改變a的值為20.

peer chaincode invoke -n mycc -c '{"Args":["set", "a", "20"]}' -C myc

最后查詢

peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc

8.測試新的chaincode

這個案例中,我們只實現(xiàn)了asset。我們可以很輕松的測試其他的chaincode通過吧這些chaincode加入到chaincode子目錄下,然后重啟網(wǎng)絡(luò)。此時,他們能夠在chaincode容器中被訪問。


總結(jié)

以上是生活随笔為你收集整理的Hyperledger Fabric 1.0 实战开发系列 第三课 chaincode开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 97欧美 | 色一情一乱一乱一区91av | 精品国产a线一区二区三区东京热 | 色多多视频在线观看 | 狠狠操中文字幕 | videos另类灌满极品另类 | 一级黄色影院 | 日本裸体xx少妇18在线 | 伊人影院网| 日韩三级精品 | 成人午夜在线 | 不卡欧美| 日本少妇网站 | 男人把女人捅爽 | 国产对白视频 | 国产精品免费无遮挡无码永久视频 | aaaa一级片| 无码任你躁久久久久久老妇 | 国产黄在线免费观看 | 国产日韩欧美视频 | 99久久婷婷国产一区二区三区 | julia在线播放88mav | 亚洲欧美一区二区在线观看 | 黄色aa大片 | 亚洲精品一品 | 国产又爽又黄视频 | 李华月全部毛片 | 久久精彩免费视频 | 日本丰满熟妇videossex一 | 国产xxxxx在线观看 | wwwyoujizz日本 | 亚洲国产一区二区在线观看 | 国产精品免费看久久久无码 | 日韩高清在线观看一区 | 91原创视频在线观看 | 无码人妻av一区二区三区波多野 | 伊人网狼人 | 国产又粗又猛又黄又爽 | 在线免费看污视频 | 亚洲天堂第一区 | 欧美人与动性xxxxx杂性 | 日韩不卡高清 | 超碰97人人干 | 欧美日韩一区视频 | 超碰520| 蜜臀精品| 亚洲自拍偷拍网站 | 免费在线黄色av | 精品久久久久久久中文字幕 | 日本免费小视频 | a久久久久久 | 国产香蕉精品 | 久久亚洲av无码西西人体 | 亚洲男人天堂网址 | 牛牛视频在线观看 | m3u8成人免费视频 | 国产精品网友自拍 | 人妻与黑人一区二区三区 | 最近免费中文字幕中文高清百度 | 中文字幕免费高清网站 | 精品视频在线观看 | 天天躁日日摸久久久精品 | 青青国产精品 | 日本在线三级 | 国产视频你懂得 | 中文字幕日本一区 | 国产三区四区视频 | 欧美性色网站 | 欧美精品亚洲一区 | 岛国一区二区 | 校园春色自拍偷拍 | 国产1页| 中文一区二区在线观看 | 久久高清无码电影 | 三级国产在线 | 免费一级网站 | 乌克兰av在线 | 99热这里只有精品3 成年人黄色网址 | 中文字幕人妻色偷偷久久 | 亚洲电影影音先锋 | 欧美一级精品 | 91福利在线免费观看 | 清纯唯美第一页 | 青娱乐福利视频 | 久久亚洲AV无码精品 | 欧美一卡二卡三卡四卡 | 高清视频一区二区 | 国产精品美女视频 | 精品一区二区成人免费视频 | 毛片你懂的 | 国产精品视频一区二区三区 | 深爱婷婷网 | 国产古装艳史毛片hd | 亚洲一级一级 | 国产夫妻性生活视频 | 91香蕉久久 | 日本久色 | 熟女人妻一区二区三区免费看 | 五月婷婷中文字幕 |