(翻譯)fabric1.2.1新特性-私有數(shù)據(jù)

私有數(shù)據(jù)

私有數(shù)據(jù)的應(yīng)用

在同一通道內(nèi)某一組織持有私有數(shù)據(jù),只要被認證的組織才可以訪問雀鹃。如果為了保持數(shù)據(jù)的隱私性而建立不同的通道,可能會增加通道以及相關(guān)鏈碼的維護成本。

私有數(shù)據(jù)集

一個私有數(shù)據(jù)集由兩個元素組成:

  1. 真實的私有數(shù)據(jù)
    只有在被認證的組織中的peer節(jié)點才能查看通過gossip協(xié)議通訊的私有數(shù)據(jù)屈呕。這些數(shù)據(jù)被保存在peer節(jié)點的私有數(shù)據(jù)庫(SideDB)中。共識節(jié)點中不包含私有數(shù)據(jù)棺亭。
  2. 數(shù)據(jù)的哈希值
    數(shù)據(jù)的哈希值被確認虎眨、排序公示、以及記錄在通道中每個peer節(jié)點賬本中镶摘。這些哈希數(shù)據(jù)作為交易的證據(jù)嗽桩,用于狀態(tài)的檢驗,以及審計

案例

考慮一個由5個組織組成的聯(lián)盟凄敢,在一個通道內(nèi)進行貿(mào)易交易:

  • 農(nóng)場主
  • 分銷商
  • 貨運商
  • 批發(fā)商
  • 零售商

a. 分銷商想與農(nóng)場主以及貨運商建立一條私有的機密的交易線路碌冶,交易數(shù)據(jù)不讓批發(fā)商以及零售商知道(不暴露交易價格)

b. 分銷商想與批發(fā)商建立一條私有的交易關(guān)系,應(yīng)為他向他們收取的費用低于零售商

b. 批發(fā)商想與零售商以及貨運商建立一條私有的交易關(guān)系

這樣在5個組織之間存在3條各自隱私的私有數(shù)據(jù)集合(private data collections PDC)

  1. PDC1:分銷商涝缝、農(nóng)場主和貨運商
  2. PDC2:分銷商和批發(fā)商
  3. PDC3:批發(fā)商扑庞、零售商和貨運商
    [圖片上傳失敗...(image-b10218-1532614924062)]

私有數(shù)據(jù)在fabric中的應(yīng)用

私有數(shù)據(jù)集合定義配置文件

私有數(shù)據(jù)集合的定義,使用控制臺命令 peer chaincode 鏈碼部署時俊卤,使用配置項 --collections-config 指定配置文件嫩挤,如果使用sdk部署鏈碼請參考相關(guān)文檔

集合定義配置文件由5個屬性組成:

  • name:集合名稱
  • policy:定義組織peer節(jié)點,允許使用簽名策略語法來持久化收集數(shù)據(jù)消恍,每個成員被包含在簽名策略列表中岂昭。
  • requiredPeerCount:在peer節(jié)點簽名背書并返回提案響應(yīng)給客戶端,成功傳送私有數(shù)據(jù)的最小認可節(jié)點狠怨。
  • maxPeerCount:為了數(shù)據(jù)冗余保存的目的约啊,需要同步保存私有數(shù)據(jù)的被認可的最大peer節(jié)點數(shù)量。如果一個可信節(jié)點宕機后佣赖,其他的持有私有冗余數(shù)據(jù)的節(jié)點依然可以提供數(shù)據(jù)請求訪問服務(wù)恰矩。
  • blockToLive:私有數(shù)據(jù)在sideDB保存時長。如果要一致保存憎蛤,則配置為0.

樣例如下:

[
{
   "name": "collectionMarbles",
   "policy": "OR('Org1MSP.member', 'Org2MSP.member')",
   "requiredPeerCount": 0,
   "maxPeerCount": 3,
   "blockToLive":1000000
},
{
   "name": "collectionMarblePrivateDetails",
   "policy": "OR('Org1MSP.member')",
   "requiredPeerCount": 0,
   "maxPeerCount": 3,
   "blockToLive":3
}
]

