若是某個渠道上的一組組織須要將數據與該渠道上的其餘組織保密,他們能夠選擇建立一個僅包含須要訪問數據的組織的新渠道。可是,在每種狀況下建立單獨的通道會產生額外的管理開銷(維護鏈代碼版本,策略,MSP等)。html
超級帳本 Fabric 引入了 sideDB 機制,經過 Hash 處理和私有數據結構,在通道內部實現了更細粒度的隱私保護。Hash 後的交易內容仍然會發送到排序節點,並提交到公共的數據庫和帳本結構中。而受權組的 Peer 節點則在本地維護私有的狀態數據庫和區塊鏈結構,保存交易的明文內容。這就保證了通道內其餘節點沒法看到受權組的交易內容。git
私密數據分爲兩部分:github
<html> <img style="-webkit-user-select: none;cursor: zoom-in;" src="https://hyperledger-fabric.readthedocs.io/en/release-1.4/_images/PrivateDataConcept-2.png" width=60% height=60% align=center /> </html> ## 2.私有數據在fabric中的交易流程 1. SDK將交易發送給背書節點,該背書節點須要經過policy(此處的policy爲instantiation設定的)驗證。 2. 背書節點模擬執行交易,並將真實的私密數據 key和value存儲於瞬時數據庫(private transient DB)中。基於collection policy,驗證經過的peer節點,經過gossip同步真實的私密數據,並將其存儲於瞬時數據庫中。背書節點將模擬執行後的結果返回給SDK,返回的數據中僅有公共數據(hash過的私密數據)。 3. SDK將peer返回的結果打包後發送給orderer,和普通的區塊同樣,orderer切塊後,將其分發給peer,此時全部的peer都拿到了公共數據,全部的peer均可以去驗證私有數據,沒有經過collection policy的peer,也能夠驗證,並且還不擁有真實的私密數據,保證了數據的私密性。 4. 在commit以前,peer首先去判斷本身是否經過collection policy的檢查,若經過,將去檢查本身的瞬時數據庫中是否有真實的私密數據,若是沒有,將嘗試從別的peer處拉取數據。 5. 取到私密數據後,首先去和公共數據的hash去作比對,若一致,此時進行commit操做,將私密數據的HASH寫入到公共數據庫中。提交該交易和這個區塊到帳本中,成功提交後,私密數據將會從瞬時數據庫拷貝到私密數據庫中,並從瞬時數據庫中刪除。此時整個交易流程結束,數據成功寫入到帳本內。web
name:集合的名稱。 policy:定義容許持久保存集合數據的組織peer節點。 requiredPeerCount:傳播私有數據所需的對等數量,做爲承認鏈代碼的條件 maxPeerCount:出於數據冗餘目的,當前承認peer節點將嘗試將數據分發到的其餘peer的數量。 blockToLive:此值表示數據應以塊爲單位存儲在私有數據庫中的時間。數據將在專用數據庫上爲指定數量的塊生效,以後將被清除,從而使這些數據從網絡中過期。要無限期地保留私有數據,即永遠不要清除私有數據,請將blockToLive屬性設置爲0。 memberOnlyRead:值true表示peer自動強制只容許屬於其中一個集合成員組織的客戶端對私有數據進行讀取訪問。
樣例數據庫
[ { "name": "collectionMarbles", "policy": "OR('Org1MSP.member', 'Org2MSP.member')", "requiredPeerCount": 0, "maxPeerCount": 3, "blockToLive":1000000, "memberOnlyRead": true }, { "name": "collectionMarblePrivateDetails", "policy": "OR('Org1MSP.member')", "requiredPeerCount": 0, "maxPeerCount": 3, "blockToLive":3, "memberOnlyRead": true } ]
// Peers in Org1 and Org2 will have this private data in a side database type marble struct { ObjectType string `json:"docType"` Name string `json:"name"` Color string `json:"color"` Size int `json:"size"` Owner string `json:"owner"` } // Only peers in Org1 will have this private data in a side database type marblePrivateDetails struct { ObjectType string `json:"docType"` Name string `json:"name"` Price int `json:"price"` }
具體訪問私人數據將受到以下限制:json
name, color, size, and owner 將對渠道的全部成員(Org1和Org2)可見 price 僅對Org1的成員可見
<html> <img style="-webkit-user-select: none;cursor: zoom-in;" src="https://hyperledger-fabric.readthedocs.io/en/release-1.4/_images/SideDB-org2.png" width=60% height=60% align=center /> </html> <html> <img style="-webkit-user-select: none;cursor: zoom-in;" src="https://hyperledger-fabric.readthedocs.io/en/release-1.4/_images/SideDB-org2.png" width=60% height=60% align=center /> </html>網絡
stub.PutPrivateData("collectionMarbles", colorNameIndexKey, value) valAsbytes, err := stub.GetPrivateData("collectionMarbles", name) //get the marble from chaincode state
./byfn.sh up -c mychannel -s couchdb
peer chaincode install -n marblesp -v 1.0 -p github.com/chaincode/marbles02_private/go/
export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -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
export MARBLE=$(echo -n "{\"name\":\"marble1\",\"color\":\"blue\",\"size\":35,\"owner\":\"tom\",\"price\":99}" | base64 | tr -d \\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"]}' --transient "{\"marble\":\"$MARBLE\"}" peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarble","marble1"]}'