Fabric Private Data Collection

Dinesh Rivankar
4 min readOct 12, 2019

Hyperledger Fabric uses channels to keep the data private for other participants in the network. However, creating many channels for each type of transaction makes it more complicated for managing. Fabric starting from v 1.2 added the ability to create a private data collections which allows organizations within the channel to endorse, invoke and query private data collections without creating additional channels.

Private data collections are sent via gossip protocol to the authorized organization peers without the involvement of ordering service. These collections are stored in private state database of an authorized organization peers, which can be accessed via chaincode. Each anchor peer on the channel need to configure “CORE_PEER_GOSSIP_EXTERNALENDPOINT” for enabling cross organization communication.

Transaction flow

1. Client send proposal to invoke the chaincode function, the private data is sent in “transient” field of the proposal.

2. Endorsing peers stimulates the proposed transaction and stores the private data in “transient data store”.

3. Endorsing peer response back to the client with endorsement and hash of private data.

4. Client submits the transaction to the ordering service which includes the private data hash.

5. Before committing the block, all the authorized peers will use the private data collection policy to verify their access. If they are authorized, then check if private data is already received in transient data store. If not, then fetch from other authorized organizations.

6. After fetching the private data, peer needs to validate it with the hash stored on the transaction block. On successful validation the private data is moved to private state database and deleted from the transient data store.

Collection definition

Collection is a simple JSON file which defines access rules and duration of a given collection data. This collection file will be input to the chaincode instantiate call ( — collections-config)

[
{
"name": "collectionMarbles", // Collection name
"policy": "OR('Org1MSP.member', 'Org2MSP.member')", // Policy for allowing organization peers to store the collection data
"requiredPeerCount": 0, // Number of peers required to disseminate the private data as a condition of the endorsement
"maxPeerCount": 3, // Number of other peers the current endorsing peers distribute the data
"blockToLive":1000000, // How long data should live in private data.
"memberOnlyRead": true // Read access to the private data.
},
{
"name": "collectionMarblePrivateDetails",
"policy": "OR('Org1MSP.member')",
"requiredPeerCount": 0,
"maxPeerCount": 3,
"blockToLive":3,
"memberOnlyRead": true
}
]

Collection Read / Write

The chaincode API provides 2 function to read and write data to private data collections. Before moving to the read / write, one need to define the data structure for the collection. Below is the sample structure for the above collection definition.

type marble struct {
ObjectType string `json:"docType"`
Name string `json:"name"`
Color string `json:"color"`
Size int `json:"size"`
Owner string `json:"owner"`
}
type marblePrivateDetails struct {
ObjectType string `json:"docType"
Name string `json:"name"`
Price int `json:"price"`
}

If we look at the collection definition and the data structure, the first collection “collectionMarbles” is available for both the organization (Org 1 & Org 2), however the collection “collectionMarblePrivateDetails” is accessible to only Org 1.

Use chaincode GetPrivateData() function to read the private data collection. The function takes two parameter, collection name and data key. Similarly use PutPrivateData() function for writing private data to collection.

Private data in action

For exploration we will be using the marble private data example. Network orchestration will be done using Docker Swarm . Kindly follow below article to understand the network orchestration with docker swarm.

Step #1

Clone the below repository for exploring the private data example.

Git clone https://github.com/dineshrivankar/fabric-private-data.git

Step #2

Create a docker swarm network by running the “network-setup.sh” script from home directory of the cloned repository. This is one time activity if we are running the experiments multiple times.

The script will create a new swarm cluster and a overly network for communication.

./network-setup.sh

Step #3

Generate Crypto material required for all the participants and deploy the peers by running the below script. For exploration we will use Solo mode for the Ordering service.

./deploy.sh

Step #4

Org1 runs a cli container, below script will create a channel, join all the peers to the channel, install & instantiate chaincode, invoke & query chaincode.

./run.sh

Final output:

# ------------------------------------------------------------------
# Query chaincode - readMarble : Query from Org1 peer (Authorized)
# ------------------------------------------------------------------
{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}
# ------------------------------------------------------------------
# Query chaincode - readMarble : Query from Org2 peer (Authorized)
# ------------------------------------------------------------------
{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}
# ------------------------------------------------------------------
# Query chaincode - readMarblePrivateDetails : Query from Org1 peer (Authorized)
# ------------------------------------------------------------------
{"docType":"marblePrivateDetails","name":"marble1","price":99}
# ------------------------------------------------------------------
# Query chaincode - readMarblePrivateDetails : Query from Org2 peer (Unauthorized)
# ------------------------------------------------------------------
Error: endorsement failure during query. response: status:500 message:"{\"Error\":\"Failed to get private details for marble1: GET_STATE failed: transaction ID: 20489156230ee4ae2474319e9b02834dc5090dca69d78eafddb5346024d0eb60: tx creator does not have read access permission on privatedata in chaincodeName:marblespcollectionName: collectionMarblePrivateDetails\"}"

“readMarble” collection is available for both the organizations and hence collection data is accessible. However “readMarblePrivateDetails” is accessible to only Org1.

Step #5

Reset the network by running below script.

./reset.sh

That’s it!!

Feel free to shout out for any suggestions or improvements.
Happy Learning !!!

--

--

Dinesh Rivankar

Architect, Blockchain Innovation Group. #TOGAF #ConfidentialComputing #Corda #Hyperledger #SmartContract