Fabric 私密数据
1.私密数据的定义
如果某个渠道上的一组组织需要将数据与该渠道上的其他组织保密,他们可以选择创建一个仅包含需要访问数据的组织的新渠道。但是,在每种情况下创建单独的通道会产生额外的管理开销(维护链代码版本,策略,MSP等)。
超级账本 Fabric 引入了 sideDB 机制,通过 Hash 处理和私有数据结构,在通道内部实现了更细粒度的隐私保护。Hash 后的交易内容仍然会发送到排序节点,并提交到公共的数据库和账本结构中。而授权组的 Peer 节点则在本地维护私有的状态数据库和区块链结构,保存交易的明文内容。这就保证了通道内其他节点无法看到授权组的交易内容。
私密数据分为两部分:
- 一个是真正的key,value,它被存在 peer的私密数据库(private state)中。
- 另一部分为公共数据,它是真实的私密数据key,value 哈希后的值 hash(key),hash(value),它被存在普通的peer数据库中(state),orderer端可以拿到该值。没有被分配私密数据权限的peer,也仅仅可以存储hash后的key和value。
3.私密数据使用案例
- 构建集合定义JSON文件
将通道上的数据私有化的第一步是构建一个集合定义,用于定义对私有数据的访问。
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
}
]
- 使用链代码API读取和写入私有数据
// 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"`
}
具体访问私人数据将受到如下限制:
name, color, size, and owner 将对渠道的所有成员(Org1和Org2)可见
price 仅对Org1的成员可见
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"]}'