Private Data: Implicit Data Collections in Hyperledger Fabric v2.0

Overview

Private data is an important feature in Hyperledger Fabric, allowing certain data to be stored only inside selected organizations. This provides data privacy within a channel, and reduces the number of channels required if the privacy is needed at data level. In Fabric v2.0, an implicit collection is introduced for each organization, and application chaincode can use it without a collection is defined explicitly. This article is to explore the implicit collection, and see how it is being used in both lifecycle chaincode and an application chaincode.

Private Data at a Glance

You can find introduction of Private Data here in Fabric documentation. Here is a quick overview.

Illustration of Private Data
[
{
"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
}
]

Demonstration Setup

Our demonstration is built on First Network of fabric-samples. This brings up a fabric network with a raft-based orderer cluster, two peer organizations, each of which has two peers (total four peers). A channel mychannel is created and all peers join it. In order to observe the state, we use CouchDB for each peer as the state database and use Fauxton to observe the databases inside CouchDB.

Demonstration

The overall demonstration is grouped into three parts. First we bring up the environment, which is the First Network and prepare the application chaincode sacc_private. Then we deploy chaincode to this fabric network, using lifecycle chaincode. Our focus is mainly on the use of implicit collection during the chaincode operation. Finally we will interact with our application chaincode and see how we can refer to the implicit collection.

Demonstration Flow

Bring Up Environment

Step 1: Bring up all components and setup mychannel

cd fabric-samples/first-network
./byfn.sh up -n -s couchdb
  • peer1.org1.example.com: http://<host_ip>:6984/_utils/
  • peer0.org2.example.com: http://<host_ip>:7984/_utils/
  • peer1.org2.example.com: http://<host_ip>:8984/_utils/
Four tags are opened, one for CouchDB of each peer
cd fabric-samples/chaincode
cp -r sacc sacc_private
cd sacc_private
GO111MODULE=on go mod vendor

Deploy Application Chaincode in First Network

We go through the complete lifecycle process to deploy our application chaincode.

docker exec cli peer lifecycle chaincode package sacc.tar.gz --path github.com/hyperledger/fabric-samples/chaincode/sacc_private/ --label sacc_1docker exec cli ls
The package file is created after chaincode packaging.
# peer0.org1
docker exec cli peer lifecycle chaincode install sacc.tar.gz
# peer0.org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt cli peer lifecycle chaincode install sacc.tar.gz
Package ID is given after chaincode package is installed in peer.
docker exec cli peer lifecycle chaincode approveformyorg --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 --channelID mychannel --name mycc --version 1 --sequence 1 --waitForEvent --package-id sacc_1:669c48a3aa18f629e86cbe99fd4fccae2575b400c0f7da8741f68517ae4a6579
peer0.org1
peer1.org1
peer0.org2
peer1.org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt cli peer lifecycle chaincode approveformyorg --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 --channelID mychannel --name mycc --version 1 --sequence 1 --waitForEvent --package-id sacc_1:669c48a3aa18f629e86cbe99fd4fccae2575b400c0f7da8741f68517ae4a6579
both peer0.org1 and peer1.org1
both peer0.org2 and peer1.org2
docker exec cli peer lifecycle chaincode commit -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 --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --channelID mychannel --name mycc --version 1 --sequence 1

Use Application Chaincode

We use invoke and query chaincode to interact with the deployed chaincode. As a comparison, we first use the original set and get, as a reference to compare our new functions working on data collection.

docker exec cli 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 --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -C mychannel -n mycc -c '{"Args":["set","name","kc"]}'# query from peer0.org1
docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'
# query from peer0.org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'
All peers has this data.
docker exec cli 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 --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -C mychannel -n mycc -c '{"Args":["setPrivateOrg1","name","peter"]}'# query from peer0.org1
docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["getPrivateOrg1","name"]}'
# query from peer0.org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt cli peer chaincode query -C mychannel -n mycc -c '{"Args":["getPrivateOrg1","name"]}'
peer0.org1 and peer1.org1
peer0.org2 and peer1.org2

Summary

In this article we have demonstrated and observed how the implicit collection looks like and is being used.

Visit http://www.ledgertech.biz/kcarticles.html for all my works. Reach me on https://www.linkedin.com/in/ktam1/ or follow me @kctheservant in Twitter.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store