github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/docs/source/private_data_tutorial.rst (about)

     1  
     2  Using Private Data in Fabric
     3  ============================
     4  
     5  This tutorial will demonstrate the use of collections to provide storage
     6  and retrieval of private data on the blockchain network for authorized peers
     7  of organizations.
     8  
     9  The information in this tutorial assumes knowledge of private data
    10  stores and their use cases. For more information, check out :doc:`private-data/private-data`.
    11  
    12  .. note:: These instructions use the new Fabric chaincode lifecycle introduced
    13            in the Fabric v2.0 Alpha release. If you would like to use the previous
    14            lifecycle model to use private data with chaincode, visit the v1.4
    15            version of the `Using Private Data in Fabric tutorial <https://hyperledger-fabric.readthedocs.io/en/release-1.4/private_data_tutorial.html>`__.
    16  
    17  The tutorial will take you through the following steps to practice defining,
    18  configuring and using private data with Fabric:
    19  
    20  #. :ref:`pd-build-json`
    21  #. :ref:`pd-read-write-private-data`
    22  #. :ref:`pd-install-define_cc`
    23  #. :ref:`pd-store-private-data`
    24  #. :ref:`pd-query-authorized`
    25  #. :ref:`pd-query-unauthorized`
    26  #. :ref:`pd-purge`
    27  #. :ref:`pd-indexes`
    28  #. :ref:`pd-ref-material`
    29  
    30  This tutorial will use the `marbles private data sample <https://github.com/hyperledger/fabric-samples/tree/master/chaincode/marbles02_private>`__
    31  --- running on the Building Your First Network (BYFN) tutorial network --- to
    32  demonstrate how to create, deploy, and use a collection of private data.
    33  The marbles private data sample will be deployed to the :doc:`build_network`
    34  (BYFN) tutorial network. You should have completed the task :doc:`install`;
    35  however, running the BYFN tutorial is not a prerequisite for this tutorial.
    36  Instead the necessary commands are provided throughout this tutorial to use the
    37  network. We will describe what is happening at each step, making it possible to
    38  understand the tutorial without actually running the sample.
    39  
    40  .. _pd-build-json:
    41  
    42  Build a collection definition JSON file
    43  ------------------------------------------
    44  
    45  The first step in privatizing data on a channel is to build a collection
    46  definition which defines access to the private data.
    47  
    48  The collection definition describes who can persist data, how many peers the
    49  data is distributed to, how many peers are required to disseminate the private
    50  data, and how long the private data is persisted in the private database. Later,
    51  we will demonstrate how chaincode APIs ``PutPrivateData`` and ``GetPrivateData``
    52  are used to map the collection to the private data being secured.
    53  
    54  A collection definition is composed of the following properties:
    55  
    56  .. _blockToLive:
    57  
    58  - ``name``: Name of the collection.
    59  
    60  - ``policy``: Defines the organization peers allowed to persist the collection data.
    61  
    62  - ``requiredPeerCount``: Number of peers required to disseminate the private data as
    63    a condition of the endorsement of the chaincode
    64  
    65  - ``maxPeerCount``: For data redundancy purposes, the number of other peers
    66    that the current endorsing peer will attempt to distribute the data to.
    67    If an endorsing peer goes down, these other peers are available at commit time
    68    if there are requests to pull the private data.
    69  
    70  - ``blockToLive``: For very sensitive information such as pricing or personal information,
    71    this value represents how long the data should live on the private database in terms
    72    of blocks. The data will live for this specified number of blocks on the private database
    73    and after that it will get purged, making this data obsolete from the network.
    74    To keep private data indefinitely, that is, to never purge private data, set
    75    the ``blockToLive`` property to ``0``.
    76  
    77  - ``memberOnlyRead``: a value of ``true`` indicates that peers automatically
    78    enforce that only clients belonging to one of the collection member organizations
    79    are allowed read access to private data.
    80  
    81  To illustrate usage of private data, the marbles private data example contains
    82  two private data collection definitions: ``collectionMarbles``
    83  and ``collectionMarblePrivateDetails``. The ``policy`` property in the
    84  ``collectionMarbles`` definition allows all members of  the channel (Org1 and
    85  Org2) to have the private data in a private database. The
    86  ``collectionMarblesPrivateDetails`` collection allows only members of Org1 to
    87  have the private data in their private database.
    88  
    89  For more information on building a policy definition refer to the :doc:`endorsement-policies`
    90  topic.
    91  
    92  .. code:: json
    93  
    94   // collections_config.json
    95  
    96   [
    97     {
    98          "name": "collectionMarbles",
    99          "policy": "OR('Org1MSP.member', 'Org2MSP.member')",
   100          "requiredPeerCount": 0,
   101          "maxPeerCount": 3,
   102          "blockToLive":1000000,
   103          "memberOnlyRead": true
   104     },
   105  
   106     {
   107          "name": "collectionMarblePrivateDetails",
   108          "policy": "OR('Org1MSP.member')",
   109          "requiredPeerCount": 0,
   110          "maxPeerCount": 3,
   111          "blockToLive":3,
   112          "memberOnlyRead": true
   113     }
   114   ]
   115  
   116  The data to be secured by these policies is mapped in chaincode and will be
   117  shown later in the tutorial.
   118  
   119  This collection definition file is deployed when the chaincode definition is
   120  committed to the channel using the `peer lifecycle chaincode commit command <http://hyperledger-fabric.readthedocs.io/en/latest/commands/peerchaincode.html#peer-chaincode-instantiate>`__.
   121  More details on this process are provided in Section 3 below.
   122  
   123  .. _pd-read-write-private-data:
   124  
   125  Read and Write private data using chaincode APIs
   126  ------------------------------------------------
   127  
   128  The next step in understanding how to privatize data on a channel is to build
   129  the data definition in the chaincode. The marbles private data sample divides
   130  the private data into two separate data definitions according to how the data will
   131  be accessed.
   132  
   133  .. code-block:: GO
   134  
   135   // Peers in Org1 and Org2 will have this private data in a side database
   136   type marble struct {
   137     ObjectType string `json:"docType"`
   138     Name       string `json:"name"`
   139     Color      string `json:"color"`
   140     Size       int    `json:"size"`
   141     Owner      string `json:"owner"`
   142   }
   143  
   144   // Only peers in Org1 will have this private data in a side database
   145   type marblePrivateDetails struct {
   146     ObjectType string `json:"docType"`
   147     Name       string `json:"name"`
   148     Price      int    `json:"price"`
   149   }
   150  
   151  Specifically access to the private data will be restricted as follows:
   152  
   153  - ``name, color, size, and owner`` will be visible to all members of the channel (Org1 and Org2)
   154  - ``price`` only visible to members of Org1
   155  
   156  Thus two different sets of private data are defined in the marbles private data
   157  sample. The mapping of this data to the collection policy which restricts its
   158  access is controlled by chaincode APIs. Specifically, reading and writing
   159  private data using a collection definition is performed by calling ``GetPrivateData()``
   160  and ``PutPrivateData()``, which can be found `here <https://godoc.org/github.com/hyperledger/fabric-chaincode-go/shim#ChaincodeStub>`_.
   161  
   162  The following diagrams illustrate the private data model used by the marbles
   163  private data sample.
   164  
   165   .. image:: images/SideDB-org1.png
   166  
   167   .. image:: images/SideDB-org2.png
   168  
   169  
   170  Reading collection data
   171  ~~~~~~~~~~~~~~~~~~~~~~~~
   172  
   173  Use the chaincode API ``GetPrivateData()`` to query private data in the
   174  database.  ``GetPrivateData()`` takes two arguments, the **collection name**
   175  and the data key. Recall the collection  ``collectionMarbles`` allows members of
   176  Org1 and Org2 to have the private data in a side database, and the collection
   177  ``collectionMarblePrivateDetails`` allows only members of Org1 to have the
   178  private data in a side database. For implementation details refer to the
   179  following two `marbles private data functions <https://github.com/hyperledger/fabric-samples/blob/master/chaincode/marbles02_private/go/marbles_chaincode_private.go>`__:
   180  
   181   * **readMarble** for querying the values of the ``name, color, size and owner`` attributes
   182   * **readMarblePrivateDetails** for querying the values of the ``price`` attribute
   183  
   184  When we issue the database queries using the peer commands later in this tutorial,
   185  we will call these two functions.
   186  
   187  Writing private data
   188  ~~~~~~~~~~~~~~~~~~~~
   189  
   190  Use the chaincode API ``PutPrivateData()`` to store the private data
   191  into the private database. The API also requires the name of the collection.
   192  Since the marbles private data sample includes two different collections, it is called
   193  twice in the chaincode:
   194  
   195  1. Write the private data ``name, color, size and owner`` using the
   196     collection named ``collectionMarbles``.
   197  2. Write the private data ``price`` using the collection named
   198     ``collectionMarblePrivateDetails``.
   199  
   200  For example, in the following snippet of the ``initMarble`` function,
   201  ``PutPrivateData()`` is called twice, once for each set of private data.
   202  
   203  .. code-block:: GO
   204  
   205    // ==== Create marble object, marshal to JSON, and save to state ====
   206  	marble := &marble{
   207  		ObjectType: "marble",
   208  		Name:       marbleInput.Name,
   209  		Color:      marbleInput.Color,
   210  		Size:       marbleInput.Size,
   211  		Owner:      marbleInput.Owner,
   212  	}
   213  	marbleJSONasBytes, err := json.Marshal(marble)
   214  	if err != nil {
   215  		return shim.Error(err.Error())
   216  	}
   217  
   218  	// === Save marble to state ===
   219  	err = stub.PutPrivateData("collectionMarbles", marbleInput.Name, marbleJSONasBytes)
   220  	if err != nil {
   221  		return shim.Error(err.Error())
   222  	}
   223  
   224  	// ==== Create marble private details object with price, marshal to JSON, and save to state ====
   225  	marblePrivateDetails := &marblePrivateDetails{
   226  		ObjectType: "marblePrivateDetails",
   227  		Name:       marbleInput.Name,
   228  		Price:      marbleInput.Price,
   229  	}
   230  	marblePrivateDetailsBytes, err := json.Marshal(marblePrivateDetails)
   231  	if err != nil {
   232  		return shim.Error(err.Error())
   233  	}
   234  	err = stub.PutPrivateData("collectionMarblePrivateDetails", marbleInput.Name, marblePrivateDetailsBytes)
   235  	if err != nil {
   236  		return shim.Error(err.Error())
   237  	}
   238  
   239  
   240  To summarize, the policy definition above for our ``collection.json``
   241  allows all peers in Org1 and Org2 to store and transact
   242  with the marbles private data ``name, color, size, owner`` in their
   243  private database. But only peers in Org1 can store and transact with
   244  the ``price`` private data in its private database.
   245  
   246  As an additional data privacy benefit, since a collection is being used,
   247  only the private data hashes go through orderer, not the private data itself,
   248  keeping private data confidential from orderer.
   249  
   250  Start the network
   251  -----------------
   252  
   253  Now we are ready to step through some commands which demonstrate how to use
   254  private data.
   255  
   256  :guilabel:`Try it yourself`
   257  
   258  Before installing, defining, and using the marbles private data chaincode below,
   259  we need to start the BYFN network. For the sake of this tutorial, we want to
   260  operate from a known initial state. The following command will kill any active
   261  or stale docker containers and remove previously generated artifacts.
   262  Therefore let's run the following command to clean up any previous
   263  environments:
   264  
   265  .. code:: bash
   266  
   267     cd fabric-samples/first-network
   268     ./byfn.sh down
   269  
   270  
   271  If you've already run through this tutorial, you'll also want to delete the
   272  underlying docker containers for the marbles private data chaincode. Let's run
   273  the following commands to clean up previous environments:
   274  
   275  .. code:: bash
   276  
   277     docker rm -f $(docker ps -a | awk '($2 ~ /dev-peer.*.marblesp.*/) {print $1}')
   278     docker rmi -f $(docker images | awk '($1 ~ /dev-peer.*.marblesp.*/) {print $3}')
   279  
   280  Start up the BYFN network with CouchDB by running the following command:
   281  
   282  .. code:: bash
   283  
   284     ./byfn.sh up -c mychannel -s couchdb
   285  
   286  This will create a simple Fabric network consisting of a single channel named
   287  ``mychannel`` with two organizations (each maintaining two peer nodes) and an
   288  ordering service while using CouchDB as the state database. Either LevelDB or
   289  CouchDB may be used with collections. CouchDB was chosen to demonstrate how to
   290  use indexes with private data.
   291  
   292  .. note:: For collections to work, it is important to have cross organizational
   293             gossip configured correctly. Refer to our documentation on :doc:`gossip`,
   294             paying particular attention to the section on "anchor peers". Our tutorial
   295             does not focus on gossip given it is already configured in the BYFN sample,
   296             but when configuring a channel, the gossip anchors peers are critical to
   297             configure for collections to work properly.
   298  
   299  .. _pd-install-define_cc:
   300  
   301  Install and define a chaincode with a collection
   302  -------------------------------------------------
   303  
   304  Client applications interact with the blockchain ledger through chaincode.
   305  Therefore we need to install a chaincode on every peer that will execute and
   306  endorse our transactions. However, before we can interact with our chaincode,
   307  the members of the channel need to agree on a chaincode definition that
   308  establishes chaincode governance, including the private data collection
   309  configuration. We are going to package, install, and then define the chaincode
   310  on the channel using :doc:`commands/peerlifecycle`.
   311  
   312  Install chaincode on all peers
   313  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   314  
   315  The chaincode needs to be packaged before it can be installed on our peers.
   316  We can use the `peer lifecycle chaincode package <http://hyperledger-fabric.readthedocs.io/en/latest/commands/peerlifecycle.html#peer-lifecycle-chaincode-package>`__ command
   317  to package the marbles chaincode.
   318  
   319  The BYFN network includes two organizations, Org1 and Org2, with two peers each.
   320  Therefore, the chaincode package has to be installed on four peers:
   321  
   322  - peer0.org1.example.com
   323  - peer1.org1.example.com
   324  - peer0.org2.example.com
   325  - peer1.org2.example.com
   326  
   327  After the chaincode is packaged, we can use the `peer lifecycle chaincode install <http://hyperledger-fabric.readthedocs.io/en/latest/commands/peerlifecycle.html#peer-lifecycle-chaincode-install>`__
   328  command to install the Marbles chaincode on each peer.
   329  
   330  :guilabel:`Try it yourself`
   331  
   332  Assuming you have started the BYFN network, enter the CLI container:
   333  
   334  .. code:: bash
   335  
   336      docker exec -it cli bash
   337  
   338  Your command prompt will change to something similar to:
   339  
   340  .. code:: bash
   341  
   342      bash-4.4#
   343  
   344  1. Use the following command to package the marbles private data chaincode from
   345  the git repository inside your local container.
   346  
   347  .. code:: bash
   348  
   349      peer lifecycle chaincode package marblesp.tar.gz --path github.com/hyperledger/fabric-samples/chaincode/marbles02_private/go/ --lang golang --label marblespv1
   350  
   351  This command will create a chaincode package named marblesp.tar.gz.
   352  
   353  2. Use the following command to install the chaincode package onto the peer
   354  ``peer0.org1.example.com`` in your BYFN network. By default, after starting the
   355  BYFN network, the active peer is set to
   356  ``CORE_PEER_ADDRESS=peer0.org1.example.com:7051``:
   357  
   358  .. code:: bash
   359  
   360      peer lifecycle chaincode install marblesp.tar.gz
   361  
   362  A successful install command will return the chaincode identifier, similar to
   363  the response below:
   364  
   365  .. code:: bash
   366  
   367      2019-04-22 19:09:04.336 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nKmarblespv1:57f5353b2568b79cb5384b5a8458519a47186efc4fcadb98280f5eae6d59c1cd\022\nmarblespv1" >
   368      2019-04-22 19:09:04.336 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: marblespv1:57f5353b2568b79cb5384b5a8458519a47186efc4fcadb98280f5eae6d59c1cd
   369  
   370  3. Use the CLI to switch the active peer to the second peer in Org1 and install
   371  the chaincode. Copy and paste the following entire block of commands into the
   372  CLI container and run them:
   373  
   374  .. code:: bash
   375  
   376      export CORE_PEER_ADDRESS=peer1.org1.example.com:8051
   377      peer lifecycle chaincode install marblesp.tar.gz
   378  
   379  4. Use the CLI to switch to Org2. Copy and paste the following block of commands
   380  as a group into the peer container and run them all at once:
   381  
   382  .. code:: bash
   383  
   384      export CORE_PEER_LOCALMSPID=Org2MSP
   385      export PEER0_ORG2_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
   386      export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
   387      export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
   388  
   389  5. Switch the active peer to the first peer in Org2 and install the chaincode:
   390  
   391  .. code:: bash
   392  
   393      export CORE_PEER_ADDRESS=peer0.org2.example.com:9051
   394      peer lifecycle chaincode install marblesp.tar.gz
   395  
   396  6. Switch the active peer to the second peer in org2 and install the chaincode:
   397  
   398  .. code:: bash
   399  
   400      export CORE_PEER_ADDRESS=peer1.org2.example.com:10051
   401      peer lifecycle chaincode install marblesp.tar.gz
   402  
   403  
   404  Approve the chaincode definition
   405  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   406  
   407  Each channel member that wants to use the chaincode needs to approve a chaincode
   408  definition for their organization. Since both organizations are going to use the
   409  chaincode in this tutorial, we need to approve the chaincode definition for both
   410  Org1 and Org2.
   411  
   412  The chaincode definition includes the package identifier that was returned by
   413  the install command. This packege ID is used to associate the chaincode package
   414  installed on your peers with the chaincode definition approved by your
   415  organization. We can also use the `peer lifecycle chaincode queryinstalled <http://hyperledger-fabric.readthedocs.io/en/latest/commands/peerlifecycle.html#peer-lifecycle-chaincode-queryinstalled>`__
   416  command to find the package ID of ``marblesp.tar.gz``.
   417  
   418  Once we have the package ID, we can then use the `peer lifecycle chaincode approveformyorg <http://hyperledger-fabric.readthedocs.io/en/latest/commands/peerlifecycle.html#peer-lifecycle-chaincode-approveformyorg>`__
   419  command to approve a definition of the marbles chaincode for Org1 and Org2. To approve
   420  the private data collection definition that accompanies the ``marbles02_private``,
   421  sample, provide the path to the collections JSON file using the
   422  ``--collections-config`` flag.
   423  
   424  :guilabel:`Try it yourself`
   425  
   426  Run the following commands inside the CLI container to approve a definition for
   427  Org1 and Org2.
   428  
   429  1. Use the following command to query your peer for the package ID of the
   430  installed chaincode.
   431  
   432  .. code:: bash
   433  
   434      peer lifecycle chaincode queryinstalled
   435  
   436  The command will return the same package identifier as the install command.
   437  You should see output similar to the following:
   438  
   439  .. code:: bash
   440  
   441      Installed chaincodes on peer:
   442      Package ID: marblespv1:57f5353b2568b79cb5384b5a8458519a47186efc4fcadb98280f5eae6d59c1cd, Label: marblespv1
   443      Package ID: mycc_1:27ef99cb3cbd1b545063f018f3670eddc0d54f40b2660b8f853ad2854c49a0d8, Label: mycc_1
   444  
   445  2. Declare the package ID as an environment variable. Paste the package ID of
   446  marblespv1 returned by the ``peer lifecycle chaincode queryinstalled`` into
   447  the command below. The package ID may not be the same for all users, so you
   448  need to complete this step using the package ID returned from your console.
   449  
   450  .. code:: bash
   451  
   452      export CC_PACKAGE_ID=marblespv1:57f5353b2568b79cb5384b5a8458519a47186efc4fcadb98280f5eae6d59c1cd
   453  
   454  3. Make sure we are running the CLI as Org1. Copy and paste the following block
   455  of commands as a group into the peer container and run them all at once:
   456  
   457  .. code :: bash
   458  
   459      export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
   460      export CORE_PEER_LOCALMSPID=Org1MSP
   461      export PEER0_ORG1_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   462      export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
   463      export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
   464  
   465  4. Use the following command to approve a definition of the marbles private data
   466  chaincode for Org1. This command includes a path to the collection definition
   467  file. The approval is distributed within each organization using gossip, so
   468  the command does not need to target every peer within an organization.
   469  
   470  .. code:: bash
   471  
   472      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
   473      peer lifecycle chaincode approveformyorg --channelID mychannel --name marblesp --version 1.0 --collections-config $GOPATH/src/github.com/hyperledger/fabric-samples/chaincode/marbles02_private/collections_config.json --signature-policy "OR('Org1MSP.member','Org2MSP.member')" --init-required --package-id $CC_PACKAGE_ID --sequence 1 --tls true --cafile $ORDERER_CA
   474  
   475  When the command completes successfully you should see something similar to:
   476  
   477  .. code:: bash
   478  
   479      2019-03-18 16:04:09.046 UTC [cli.lifecycle.chaincode] InitCmdFactory -> INFO 001 Retrieved channel (mychannel) orderer endpoint: orderer.example.com:7050
   480      2019-03-18 16:04:11.253 UTC [chaincodeCmd] ClientWait -> INFO 002 txid [efba188ca77889cc1c328fc98e0bb12d3ad0abcda3f84da3714471c7c1e6c13c] committed with status (VALID) at
   481  
   482  5. Use the CLI to switch to Org2. Copy and paste the following block of commands
   483  as a group into the peer container and run them all at once.
   484  
   485  .. code:: bash
   486  
   487      export CORE_PEER_ADDRESS=peer0.org2.example.com:9051
   488      export CORE_PEER_LOCALMSPID=Org2MSP
   489      export PEER0_ORG2_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
   490      export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
   491      export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
   492  
   493  6. You can now approve the chaincode definition for Org2:
   494  
   495  .. code:: bash
   496  
   497      peer lifecycle chaincode approveformyorg --channelID mychannel --name marblesp --version 1.0 --collections-config $GOPATH/src/github.com/hyperledger/fabric-samples/chaincode/marbles02_private/collections_config.json --signature-policy "OR('Org1MSP.member','Org2MSP.member')" --init-required --package-id $CC_PACKAGE_ID --sequence 1 --tls true --cafile $ORDERER_CA
   498  
   499  Commit the chaincode definition
   500  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   501  
   502  Once a sufficient number of organizations (in this case, a majority) have
   503  approved a chaincode definition, one organization commit the definition to the
   504  channel.
   505  
   506  Use the `peer lifecycle chaincode commit <http://hyperledger-fabric.readthedocs.io/en/latest/commands/peerlifecycle.html#peer-lifecycle-chaincode-commit>`__
   507  command to commit the chaincode definition. This command needs to target the
   508  peers in Org1 and Org2 to collect endorsements for the commit transaction. The
   509  peers will endorse the transaction only if their organizations have approved the
   510  chaincode definition. This command will also deploy the collection definition to
   511  the channel.
   512  
   513  We are ready to use the chaincode after the chaincode definition has been
   514  committed to the channel. Because the marbles private data chaincode contains an
   515  initiation function, we need to use the `peer chaincode invoke <http://hyperledger-fabric.readthedocs.io/en/master/commands/peerchaincode.html?%20chaincode%20instantiate#peer-chaincode-instantiate>`__ command
   516  to invoke ``Init()`` before we can use other functions in the chaincode.
   517  
   518  :guilabel:`Try it yourself`
   519  
   520  1. Run the following commands to commit the definition of the marbles private
   521  data chaincode to the BYFN channel ``mychannel``.
   522  
   523  .. code:: bash
   524  
   525      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
   526      export ORG1_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   527      export ORG2_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
   528      peer lifecycle chaincode commit -o orderer.example.com:7050 --channelID mychannel --name marblesp --version 1.0 --sequence 1 --collections-config $GOPATH/src/github.com/hyperledger/fabric-samples/chaincode/marbles02_private/collections_config.json --signature-policy "OR('Org1MSP.member','Org2MSP.member')" --init-required --tls true --cafile $ORDERER_CA --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles $ORG1_CA --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles $ORG2_CA
   529  
   530    .. note:: When specifying the value of the ``--collections-config`` flag, you will
   531              need to specify the fully qualified path to the collections_config.json file.
   532              For example:
   533  
   534              .. code:: bash
   535  
   536                   --collections-config  $GOPATH/src/github.com/hyperledger/fabric-samples/chaincode/marbles02_private/collections_config.json
   537  
   538    When the commit transaction completes successfully you should see something
   539    similar to:
   540  
   541    .. code:: bash
   542  
   543        [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
   544        [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
   545  
   546  2. Use the following command to invoke the ``Init`` function to initialize the
   547  chaincode:
   548  
   549  .. code:: bash
   550  
   551      peer chaincode invoke -o orderer.example.com:7050 --channelID mychannel --name marblesp --isInit --tls true --cafile $ORDERER_CA --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles $ORG1_CA -c '{"Args":["Init"]}'
   552  
   553  .. _pd-store-private-data:
   554  
   555  Store private data
   556  ------------------
   557  
   558  Acting as a member of Org1, who is authorized to transact with all of the private data
   559  in the marbles private data sample, switch back to an Org1 peer and
   560  submit a request to add a marble:
   561  
   562  :guilabel:`Try it yourself`
   563  
   564  Copy and paste the following set of commands to the CLI command line.
   565  
   566  .. code:: bash
   567  
   568      export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
   569      export CORE_PEER_LOCALMSPID=Org1MSP
   570      export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   571      export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
   572      export PEER0_ORG1_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   573  
   574  Invoke the marbles ``initMarble`` function which
   575  creates a marble with private data ---  name ``marble1`` owned by ``tom`` with a color
   576  ``blue``, size ``35`` and price of ``99``. Recall that private data **price**
   577  will be stored separately from the private data **name, owner, color, size**.
   578  For this reason, the ``initMarble`` function calls the ``PutPrivateData()`` API
   579  twice to persist the private data, once for each collection. Also note that
   580  the private data is passed using the ``--transient`` flag. Inputs passed
   581  as transient data will not be persisted in the transaction in order to keep
   582  the data private. Transient data is passed as binary data and therefore when
   583  using CLI it must be base64 encoded. We use an environment variable
   584  to capture the base64 encoded value, and use ``tr`` command to strip off the
   585  problematic newline characters that linux base64 command adds.
   586  
   587  .. code:: bash
   588  
   589     export MARBLE=$(echo -n "{\"name\":\"marble1\",\"color\":\"blue\",\"size\":35,\"owner\":\"tom\",\"price\":99}" | base64 | tr -d \\n)
   590     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\"}"
   591  
   592  You should see results similar to:
   593  
   594   ``[chaincodeCmd] chaincodeInvokeOrQuery->INFO 001 Chaincode invoke successful. result: status:200``
   595  
   596  .. _pd-query-authorized:
   597  
   598  Query the private data as an authorized peer
   599  --------------------------------------------
   600  
   601  Our collection definition allows all members of Org1 and Org2
   602  to have the ``name, color, size, owner`` private data in their side database,
   603  but only peers in Org1 can have the ``price`` private data in their side
   604  database. As an authorized peer in Org1, we will query both sets of private data.
   605  
   606  The first ``query`` command calls the ``readMarble`` function which passes
   607  ``collectionMarbles`` as an argument.
   608  
   609  .. code-block:: GO
   610  
   611     // ===============================================
   612     // readMarble - read a marble from chaincode state
   613     // ===============================================
   614  
   615     func (t *SimpleChaincode) readMarble(stub shim.ChaincodeStubInterface, args []string) pb.Response {
   616     	var name, jsonResp string
   617     	var err error
   618     	if len(args) != 1 {
   619     		return shim.Error("Incorrect number of arguments. Expecting name of the marble to query")
   620     	}
   621  
   622     	name = args[0]
   623     	valAsbytes, err := stub.GetPrivateData("collectionMarbles", name) //get the marble from chaincode state
   624  
   625     	if err != nil {
   626     		jsonResp = "{\"Error\":\"Failed to get state for " + name + "\"}"
   627     		return shim.Error(jsonResp)
   628     	} else if valAsbytes == nil {
   629     		jsonResp = "{\"Error\":\"Marble does not exist: " + name + "\"}"
   630     		return shim.Error(jsonResp)
   631     	}
   632  
   633     	return shim.Success(valAsbytes)
   634     }
   635  
   636  The second ``query`` command calls the ``readMarblePrivateDetails``
   637  function which passes ``collectionMarblePrivateDetails`` as an argument.
   638  
   639  .. code-block:: GO
   640  
   641     // ===============================================
   642     // readMarblePrivateDetails - read a marble private details from chaincode state
   643     // ===============================================
   644  
   645     func (t *SimpleChaincode) readMarblePrivateDetails(stub shim.ChaincodeStubInterface, args []string) pb.Response {
   646     	var name, jsonResp string
   647     	var err error
   648  
   649     	if len(args) != 1 {
   650     		return shim.Error("Incorrect number of arguments. Expecting name of the marble to query")
   651     	}
   652  
   653     	name = args[0]
   654     	valAsbytes, err := stub.GetPrivateData("collectionMarblePrivateDetails", name) //get the marble private details from chaincode state
   655  
   656     	if err != nil {
   657     		jsonResp = "{\"Error\":\"Failed to get private details for " + name + ": " + err.Error() + "\"}"
   658     		return shim.Error(jsonResp)
   659     	} else if valAsbytes == nil {
   660     		jsonResp = "{\"Error\":\"Marble private details does not exist: " + name + "\"}"
   661     		return shim.Error(jsonResp)
   662     	}
   663     	return shim.Success(valAsbytes)
   664     }
   665  
   666  Now :guilabel:`Try it yourself`
   667  
   668  Query for the ``name, color, size and owner`` private data of ``marble1`` as a member of Org1.
   669  Note that since queries do not get recorded on the ledger, there is no need to pass
   670  the marble name as a transient input.
   671  
   672  .. code:: bash
   673  
   674      peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarble","marble1"]}'
   675  
   676  You should see the following result:
   677  
   678  .. code:: bash
   679  
   680      {"color":"blue","docType":"marble","name":"marble1","owner":"tom","size":35}
   681  
   682  Query for the ``price`` private data of ``marble1`` as a member of Org1.
   683  
   684  .. code:: bash
   685  
   686      peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'
   687  
   688  You should see the following result:
   689  
   690  .. code:: bash
   691  
   692      {"docType":"marblePrivateDetails","name":"marble1","price":99}
   693  
   694  .. _pd-query-unauthorized:
   695  
   696  Query the private data as an unauthorized peer
   697  ----------------------------------------------
   698  
   699  Now we will switch to a member of Org2 which has the marbles private data
   700  ``name, color, size, owner`` in its side database, but does not have the
   701  marbles ``price`` private data in its side database. We will query for both
   702  sets of private data.
   703  
   704  Switch to a peer in Org2
   705  ~~~~~~~~~~~~~~~~~~~~~~~~
   706  
   707  From inside the docker container, run the following commands to switch to
   708  the peer which is unauthorized to access the marbles ``price`` private data.
   709  
   710  :guilabel:`Try it yourself`
   711  
   712  .. code:: bash
   713  
   714      export CORE_PEER_ADDRESS=peer0.org2.example.com:9051
   715      export CORE_PEER_LOCALMSPID=Org2MSP
   716      export PEER0_ORG2_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
   717      export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
   718      export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
   719  
   720  Query private data Org2 is authorized to
   721  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   722  
   723  Peers in Org2 should have the first set of marbles private data (``name,
   724  color, size and owner``) in their side database and can access it using the
   725  ``readMarble()`` function which is called with the ``collectionMarbles``
   726  argument.
   727  
   728  :guilabel:`Try it yourself`
   729  
   730  .. code:: bash
   731  
   732      peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarble","marble1"]}'
   733  
   734  You should see something similar to the following result:
   735  
   736  .. code:: json
   737  
   738      {"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}
   739  
   740  Query private data Org2 is not authorized to
   741  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   742  
   743  Peers in Org2 do not have the marbles ``price`` private data in their side database.
   744  When they try to query for this data, they get back a hash of the key matching
   745  the public state but will not have the private state.
   746  
   747  :guilabel:`Try it yourself`
   748  
   749  .. code:: bash
   750  
   751      peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'
   752  
   753  You should see a result similar to:
   754  
   755  .. code:: json
   756  
   757      {"Error":"Failed to get private details for marble1: GET_STATE failed:
   758      transaction ID: b04adebbf165ddc90b4ab897171e1daa7d360079ac18e65fa15d84ddfebfae90:
   759      Private data matching public hash version is not available. Public hash
   760      version = &version.Height{BlockNum:0x6, TxNum:0x0}, Private data version =
   761      (*version.Height)(nil)"}
   762  
   763  Members of Org2 will only be able to see the public hash of the private data.
   764  
   765  .. _pd-purge:
   766  
   767  Purge Private Data
   768  ------------------
   769  
   770  For use cases where private data only needs to be on the ledger until it can be
   771  replicated into an off-chain database, it is possible to "purge" the data after
   772  a certain set number of blocks, leaving behind only hash of the data that serves
   773  as immutable evidence of the transaction.
   774  
   775  There may be private data including personal or confidential
   776  information, such as the pricing data in our example, that the transacting
   777  parties don't want disclosed to other organizations on the channel. Thus, it
   778  has a limited lifespan, and can be purged after existing unchanged on the
   779  blockchain for a designated number of blocks using the ``blockToLive`` property
   780  in the collection definition.
   781  
   782  Our ``collectionMarblePrivateDetails`` definition has a ``blockToLive``
   783  property value of three meaning this data will live on the side database for
   784  three blocks and then after that it will get purged. Tying all of the pieces
   785  together, recall this collection definition  ``collectionMarblePrivateDetails``
   786  is associated with the ``price`` private data in the  ``initMarble()`` function
   787  when it calls the ``PutPrivateData()`` API and passes the
   788  ``collectionMarblePrivateDetails`` as an argument.
   789  
   790  We will step through adding blocks to the chain, and then watch the price
   791  information get purged by issuing four new transactions (Create a new marble,
   792  followed by three marble transfers) which adds four new blocks to the chain.
   793  After the fourth transaction (third marble transfer), we will verify that the
   794  price private data is purged.
   795  
   796  :guilabel:`Try it yourself`
   797  
   798  Switch back to peer0 in Org1 using the following commands. Copy and paste the
   799  following code block and run it inside your peer container:
   800  
   801  .. code:: bash
   802  
   803      export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
   804      export CORE_PEER_LOCALMSPID=Org1MSP
   805      export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   806      export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
   807      export PEER0_ORG1_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   808  
   809  Open a new terminal window and view the private data logs for this peer by
   810  running the following command:
   811  
   812  .. code:: bash
   813  
   814      docker logs peer0.org1.example.com 2>&1 | grep -i -a -E 'private|pvt|privdata'
   815  
   816  You should see results similar to the following. Note the highest block number
   817  in the list. In the example below, the highest block height is ``4``.
   818  
   819  .. code:: bash
   820  
   821      [pvtdatastorage] func1 -> INFO 023 Purger started: Purging expired private data till block number [0]
   822      [pvtdatastorage] func1 -> INFO 024 Purger finished
   823      [kvledger] CommitLegacy -> INFO 022 Channel [mychannel]: Committed block [0] with 1 transaction(s)
   824      [kvledger] CommitLegacy -> INFO 02e Channel [mychannel]: Committed block [1] with 1 transaction(s)
   825      [kvledger] CommitLegacy -> INFO 030 Channel [mychannel]: Committed block [2] with 1 transaction(s)
   826      [kvledger] CommitLegacy -> INFO 036 Channel [mychannel]: Committed block [3] with 1 transaction(s)
   827      [kvledger] CommitLegacy -> INFO 03e Channel [mychannel]: Committed block [4] with 1 transaction(s)
   828  
   829  Back in the peer container, query for the **marble1** price data by running the
   830  following command. (A Query does not create a new transaction on the ledger
   831  since no data is transacted).
   832  
   833  .. code:: bash
   834  
   835      peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'
   836  
   837  You should see results similar to:
   838  
   839  .. code:: bash
   840  
   841      {"docType":"marblePrivateDetails","name":"marble1","price":99}
   842  
   843  The ``price`` data is still in the private data ledger.
   844  
   845  Create a new **marble2** by issuing the following command. This transaction
   846  creates a new block on the chain.
   847  
   848  .. code:: bash
   849  
   850      export MARBLE=$(echo -n "{\"name\":\"marble2\",\"color\":\"blue\",\"size\":35,\"owner\":\"tom\",\"price\":99}" | base64 | tr -d \\n)
   851      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\"}"
   852  
   853  Switch back to the Terminal window and view the private data logs for this peer
   854  again. You should see the block height increase by 1.
   855  
   856  .. code:: bash
   857  
   858      docker logs peer0.org1.example.com 2>&1 | grep -i -a -E 'private|pvt|privdata'
   859  
   860  Back in the peer container, query for the **marble1** price data again by
   861  running the following command:
   862  
   863  .. code:: bash
   864  
   865      peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'
   866  
   867  The private data has not been purged, therefore the results are unchanged from
   868  previous query:
   869  
   870  .. code:: bash
   871  
   872      {"docType":"marblePrivateDetails","name":"marble1","price":99}
   873  
   874  Transfer marble2 to "joe" by running the following command. This transaction
   875  will add a second new block on the chain.
   876  
   877  .. code:: bash
   878  
   879      export MARBLE_OWNER=$(echo -n "{\"name\":\"marble2\",\"owner\":\"joe\"}" | base64 | tr -d \\n)
   880      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":["transferMarble"]}' --transient "{\"marble_owner\":\"$MARBLE_OWNER\"}"
   881  
   882  Switch back to the Terminal window and view the private data logs for this peer
   883  again. You should see the block height increase by 1.
   884  
   885  .. code:: bash
   886  
   887      docker logs peer0.org1.example.com 2>&1 | grep -i -a -E 'private|pvt|privdata'
   888  
   889  Back in the peer container, query for the marble1 price data by running the
   890  following command:
   891  
   892  .. code:: bash
   893  
   894      peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'
   895  
   896  You should still be able to see the price private data.
   897  
   898  .. code:: bash
   899  
   900      {"docType":"marblePrivateDetails","name":"marble1","price":99}
   901  
   902  Transfer marble2 to "tom" by running the following command. This transaction
   903  will create a third new block on the chain.
   904  
   905  .. code:: bash
   906  
   907      export MARBLE_OWNER=$(echo -n "{\"name\":\"marble2\",\"owner\":\"tom\"}" | base64 | tr -d \\n)
   908      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":["transferMarble"]}' --transient "{\"marble_owner\":\"$MARBLE_OWNER\"}"
   909  
   910  Switch back to the Terminal window and view the private data logs for this peer
   911  again. You should see the block height increase by 1.
   912  
   913  .. code:: bash
   914  
   915      docker logs peer0.org1.example.com 2>&1 | grep -i -a -E 'private|pvt|privdata'
   916  
   917  Back in the peer container, query for the marble1 price data by running the
   918  following command:
   919  
   920  .. code:: bash
   921  
   922      peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'
   923  
   924  You should still be able to see the price data.
   925  
   926  .. code:: bash
   927  
   928      {"docType":"marblePrivateDetails","name":"marble1","price":99}
   929  
   930  Finally, transfer marble2 to "jerry" by running the following command. This
   931  transaction will create a fourth new block on the chain. The ``price`` private
   932  data should be purged after this transaction.
   933  
   934  .. code:: bash
   935  
   936      export MARBLE_OWNER=$(echo -n "{\"name\":\"marble2\",\"owner\":\"jerry\"}" | base64 | tr -d \\n)
   937      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":["transferMarble"]}' --transient "{\"marble_owner\":\"$MARBLE_OWNER\"}"
   938  
   939  Switch back to the Terminal window and view the private data logs for this peer
   940  again. You should see the block height increase by 1.
   941  
   942  .. code:: bash
   943  
   944      docker logs peer0.org1.example.com 2>&1 | grep -i -a -E 'private|pvt|privdata'
   945  
   946  Back in the peer container, query for the marble1 price data by running the following command:
   947  
   948  .. code:: bash
   949  
   950      peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'
   951  
   952  Because the price data has been purged, you should no longer be able to see it.
   953  You should see something similar to:
   954  
   955  .. code:: bash
   956  
   957      Error: endorsement failure during query. response: status:500
   958      message:"{\"Error\":\"Marble private details does not exist: marble1\"}"
   959  
   960  .. _pd-indexes:
   961  
   962  Using indexes with private data
   963  -------------------------------
   964  
   965  Indexes can also be applied to private data collections, by packaging indexes in
   966  the ``META-INF/statedb/couchdb/collections/<collection_name>/indexes`` directory
   967  alongside the chaincode. An example index is available `here <https://github.com/hyperledger/fabric-samples/blob/master/chaincode/marbles02_private/go/META-INF/statedb/couchdb/collections/collectionMarbles/indexes/indexOwner.json>`__ .
   968  
   969  For deployment of chaincode to production environments, it is recommended
   970  to define any indexes alongside chaincode so that the chaincode and supporting
   971  indexes are deployed automatically as a unit, once the chaincode has been
   972  installed on a peer and instantiated on a channel. The associated indexes are
   973  automatically deployed upon chaincode instantiation on the channel when
   974  the  ``--collections-config`` flag is specified pointing to the location of
   975  the collection JSON file.
   976  
   977  
   978  .. _pd-ref-material:
   979  
   980  Additional resources
   981  --------------------
   982  
   983  For additional private data education, a video tutorial has been created.
   984  
   985  .. note:: The video uses the previous lifecycle model to install private data
   986            collections with chaincode.
   987  
   988  .. raw:: html
   989  
   990     <br/><br/>
   991     <iframe width="560" height="315" src="https://www.youtube.com/embed/qyjDi93URJE" frameborder="0" allowfullscreen></iframe>
   992     <br/><br/>
   993  
   994  .. Licensed under Creative Commons Attribution 4.0 International License
   995     https://creativecommons.org/licenses/by/4.0/