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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Fabric中的Transient Data与Private Data

發(fā)布時間:2024/8/23 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Fabric中的Transient Data与Private Data 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在Hyperledger Fabric中有兩個相關(guān)的概念:私有數(shù)據(jù)(Private Data)和暫態(tài)數(shù)據(jù)(Transient Data)。本文提供四個示例程序,分別對應(yīng)私有數(shù)據(jù)和暫態(tài)數(shù)據(jù)的四種組合使用方式,并通過觀察賬本的交易以及世界狀態(tài)數(shù)據(jù)庫,理解為什么在使用私有數(shù)據(jù)時應(yīng)當(dāng)采用暫態(tài)數(shù)據(jù)作為輸入。

從技術(shù)上講,私有數(shù)據(jù)和暫態(tài)數(shù)據(jù)是兩個不同的概念。私有數(shù)據(jù)是考慮如何在通道的部分機(jī)構(gòu)之間共享數(shù)據(jù),而暫態(tài)數(shù)據(jù)則是使用私有數(shù)據(jù)時的一種輸入方法。有趣的是,這兩者并沒有直接的關(guān)系,雖然在現(xiàn)實(shí)中,當(dāng)我們需要安全的使用私有數(shù)據(jù)時,通常都應(yīng)當(dāng)使用暫態(tài)數(shù)據(jù)作為輸入。

Hyperledger Fabric區(qū)塊鏈開發(fā)教程:?Fabric Node.js開發(fā)詳解?|?Fabric Java開發(fā)詳解?|?Fabric Golang開發(fā)詳解

1、基本概念

先讓我們重溫一下在演示程序中將要用到的一些核心概念。

賬本:在Hyperledger Fabric中,當(dāng)一個peer節(jié)點(diǎn)加入通道后,就會維護(hù)一個賬本的副本。賬本包含一個用于保存區(qū)塊的區(qū)塊鏈數(shù)據(jù)結(jié)構(gòu),以及一個用于保存最新狀態(tài)的世界狀態(tài)數(shù)據(jù)庫。當(dāng)peer節(jié)點(diǎn)從排序服務(wù)收到一個新的區(qū)塊并且驗(yàn)證成功后,peer節(jié)點(diǎn)就將區(qū)塊提交進(jìn)賬本,并根據(jù)區(qū)塊中每個交易的
RWSet來更新相應(yīng)的世界狀態(tài)。

基于共識機(jī)制,在一個通道中,不同的peer節(jié)點(diǎn)上的賬本的大部分都是一致的。不過有一個例外,Fabric支持在部分通道之間存在的私有數(shù)據(jù)。

私有數(shù)據(jù):在一個通道內(nèi)有時會需要僅在部分機(jī)構(gòu)之間共享數(shù)據(jù)。Hyperledger Fabric引入私有數(shù)據(jù)的目的就是滿足這一需求。通過定義數(shù)據(jù)集,我們可以聲明私有數(shù)據(jù)實(shí)現(xiàn)的機(jī)構(gòu)子集,同時所有節(jié)點(diǎn)(包括在機(jī)構(gòu)子集之外的其他節(jié)點(diǎn))都會保存私有數(shù)據(jù)哈希的記錄以便作為數(shù)據(jù)存在的證據(jù)或者用于審計(jì)目的。

可以利用鏈碼API來使用私有數(shù)據(jù)。我們在示例代碼中使用PutPrivateData和GetPrivateData這兩個API。作為對比,我們使用PutState和GetState完成對公共狀態(tài)的讀寫。

在Fabric 2.0中,會為每個機(jī)構(gòu)準(zhǔn)備一個隱含的數(shù)據(jù)集。本教程將利用這個隱含的數(shù)據(jù)集,因此我們不需要單獨(dú)的數(shù)據(jù)集定義文件。

Fabric的賬本結(jié)構(gòu)以及私有數(shù)據(jù)的位置如下圖所示,在后面的演示代碼中,我們將查看交易以及世界狀態(tài)數(shù)據(jù)庫的內(nèi)容:

