842 lines
31 KiB
ReStructuredText
842 lines
31 KiB
ReStructuredText
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
|