提交私有數(shù)據(jù)

授權(quán)peer節(jié)點之間私有數(shù)據(jù)的同步需要通過core.yaml配置文件中g(shù)ossip模塊下面的pvtData子模塊的配置項

  • pullRetryThreshold 限定將嘗試從peer節(jié)點中提取對應(yīng)于給定塊的私有數(shù)據(jù)的最大持續(xù)時間外傅,直到在沒有私有數(shù)據(jù)的情況下提交塊為止纪吮。
    • 如果請求節(jié)點在pullRetryThreshold限定時間內(nèi)檢索完私有數(shù)據(jù),節(jié)點將向賬本提交交易(包含私有數(shù)據(jù)的哈希值)萎胰,并在狀態(tài)數(shù)據(jù)庫保存私有數(shù)據(jù)碾盟,從邏輯上區(qū)分其他通道的狀態(tài)數(shù)據(jù)
    • 如果請求節(jié)點沒有在pullRetryThreshold限定時間內(nèi)檢索完私有數(shù)據(jù),節(jié)點將向他的區(qū)塊鏈(*不明白)提交交易(包含私有數(shù)據(jù)的哈希值)技竟,不包括私有數(shù)據(jù)冰肴。
    • 如果一個有權(quán)擁有私有數(shù)據(jù)的節(jié)點丟失了私有數(shù)據(jù),他將沒有能力為將來涉及到該私有數(shù)據(jù)的交易背書榔组。
  • transientstoreMaxBlockRetention 從當前賬本高度開始計算至設(shè)定值以及設(shè)定值倍數(shù)的提交區(qū)塊熙尉,刪除臨時保存的私有數(shù)據(jù)。
  • pushAckTimeout 等待每個peer節(jié)點推送背書私有數(shù)據(jù)確認信息的最長時間搓扯。
  • btlPullMargin 阻止實時拉取邊界检痰,用作緩沖區(qū)以防止peer節(jié)點嘗試從即將在下N個塊中清除的peer節(jié)點處獲取私有數(shù)據(jù)。這有助于新加入的peer節(jié)點更快的同步當前區(qū)塊鏈數(shù)據(jù)擅编。

背書

背書節(jié)點在向其他被認可的節(jié)點散播私有數(shù)據(jù)中扮演重要的角色攀细,他確保在通道中私有數(shù)據(jù)的有效性。為了協(xié)助散播爱态,在集合定義中的參數(shù)maxPeerCount 和requiredPeerCount 控制了傳播行為谭贪。

當背書節(jié)點不能成功的向小于requiredPeerCount配置的節(jié)點傳播私有數(shù)據(jù),他將向客戶端返回一個錯誤锦担。背書節(jié)點將嘗試向其他組織的節(jié)點散播私有數(shù)據(jù)俭识,以確保每個授權(quán)組織都有一份私有數(shù)據(jù)的拷貝。由于交易不是在鏈碼執(zhí)行時提交洞渔,因此背書節(jié)點和接收節(jié)點將私有數(shù)據(jù)的副本與區(qū)塊鏈一起存儲在本地臨時存儲中套媚,直到交易被提交。

在鏈碼中操作私有數(shù)據(jù)集合

鏈碼的shim APIs接口提供常用私有數(shù)據(jù)操作方法:

  • PutPrivateData(collection,key,value)
  • GetPrivateData(collection,key)
  • GetPrivateDataByRange(collection, startKey, endKey string)
  • GetPrivateDataByPartialCompositeKey(collection, objectType string, keys []string)
  • GetPrivateDataQueryResult(collection, query string) (*只有使用couchdb才能使用富查詢語句)

詳細接口說明

在鏈碼提案中傳遞私有數(shù)據(jù)