暫態(tài)數(shù)據(jù):許多鏈碼函數(shù)在被調(diào)用時需要額外的輸入數(shù)據(jù)。在大多數(shù)情況下我們會在調(diào)用函數(shù)時傳入一組參數(shù),而鏈碼參數(shù),包括函數(shù)名和函數(shù)參數(shù),都會作為有效交易的一部分保存在區(qū)塊內(nèi),因此將永久性的存在于賬本中。如果出于某種原因我們不希望在鏈上永久保存參數(shù)列表,我們就可以使用暫態(tài)數(shù)據(jù)。暫態(tài)數(shù)據(jù)是一種可以向鏈碼函數(shù)傳參但不需要將其保存在交易記錄中的輸入方法。當(dāng)使用暫態(tài)數(shù)據(jù)時,需要一個特殊的鏈碼API即GetRansient方法來讀取暫態(tài)數(shù)據(jù)。我們接下來將在演示代碼中看到。

因此,鏈碼的設(shè)計(jì)需要根據(jù)業(yè)務(wù)需求設(shè)計(jì)鏈碼,決定哪些數(shù)據(jù)應(yīng)當(dāng)作為正常參數(shù)輸入并記錄在交易中,哪些數(shù)據(jù)應(yīng)當(dāng)作為暫態(tài)數(shù)據(jù)輸入而不必記錄在鏈上。

私有數(shù)據(jù)與暫態(tài)數(shù)據(jù)的關(guān)系:私有數(shù)據(jù)與暫態(tài)數(shù)據(jù)并不是直接相關(guān)的,我們可以只使用私有數(shù)據(jù)而不利用暫態(tài)數(shù)據(jù)作為輸入,也可以在非私有數(shù)據(jù)中使用暫態(tài)數(shù)據(jù)。因此我們可以得到示例中的四種應(yīng)用場景并觀察每種場景下的結(jié)果。

私有數(shù)據(jù)與暫態(tài)數(shù)據(jù)的關(guān)系如下圖所示:

輸入方法的選擇以及是否是否私有數(shù)據(jù)依賴于具體的業(yè)務(wù)需求,因?yàn)殒湸a函數(shù)反應(yīng)了真實(shí)的業(yè)務(wù)交易。我們可以選擇普通的參數(shù)列表、暫態(tài)數(shù)據(jù)或者同時使用兩種方式的輸入,也可以向公共狀態(tài)或者私有數(shù)據(jù)集寫入數(shù)據(jù)。我們需要的是正確地選擇需要使用的鏈碼API。

2、應(yīng)用場景概述

如前所述,我們將私有數(shù)據(jù)和暫態(tài)數(shù)據(jù)進(jìn)行2X2的組合,概述如下:

場景1:不使用私有數(shù)據(jù),不輸入暫態(tài)數(shù)據(jù)

在這種場景下,數(shù)據(jù)被寫入賬本中的公開狀態(tài)部分,所有的peer節(jié)點(diǎn)將保存相同的賬本數(shù)據(jù)。在鏈碼中使用PutState和GetState來訪問這部分?jǐn)?shù)據(jù)。當(dāng)我們調(diào)用鏈碼時,使用普通的參數(shù)列表指定輸入數(shù)據(jù)。

當(dāng)通道中的所有機(jī)構(gòu)都需要相同的數(shù)據(jù)時,適合采用這種方式。

場景2:使用私有數(shù)據(jù),不輸入暫態(tài)數(shù)據(jù)

在這種場景下,數(shù)據(jù)被寫入賬本中的私有數(shù)據(jù)部分,并且只有在私有數(shù)據(jù)集定義的機(jī)構(gòu)的peer節(jié)點(diǎn)上會保存數(shù)據(jù)。在鏈碼中我們使用PutPrivateData和GetPrivateData來訪問私有數(shù)據(jù)集。當(dāng)我們調(diào)用鏈碼時,使用普通的參數(shù)列表指定輸入數(shù)據(jù)。

當(dāng)應(yīng)用中存在對部分?jǐn)?shù)據(jù)的隱私需求,而對于輸入數(shù)據(jù)不敏感時,可以采用這種方式。

場景3:使用私有數(shù)據(jù),輸入暫態(tài)數(shù)據(jù)

類似于場景2,數(shù)據(jù)被寫入賬本中的私有數(shù)據(jù)部分,只有在私有數(shù)據(jù)集定義中的那些peer節(jié)點(diǎn)會保存這部分私有數(shù)據(jù)。在鏈碼中,我們使用PutPrivateData和GetPrivateData來訪問數(shù)據(jù)集。當(dāng)我們調(diào)用鏈碼時,采用暫態(tài)數(shù)據(jù)作為輸入,因此在鏈碼中我們需要使用GetTransient來處理輸入數(shù)據(jù)。

