私有数据
从v1.2开始,Fabric 提供了创建私有数据集合的功能,它允许在通道上定义的组织子集能够背书、提交或查询私有数据,而无需创建单独的通道。
产生的原因:一个通道上的一组组织需要对该通道上的其他组织保持数据私有
原来的办法:可以选择创建一个新通道,其中只包含需要访问数据的组织
原来办法的缺点:
- 在每种情况下创建单独的通道会产生额外的管理开销(维护链码版本、策略、MSP等)
- 不能在保留一部分数据私有的同时,可以让所有通道参与者看到该事务。
故产生了私有数据这一个概念。
私有数据集合
私有数据集合是两个元素的集合:
- 实际的私有数据,通过 Gossip 协议点对点地发送给授权可以看到它的组织。私有数据保存在被授权的组织的节点上的私有数据库上,它们可以被授权节点的链码访问。排序节点不能影响这里也不能看到私有数据。注意,由于 gossip 以点对点的方式向授权组织分发私有数据,所以必须设置通道上的锚节点,也就是每个节点上的 CORE_PEER_GOSSIP_EXTERNALENDPOINT 配置,以此来引导跨组织的通信。
- 该数据的 hash 值,该 hash 值被背书、排序之后写入通道上每个节点的账本。Hash 值作为交易的证明用于状态验证,并可用于审计
下面的图表分别说明了被授权和未被授权拥有私有数据的节点的账本内容。
什么时候使用一个通道内的组织集合,什么时候使用单独的通道
- 当必须将整个账本在属于通道成员的组织中保密时,使用通道比较合适。
- 当账本必须共享给一些组织,但是只有其中的部分组织可以在交易中使用这些数据的一部分或者全部时,使用集合比较合适。此外,由于私有数据是点对点传播的,而不是通过块传播的,所以在交易数据必须对排序服务节点保密时,应该使用私有数据集合。
fabric 私有数据 官方示例 Marbles
该官方示例在fabric-samples/chaincode/marbles02_private中
打开看看其中的代码
打开链码查看:
在marble数据库中 price字段只有org1中的节点可以访问。
私有数据集合的定义:
在collections_config.json中
接下来我们开始搭建环境并安装链码:
打开test-network网络
./network.sh up
创建通道
./network.sh createChannel
配置环境变量
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
创建链码包
peer lifecycle chaincode package marblep.tar.gz --path ../chaincode/marbles02_private/go/ --lang golang --label marblep_1
初始化成员org1节点
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
在org1的节点上安装链码
peer lifecycle chaincode install marblep.tar.gz
初始化成员org2节点
export PATH=${PWD}/../bin:$PATH
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
在org2的节点上安装链码
peer lifecycle chaincode install marblep.tar.gz
将获得的packageId 配置环境变量
export CC_PACKAGE_ID=marblep_1:065bc0804f121c7b4881e00f9409c7529e0860f114e630df62b5eec488c9dcbd
order CA 证书配置环境变量
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
提交链码(org1和org2都要进行操作)
注意:这里要将私有数据的配置文件通过--collections-config配置到这个地方来
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls true --cafile "$ORDERER_CA" --channelID mychannel --name marblep --version 1.0 --collections-config ../chaincode/marbles02_private/collections_config.json --package-id $CC_PACKAGE_ID --sequence 1
查看一下链码是否就绪
注意:这里也要有--collections-config
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name marblep --version 1.0 --collections-config ../chaincode/marbles02_private/collections_config.json --sequence 1 --tls true --cafile "$ORDERER_CA" --output json
提交链码(org1或者org2提交一次即可)
注意:这里也要有--collections-config
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marblep --version 1.0 --sequence 1 --tls true --collections-config ../chaincode/marbles02_private/collections_config.json --cafile "$ORDERER_CA" --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
初始化链码
export MARBLE=$(echo -n "{\"name\":\"marble1\",\"color\":\"blue\",\"size\":35,\"owner\":\"tom\",\"price\":99}" | base64 | tr -d \\n)
peer chaincode invoke -o localhost:7050 \
> --ordererTLSHostnameOverride orderer.example.com \
> --tls --cafile "$ORDERER_CA" \
> -C mychannel \
> -n marblep \
> --transient "{\"marble\":\"$MARBLE\"}" \
> --peerAddresses localhost:7051 \
> --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" \
> --peerAddresses localhost:9051 \
> --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" \
> -c '{"function":"InitMarble","Args":[]}'
测试
在 org1中 查询链码中的数据
peer chaincode query -C mychannel -n marblep -c '{"Args":["readMarble","marble1"]}'
在 org1中 查询链码中的私有数据
peer chaincode query -C mychannel -n marblep -c '{"Args":["readMarblePrivateDetails","marble1"]}'
在org2中 查询链码中的数据(将身份改为org2)
peer chaincode query -C mychannel -n marblep -c '{"Args":["readMarble","marble1"]}'
在 org2中 查询链码中的私有数据
peer chaincode query -C mychannel -n marblep -c '{"Args":["readMarblePrivateDetails","marble1"]}'
更换marble资产人
export MARBLE_OWNER=$(echo -n "{\"name\":\"marble1\",\"color\":\"red\",\"size\":35,\"owner\":\"Alice\",\"price\":99}" | base64 | tr -d \\n)
peer chaincode invoke -o localhost:7050 --tls --cafile $ORDERER_CA -C mychannel -n marblep -c '{"Args":["transferMarble"]}' --transient "{\"marble_owner\":\"$MARBLE_OWNER\"}"