由于鏈碼提案保存在區(qū)塊鏈中磁椒,因此不要在鏈碼提案的主要部分中包含私有數(shù)據(jù)也很重要堤瘤。在鏈碼提案中有一塊特殊的區(qū)域叫做臨時區(qū)域,被用于從客戶端傳遞私有數(shù)據(jù)到peer節(jié)點調(diào)用鏈碼浆熔。鏈碼可以使用GetTransient()接口從臨時區(qū)域獲取數(shù)據(jù)本辐。

注意事項

  • 調(diào)用執(zhí)行范圍查詢或者富查詢鏈碼的客戶端應(yīng)該知道,他們可能會受到結(jié)構(gòu)集的子集医增,具體取決于私有數(shù)據(jù)的傳播慎皱。客戶端可以查詢多個peer節(jié)點叶骨,并比較結(jié)果以確定peer節(jié)點是否可能缺少某些結(jié)果集茫多。
  • 不支持在單個交易中執(zhí)行查詢(范圍查詢或者富查詢)并且更新數(shù)據(jù),由于查詢結(jié)果無法在無法訪問私有數(shù)據(jù)或者丟失私有數(shù)據(jù)的節(jié)點進行驗證忽刽。如果鏈碼同時調(diào)用查詢天揖、更新私有數(shù)據(jù)夺欲,提案請求將會返回一個錯誤。如果你的應(yīng)用程序可以容仍鏈碼執(zhí)行和驗證/提交時間之間的結(jié)果集更改宝剖,那么你可以調(diào)用一個鏈碼函數(shù)來執(zhí)行查詢洁闰,然后調(diào)用第二個鏈碼函數(shù)來進行更新。注意万细,在同一交易中,調(diào)用GetPrivateData()檢索單個鍵纸泄,并且調(diào)用PutPrivateData()更新數(shù)據(jù)赖钞,因為所有的peer節(jié)點可以一句散列鍵版本來驗證鍵讀取。
  • 注意聘裁,私有數(shù)據(jù)集合僅僅定義了哪些組織的節(jié)點被授權(quán)接收以及存儲私有數(shù)據(jù)雪营,意味著哪些peer節(jié)點可以被用于查詢私有數(shù)據(jù),私有數(shù)據(jù)集合本身不限制鏈碼中的訪問控制衡便。例如献起,如果非授權(quán)客戶端能夠在有權(quán)訪問私有數(shù)據(jù)的peer節(jié)點調(diào)用鏈碼,則鏈碼在邏輯上仍然像往常一樣強制執(zhí)行訪問控制镣陕,例如通過GetCreator()鏈碼API或使用客戶端身份鏈碼庫谴餐。

為私有數(shù)據(jù)集合建立索引

在使用couchdb作為狀態(tài)數(shù)據(jù)庫的時候,可以使用json格式的文件配置數(shù)據(jù)庫的索引呆抑,并且索引文件需要放在指定目錄下岂嗓,比如:
索引文件路徑:META-INF/statedb/couchdb/indexes
索引文件內(nèi)容:

{"index":{"fields":["docType","owner"]},"ddoc":"indexOwnerDoc", "name":"indexOwner","type":"json"}

私有數(shù)據(jù)清理

通過上面提到的配置項blockToLive,來執(zhí)行私有數(shù)據(jù)的定期清理。
回想一下鹊碍,在提交之前厌殉,peer節(jié)點私有數(shù)據(jù)保存在本地臨時數(shù)據(jù)庫。

升級集合定義

如果鏈碼引用了集合侈咕,則鏈碼將使用先前的集合定義,除非在升級時指定了新的集合定義公罕。如果在升級期間指定了集合配置,則必須包含每個現(xiàn)有集合的定義耀销,并且可以添加新的集合定義楼眷。

當peer節(jié)點提交包含鏈碼升級的交易時,集合更新將生效树姨,請注意摩桶,無法刪除集合帽揪,因為在通道的區(qū)塊鏈中可能存在無法刪除的先前私有數(shù)據(jù)哈希

