913 lines
41 KiB
ReStructuredText
913 lines
41 KiB
ReStructuredText
End-to-End Flow
|
|
===============
|
|
|
|
The end-to-end verification provisions a sample Fabric network consisting of
|
|
two organizations, each maintaining two peers, and a Kafka-based ordering service.
|
|
|
|
This verification makes use of two fundamental tools, which are necessary to
|
|
create a functioning transactional network with digital signature validation
|
|
and access control:
|
|
|
|
* cryptogen - generates the x509 certificates used to identify and authenticate the various components in the network.
|
|
* configtxgen - generates the requisite configuration artifacts for orderer bootstrap and channel creation.
|
|
|
|
Each tool consumes a configuration yaml file, within which we specify the topology
|
|
of our network (cryptogen) and the location of our certificates for various
|
|
configuration operations (configtxgen). Once the tools have been successfully run,
|
|
we are able to launch our network. More detail on the tools and the structure of
|
|
the network will be provided later in this document. For now, let's get going...
|
|
|
|
Prerequisites
|
|
-------------
|
|
|
|
- `Git client <https://git-scm.com/downloads>`__
|
|
- `Docker <https://www.docker.com/products/overview>`__ - v1.12 or higher
|
|
- `Docker Compose <https://docs.docker.com/compose/overview/>`__ - v1.8 or higher
|
|
- `Homebrew <https://brew.sh/>`__ - OSX only
|
|
- `Xcode <https://itunes.apple.com/us/app/xcode/id497799835?mt=12>`__ - OSX only (this can take upwards of an hour)
|
|
- `Docker Toolbox <https://docs.docker.com/toolbox/toolbox_install_windows/>`__ - Windows users only
|
|
- `Go <https://golang.org/>`__ - 1.7 or higher
|
|
|
|
On Windows machines you will also need the following which provides a better alternative to the Windows command prompt:
|
|
|
|
- `Git Bash <https://git-scm.com/downloads>`__
|
|
|
|
.. note:: On older versions of Windows, such as Windows 7, you
|
|
typically get this as part of installing Docker
|
|
Toolbox. However experience has shown this to be a poor
|
|
development environment with limited functionality. It is
|
|
suitable to run docker based scenarios, such as
|
|
:doc:`getting_started`, but you may not be able to find a
|
|
suitable ``make`` command to successfuly go through the
|
|
scenario described here.
|
|
|
|
Setting the $GOPATH
|
|
^^^^^^^^^^^^^^^^^^^
|
|
Make sure you have properly setup your Host's `GOPATH environment
|
|
variable <https://github.com/golang/go/wiki/GOPATH>`__. This is necessary for the
|
|
code to compile properly.
|
|
|
|
Now create the following directory structure and ``cd`` into it:
|
|
|
|
.. code:: bash
|
|
|
|
mkdir -p $GOPATH/src/github.com/hyperledger
|
|
cd $GOPATH/src/github.com/hyperledger
|
|
|
|
- Clone the Fabric code base into this path.
|
|
|
|
.. code:: bash
|
|
|
|
git clone http://gerrit.hyperledger.org/r/fabric
|
|
|
|
or though a mirrored repository in github:
|
|
|
|
.. code:: bash
|
|
|
|
git clone https://github.com/hyperledger/fabric.git
|
|
|
|
- If you are running OSX, perform the following:
|
|
|
|
.. code:: bash
|
|
|
|
brew install gnu-tar --with-default-names
|
|
brew install libtool
|
|
|
|
Build the binaries
|
|
^^^^^^^^^^^^^^^^^^
|
|
|
|
- Now make the platform-specific binaries for ``cryptogen`` and ``configtxgen``.
|
|
|
|
.. code:: bash
|
|
|
|
cd $GOPATH/src/github.com/hyperledger/fabric
|
|
# ensure sure you are in the /fabric directory where the Makefile resides
|
|
make release
|
|
|
|
This will output platform-specific binaries into the ``fabric/release`` folder.
|
|
|
|
- Next, make the Fabric images. This typically takes between five to ten minutes, so
|
|
be patient:
|
|
|
|
.. code:: bash
|
|
|
|
# make sure you are in the /fabric directory
|
|
make 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
|
|
|
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
|
hyperledger/fabric-couchdb latest e2df4dd39ca9 38 minutes ago 1.51 GB
|
|
hyperledger/fabric-couchdb x86_64-1.0.0-beta e2df4dd39ca9 38 minutes ago 1.51 GB
|
|
hyperledger/fabric-kafka latest 08af4d797266 40 minutes ago 1.3 GB
|
|
hyperledger/fabric-kafka x86_64-1.0.0-beta 08af4d797266 40 minutes ago 1.3 GB
|
|
hyperledger/fabric-zookeeper latest 444e9e695367 40 minutes ago 1.31 GB
|
|
hyperledger/fabric-zookeeper x86_64-1.0.0-beta 444e9e695367 40 minutes ago 1.31 GB
|
|
hyperledger/fabric-testenv latest 8678d3101930 41 minutes ago 1.41 GB
|
|
hyperledger/fabric-testenv x86_64-1.0.0-beta 8678d3101930 41 minutes ago 1.41 GB
|
|
hyperledger/fabric-buildenv latest 60911392c82e 41 minutes ago 1.33 GB
|
|
hyperledger/fabric-buildenv x86_64-1.0.0-beta 60911392c82e 41 minutes ago 1.33 GB
|
|
hyperledger/fabric-orderer latest 2afab937b9cc 41 minutes ago 182 MB
|
|
hyperledger/fabric-orderer x86_64-1.0.0-beta 2afab937b9cc 41 minutes ago 182 MB
|
|
hyperledger/fabric-peer latest 9560e58e8089 41 minutes ago 185 MB
|
|
hyperledger/fabric-peer x86_64-1.0.0-beta 9560e58e8089 41 minutes ago 185 MB
|
|
hyperledger/fabric-javaenv latest 881ca5219fad 42 minutes ago 1.43 GB
|
|
hyperledger/fabric-javaenv x86_64-1.0.0-beta 881ca5219fad 42 minutes ago 1.43 GB
|
|
hyperledger/fabric-ccenv latest 28af77ffe9e9 43 minutes ago 1.29 GB
|
|
hyperledger/fabric-ccenv x86_64-1.0.0-beta 28af77ffe9e9 43 minutes ago 1.29 GB
|
|
hyperledger/fabric-baseimage x86_64-0.3.0 f4751a503f02 3 months ago 1.27 GB
|
|
hyperledger/fabric-baseos x86_64-0.3.0 c3a4cf3b3350 3 months ago 161 MB
|
|
|
|
If you failed to compile the ``fabric-testenv`` image, then you can
|
|
perform a ``make clean`` followed by another ``make docker``.
|
|
|
|
Cryptogen Tool
|
|
--------------
|
|
We will use the cryptogen tool to generate the cryptographic material (x509 certs)
|
|
for our various network entities. The certificates are based on a standard PKI
|
|
implementation where validation is achieved by reaching a common trust anchor.
|
|
|
|
How does it work?
|
|
^^^^^^^^^^^^^^^^^
|
|
|
|
Cryptogen consumes a file - ``crypto-config.yaml`` - that contains the network
|
|
topology and allows us to generate a library of certificates for both the
|
|
Organizations and the components that belong to those Organizations. Each
|
|
Organization is provisioned a unique root certificate (``ca-cert``), that binds
|
|
specific components (peers and orderers) to that Org. Transactions and communications
|
|
within Fabric are signed by an entity's private key (``keystore``), and then verified
|
|
by means of a public key (``signcerts``). You will notice a "count" variable within
|
|
this file. We use this to specify the number of peers per Organization; in our
|
|
case it's two peers per Org. The rest of this template is extremely
|
|
self-explanatory.
|
|
|
|
After we run the tool, the certs will be parked in a folder titled ``crypto-config``.
|
|
|
|
Configuration Transaction Generator
|
|
-----------------------------------
|
|
|
|
The `configtxgen
|
|
tool <https://github.com/hyperledger/fabric/blob/master/docs/source/configtxgen.rst>`__
|
|
is used to create four artifacts: orderer **bootstrap block**, fabric
|
|
**channel configuration transaction**, and two **anchor peer transactions** - one
|
|
for each Peer Org.
|
|
|
|
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 anchor peer transactions, as the name might suggest, specify each
|
|
Org's anchor peer on this channel.
|
|
|
|
How does it work?
|
|
^^^^^^^^^^^^^^^^^
|
|
|
|
Configtxgen consumes a file - ``configtx.yaml`` - that contains the definitions
|
|
for the sample network. There are three members - one Orderer Org (``OrdererOrg``)
|
|
and two Peer Orgs (``Org1`` & ``Org2``) each managing and maintaining two peer nodes.
|
|
This file also specifies a consortium - ``SampleConsortium`` - consisting of our
|
|
two Peer Orgs. Pay specific attention to the "Profiles" section at the top of
|
|
this file. You will notice that we have two unique headers. One for the orderer genesis
|
|
block - ``TwoOrgsOrdererGenesis`` - and one for our channel - ``TwoOrgsChannel``.
|
|
These headers are important, as we will pass them in as arguments when we create
|
|
our artifacts. This file also contains two additional specifications that are worth
|
|
noting. Firstly, we specify the anchor peers for each Peer Org
|
|
(``peer0.org1.example.com`` & ``peer0.org2.example.com``). Secondly, we point to
|
|
the location of the MSP directory for each member, in turn allowing us to store the
|
|
root certificates for each Org in the orderer genesis block. This is a critical
|
|
concept. Now any network entity communicating with the ordering service can have
|
|
its digital signature verified.
|
|
|
|
For ease of use, a script - ``generateArtifacts.sh`` - is provided. The
|
|
script will generate the crypto material and our four configuration artifacts, and
|
|
subsequently output these files into the ``channel-artifacts`` folder.
|
|
|
|
Run the shell script
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Make sure you are in the ``examples/solo`` directory where the script resides.
|
|
Decide upon a unique name for your channel and replace the <channel-ID> parm
|
|
with a name of your choice. The script will fail if you do not supply a name.
|
|
|
|
.. code:: bash
|
|
|
|
cd examples/solo
|
|
./generateArtifacts.sh <channel-ID>
|
|
|
|
The output of the script is somewhat verbose, as it generates the crypto
|
|
libraries and multiple artifacts. However, you will notice five distinct
|
|
and self-explanatory messages in your terminal. They are as follows:
|
|
|
|
.. code:: bash
|
|
|
|
##########################################################
|
|
##### Generate certificates using cryptogen tool #########
|
|
##########################################################
|
|
|
|
##########################################################
|
|
######### Generating Orderer Genesis block ##############
|
|
##########################################################
|
|
|
|
#################################################################
|
|
### Generating channel configuration transaction 'channel.tx' ###
|
|
#################################################################
|
|
|
|
#################################################################
|
|
####### Generating anchor peer update for Org0MSP ##########
|
|
#################################################################
|
|
|
|
#################################################################
|
|
####### Generating anchor peer update for Org1MSP ##########
|
|
#################################################################
|
|
|
|
|
|
These configuration transactions will bundle the crypto material for the
|
|
participating members and their network components and output an orderer
|
|
genesis block and three channel transaction artifacts. These artifacts are
|
|
required to successfully bootstrap a Fabric network and create a channel to
|
|
transact upon.
|
|
|
|
Manually generate the artifacts (optional)
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
You can refer to the ``generateArtifacts.sh`` script for the commands, however
|
|
for the sake of convenience we will also provide them here.
|
|
|
|
First, let's set the environment variable for our platform architecture.
|
|
This command will detect your OS and use the appropriate binaries for the subsequent steps:
|
|
|
|
.. code:: bash
|
|
|
|
# for power or z
|
|
os_arch=$(echo "$(uname -s)-$(uname -m)" | awk '{print tolower($0)}')
|
|
|
|
# for linux, osx or windows
|
|
os_arch=$(echo "$(uname -s)-amd64" | awk '{print tolower($0)}')
|
|
|
|
Check to make sure it is set properly:
|
|
|
|
.. code:: bash
|
|
|
|
echo $os_arch
|
|
|
|
Now let's run the tool. Our platform specific binary is in the ``release``
|
|
directory, so we need to provide the relative path to where the tool resides.
|
|
Make sure you are in ``examples/solo``:
|
|
|
|
.. code:: bash
|
|
|
|
./../../release/$os_arch/bin/cryptogen generate --config=./crypto-config.yaml
|
|
|
|
You will likely see the following warning. It's innocuous, ignore it:
|
|
|
|
.. code:: bash
|
|
|
|
[bccsp] GetDefault -> WARN 001 Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP.
|
|
|
|
Next, we need to tell the ``configtxgen`` tool where to look for the
|
|
``configtx.yaml`` file that it needs to ingest. We will tell it look in our
|
|
present working directory:
|
|
|
|
.. code:: bash
|
|
|
|
FABRIC_CFG_PATH=$PWD
|
|
|
|
Create the orderer genesis block:
|
|
|
|
.. code:: bash
|
|
|
|
./../../release/$os_arch/bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
|
|
|
|
You can ignore the logs regarding intermediate certs, we are not using them in
|
|
this crypto implementation.
|
|
|
|
Create the channel transaction artifact:
|
|
|
|
.. code:: bash
|
|
|
|
# make sure to set the <channel-ID> parm
|
|
./../../release/$os_arch/bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID <channel-ID>
|
|
|
|
Define the anchor peer for Org1 on the channel:
|
|
|
|
.. code:: bash
|
|
|
|
# make sure to set the <channel-ID> parm
|
|
./../../release/$os_arch/bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID <channel-ID> -asOrg Org1MSP
|
|
|
|
Define the anchor peer for Org2 on the channel:
|
|
|
|
.. code:: bash
|
|
|
|
# make sure to set the <channel-ID> parm
|
|
./../../release/$os_arch/bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID <channel-ID> -asOrg Org2MSP
|
|
|
|
Run the end-to-end test with Docker
|
|
-----------------------------------
|
|
|
|
Make sure you are in the ``/solo`` directory. Then use docker-compose
|
|
to spawn the network entities and drive the tests. Notice that you can set a
|
|
``TIMEOUT`` variable (specified in seconds) so that your cli container does not
|
|
exit after the script completes. You can choose any value:
|
|
|
|
.. code:: bash
|
|
|
|
# the TIMEOUT variable is optional
|
|
CHANNEL_NAME=<channel-id> TIMEOUT=<pick_a_value> docker-compose -f docker-compose-cli.yaml up -d
|
|
|
|
If you created a unique channel name, be sure to pass in that parameter.
|
|
For example,
|
|
|
|
.. code:: bash
|
|
|
|
CHANNEL_NAME=abc TIMEOUT=1000 docker-compose -f docker-compose-cli.yaml up -d
|
|
|
|
Wait, 60 seconds or so. 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
|
|
|
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
|
b568de3fe931 dev-peer1.org2.example.com-mycc-1.0 "chaincode -peer.a..." 4 minutes ago Up 4 minutes dev-peer1.org2.example.com-mycc-1.0
|
|
17c1c82087e7 dev-peer0.org1.example.com-mycc-1.0 "chaincode -peer.a..." 4 minutes ago Up 4 minutes dev-peer0.org1.example.com-mycc-1.0
|
|
0e1c5034c47b dev-peer0.org2.example.com-mycc-1.0 "chaincode -peer.a..." 4 minutes ago Up 4 minutes dev-peer0.org2.example.com-mycc-1.0
|
|
71339e7e1d38 hyperledger/fabric-peer "peer node start -..." 5 minutes ago Up 5 minutes 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp peer1.org1.example.com
|
|
add6113ffdcf hyperledger/fabric-peer "peer node start -..." 5 minutes ago Up 5 minutes 0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp peer1.org2.example.com
|
|
689396c0e520 hyperledger/fabric-peer "peer node start -..." 5 minutes ago Up 5 minutes 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0.org1.example.com
|
|
65424407a653 hyperledger/fabric-orderer "orderer" 5 minutes ago Up 5 minutes 0.0.0.0:7050->7050/tcp orderer.example.com
|
|
ce14853db660 hyperledger/fabric-peer "peer node start -..." 5 minutes ago Up 5 minutes 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp peer0.org2.example.com
|
|
|
|
If you set a moderately high ``TIMEOUT`` value, then you will see your cli
|
|
container as well.
|
|
|
|
What's happening behind the scenes?
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
- A script - ``script.sh`` - is baked inside the CLI container. The
|
|
script drives the ``createChannel`` command against the supplied channel name
|
|
and uses the channel.tx file for channel configuration.
|
|
|
|
- The output of ``createChannel`` is a genesis block -
|
|
``<your_channel_name>.block`` - which gets stored on the peers' file systems and contains
|
|
the channel configuration specified from channel.tx.
|
|
|
|
- The ``joinChannel`` command is exercised for all four peers, which takes as
|
|
input the previously generated genesis block. This command instructs the
|
|
peers to join ``<your_channel_name>`` and create a chain starting with ``<your_channel_name>.block``.
|
|
|
|
- Now we have a channel consisting of four peers, and two
|
|
organizations. This is our ``TwoOrgsChannel`` profile.
|
|
|
|
- ``peer0.org1.example.com`` and ``peer1.org1.example.com`` belong to Org1;
|
|
``peer0.org2.example.com`` and ``peer1.org2.example.com`` belong to Org2
|
|
|
|
- These relationships are defined through the ``crypto-config.yaml`` and
|
|
the MSP path is specified in our docker compose.
|
|
|
|
- The anchor peers for Org1MSP (``peer0.org1.example.com``) and
|
|
Org2MSP (``peer0.org2.example.com``) are then updated. We do this by passing
|
|
the ``Org1MSPanchors.tx`` and ``Org2MSPanchors.tx`` artifacts to the ordering
|
|
service along with the name of our channel.
|
|
|
|
- A chaincode - **chaincode_example02** - is installed on ``peer0.org1.example.com`` and
|
|
``peer0.org2.example.com``
|
|
|
|
- The chaincode is then "instantiated" on ``peer0.org2.example.com``. Instantiation
|
|
adds the chaincode to the channel, starts the container for the target peer,
|
|
and initializes 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-peer0.org2.example.com-mycc-1.0`` starting.
|
|
|
|
- The instantiation also passes in an argument for the endorsement
|
|
policy. The policy is defined as
|
|
``-P "OR ('Org1MSP.member','Org2MSP.member')"``, meaning that any
|
|
transaction must be endorsed by a peer tied to Org1 or Org2.
|
|
|
|
- A query against the value of "a" is issued to ``peer0.org1.example.com``. The
|
|
chaincode was previously installed on ``peer0.org1.example.com``, so this will start
|
|
a container for Org1 peer0 by the name of ``dev-peer0.org1.example.com-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.org1.example.com`` to move "10" from "a" to "b"
|
|
|
|
- The chaincode is then installed on ``peer1.org2.example.com``
|
|
|
|
- A query is sent to ``peer1.org2.example.com`` for the value of "a". This starts a
|
|
third chaincode container by the name of ``dev-peer1.org2.example.com-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 an ``init`` or
|
|
traditional transaction - read/write - 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 ``peer1.org1.example.com`` in the above example) . Finally, the chaincode is accessible
|
|
after it is installed (like ``peer1.org2.example.com`` in the above example) because it
|
|
has already been instantiated.
|
|
|
|
How do I see these transactions?
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Check the logs for the CLI docker container.
|
|
|
|
.. code:: bash
|
|
|
|
docker logs -f cli
|
|
|
|
You should see the following output:
|
|
|
|
.. code:: bash
|
|
|
|
2017-05-16 17:08:01.366 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
|
|
2017-05-16 17:08:01.366 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
|
|
2017-05-16 17:08:01.366 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08F1E3ECC80510...6D7963631A0A0A0571756572790A0161
|
|
2017-05-16 17:08:01.367 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: E61DB37F4E8B0D32C9FE10E3936BA9B8CD278FAA1F3320B08712164248285C54
|
|
Query Result: 90
|
|
2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting.....
|
|
===================== Query 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-peer0.org2.example.com-mycc-1.0
|
|
04:30:45.947 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
|
|
ex02 Init
|
|
Aval = 100, Bval = 200
|
|
|
|
$ docker logs dev-peer0.org1.example.com-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-peer1.org2.example.com-mycc-1.0
|
|
04:31:30.420 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
|
|
ex02 Invoke
|
|
Query Response:{"Name":"a","Amount":"90"}
|
|
|
|
All in one
|
|
^^^^^^^^^^
|
|
|
|
You can also generate the artifacts and crypto, and drive the tests using a single
|
|
shell script. The ``cryptogen``, ``configtxgen`` and ``docker-compose`` commands are
|
|
embedded in the script. If you choose not to supply a channel ID, then the
|
|
script will use a default name of ``mychannel``. The cli timeout parameter
|
|
is an optional value; if you choose not to set it, then your cli container
|
|
will exit upon conclusion of the script.
|
|
|
|
.. code:: bash
|
|
|
|
./network_setup.sh up
|
|
|
|
OR
|
|
|
|
.. code:: bash
|
|
|
|
./network_setup.sh up <channel-ID> <timeout-value>
|
|
|
|
Understanding the docker-compose topology
|
|
-----------------------------------------
|
|
|
|
The ``solo`` folder offers us two flavors of docker-compose files, both of which
|
|
are extended from the ``docker-compose-base.yaml``. Our first flavor,
|
|
``docker-compose-cli.yaml``, provides us with a CLI container, along with an orderer,
|
|
four peers, and the optional couchDB containers. We use this docker-compose for
|
|
the entirety of the instructions on this page.
|
|
|
|
The second flavor, ``docker-compose-e2e.yaml``, is constructed to run end-to-end tests
|
|
using the Node.js SDK. Aside from functioning with the SDK, its primary differentiation
|
|
is that there are containers for the fabric-ca servers. As a result, we are able
|
|
to send REST calls to the organizational CAs for user registration and enrollment.
|
|
|
|
If you want to use the ``docker-compose-e2e.yaml`` without first running the
|
|
**All in one** script, then we will need to make four slight modifications.
|
|
We need to point to the private keys for our Organization's CA's. You can locate
|
|
these values in your crypto-config folder. For example, to locate the private
|
|
key for Org1 we would follow this path - ``crypto-config/peerOrganizations/org1.example.com/ca/``.
|
|
The private key is a long hash value followed by ``_sk``. The path for Org2
|
|
would be - ``crypto-config/peerOrganizations/org2.example.com/ca/``.
|
|
|
|
In the ``docker-compose-e2e.yaml`` update the FABRIC_CA_SERVER_TLS_KEYFILE variable
|
|
for ca0 and ca1. You also need to edit the path that is provided in the command
|
|
to start the ca server. You are providing the same private key twice for each
|
|
CA container.
|
|
|
|
Manually exercise the commands
|
|
------------------------------
|
|
|
|
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-peer1.org2.example.com-mycc-1.0 latest 4bc5e9b5dd97 5 seconds ago 176 MB
|
|
dev-peer0.org1.example.com-mycc-1.0 latest 6f2aeb032076 22 seconds ago 176 MB
|
|
dev-peer0.org2.example.com-mycc-1.0 latest 509b8e393cc6 39 seconds ago 176 MB
|
|
|
|
Remove these images:
|
|
|
|
.. code:: bash
|
|
|
|
docker rmi <IMAGE ID> <IMAGE ID> <IMAGE ID>
|
|
|
|
For example:
|
|
|
|
.. code:: bash
|
|
|
|
docker rmi -f 4bc 6f2 509
|
|
|
|
Ensure you have the configuration artifacts. If you deleted them, run
|
|
the shell script again:
|
|
|
|
.. code:: bash
|
|
|
|
# remember to supply a channel ID
|
|
./generateArtifacts.sh <channel-ID>
|
|
|
|
Modify the docker-compose file
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Open the ``docker-compose-cli.yaml`` file and comment out the command to run
|
|
``script.sh``. Navigate down to the cli container 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}; sleep $TIMEOUT'
|
|
|
|
Save the file and return to the ``/solo`` directory.
|
|
|
|
Now restart your network:
|
|
|
|
.. code:: bash
|
|
|
|
# make sure you are in the /solo directory where your docker-compose script resides
|
|
CHANNEL_NAME=<channel-id> TIMEOUT=<pick_a_value> docker-compose -f docker-compose-cli.yaml up -d
|
|
|
|
If you want to see the realtime logs for your network, then do not supply the ``-d`` flag.
|
|
If you let the logs stream, then you will need to open a second terminal to execute the CLI calls.
|
|
|
|
Command syntax
|
|
^^^^^^^^^^^^^^
|
|
|
|
Refer to the create and join commands in the ``script.sh`` for the exact syntax.
|
|
|
|
For the following CLI commands against `peer0.org1.example.com` to work, we need
|
|
to preface our commands with the four environment variables given below. These
|
|
variables for ``peer0.org1.example.com`` are baked into the CLI container,
|
|
therefore we can operate without passing them. **HOWEVER**, if you want to send
|
|
calls to other peers or the orderer, then you will need to provide these
|
|
values accordingly. Inspect the ``docker-compose-base.yaml`` for the specific
|
|
paths:
|
|
|
|
.. code:: bash
|
|
|
|
# Environment variables for PEER0
|
|
|
|
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
|
|
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
|
|
CORE_PEER_LOCALMSPID="Org1MSP"
|
|
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
|
|
|
|
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
|
|
``channel.tx``, however you can mount your own configuration transaction
|
|
with a different name.
|
|
|
|
.. code:: bash
|
|
|
|
# the channel.tx file is mounted in the channel-artifacts directory within your cli container
|
|
# as a result, we pass the full path for the file
|
|
# we also pass the path for the orderer ca-cert in order to verify the TLS handshake
|
|
# be sure to replace the $CHANNEL_NAME variable appropriately
|
|
|
|
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.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 when targeting a peer other than
|
|
``peer0.org1.example.com``.
|
|
|
|
Join channel
|
|
^^^^^^^^^^^^
|
|
|
|
Join specific peers to the channel
|
|
|
|
.. code:: bash
|
|
|
|
# By default, this joins ``peer0.org1.example.com`` only
|
|
# the channel.block was returned by the previous command
|
|
|
|
peer channel join -b <YOUR_CHANNEL.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 ``Org1`` or ``Org2``.
|
|
The command is:
|
|
|
|
.. code:: bash
|
|
|
|
# be sure to replace the $CHANNEL_NAME environment variable
|
|
# if you did not install your chaincode with a name of mycc, then modify that argument as well
|
|
|
|
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C $CHANNEL_NAME -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"
|
|
|
|
See the `endorsement
|
|
policies <http://hyperledger-fabric.readthedocs.io/en/latest/endorsement-policies.html>`__
|
|
documentation for more details on policy implementation.
|
|
|
|
Invoke chaincode
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. code:: bash
|
|
|
|
# be sure to set the -C and -n flags appropriately
|
|
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
|
|
|
|
Make sure to wait a few seconds for the operation to complete.
|
|
|
|
Query chaincode
|
|
^^^^^^^^^^^^^^^
|
|
|
|
.. code:: bash
|
|
|
|
# be sure to set the -C and -n flags appropriately
|
|
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
|
|
|
|
The result of the above command should be the following:
|
|
|
|
.. code:: bash
|
|
|
|
Query Result: 90
|
|
|
|
Feel free to start over and manipulate the key value pairs and subsequent
|
|
invocations.
|
|
|
|
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 **Manually exercise the commands** section, except when starting
|
|
the network pass the couchdb docker-compose as well:
|
|
|
|
.. code:: bash
|
|
|
|
# make sure you are in the /solo directory where your docker-compose script resides
|
|
CHANNEL_NAME=<channel-id> TIMEOUT=<pick_a_value> docker-compose -f docker-compose-cli.yaml -f docker-compose-couch.yaml up -d
|
|
|
|
**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 makes the
|
|
CouchDB REST API available, and 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 CouchDB 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.
|
|
|
|
We will follow the same process to create and join the channel as outlined in the
|
|
**Manually exercise the commands** section above. Once you have joined your
|
|
peer(s) to the channel, use the following steps to interact with the **marbles02**
|
|
chaincode:
|
|
|
|
- Install and instantiate the chaincode on ``peer0.org1.example.com``:
|
|
|
|
.. code:: bash
|
|
|
|
# be sure to modify the $CHANNEL_NAME variable accordingly for the instantiate command
|
|
|
|
peer chaincode install -o orderer.example.com:7050 -n marbles -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02
|
|
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C $CHANNEL_NAME -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
|
|
|
|
# be sure to modify the $CHANNEL_NAME variable accordingly
|
|
|
|
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
|
|
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble2","red","50","tom"]}'
|
|
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble3","blue","70","tom"]}'
|
|
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["transferMarble","marble2","jerry"]}'
|
|
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["transferMarblesBasedOnColor","blue","jerry"]}'
|
|
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["delete","marble1"]}'
|
|
|
|
|
|
- If you chose to map the CouchDB ports in docker-compose, you can now view
|
|
the state database through the CouchDB web interface (Fauxton) by opening
|
|
a browser and navigating to the following URL:
|
|
|
|
``http://localhost:5984/_utils``
|
|
|
|
You should see a database named ``mychannel`` (or your unique channel name) and
|
|
the documents inside it.
|
|
|
|
.. note:: For the below commands, be sure to update the $CHANNEL_NAME variable appropriately.
|
|
|
|
You can run regular queries from the CLI (e.g. reading ``marble2``):
|
|
|
|
.. code:: bash
|
|
|
|
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["readMarble","marble2"]}'
|
|
|
|
The output should display the details of ``marble2``:
|
|
|
|
.. code:: bash
|
|
|
|
Query Result: {"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}
|
|
|
|
You can retrieve the history of a specific marble - e.g. ``marble1``:
|
|
|
|
.. code:: bash
|
|
|
|
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}'
|
|
|
|
The output should display 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 $CHANNEL_NAME -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}}]
|
|
|
|
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-base.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
|
|
---------------
|
|
|
|
- It's recommended to start your network fresh. Use the following command
|
|
to remove artifacts, crypto, containers and chaincode images:
|
|
|
|
.. code:: bash
|
|
|
|
./network_setup.sh down
|
|
|
|
- If you see docker errors, first check your version (should be 1.12 or above),
|
|
and then try restarting your docker process. Problems with Docker are
|
|
oftentimes not immediately recognizable. For example, you may see errors
|
|
resulting from an inability to access crypto material mounted within a
|
|
container.
|
|
|
|
- If they persist remove your images and start from scratch:
|
|
|
|
.. code:: bash
|
|
|
|
make clean
|
|
make 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. ``dev-peer1.org2.example.com-mycc-1.0`` or
|
|
``dev-peer0.org1.example.com-mycc-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}')
|
|
|
|
- If you see something similar to the following:
|
|
|
|
.. code:: bash
|
|
|
|
Error connecting: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure
|
|
Error: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure
|
|
|
|
Make sure you pointed to the correct binaries in the release folder when
|
|
generating the artifacts, and that your backend is running against "beta" images
|
|
or compiled images from the current master branch.
|
|
|
|
If you see the below error:
|
|
|
|
.. code:: bash
|
|
|
|
[configtx/tool/localconfig] Load -> CRIT 002 Error reading configuration: Unsupported Config Type ""
|
|
panic: Error reading configuration: Unsupported Config Type ""
|
|
|
|
Then you did not set the ``FABRIC_CFG_PATH`` environment variable properly. The
|
|
configtxgen tool needs this variable in order to locate the configtx.yaml. Go
|
|
back and recreate your channel artifacts.
|
|
|
|
- To cleanup the network, use the ``down`` option:
|
|
|
|
.. code:: bash
|
|
|
|
./network_setup.sh down
|
|
|
|
- If you continue to see errors, share your logs on the **# fabric-questions**
|
|
channel on `Hyperledger Rocket Chat <https://chat.hyperledger.org/home>`__.
|
|
|
|
.. Licensed under Creative Commons Attribution 4.0 International License
|
|
https://creativecommons.org/licenses/by/4.0/
|