若是某个渠道上的一组组织须要将数据与该渠道上的其余组织保密,他们能够选择建立一个仅包含须要访问数据的组织的新渠道。可是,在每种状况下建立单独的通道会产生额外的管理开销(维护链代码版本,策略,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"]}'