實際操作

1. 創(chuàng)建一個集合定義的json格式文件硝清,配置項參數(shù)說明見上面部分。

// collections_config.json

[
  {
       "name": "collectionMarbles",
       "policy": "OR('Org1MSP.member', 'Org2MSP.member')",
       "requiredPeerCount": 0,
       "maxPeerCount": 3,
       "blockToLive":1000000
  },

  {
       "name": "collectionMarblePrivateDetails",
       "policy": "OR('Org1MSP.member')",
       "requiredPeerCount": 0,
       "maxPeerCount": 3,
       "blockToLive":3
  }
]

在鏈碼初始化的時候使用命令加載該配置文件

peer chaincode instantiate ... --collections-config

2. 使用鏈碼API對私有數(shù)據(jù)進行讀寫操作
在鏈碼中定義私有數(shù)據(jù)

// Org1 與 Org2 組織中的peer節(jié)點可以從sidedb中訪問私有數(shù)據(jù)
type marble struct {
  ObjectType string `json:"docType"`
  Name       string `json:"name"`
  Color      string `json:"color"`
  Size       int    `json:"size"`
  Owner      string `json:"owner"`
}

// Org1組織中的Peer節(jié)點可以從sidedb中訪問私有數(shù)據(jù)
type marblePrivateDetails struct {
  ObjectType string `json:"docType"`
  Name       string `json:"name"`
  Price      int    `json:"price"`
}type marble struct {
  ObjectType string `json:"docType"`
  Name       string `json:"name"`
  Color      string `json:"color"`
  Size       int    `json:"size"`
  Owner      string `json:"owner"`
}

type marblePrivateDetails struct {
  ObjectType string `json:"docType"`
  Name       string `json:"name"`
  Price      int    `json:"price"`
}
定義的規(guī)則如下:
- "name,color,size,and owner" 可以被Org1和Org2組織下的所有成員訪問
- "price" 僅僅被Org1組織下的成員訪問

在彈珠游戲私人數(shù)據(jù)樣例中定義了兩組不同的私有數(shù)據(jù)转晰。此數(shù)據(jù)到限制其訪問的集合策略的映射由鏈碼API控制芦拿。具體來說士飒,使用集合定義讀寫私人數(shù)據(jù)是通過接口GetPrivateData()和PutPrivateData()來執(zhí)行的,具體說明蔗崎。

下圖說明了彈珠游戲私有數(shù)據(jù)樣本使用的私有數(shù)據(jù)模型酵幕。
[圖片上傳失敗...(image-b56201-1532614924062)]
[圖片上傳失敗...(image-944cf3-1532614924062)]

  • 讀集合數(shù)據(jù)
    使用鏈碼API GetPrivateData()從數(shù)據(jù)庫中查詢私有數(shù)據(jù)。GetPrivateData有兩個參數(shù)缓苛,集合名稱與數(shù)據(jù)鍵芳撒。回想一下集合collectionMarbles 允許Org1和Org2中的成員訪問sideDB中的私有數(shù)據(jù)未桥,集合collectionMarblePrivateDetails允許Org1中的成員訪問sideDB中的私有數(shù)據(jù)笔刹。相關(guān)實現(xiàn)細節(jié),請參閱一下兩個彈珠游戲私有數(shù)據(jù)函數(shù)

    • readMarble 查詢"name, color, size, owner"屬性的值
    • readMarblePrivateDetails 查詢"price"屬性的值
  • 寫集合數(shù)據(jù)
    使用鏈碼API PutPrivateData() 往私有數(shù)據(jù)庫中存儲私有數(shù)據(jù)冬耿。

    • 使用集合名稱collectionMarbles舌菜,寫私有數(shù)據(jù)"name, color, size, owner"
    • 使用集合名稱collectionMarblePrivateDetails,寫私有數(shù)據(jù)"price"

