Observing Private Data in Ledger: Adding and Removing Organization in Distribution Policy

Overview

Private data in Hyperledger Fabric provides a way to keep privacy on certain data within a channel. While in a typical setup, all member organizations of a channel keep the same set of data, there are situations in which some data needs to be kept by a subset of organizations. It is largely due to business requirements. Other organizations in the same channel will not keep this data, but a hash of data as an existential evidence of such a piece of data. More detail about private data can be seen here.

In the architecture reference about private data,

In this article we create a test to observe these points. The test environment is a three-organization setup. By tuning the collection definition, we will observe how private data is being handled when a new organization is added and then another is removed.

Test Setup

Our fabric network comes with three peer organizations, each of which a peer (peer0) is deployed. A channel is created and all the peers join . We only designated an anchor peer on peer0.org1.example.com.

The configuration is adopted from First Network, with proper modification on crypto-config.yaml and configtx.yaml to reflect our network setup.

Crypto material (inside crypto-config/) and channel artifacts (inside channel-artifacts/) are properly generated. For simplicity we just use this set of pre-generated material.

To demonstrate private data, a chaincode sacc_private3org is developed. It adopts from Simple Asset Chaincode (sacc), by adding two functions and . The data collection is called . This chaincode is inside chaincode/sacc_private3org/, which is mapped to the CLI container.

Image for post
Image for post
sacc_private3org.go: showing setPrivate() and getPrivate() functions

Besides, we have created three collection definition files. They are,

  • org1–2.json ( for Org1 and Org2)
  • org1–2–3.json ( for Org1, Org2 and Org3)
  • org1–3.json ( for Org1 and Org3)

As an example, in org1–2.json, we specify a collection with name , and peers of organization Org1 and Org2 keep this data.

Image for post
Image for post
Example of Collection Definition: org1–2.json

These collection definition files are stored under collection/, which is also mapped to the CLI container. When we approve and commit chaincode definition, we will refer to one of them for our testing.

Finally, we include a CouchDB for each peer. The purpose is to observe the databases for private data in each peer.

The test is done following the sequence of collection files. We first set Org1 and Org2 keeping the private data (Scenario 1). After everything is working well, we will add Org3 into collection policy (Scenario 2). As far as we are keeping the chaincode name and tuning the sequence number, it is equivalent to an update and existing ledger will be maintained. Finally, we will remove Org2 from the policy, that is, Org1 and Org3 in collection policy (Scenario 3) and see what happens in the private data still in Org2.

Test Step

Preparation

Clone the repository in the fabric-samples/. Note that the crypto material and channel artifacts are already generated. A script bringupnetwork.sh is created to deploy our network.

cd fabric-samples
git clone https://github.com/kctam/3org-privatedata-200
cd 3org-privatedata-200
./bringupnetwork.sh

Upon completion we see three peers, one for each organization, and three couchdb containers, one for each peer.

Image for post
Image for post

And with anchor peers peer0.org1.example.com is configured, peers know the channel member of cross-organization. Check logs of all peers.

Image for post
Image for post
Docker logs of peer0.org1.example.com
Image for post
Image for post
Docker logs of peer0.org2.example.com (only anchor peer is learnt)
Image for post
Image for post
Docker logs of peer0.org3.example.com (only anchor peer is learnt)

With this the network is ready for private data testing.

As we are not modifying the chaincode in these scenarios, this packaging and installation is done only once.


cd chaincode/sacc_private3org
GO111MODULE=on go mod vendor

docker exec cli peer lifecycle chaincode package sacc.tar.gz --path github.com/hyperledger/fabric-samples/chaincode/sacc_private3org/ --label sacc_1

docker exec cli peer lifecycle chaincode install sacc.tar.gz

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

docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp -e CORE_PEER_ADDRESS=peer0.org3.example.com:11051 -e CORE_PEER_LOCALMSPID="Org3MSP" -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt cli peer lifecycle chaincode install sacc.tar.gz

Scenario 1: Private Data for Org1 and Org2

First we deploy chaincode with collection/org1–2.json, marked as sequence

Approve chaincode from three organizations

Image for post
Image for post

Commit chaincode

Image for post
Image for post

docker exec cli peer chaincode invoke -o orderer.example.com:7050 --tls true --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 mycc --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 '{"Args":["setPrivate","name","Alice"]}'

Image for post
Image for post

We will see private data can be accessed in peers of Org1 and Org2, but not in Org3 as it is outside our collection policy.

We can see the private data is stored in Org1 and Org2, while only the hash is seen in Org3. This shows our collection policy works well

Image for post
Image for post
Collection policy: Org1 and Org2

Scenario 2: Add Org3 into Policy

Then we deploy chaincode with collection/org1–2-3.json, marked as sequence

Approve chaincode from three organizations

Image for post
Image for post

Commit chaincode

Image for post
Image for post

Image for post
Image for post

We see private data is accessible from all organizations, per our updated collection policy. Obviously peer of Org3 obtains the private data as it is not visible previously (Step 5).

Image for post
Image for post
With collection policy changed to include Org3, peer0.org3.example.com obtains the private data through reconciliation

And from the log we see the reconciliation happens, and peer0.org3.example.com learns back the private data.

Image for post
Image for post
Private data reconciliation as peer0.org3.example.com now part of collection policy

Scenario 3: Remove Org2 from Policy

Finally we deploy chaincode with collection/org1-3.json, marked as sequence

Approve chaincode from three organizations

Image for post
Image for post

Commit chaincode

Image for post
Image for post

Image for post
Image for post

We see private data is now not accessible in Org2, as in our new collection policy we include only Org1 and Org3.

We still see the previous private data stored in peer0.org2.example.com, although it cannot be read per our new collection policy.

Image for post
Image for post
The previous private data is still kept in ledger of peer0.org2.example.com

Let’s invoke to set a new private data.

docker exec cli peer chaincode invoke -o orderer.example.com:7050 --tls true --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 mycc --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.org3.example.com:11051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt -c '{"Args":["setPrivate","age","30"]}'

From the ledger we know that only peers of Org1 and Org3 get the new private data, and peer of Org2 does not. Its hash is updated (as other peers), but not the private data.

Image for post
Image for post
Collection policy: Org1 and Org3

Observation

When a new organization is added to policy, like Org3 in Scenario 2, as far as we are maintaining the same chaincode name and deploying with a new sequence number, Org3 will learn the private data and keep it in its ledger. When we make a query on peer of Org3, we get back the private data.

When we remove an organization from a policy, like Org2 in Scenario 3, the private data immediately cannot be read from the peer of Org2. This is our expected result. However the previous data stored in private data is still in the ledger. Therefore, removing an organization from collection policy does not remove the data which is already in the ledger. In fact I do not expect any possible way to remove them. Nevertheless, new private data is not written in Org2 as it is already out of the policy. To a certain extent it always meets our intention.

Summary

In this article we have created a three-organization network for private data testing. By adding and removing an organization from the collection policy, we can see how Hyperledger Fabric handles the private data according to the collection policy.

Happy to share what I learn on blockchain. Visit http://www.ledgertech.biz/kcarticles.html for my works. or reach me on https://www.linkedin.com/in/ktam1/.

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