場景4:不使用私有數(shù)據(jù),輸入暫態(tài)數(shù)據(jù)

這是一個想象的場景,只是用來表明在不使用私有數(shù)據(jù)時,也可以使用暫態(tài)數(shù)據(jù)作為輸入。我們在鏈碼中使用PutState和GetState來將數(shù)據(jù)保存到賬本的公共狀態(tài),而采用暫態(tài)數(shù)據(jù)作為鏈碼調(diào)用的輸入?yún)?shù)。和之前一樣,我們在鏈碼中使用GetTransient方法來處理輸入數(shù)據(jù)。

3、演示環(huán)境搭建

在這些演示中我們使用Fabric 2.0,使用First Network作為Fabric網(wǎng)絡(luò)。我們采用CouchDB選項(xiàng)啟動網(wǎng)絡(luò),以便于查看世界狀態(tài)數(shù)據(jù)庫的內(nèi)容。我們將重點(diǎn)關(guān)注peer0.org1.example.com (couchdb port 5984) 和 peer0.org2.example.com (couchdb port 7984) 以便查看兩個機(jī)構(gòu)中的節(jié)點(diǎn)的行為。

在私有數(shù)據(jù)部分,我們使用Org1內(nèi)置的隱含私有數(shù)據(jù)集(_implicit_org_Org1MSP)。只有Org1中的peer節(jié)點(diǎn)可以保存私有數(shù)據(jù),而Org1和Org2中的節(jié)點(diǎn)都可以保存數(shù)據(jù)哈希。

我們修改了fabric-samples中的SACC鏈碼。SACC鏈碼有兩個函數(shù)set和get。為了展示私有數(shù)據(jù)和暫態(tài)數(shù)據(jù),我們創(chuàng)建以下函數(shù):

  • setPrivate:使用相同的參數(shù)列表,數(shù)據(jù)保存在Org1隱含的私有數(shù)據(jù)集
  • setPrivateTransient:使用暫態(tài)數(shù)據(jù)輸入,數(shù)據(jù)保存在Org1隱含的私有數(shù)據(jù)集
  • setTransient:使用暫態(tài)數(shù)據(jù)輸入,數(shù)據(jù)保存在公共狀態(tài)
  • getPrivate:提取保存在Org1隱含的私有數(shù)據(jù)集中的數(shù)據(jù)

修改后的SACC鏈碼如下:

/** Copyright IBM Corp All Rights Reserved** SPDX-License-Identifier: Apache-2.0*/package mainimport ("encoding/json""fmt""github.com/hyperledger/fabric-chaincode-go/shim""github.com/hyperledger/fabric-protos-go/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 if fn == "setPrivate" {result, err = setPrivate(stub, args)} else if fn == "setTransient" {result, err = setTransient(stub, args)} else if fn == "setPrivateTransient" {result, err = setPrivateTransient(stub, args)} else if fn == "getPrivate" {result, err = getPrivate(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 }func setPrivate(stub shim.ChaincodeStubInterface, args []string) (string, error) {if len(args) != 2 {return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value")}err := stub.PutPrivateData("_implicit_org_Org1MSP", args[0], []byte(args[1]))if err != nil {return "", fmt.Errorf("Failed to set asset: %s", args[0])}return args[1], nil }func setTransient(stub shim.ChaincodeStubInterface, args []string) (string, error) {type keyValueTransientInput struct {Key string `json:"key"`Value string `json:"value"`}if len(args) != 0 {return "", fmt.Errorf("Incorrect arguments. Expecting no data when using transient")}transMap, err := stub.GetTransient()if err != nil {return "", fmt.Errorf("Failed to get transient")}// assuming only "name" is processedkeyValueAsBytes, ok := transMap["keyvalue"]if !ok {return "", fmt.Errorf("key must be keyvalue")}var keyValueInput keyValueTransientInputerr = json.Unmarshal(keyValueAsBytes, &keyValueInput)if err != nil {return "", fmt.Errorf("Failed to decode JSON")}err = stub.PutState(keyValueInput.Key, []byte(keyValueInput.Value))if err != nil {return "", fmt.Errorf("Failed to set asset")}return keyValueInput.Value, nil }func setPrivateTransient(stub shim.ChaincodeStubInterface, args []string) (string, error) {type keyValueTransientInput struct {Key string `json:"key"`Value string `json:"value"`}if len(args) != 0 {return "", fmt.Errorf("Incorrect arguments. Expecting no data when using transient")}transMap, err := stub.GetTransient()if err != nil {return "", fmt.Errorf("Failed to get transient")}// assuming only "name" is processedkeyValueAsBytes, ok := transMap["keyvalue"]if !ok {return "", fmt.Errorf("key must be keyvalue")}var keyValueInput keyValueTransientInputerr = json.Unmarshal(keyValueAsBytes, &keyValueInput)if err != nil {return "", fmt.Errorf("Failed to decode JSON")}err = stub.PutPrivateData("_implicit_org_Org1MSP", keyValueInput.Key, []byte(keyValueInput.Value))if err != nil {return "", fmt.Errorf("Failed to set asset")}return keyValueInput.Value, 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 }// Get returns the value of the specified asset key func getPrivate(stub shim.ChaincodeStubInterface, args []string) (string, error) {if len(args) != 1 {return "", fmt.Errorf("Incorrect arguments. Expecting a key")}value, err := stub.GetPrivateData("_implicit_org_Org1MSP", 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)} }

4、Fabric私有數(shù)據(jù)和暫態(tài)數(shù)據(jù)演示

首先啟動First Network,不要部署默認(rèn)鏈碼,啟用CouchDB選項(xiàng):

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

當(dāng)看到所有容器(5個排序節(jié)點(diǎn),4個peer節(jié)點(diǎn),4個couchdb,一個CLI)啟動后:

創(chuàng)建一個新的鏈碼目錄:

cd fabric-samples/chaincode cp -r sacc sacc_privatetransientdemo cd sacc_privatetransientdemo

然后使用上面的鏈碼替換sacc.go。

在第一次運(yùn)行之前我們需要先加載依賴的模塊:

GO111MODULE=on go mod vendor

最后我們使用lifecycle chaincode命令部署這個鏈碼。

5、場景1演示:不使用Fabric私有數(shù)據(jù)和暫態(tài)數(shù)據(jù)輸入

場景1時最常用的一種:使用普通的參數(shù)列表作為鏈碼方法的輸入,然后將其保存在公共狀態(tài)中,所有peer節(jié)點(diǎn)持有完全相同的數(shù)據(jù)。我們調(diào)用鏈碼的set和get方法。

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","alice"]}'docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'

結(jié)果如下:

我們首先查看世界狀態(tài)。這個數(shù)據(jù)同時保存在peer0.org1.example.com 和peer0.org2.example.com的公共狀態(tài)中(mychannel_mycc)。

當(dāng)查看區(qū)塊鏈中的交易記錄時,我么看到WriteSet中的鍵/值對是:name/alice,采用base64編碼。

我們也可以看到調(diào)用鏈碼時的參數(shù)列表,3個base64編碼的參數(shù)分別是:set、name和alice。

和預(yù)期一樣,RWSet更新了公開狀態(tài),輸入?yún)?shù)被記錄在交易中。

6、場景2演示:使用私有數(shù)據(jù),不適用暫態(tài)數(shù)據(jù)輸入

在場景2中,鏈碼調(diào)用還是采用普通的參數(shù)列表,數(shù)據(jù)則保存在Org1的私有數(shù)據(jù)集。我們使用setPrivate和getPrivate訪問鏈碼

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":["setPrivate","name","bob"]}'docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["getPrivate","name"]}'

我們首先查看世界狀態(tài)。在peer0.org1.example.com中我們可以看到數(shù)據(jù)保存為私有數(shù)據(jù),
創(chuàng)建了兩個數(shù)據(jù)庫:一個用于實(shí)際數(shù)據(jù),一個用于數(shù)據(jù)哈希。在peer0.org2.example.com
上,我們看到只有哈希文件。


內(nèi)容的哈希在兩個機(jī)構(gòu)的節(jié)點(diǎn)上都是一樣的。此外,在peer0.org1.example.com中我們可以
看到調(diào)用鏈碼時輸入的數(shù)據(jù)。

當(dāng)查看區(qū)塊鏈中的交易記錄時,我們看到?jīng)]有RWSet。相反我們看到數(shù)據(jù)被應(yīng)用于
Org1隱含的數(shù)據(jù)集,它指向已經(jīng)保存在peer中的數(shù)據(jù),通過hash得以保護(hù)這部分?jǐn)?shù)據(jù)的隱私。