如下的樣例中亦镶,在initMarble函數(shù)中日月,調(diào)用PutPrivateData() 兩次,分別設(shè)置不同的私有數(shù)據(jù)缤骨。

 // ==== Create marble object and marshal to JSON ====
       objectType := "marble"
       marble := &marble{objectType, marbleName, color, size, owner}
       marbleJSONasBytes, err := json.Marshal(marble)
       if err != nil {
               return shim.Error(err.Error())
       }
       //Alternatively, build the marble json string manually if you don't want to use struct marshalling
       //marbleJSONasString := `{"docType":"Marble",  "name": "` + marbleName + `", "color": "` + color + `", "size": ` + strconv.Itoa(size) + `, "owner": "` + owner + `"}`
       //marbleJSONasBytes := []byte(str)

       // === Save marble to state ===
       err = stub.PutPrivateData("collectionMarbles", marbleName, marbleJSONasBytes)
       if err != nil {
               return shim.Error(err.Error())
       }

       // ==== Save marble private details ====
       objectType = "marblePrivateDetails"
       marblePrivateDetails := &marblePrivateDetails{objectType, marbleName, price}
       marblePrivateDetailsBytes, err := json.Marshal(marblePrivateDetails)
       if err != nil {
               return shim.Error(err.Error())
       }
       err = stub.PutPrivateData("collectionMarblePrivateDetails", marbleName, marblePrivateDetailsBytes)
       if err != nil {
               return shim.Error(err.Error())
}

作為額外的數(shù)據(jù)隱私優(yōu)勢爱咬,由于正在使用集合,因此z還有私有數(shù)據(jù)哈希值傳遞給orderer節(jié)點荷憋,而不是私有數(shù)據(jù)本身台颠,從而使私有數(shù)據(jù)對orderer節(jié)點保密

3. 使用集合安裝并初始化鏈碼
創(chuàng)建一個solo共識的fabric網(wǎng)絡(luò)(1個orderer,兩個org組織,分別包含兩個peer節(jié)點)勒庄,包含以下節(jié)點:

  • peer0.org1.example.com
  • peer1.org1.example.com
  • peer0.org2.example.com
  • peer1.org2.example.com
  • orderer.example.com

a. 安裝鏈碼
使用如下命令分別在4個peer節(jié)點安裝彈珠游戲鏈碼

peer chaincode install -n marblesp -v 1.0 -0 github.com/chaincode/marbles02_private/go/

安裝成功后串前,peer節(jié)點日志會看到如下信息:

 install -> INFO 003 Installed remotely response:<status:200 payload:"OK"> 

b. 初始化鏈碼
使用管理員MSP在peer節(jié)點初始化鏈碼

 peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n marblesp -v 1.0 -c '{"Args":["init"]}' -P "OR('Org1MSP.member','Org2MSP.member')" --collections-config  $GOPATH/src/github.com/chaincode/marbles02_private/collections_config.json 

上面的參數(shù)根據(jù)實際情況進行改寫修改

當鏈碼初始化成功以后,可以看到如下日志信息:

[chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
[chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc

4. 存儲私有數(shù)據(jù)
使用如下命令初始化一個彈珠:

peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n marblesp -c '{"Args":["initMarble","marble1","blue","35","tom","99"]}'

初始化成功后实蔽,可以看到如下日志:

[chaincodeCmd] chaincodeInvokeOrQuery->INFO 001 Chaincode invoke successful. result: status:200

5. 在授權(quán)peer節(jié)點上查詢私有數(shù)據(jù)
如下的鏈碼例子荡碾,使用readMarble與readMarblereadMarblePrivateDetails方法分別查詢collectionMarble與collectionMarblePrivateDetails集合中的私有數(shù)據(jù):

// ===============================================
// readMarble - read a marble from chaincode state
// ===============================================

func (t *SimpleChaincode) readMarble(stub shim.ChaincodeStubInterface, args []string) pb.Response {
        var name, jsonResp string
    var err error
    if len(args) != 1 {
                return shim.Error("Incorrect number of arguments. Expecting name of the marble to query")
        }

name = args[0]
valAsbytes, err := stub.GetPrivateData("collectionMarbles", name) //get the marble from chaincode state

        if err != nil {
    jsonResp = "{\"Error\":\"Failed to get state for " + name + "\"}"
    return shim.Error(jsonResp)
} else if valAsbytes == nil {
    jsonResp = "{\"Error\":\"Marble does not exist: " + name + "\"}"
    return shim.Error(jsonResp)
}

return shim.Success(valAsbytes)
}
// ===============================================
// readMarblereadMarblePrivateDetails - read a marble private details from chaincode state
// ===============================================

func (t *SimpleChaincode) readMarblePrivateDetails(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var name, jsonResp string
var err error

if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting name of the marble to query")
}

name = args[0]
valAsbytes, err := stub.GetPrivateData("collectionMarblePrivateDetails", name) //get the marble private details from chaincode state

if err != nil {
jsonResp = "{\"Error\":\"Failed to get private details for " + name + ": " + err.Error() + "\"}"
return shim.Error(jsonResp)
} else if valAsbytes == nil {
jsonResp = "{\"Error\":\"Marble private details does not exist: " + name + "\"}"
return shim.Error(jsonResp)
}
return shim.Success(valAsbytes)
}

在Org1的成員節(jié)點下查詢marble1的私有數(shù)據(jù)"name,color,size,owner":

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarble","marble1"]}'

查詢結(jié)果如下:

{"color":"blue","docType":"marble","name":"marble1","owner":"tom","size":35}

在Org1的成員節(jié)點下查詢marble1的私有數(shù)據(jù)"price":

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

查詢結(jié)果如下:

{"docType":"marblePrivateDetails","name":"marble1","price":99}

6. 在未授權(quán)peer節(jié)點上查詢私有數(shù)據(jù)
從上面定義的私有數(shù)據(jù)訪問集合中,Org2定義了"name,color,size,owner"私有數(shù)據(jù)的訪問權(quán)限局装,但是沒有定義"price"私有數(shù)據(jù)的訪問權(quán)限坛吁。

  • 查詢被授權(quán)的私有數(shù)據(jù)
 peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarble","marble1"]}'

查詢結(jié)果如下:

{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}
  • 查詢未被授權(quán)的私有數(shù)據(jù)
peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

查詢結(jié)果如下:

{"Error":"Failed to get private details for marble1: GET_STATE failed:
transaction ID: b04adebbf165ddc90b4ab897171e1daa7d360079ac18e65fa15d84ddfebfae90:
Private data matching public hash version is not available. Public hash
version = &version.Height{BlockNum:0x6, TxNum:0x0}, Private data version =
(*version.Height)(nil)"}"

7. 清理私有數(shù)據(jù)
在私有數(shù)據(jù)集合中配置的屬性blockToLive,可以設(shè)置在多少個區(qū)塊后清理私有數(shù)據(jù)铐尚,只留下數(shù)據(jù)的哈希值拨脉,作為交易的不可改變的證據(jù)。

比如我們在創(chuàng)建上面的樣例鏈碼的時候宣增,設(shè)置私有數(shù)據(jù)集合屬性blockToLive=4玫膀。

在上面的樣例中,我們已經(jīng)初始化了一個marble1爹脾,其中price=99帖旨,使用如下命令查詢:

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

查詢結(jié)果如下:

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 -C mychannel -n marblesp -c '{"Args":["transferMarble","marble2","tom"]}'

然后再創(chuàng)建一個新的marble2資產(chǎn):

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 -C mychannel -n marblesp -c '{"Args":["initMarble","marble2","blue","35","tom","99"]}'

此時區(qū)塊增加1攒钳。
此時查詢marble1資產(chǎn)中的price值:

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

查詢結(jié)果如下:

{"docType":"marblePrivateDetails","name":"marble1","price":99}

在使用如下命令分別把marble2資產(chǎn)轉(zhuǎn)移給其他角色:

peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n marblesp -c '{"Args":["transferMarble","marble2","tom"]}'

在把資產(chǎn)轉(zhuǎn)移3次以后缠诅,區(qū)塊再次增加3次财饥。此時再查詢marble1資產(chǎn)中的price值:

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 -C mychannel -n marblesp -c '{"Args":["transferMarble","marble2","tom"]}'

查詢結(jié)果如下:

Error: endorsement failure during query. response: status:500
message:"{\"Error\":\"Marble private details does not exist: marble1\"}"

表明私有數(shù)據(jù)已經(jīng)被清除闸氮。

8. 使用帶有索引的私有數(shù)據(jù)

索引也可用于私有數(shù)據(jù)集合,通過打包與鏈碼同級目錄下META-INF/statedb/couchdb/collections/<collection_name>/indexes的索引文件货抄。

為了將鏈碼部署到生產(chǎn)環(huán)境述召,建議在鏈碼同級目錄下定義索引,以便鏈碼和相關(guān)所以作為一個單元一起自動部署蟹地,一旦鏈碼被安裝在節(jié)點并被初始化到通道桨武。當指定--collections-config 標志指向集合json文件的位置時,關(guān)聯(lián)索引將在通道上的鏈碼實例化時自動部署锈津。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市凉蜂,隨后出現(xiàn)的幾起案子琼梆,更是在濱河造成了極大的恐慌,老刑警劉巖窿吩,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茎杂,死亡現(xiàn)場離奇詭異,居然都是意外死亡纫雁,警方通過查閱死者的電腦和手機煌往,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來轧邪,“玉大人刽脖,你說我怎么就攤上這事〖捎蓿” “怎么了曲管?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長硕糊。 經(jīng)常有香客問我院水,道長,這世上最難降的妖魔是什么简十? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任檬某,我火速辦了婚禮,結(jié)果婚禮上螟蝙,老公的妹妹穿的比我還像新娘恢恼。我一直安慰自己,他們只是感情好胶逢,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布厅瞎。 她就那樣靜靜地躺著饰潜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪和簸。 梳的紋絲不亂的頭發(fā)上彭雾,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音锁保,去河邊找鬼薯酝。 笑死,一個胖子當著我的面吹牛爽柒,可吹牛的內(nèi)容都是我干的吴菠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼浩村,長吁一口氣:“原來是場噩夢啊……” “哼做葵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起心墅,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤酿矢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后怎燥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘫筐,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年铐姚,在試婚紗的時候發(fā)現(xiàn)自己被綠了策肝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡隐绵,死狀恐怖之众,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情氢橙,我是刑警寧澤酝枢,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站悍手,受9級特大地震影響帘睦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜坦康,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一竣付、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧滞欠,春花似錦古胆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惹恃。三九已至,卻和暖如春棺牧,著一層夾襖步出監(jiān)牢的瞬間巫糙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工颊乘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留参淹,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓乏悄,卻偏偏與公主長得像浙值,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子檩小,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 31,934評論 2 89
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理开呐,服務(wù)發(fā)現(xiàn),斷路器规求,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 每次收拾東西都能收拾出一段回憶來负蚊。 去年除夕前翻到了初中的日記本,這次是一大堆照片颓哮。 照片上的媽媽真的太美了。白色...
    Daring_dd閱讀 242評論 0 0
  • 一夢半輩鸵荠,輾轉(zhuǎn)古道老轍 佇在塵里塵外 驀然踉蹌沉坷 子夜猶聞劇續(xù)播 歸心似過客 有掛念有太多爭辯 無情的人未必認真...
    yesuns閱讀 236評論 0 0
  • 人吶蛹找,還是放寬點心吧姨伤,要離開的,留也留不住庸疾。 真的會傷感乍楚。 但我認了。我絕不是那種不認命要撈回來的人届慈。 我不是徒溪。 ...
    老驢三兒閱讀 458評論 0 1