|
@@ -0,0 +1,841 @@
|
|
|
+End-to-End Flow
|
|
|
+===============
|
|
|
+
|
|
|
+The end-to-end verification demonstrates usage of the configuration
|
|
|
+transaction tool for orderer bootstrap and channel creation. The tool
|
|
|
+consumes a configuration transaction yaml file, which defines the
|
|
|
+cryptographic material (certs) used for member identity and network
|
|
|
+authentication. In other words, the MSP information for each member and
|
|
|
+its corresponding network entities.
|
|
|
+
|
|
|
+*Currently the crypto material is baked into the directory. However,
|
|
|
+there will be a tool in the near future to organically generate the
|
|
|
+certificates*
|
|
|
+
|
|
|
+Prerequisites
|
|
|
+-------------
|
|
|
+
|
|
|
+- Follow the steps for setting up a `development
|
|
|
+ environment <http://hyperledger-fabric.readthedocs.io/en/latest/dev-setup/devenv.html>`__
|
|
|
+
|
|
|
+- Clone the Fabric code base.
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ git clone http://gerrit.hyperledger.org/r/fabric
|
|
|
+
|
|
|
+ or though a mirrored repository in github:
|
|
|
+
|
|
|
+ ::
|
|
|
+
|
|
|
+ git clone https://github.com/hyperledger/fabric.git
|
|
|
+
|
|
|
+- Make the ``configtxgen`` tool.
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ cd $GOPATH/src/github.com/hyperledger/fabric/devenv
|
|
|
+ vagrant up
|
|
|
+ vagrant ssh
|
|
|
+ # ensure sure you are in the /fabric directory where the Makefile resides
|
|
|
+ make configtxgen
|
|
|
+
|
|
|
+- Make the peer and orderer images.
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ # make sure you are in vagrant and in the /fabric directory
|
|
|
+ make peer-docker orderer-docker
|
|
|
+
|
|
|
+ Execute a ``docker images`` command in your terminal. If the images
|
|
|
+ compiled successfully, you should see an output similar to the
|
|
|
+ following:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ vagrant@hyperledger-devenv:v0.3.0-4eec836:/opt/gopath/src/github.com/hyperledger/fabric$ docker images
|
|
|
+ REPOSITORY TAG IMAGE ID CREATED SIZE
|
|
|
+ hyperledger/fabric-orderer latest 264e45897bfb 10 minutes ago 180 MB
|
|
|
+ hyperledger/fabric-orderer x86_64-0.7.0-snapshot-a0d032b 264e45897bfb 10 minutes ago 180 MB
|
|
|
+ hyperledger/fabric-peer latest b3d44cff07c6 10 minutes ago 184 MB
|
|
|
+ hyperledger/fabric-peer x86_64-0.7.0-snapshot-a0d032b b3d44cff07c6 10 minutes ago 184 MB
|
|
|
+ hyperledger/fabric-javaenv latest 6e2a2adb998a 10 minutes ago 1.42 GB
|
|
|
+ hyperledger/fabric-javaenv x86_64-0.7.0-snapshot-a0d032b 6e2a2adb998a 10 minutes ago 1.42 GB
|
|
|
+ hyperledger/fabric-ccenv latest 0ce0e7dc043f 12 minutes ago 1.29 GB
|
|
|
+ hyperledger/fabric-ccenv x86_64-0.7.0-snapshot-a0d032b 0ce0e7dc043f 12 minutes ago 1.29 GB
|
|
|
+ hyperledger/fabric-baseimage x86_64-0.3.0 f4751a503f02 4 weeks ago 1.27 GB
|
|
|
+ hyperledger/fabric-baseos x86_64-0.3.0 c3a4cf3b3350 4 weeks ago 161 MB
|
|
|
+
|
|
|
+Configuration Transaction Generator
|
|
|
+-----------------------------------
|
|
|
+
|
|
|
+The `configtxgen
|
|
|
+tool <https://github.com/hyperledger/fabric/blob/master/docs/source/configtxgen.rst>`__
|
|
|
+is used to create two artifacts: - orderer **bootstrap block** - fabric
|
|
|
+**channel configuration transaction**
|
|
|
+
|
|
|
+The orderer block is the genesis block for the ordering service, and the
|
|
|
+channel transaction file is broadcast to the orderer at channel creation
|
|
|
+time.
|
|
|
+
|
|
|
+The ``configtx.yaml`` contains the definitions for the sample network.
|
|
|
+There are two members, each managing and maintaining two peer nodes.
|
|
|
+Inspect this file to better understand the corresponding cryptographic
|
|
|
+material tied to the member components. The ``/crypto`` directory
|
|
|
+contains the admin certs, ca certs, private keys for each entity, and
|
|
|
+the signing certs for each entity.
|
|
|
+
|
|
|
+For ease of use, a script - ``generateCfgTrx.sh`` - is provided. The
|
|
|
+script will generate the two configuration artifacts.
|
|
|
+
|
|
|
+Run the shell script
|
|
|
+^^^^^^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+Make sure you are in the ``examples/e2e_cli`` directory and in your
|
|
|
+vagrant environment. You can elect to pass in a unique name for your
|
|
|
+channel or simply execute the script without the ``channel-ID``
|
|
|
+parameter. If you choose not to pass in a unique name, then a channel
|
|
|
+with the default name of ``mychannel`` will be generated.
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ cd examples/e2e_cli
|
|
|
+ # note the <channel-ID> parm is optional
|
|
|
+ ./generateCfgTrx.sh <channel-ID>
|
|
|
+
|
|
|
+After you run the shell script, you should see an output in your
|
|
|
+terminal similar to the following:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ 2017/02/28 17:01:52 Generating new channel configtx
|
|
|
+ 2017/02/28 17:01:52 Creating no-op MSP instance
|
|
|
+ 2017/02/28 17:01:52 Obtaining default signing identity
|
|
|
+ 2017/02/28 17:01:52 Creating no-op signing identity instance
|
|
|
+ 2017/02/28 17:01:52 Serializing identity
|
|
|
+ 2017/02/28 17:01:52 signing message
|
|
|
+ 2017/02/28 17:01:52 signing message
|
|
|
+ 2017/02/28 17:01:52 Writing new channel tx
|
|
|
+
|
|
|
+These configuration transactions will bundle the crypto material for the
|
|
|
+participating members and their network components and output an orderer
|
|
|
+genesis block and channel transaction artifact. These two artifacts are
|
|
|
+required for a functioning transactional network with
|
|
|
+sign/verify/authenticate capabilities.
|
|
|
+
|
|
|
+Manually generate the artifacts (optional)
|
|
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+In your vagrant environment, navigate to the ``/common/configtx/tool``
|
|
|
+directory and replace the ``configtx.yaml`` file with the supplied yaml
|
|
|
+file in the ``/e2e_cli`` directory. Then return to the ``/e2e_cli``
|
|
|
+directory.
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ # Generate orderer bootstrap block
|
|
|
+ configtxgen -profile TwoOrgs -outputBlock <block-name>
|
|
|
+ # example: configtxgen -profile TwoOrgs -outputBlock orderer.block
|
|
|
+
|
|
|
+ # Generate channel configuration transaction
|
|
|
+ configtxgen -profile TwoOrgs -outputCreateChannelTx <cfg txn name> -channelID <channel-id>
|
|
|
+ # example: configtxgen -profile TwoOrgs -outputCreateChannelTx channel.tx -channelID mychannel
|
|
|
+
|
|
|
+Run the end-to-end test with Docker
|
|
|
+-----------------------------------
|
|
|
+
|
|
|
+Make sure you are in the ``/e2e_cli`` directory. Then use docker-compose
|
|
|
+to spawn the network entities and drive the tests.
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ [CHANNEL_NAME=<channel-id>] docker-compose up -d
|
|
|
+
|
|
|
+If you created a unique channel name, be sure to pass in that parameter.
|
|
|
+For example,
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ CHANNEL_NAME=abc docker-compose up -d
|
|
|
+
|
|
|
+Wait, 30 seconds. Behind the scenes, there are transactions being sent
|
|
|
+to the peers. Execute a ``docker ps`` to view your active containers.
|
|
|
+You should see an output identical to the following:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ vagrant@hyperledger-devenv:v0.3.0-4eec836:/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli$ docker ps
|
|
|
+ CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
|
|
+ 45e3e114f7a2 dev-peer3-mycc-1.0 "chaincode -peer.a..." 4 seconds ago Up 4 seconds dev-peer3-mycc-1.0
|
|
|
+ 5970f740ad2b dev-peer0-mycc-1.0 "chaincode -peer.a..." 24 seconds ago Up 23 seconds dev-peer0-mycc-1.0
|
|
|
+ b84808d66e99 dev-peer2-mycc-1.0 "chaincode -peer.a..." 48 seconds ago Up 47 seconds dev-peer2-mycc-1.0
|
|
|
+ 16d7d94c8773 hyperledger/fabric-peer "peer node start -..." About a minute ago Up About a minute 0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp peer3
|
|
|
+ 3561a99e35e6 hyperledger/fabric-peer "peer node start -..." About a minute ago Up About a minute 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp peer2
|
|
|
+ 0baad3047d92 hyperledger/fabric-peer "peer node start -..." About a minute ago Up About a minute 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp peer1
|
|
|
+ 1216896b7b4f hyperledger/fabric-peer "peer node start -..." About a minute ago Up About a minute 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0
|
|
|
+ 155ff8747b4d hyperledger/fabric-orderer "orderer" About a minute ago Up About a minute 0.0.0.0:7050->7050/tcp orderer
|
|
|
+
|
|
|
+All in one
|
|
|
+^^^^^^^^^^
|
|
|
+
|
|
|
+You can also generate the artifacts and drive the tests using a single
|
|
|
+shell script. The ``configtxgen`` and ``docker-compose`` commands are
|
|
|
+embedded in the script.
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ ./network_setup.sh up <channel-ID>
|
|
|
+
|
|
|
+Once again, if you choose not to pass the ``channel-ID`` parameter, then
|
|
|
+your channel will default to ``mychannel``.
|
|
|
+
|
|
|
+What's happening behind the scenes?
|
|
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+- A script - ``script.sh`` - is baked inside the CLI container. The
|
|
|
+ script drives the ``createChannel`` command against the default
|
|
|
+ ``mychannel`` name.
|
|
|
+
|
|
|
+- The output of ``createChannel`` is a genesis block -
|
|
|
+ ``mychannel.block`` - which is stored on the file system.
|
|
|
+
|
|
|
+- the ``joinChannel`` command is exercised for all four peers who will
|
|
|
+ pass in the genesis block.
|
|
|
+
|
|
|
+- Now we have a channel consisting of four peers, and two
|
|
|
+ organizations.
|
|
|
+
|
|
|
+- ``PEER0`` and ``PEER1`` belong to Org0; ``PEER2`` and ``PEER3``
|
|
|
+ belong to Org1
|
|
|
+
|
|
|
+- Recall that these relationships are defined in the ``configtx.yaml``
|
|
|
+
|
|
|
+- A chaincode - *chaincode\_example02* is installed on ``PEER0`` and
|
|
|
+ ``PEER2``
|
|
|
+
|
|
|
+- The chaincode is then "instantiated" on ``PEER2``. Instantiate simply
|
|
|
+ refers to starting the container and initializing the key value pairs
|
|
|
+ associated with the chaincode. The initial values for this example
|
|
|
+ are "a","100" "b","200". This "instantiation" results in a container
|
|
|
+ by the name of ``dev-peer2-mycc-1.0`` starting.
|
|
|
+
|
|
|
+- The instantiation also passes in an argument for the endorsement
|
|
|
+ policy. The policy is defined as
|
|
|
+ ``-P "OR ('Org0MSP.member','Org1MSP.member')"``, meaning that any
|
|
|
+ transaction must be endorsed by a peer tied to Org0 or Org1.
|
|
|
+
|
|
|
+- A query against the value of "a" is issued to ``PEER0``. The
|
|
|
+ chaincode was previously installed on ``PEER0``, so this will start
|
|
|
+ another container by the name of ``dev-peer0-mycc-1.0``. The result
|
|
|
+ of the query is also returned. No write operations have occurred, so
|
|
|
+ a query against "a" will still return a value of "100"
|
|
|
+
|
|
|
+- An invoke is sent to ``PEER0`` to move "10" from "a" to "b"
|
|
|
+
|
|
|
+- The chaincode is installed on ``PEER3``
|
|
|
+
|
|
|
+- A query is sent to ``PEER3`` for the value of "a". This starts a
|
|
|
+ third chaincode container by the name of ``dev-peer3-mycc-1.0``. A
|
|
|
+ value of 90 is returned, correctly reflecting the previous
|
|
|
+ transaction during which the value for key "a" was modified by 10.
|
|
|
+
|
|
|
+What does this demonstrate?
|
|
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+Chaincode **MUST** be installed on a peer in order for it to
|
|
|
+successfully perform read/write operations against the ledger.
|
|
|
+Furthermore, a chaincode container is not started for a peer until a
|
|
|
+read/write operation is performed against that chaincode (e.g. query for
|
|
|
+the value of "a"). The transaction causes the container to start. Also,
|
|
|
+all peers in a channel maintain an exact copy of the ledger which
|
|
|
+comprises the blockchain to store the immutable, sequenced record in
|
|
|
+blocks, as well as a state database to maintain current fabric state.
|
|
|
+This includes those peers that do not have chaincode installed on them
|
|
|
+(like ``Peer3`` in the above example) . Finally, the chaincode is accessible
|
|
|
+after it is installed (like ``Peer3`` in the above example) because it
|
|
|
+already has been instantiated.
|
|
|
+
|
|
|
+How do I see these transactions?
|
|
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+Check the logs for the CLI docker container.
|
|
|
+
|
|
|
+::
|
|
|
+
|
|
|
+ docker logs -f cli
|
|
|
+
|
|
|
+You should see the following output:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ 2017-02-28 04:31:20.841 UTC [logging] InitFromViper -> DEBU 001 Setting default logging level to DEBUG for command 'chaincode'
|
|
|
+ 2017-02-28 04:31:20.842 UTC [msp] GetLocalMSP -> DEBU 002 Returning existing local MSP
|
|
|
+ 2017-02-28 04:31:20.842 UTC [msp] GetDefaultSigningIdentity -> DEBU 003 Obtaining default signing identity
|
|
|
+ 2017-02-28 04:31:20.843 UTC [msp] Sign -> DEBU 004 Sign: plaintext: 0A8F050A59080322096D796368616E6E...6D7963631A0A0A0571756572790A0161
|
|
|
+ 2017-02-28 04:31:20.843 UTC [msp] Sign -> DEBU 005 Sign: digest: 52F1A41B7B0B08CF3FC94D9D7E916AC4C01C54399E71BC81D551B97F5619AB54
|
|
|
+ Query Result: 90
|
|
|
+ 2017-02-28 04:31:30.425 UTC [main] main -> INFO 006 Exiting.....
|
|
|
+ ===================== Query on chaincode on PEER3 on channel 'mychannel' is successful =====================
|
|
|
+
|
|
|
+ ===================== All GOOD, End-2-End execution completed =====================
|
|
|
+
|
|
|
+How can I see the chaincode logs?
|
|
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+Inspect the individual chaincode containers to see the separate
|
|
|
+transactions executed against each container. Here is the combined
|
|
|
+output from each container:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ $ docker logs dev-peer2-mycc-1.0
|
|
|
+ 04:30:45.947 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
|
|
|
+ ex02 Init
|
|
|
+ Aval = 100, Bval = 200
|
|
|
+
|
|
|
+ $ docker logs dev-peer0-mycc-1.0
|
|
|
+ 04:31:10.569 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
|
|
|
+ ex02 Invoke
|
|
|
+ Query Response:{"Name":"a","Amount":"100"}
|
|
|
+ ex02 Invoke
|
|
|
+ Aval = 90, Bval = 210
|
|
|
+
|
|
|
+ $ docker logs dev-peer3-mycc-1.0
|
|
|
+ 04:31:30.420 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
|
|
|
+ ex02 Invoke
|
|
|
+ Query Response:{"Name":"a","Amount":"90"}
|
|
|
+
|
|
|
+Run the end-to-end test manually with Docker
|
|
|
+--------------------------------------------
|
|
|
+
|
|
|
+From your vagrant environment exit the currently running containers:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ docker rm -f $(docker ps -aq)
|
|
|
+
|
|
|
+Execute a ``docker images`` command in your terminal to view the
|
|
|
+chaincode images. They will look similar to the following:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ REPOSITORY TAG IMAGE ID CREATED SIZE
|
|
|
+ dev-peer3-mycc-1.0 latest 3415bc2e146c 5 hours ago 176 MB
|
|
|
+ dev-peer0-mycc-1.0 latest 140d7ee3e911 5 hours ago 176 MB
|
|
|
+ dev-peer2-mycc-1.0 latest 6e4fc412969e 5 hours ago 176 MB
|
|
|
+
|
|
|
+Remove these images:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ docker rmi <IMAGE ID> <IMAGE ID> <IMAGE ID>
|
|
|
+
|
|
|
+For example:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ docker rmi -f 341 140 6e4
|
|
|
+
|
|
|
+Ensure you have the configuration artifacts. If you deleted them, run
|
|
|
+the shell script again:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ ./generateCfgTrx.sh <channel-ID>
|
|
|
+
|
|
|
+Modify the docker-compose file
|
|
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+Open the docker-compose file and comment out the command to run
|
|
|
+``script.sh``. Navigate down to the cli image and place a ``#`` to the
|
|
|
+left of the command. For example:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
|
|
|
+ # command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}'
|
|
|
+
|
|
|
+Save the file and return to the ``/e2e_cli`` directory.
|
|
|
+
|
|
|
+Now restart your network:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ # make sure you are in the /e2e_cli directory where you docker-compose script resides
|
|
|
+ docker-compose up -d
|
|
|
+
|
|
|
+Command syntax
|
|
|
+^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+Refer to the create and join commands in the ``script.sh``.
|
|
|
+
|
|
|
+For the following CLI commands against `peer0` to work, you need to set the
|
|
|
+values for four environment variables, given below. Please make sure to override
|
|
|
+the values accordingly when calling commands against other peers and the
|
|
|
+orderer.
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ # Environment variables for PEER0
|
|
|
+ CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peer/peer0/localMspConfig
|
|
|
+ CORE_PEER_ADDRESS=peer0:7051
|
|
|
+ CORE_PEER_LOCALMSPID="Org0MSP"
|
|
|
+ CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peer/peer0/localMspConfig/cacerts/peerOrg0.pem
|
|
|
+
|
|
|
+These environment variables for each peer are defined in the supplied
|
|
|
+docker-compose file.
|
|
|
+
|
|
|
+Create channel
|
|
|
+^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+Exec into the cli container:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ docker exec -it cli bash
|
|
|
+
|
|
|
+If successful you should see the following:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ root@0d78bb69300d:/opt/gopath/src/github.com/hyperledger/fabric/peer#
|
|
|
+
|
|
|
+Specify your channel name with the ``-c`` flag. Specify your channel
|
|
|
+configuration transaction with the ``-f`` flag. In this case it is
|
|
|
+``channeltx``, however you can mount your own configuration transaction
|
|
|
+with a different name.
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ # the channel.tx and orderer.block are mounted in the crypto/orderer folder within your cli container
|
|
|
+ # as a result, we pass the full path for the file
|
|
|
+ peer channel create -o orderer0:7050 -c mychannel -f crypto/orderer/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem
|
|
|
+
|
|
|
+Since the `channel create` runs against the orderer, we need to override the
|
|
|
+four environment variables set before. So the above command in its entirety would be:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig CORE_PEER_LOCALMSPID="OrdererMSP" peer channel create -o orderer0:7050 -c mychannel -f crypto/orderer/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem
|
|
|
+
|
|
|
+
|
|
|
+**Note**: You will remain in the CLI container for the remainder of
|
|
|
+these manual commands. You must also remember to preface all commands
|
|
|
+with the corresponding environment variables for targetting a peer other than
|
|
|
+`peer0`.
|
|
|
+
|
|
|
+Join channel
|
|
|
+^^^^^^^^^^^^
|
|
|
+
|
|
|
+Join specific peers to the channel
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ # By default, this joins PEER0 only
|
|
|
+ # the mychannel.block is also mounted in the crypto/orderer directory
|
|
|
+ peer channel join -b mychannel.block
|
|
|
+
|
|
|
+You can make other peers join the channel as necessary by making appropriate
|
|
|
+changes in the four environment variables.
|
|
|
+
|
|
|
+Install chaincode onto a remote peer
|
|
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+Install the sample go code onto one of the four peer nodes
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
|
|
|
+
|
|
|
+Instantiate chaincode and define the endorsement policy
|
|
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+Instantiate the chaincode on a peer. This will launch a chaincode
|
|
|
+container for the targeted peer and set the endorsement policy for the
|
|
|
+chaincode. In this snippet, we define the policy as requiring an
|
|
|
+endorsement from one peer node that is a part of either `Org0` or `Org1`.
|
|
|
+The command is:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ peer chaincode instantiate -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org0MSP.member','Org1MSP.member')"
|
|
|
+
|
|
|
+See the `endorsement
|
|
|
+policies <http://hyperledger-fabric.readthedocs.io/en/latest/endorsement-policies/>`__
|
|
|
+documentation for more details on policy implementation.
|
|
|
+
|
|
|
+Invoke chaincode
|
|
|
+^^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'
|
|
|
+
|
|
|
+**NOTE**: Make sure to wait a few seconds for the operation to complete.
|
|
|
+
|
|
|
+Query chaincode
|
|
|
+^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
|
|
|
+
|
|
|
+The result of the above command should be as below:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ Query Result: 90
|
|
|
+
|
|
|
+Run the end-to-end test using the native binaries
|
|
|
+-------------------------------------------------
|
|
|
+
|
|
|
+Open your vagrant environment:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ cd $GOPATH/src/github.com/hyperledger/fabric/devenv
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ # you may have to first start your VM with vagrant up
|
|
|
+ vagrant ssh
|
|
|
+
|
|
|
+From the ``fabric`` directory build the issue the following commands to
|
|
|
+build the peer and orderer executables:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ make clean
|
|
|
+ make native
|
|
|
+
|
|
|
+You will also need the ``ccenv`` image. From the ``fabric`` directory:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ make peer-docker
|
|
|
+
|
|
|
+Next, open two more terminals and start your vagrant environment in
|
|
|
+each. You should now have a total of three terminals, all within
|
|
|
+vagrant.
|
|
|
+
|
|
|
+Before starting, make sure to clear your ledger folder
|
|
|
+``/var/hyperledger/``. You will want to do this after each run to avoid
|
|
|
+errors and duplication.
|
|
|
+
|
|
|
+::
|
|
|
+
|
|
|
+ rm -rf /var/hyperledger/*
|
|
|
+
|
|
|
+**Vagrant window 1**
|
|
|
+
|
|
|
+Use the ``configtxgen`` tool to create the orderer genesis block:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ configtxgen -profile SampleSingleMSPSolo -outputBlock orderer.block
|
|
|
+
|
|
|
+**Vagrant window 2**
|
|
|
+
|
|
|
+Start the orderer with the genesis block you just generated:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ ORDERER_GENERAL_GENESISMETHOD=file ORDERER_GENERAL_GENESISFILE=./orderer.block orderer
|
|
|
+
|
|
|
+**Vagrant window 1**
|
|
|
+
|
|
|
+Create the channel configuration transaction:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ configtxgen -profile SampleSingleMSPSolo -outputCreateChannelTx channel.tx -channelID <channel-ID>
|
|
|
+
|
|
|
+This will generate a ``channel.tx`` file in your current directory
|
|
|
+
|
|
|
+**Vagrant window 3**
|
|
|
+
|
|
|
+Start the peer in *"chainless"* mode
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ peer node start --peer-defaultchain=false
|
|
|
+
|
|
|
+**Note**: Use Vagrant window 1 for the remainder of commands
|
|
|
+
|
|
|
+Create channel
|
|
|
+^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+Ask peer to create a channel with the configuration parameters in
|
|
|
+``channel.tx``
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ peer channel create -o 127.0.0.1:7050 -c mychannel -f channel.tx
|
|
|
+
|
|
|
+This will return a channel genesis block - ``mychannel.block`` - in your
|
|
|
+current directory.
|
|
|
+
|
|
|
+Join channel
|
|
|
+^^^^^^^^^^^^
|
|
|
+
|
|
|
+Ask peer to join the channel by passing in the channel genesis block:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ peer channel join -b mychannel.block
|
|
|
+
|
|
|
+Install
|
|
|
+^^^^^^^
|
|
|
+
|
|
|
+Install chaincode on the peer:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ peer chaincode install -o 127.0.0.1:7050 -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
|
|
|
+
|
|
|
+Make sure the chaincode is in the filesystem:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ ls /var/hyperledger/production/chaincodes
|
|
|
+
|
|
|
+You should see ``mycc.1.0``
|
|
|
+
|
|
|
+Instantiate
|
|
|
+^^^^^^^^^^^
|
|
|
+
|
|
|
+Instantiate the chaincode:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ peer chaincode instantiate -o 127.0.0.1:7050 -C mychannel -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a", "100", "b","200"]}'
|
|
|
+
|
|
|
+Check your active containers:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ docker ps
|
|
|
+
|
|
|
+If the chaincode container started successfully, you should see:
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
|
|
+ bd9c6bda7560 dev-jdoe-mycc-1.0 "chaincode -peer.a..." 5 seconds ago Up 5 seconds dev-jdoe-mycc-1.0
|
|
|
+
|
|
|
+Invoke
|
|
|
+^^^^^^
|
|
|
+
|
|
|
+Issue an invoke to move "10" from "a" to "b":
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ peer chaincode invoke -o 127.0.0.1:7050 -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'
|
|
|
+
|
|
|
+Wait a few seconds for the operation to complete
|
|
|
+
|
|
|
+Query
|
|
|
+^^^^^
|
|
|
+
|
|
|
+Query for the value of "a":
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ # this should return 90
|
|
|
+ peer chaincode query -o 127.0.0.1:7050 -C mychannel -n mycc -c '{"Args":["query","a"]}'
|
|
|
+
|
|
|
+Don't forget to clear ledger folder ``/var/hyperledger/`` after each
|
|
|
+run!
|
|
|
+
|
|
|
+::
|
|
|
+
|
|
|
+ rm -rf /var/hyperledger/*
|
|
|
+
|
|
|
+Using CouchDB
|
|
|
+-------------
|
|
|
+
|
|
|
+The state database can be switched from the default (goleveldb) to CouchDB.
|
|
|
+The same chaincode functions are available with CouchDB, however, there is the
|
|
|
+added ability to perform rich and complex queries against the state database
|
|
|
+data content contingent upon the chaincode data being modeled as JSON.
|
|
|
+
|
|
|
+To use CouchDB instead of the default database (goleveldb), follow the same
|
|
|
+procedure in the **Prerequisites** section, and additionally perform the
|
|
|
+following two steps to enable the CouchDB containers and associate each peer
|
|
|
+container with a CouchDB container:
|
|
|
+
|
|
|
+- Make the CouchDB image.
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ # make sure you are in the /fabric directory
|
|
|
+ make couchdb
|
|
|
+
|
|
|
+- Open the ``fabric/examples/e2e_cli/docker-compose.yaml`` and un-comment
|
|
|
+ all commented statements relating to CouchDB containers and peer container
|
|
|
+ use of CouchDB. These instructions are are also outlined in the
|
|
|
+ same ``docker-compose.yaml`` file. Search the file for 'couchdb' (case insensitive) references.
|
|
|
+
|
|
|
+*chaincode_example02* should now work using CouchDB underneath.
|
|
|
+
|
|
|
+***Note***: If you choose to implement mapping of the fabric-couchdb container
|
|
|
+port to a host port, please make sure you are aware of the security
|
|
|
+implications. Mapping of the port in a development environment allows the
|
|
|
+visualization of the database via the CouchDB web interface (Fauxton).
|
|
|
+Production environments would likely refrain from implementing port mapping in
|
|
|
+order to restrict outside access to the CouchDB containers.
|
|
|
+
|
|
|
+You can use *chaincode_example02* chaincode against the CouchDB state database
|
|
|
+using the steps outlined above, however in order to exercise the query
|
|
|
+capabilities you will need to use a chaincode that has data modeled as JSON,
|
|
|
+(e.g. *marbles02*). You can locate the *marbles02* chaincode in the
|
|
|
+``fabric/examples/chaincode/go`` directory.
|
|
|
+
|
|
|
+Install, instantiate, invoke, and query *marbles02* chaincode by following the
|
|
|
+same general steps outlined above for *chaincode_example02* in the **Manually
|
|
|
+create the channel and join peers through CLI** section. After the **Join
|
|
|
+channel** step, use the following steps to interact with the *marbles02*
|
|
|
+chaincode:
|
|
|
+
|
|
|
+- Install and instantiate the chaincode in ``peer0``:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ peer chaincode install -o orderer0:7050 -n marbles -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02
|
|
|
+ peer chaincode instantiate -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02 -c '{"Args":["init"]}' -P "OR ('Org0MSP.member','Org1MSP.member')"
|
|
|
+
|
|
|
+- Create some marbles and move them around:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
|
|
|
+ peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["initMarble","marble2","red","50","tom"]}'
|
|
|
+ peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["initMarble","marble3","blue","70","tom"]}'
|
|
|
+ peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["transferMarble","marble2","jerry"]}'
|
|
|
+ peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["transferMarblesBasedOnColor","blue","jerry"]}'
|
|
|
+ peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["delete","marble1"]}'
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+- If you chose to activate port mapping, you can now view the state database
|
|
|
+ through the CouchDB web interface (Fauxton) by opening a browser and
|
|
|
+ navigating to one of the two URLs below.
|
|
|
+
|
|
|
+ For containers running in a vagrant environment:
|
|
|
+
|
|
|
+ ``http://localhost:15984/_utils``
|
|
|
+
|
|
|
+ For non-vagrant environment, use the port address that was mapped in CouchDB
|
|
|
+ container specification:
|
|
|
+
|
|
|
+ ``http://localhost:5984/_utils``
|
|
|
+
|
|
|
+ You should see a database named ``mychannel`` and the documents
|
|
|
+ inside it.
|
|
|
+
|
|
|
+- You can run regular queries from the `cli` (e.g. reading ``marble2``):
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ peer chaincode query -C mychannel -n marbles -c '{"Args":["readMarble","marble2"]}'
|
|
|
+
|
|
|
+
|
|
|
+ You should see the details of ``marble2``:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ Query Result: {"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}
|
|
|
+
|
|
|
+
|
|
|
+ Retrieve the history of ``marble1``:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ peer chaincode query -C mychannel -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}'
|
|
|
+
|
|
|
+ You should see the transactions on ``marble1``:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ Query Result: [{"TxId":"1c3d3caf124c89f91a4c0f353723ac736c58155325f02890adebaa15e16e6464", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}},{"TxId":"755d55c281889eaeebf405586f9e25d71d36eb3d35420af833a20a2f53a3eefd", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"jerry"}},{"TxId":"819451032d813dde6247f85e56a89262555e04f14788ee33e28b232eef36d98f", "Value":}]
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+- You can also perform rich queries on the data content, such as querying marble fields by owner ``jerry``:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarblesByOwner","jerry"]}'
|
|
|
+
|
|
|
+ The output should display the two marbles owned by ``jerry``:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ Query Result: [{"Key":"marble2", "Record":{"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}},{"Key":"marble3", "Record":{"color":"blue","docType":"marble","name":"marble3","owner":"jerry","size":70}}]
|
|
|
+
|
|
|
+ Query by field ``owner`` where the value is ``jerry``:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarbles","{\"selector\":{\"owner\":\"jerry\"}}"]}'
|
|
|
+
|
|
|
+ The output should display:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ Query Result: [{"Key":"marble2", "Record":{"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}},{"Key":"marble3", "Record":{"color":"blue","docType":"marble","name":"marble3","owner":"jerry","size":70}}]
|
|
|
+
|
|
|
+A Note on Data Persistence
|
|
|
+--------------------------
|
|
|
+
|
|
|
+If data persistence is desired on the peer container or the CouchDB container,
|
|
|
+one option is to mount a directory in the docker-host into a relevant directory
|
|
|
+in the container. For example, you may add the following two lines in
|
|
|
+the peer container specification in the ``docker-compose.yaml`` file:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ volumes:
|
|
|
+ - /var/hyperledger/peer0:/var/hyperledger/production
|
|
|
+
|
|
|
+
|
|
|
+For the CouchDB container, you may add the following two lines in the CouchDB
|
|
|
+container specification:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ volumes:
|
|
|
+ - /var/hyperledger/couchdb0:/opt/couchdb/data
|
|
|
+
|
|
|
+
|
|
|
+Troubleshooting
|
|
|
+---------------
|
|
|
+
|
|
|
+- Ensure you clear the file system after each run
|
|
|
+
|
|
|
+- If you see docker errors, remove your images and start from scratch.
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ make clean
|
|
|
+ make peer-docker orderer-docker
|
|
|
+
|
|
|
+- If you see the below error:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ Error: Error endorsing chaincode: rpc error: code = 2 desc = Error installing chaincode code mycc:1.0(chaincode /var/hyperledger/production/chaincodes/mycc.1.0 exits)
|
|
|
+
|
|
|
+ You likely have chaincode images (e.g. ``peer0-peer0-mycc-1.0`` or
|
|
|
+ ``peer1-peer0-mycc1-1.0``) from prior runs. Remove them and try
|
|
|
+ again.
|
|
|
+
|
|
|
+.. code:: bash
|
|
|
+
|
|
|
+ docker rmi -f $(docker images | grep peer[0-9]-peer[0-9] | awk '{print $3}')
|
|
|
+
|
|
|
+- To cleanup the network, use the ``down`` option:
|
|
|
+
|
|
|
+ .. code:: bash
|
|
|
+
|
|
|
+ ./network_setup.sh down
|