我們可以看到調(diào)用鏈碼時的參數(shù)列表。3個base64編碼的參數(shù)分別是:setPrivate、name、bob。

如果我們關(guān)系數(shù)據(jù)隱私,這可能存在問題。一方面數(shù)據(jù)保存在私有數(shù)據(jù)集中,這樣只有限定的機(jī)構(gòu)節(jié)點(diǎn)可以保存。另一方面,這部分隱私數(shù)據(jù)的鏈碼輸入?yún)s還是公開可見的,并且永久保存在所有peer節(jié)點(diǎn)的區(qū)塊鏈中。如果這不是你期望的,那么我們還需要將輸入數(shù)據(jù)隱藏掉。這就是使用暫態(tài)數(shù)據(jù)輸入的原因。

6、場景3演示:使用私有數(shù)據(jù)和暫態(tài)數(shù)據(jù)輸入

如果你希望確保數(shù)據(jù)輸入不會保存在鏈上,那么場景3是推薦的方式。在這種場景下,采用暫態(tài)數(shù)據(jù)輸入,并且數(shù)據(jù)保存在Org1的私有數(shù)據(jù)集。我們使用setPrivateTransient和getPrivate方法訪問鏈碼:

在我們的鏈碼中,我們實(shí)現(xiàn)函數(shù)時將暫態(tài)數(shù)據(jù)編碼為特定的JSON格式?{“key”:”some key”, “value”: “some value”}?(鏈碼134–137行)。我們也要求暫態(tài)數(shù)據(jù)包含一個keyvalue鍵(鏈碼149行)。為了在命令行調(diào)用
中使用暫態(tài)數(shù)據(jù),我們需要首先將其進(jìn)行base64編碼。

export KEYVALUE=$(echo -n "{\"key\":\"name\",\"value\":\"charlie\"}" | base64 | tr -d \\n)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":["setPrivateTransient"]}' \--transient "{\"keyvalue\":\"$KEYVALUE\"}"docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["getPrivate","name"]}'

結(jié)果如下:

同樣,我們首先查看世界狀態(tài)。這類似于我們在場景2中看到的內(nèi)容。實(shí)際的數(shù)據(jù)僅在peer0.org1.example.com保存,而哈希則在兩個peer節(jié)點(diǎn)中都有保存。注意修訂版本的值目前是2,而在場景2中的第一次修訂的值是1。是鏈碼調(diào)用促成了對數(shù)據(jù)的修訂。

類似于場景2,在區(qū)塊鏈上的交易記錄中,我們可以看到?jīng)]有Write Set。

我們也可以看到?jīng)]有調(diào)用鏈碼的參數(shù)列表。唯一的參數(shù)是鏈碼函數(shù)名,setPrivateTransient。
具體的調(diào)用數(shù)據(jù){“key”:”name”, “value”:”charlie”}沒有出現(xiàn)在區(qū)塊鏈上。

我們看到私有數(shù)據(jù)和隱私數(shù)據(jù)的組合提供了某種程度的數(shù)據(jù)隱私。

7、場景4演示:不適用私有數(shù)據(jù),使用暫態(tài)數(shù)據(jù)輸入

最后我們看一下想象的這個場景的演示。在場景3中,采用暫態(tài)數(shù)據(jù)作為數(shù)據(jù),
然后保存在賬本的公開狀態(tài)。我們使用setTransient和get訪問鏈碼:

export KEYVALUE=$(echo -n "{\"key\":\"name\",\"value\":\"david\"}" | base64 | tr -d \\n)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":["setTransient"]}' \--transient "{\"keyvalue\":\"$KEYVALUE\"}"docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'

結(jié)果如下:


可以看到公開狀態(tài)被更新,兩個節(jié)點(diǎn)目前有同樣的數(shù)據(jù)。注意修訂版本更新為2.

我們看到Write Set中的鍵/值對是name和david,base64編碼。

我們沒有看到參數(shù)中的輸入數(shù)據(jù),只看到調(diào)用的方法名setTransient。


原文鏈接:Hyperledger Fabric私有數(shù)據(jù)與暫態(tài)數(shù)據(jù) — 匯智網(wǎng)

原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。

總結(jié)

以上是生活随笔為你收集整理的Fabric中的Transient Data与Private Data的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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