diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 0737e6d0618..4bef44aae73 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -1,23 +1,29 @@ Getting Started =============== -.. note:: These instructions have been verified to work against the "alpha" tagged docker - images and the pre-compiled binaries within the supplied tarball file. +.. note:: These instructions have been verified to work against the version "1.0.0-alpha2" tagged docker + images and the pre-compiled setup utilities within the supplied tarball file. If you run these commands with images or tools from the current master - branch, you will see configuration and panic errors. + branch, it is possible that you will see configuration and panic errors. The getting started scenario provisions a sample Fabric network consisting of two organizations, each maintaining two peers, and a "solo" ordering service. -Prior to launching the network, we will demonstrate the usage of two fundamental tools: +Prior to launching the network, we will demonstrate the usage 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. +- cryptogen - generates the x509 certificates AND keys used to identify and + authenticate the various components in the network. +- `configtxgen `__ - + generates the requisite configuration artifacts for orderer bootstrap and + channel creation. -In no time we'll have a fully-functioning transactional network with a shared -ledger and digital signature verification. Let's get going... +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 and setup ----------------------- @@ -28,8 +34,8 @@ Prerequisites and setup - `Go `__ - 1.7 or higher - `Git Bash `__ - Windows users only; provides a better alternative to the Windows command prompt -Curl the artifacts and binaries -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Curl the artifacts and binaries & pull the docker images +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. note:: If you are running on Windows you will want to make use of your Git Bash shell for the upcoming terminal commands. @@ -46,496 +52,731 @@ Next, execute the following command: .. code:: bash - curl -L https://nexus.hyperledger.org/content/repositories/snapshots/sandbox/vex-yul-hyp-jenkins-2/fabric-binaries/release.tar.gz -o release.tar.gz 2> /dev/null; tar -xvf release.tar.gz - -This command pulls and extracts all of the necessary artifacts to set up your -network and places them into a folder titled ``release``. It also retrieves the -two binaries - cryptogen and configtxgen - which are briefly described at the top -of this page. + curl -sS https://raw.githubusercontent.com/hyperledger/fabric/master/examples/e2e_cli/bootstrap.sh | bash -Pulling the docker images -^^^^^^^^^^^^^^^^^^^^^^^^^ +This command executes a bash script (``bootstrap.sh``) that will extract all of the necessary +artifacts to set up your network and place them into a folder named ``release``. +It also retrieves the two binaries - cryptogen and configtxgen - which are briefly +described above. Finally, the script will download the Hyperledger Fabric +docker images. The script leverages an environment variable to detect your OS, allowing us to pull +platform specific binaries and images. -Change directories into ``release``. You should see the following: +The script lists out the docker images upon conclusion. You should see the +following: .. code:: bash - jdoe-mbp:release johndoe$ ls - darwin-amd64 linux-amd64 linux-ppc64le linux-s390x samples templates windows-amd64 + jdoe-mbp: johndoe$ docker images + REPOSITORY TAG IMAGE ID CREATED SIZE + hyperledger/fabric-couchdb latest 3d89ac4895f9 3 days ago 1.51 GB + hyperledger/fabric-couchdb x86_64-1.0.0-alpha2 3d89ac4895f9 3 days ago 1.51 GB + hyperledger/fabric-ca latest 86f4e4280690 3 days ago 241 MB + hyperledger/fabric-ca x86_64-1.0.0-alpha2 86f4e4280690 3 days ago 241 MB + hyperledger/fabric-kafka latest b77440c116b3 3 days ago 1.3 GB + hyperledger/fabric-kafka x86_64-1.0.0-alpha2 b77440c116b3 3 days ago 1.3 GB + hyperledger/fabric-zookeeper latest fb8ae6cea9bf 3 days ago 1.31 GB + hyperledger/fabric-zookeeper x86_64-1.0.0-alpha2 fb8ae6cea9bf 3 days ago 1.31 GB + hyperledger/fabric-orderer latest 9a63e8bac1f5 3 days ago 182 MB + hyperledger/fabric-orderer x86_64-1.0.0-alpha2 9a63e8bac1f5 3 days ago 182 MB + hyperledger/fabric-peer latest 23b4aedef57f 3 days ago 185 MB + hyperledger/fabric-peer x86_64-1.0.0-alpha2 23b4aedef57f 3 days ago 185 MB + hyperledger/fabric-javaenv latest a9ca2c90a6bf 3 days ago 1.43 GB + hyperledger/fabric-javaenv x86_64-1.0.0-alpha2 a9ca2c90a6bf 3 days ago 1.43 GB + hyperledger/fabric-ccenv latest c984ae2a1936 3 days ago 1.29 GB + hyperledger/fabric-ccenv x86_64-1.0.0-alpha2 c984ae2a1936 3 days ago 1.29 GB -You will notice that there are platform-specific folders. Each folder contains the -corresponding binaries for that platform, along with a script that we will use -to download the Fabric images. Right now we're only interested in the script. -Navigate into the folder matching your machine's OS and then into ``install``. -For example, if you were running on OSX: -.. code:: bash +Look at the names for each image; these are the components that will ultimately +comprise our Fabric network. You will also notice that you have two instances +of the same image ID - one tagged as "x86_64-1.0.0-alpha2" and one tagged as "latest". +(Note that on different architectures, the x86_64 would be replaced with the string +identifying your architecture). + +Want to run it now? +^^^^^^^^^^^^^^^^^^^ + +We provide a script that leverages these docker images to quickly bootstrap +a Fabric network, join peers to a channel, and drive transactions. If you're +already familiar with Fabric or just want to see it in action, feel free to jump +down to the :ref:`Network-Setup` section and run the script. + +If you'd like to learn more about the underlying tooling and bootstrap mechanics, +continue reading. In these next sections we'll walk through the various steps +and requirements to build a fully-functional Fabric. + +Crypto Generator +---------------- + +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 `__ +is used to create four configuration 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 tools +------------- + +We offer two approaches here. You can manually generate the certificates/keys +and the various configuration artifacts using the commands exposed below. +Alternatively, we provide a script which will generate everything in just a few +seconds. It's recommended to run through the manual approach initially, as it +will better familiarize you with the tools and command syntax. However, if you just want +to spin up your network, jump down to the :ref:`Run-the-shell-script` section. - cd darwin-amd64/install +Manually generate the artifacts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Now run the shell script to download the docker images. This will take a few -minutes so remember that patience is a virtue: +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 run the cryptogen tool. Our binary is in the ``bin`` +directory, so we need to provide the relative path to where the tool resides. +Make sure you are in ``: .. code:: bash - ./get-docker-images.sh + ./bin/cryptogen generate --config=./crypto-config.yaml -Execute a ``docker images`` command to view your images. Assuming you had no -images on your machine prior to running the script, you should see the following: +You will likely see the following warning. It's innocuous, ignore it: .. code:: bash - jdoe-mbp:install johndoe$ docker images - REPOSITORY TAG IMAGE ID CREATED SIZE - hyperledger/fabric-couchdb x86_64-1.0.0-alpha f3ce31e25872 5 weeks ago 1.51 GB - hyperledger/fabric-kafka x86_64-1.0.0-alpha 589dad0b93fc 5 weeks ago 1.3 GB - hyperledger/fabric-zookeeper x86_64-1.0.0-alpha 9a51f5be29c1 5 weeks ago 1.31 GB - hyperledger/fabric-orderer x86_64-1.0.0-alpha 5685fd77ab7c 5 weeks ago 182 MB - hyperledger/fabric-peer x86_64-1.0.0-alpha 784c5d41ac1d 5 weeks ago 184 MB - hyperledger/fabric-javaenv x86_64-1.0.0-alpha a08f85d8f0a9 5 weeks ago 1.42 GB - hyperledger/fabric-ccenv x86_64-1.0.0-alpha 91792014b61f 5 weeks ago 1.29 GB + [bccsp] GetDefault -> WARN 001 Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP. -Look at the names for each image; these are the components that will ultimately -comprise our Fabric network. +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 -Using the cryptogen tool ------------------------- + FABRIC_CFG_PATH=$PWD -First, let's set the environment variable for our platform. This command -will detect your OS and use the appropriate binaries for the subsequent steps: +Create the orderer genesis block: .. 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)}') + ./bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/orderer.genesis.block -Check to make sure the ``$os_arch`` variable is properly set: +You can ignore the logs regarding intermediate certs, we are not using them in +this crypto implementation. + +Create the channel transaction artifact: .. code:: bash - echo $os_arch + # make sure to set the parm + + ./bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID -Ok now for the fun stuff - generating the crypto material. Pop into the ``e2e`` folder: +Define the anchor peer for Org1 on the channel: .. code:: bash - cd ../../samples/e2e + # make sure to set the parm -We are going to pass in the ``crypto-config.yaml`` file as an argument for the -upcoming command. This file contains the definition/structure of our network -and lists the components that we are generating certs for. If you open the file -you will see that our network will consist of - one ``OrdererOrg`` and two -``PeerOrgs`` each maintaining two peers. You can easily modify this file to -generate certs for a more elaborate network, however we will leave the sample configuration -for the sake of simplicity. Got it? Let's run the tool now: + ./bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID -asOrg Org1MSP -.. code:: bash +Define the anchor peer for Org2 on the channel: - # this syntax requires you to be in the e2e directory - # notice that we will pass in the $os_arch variable in order to use the correct binary - ./../../$os_arch/bin/cryptogen generate --config=./crypto-config.yaml +.. code:: bash -If the tool runs successfully, you will see the various KeyStores churn out in -your terminal. The certs are then parked into a ``crypto-config`` folder that -is generated when you run the tool. + # make sure to set the parm -Using the configtxgen tool --------------------------- + ./bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID -asOrg Org2MSP -We will now use our second tool - configtxgen - to create our ordering service -genesis block and a channel configuration artifact. As the abbreviation suggests, -this tool is a configuration transaction generator. More info on the configtxgen -tool can be found `here `__ -However, at this stage (and for the sake of brevity) we will simply make use of -the tool to generate our two artifacts. +.. _Run-the-shell-script: -.. note:: The ``configtx.yaml`` file contains the definitions for our sample - network and presents the topology of the network components - three members - (OrdererOrg, Org0 & Org1), and the anchor peers for each PeerOrg - (peer0.org1 and peer0.org2). You will notice - that it is structured similarly to the ``crypto-config.yaml`` that we - just passed to generate our certs. The main difference is that we can - now point to the locations of those certs. You'll recall that in the - previous step we created a new folder called ``crypto-config`` and parked - the certs there. The ``configtx.yaml`` points to that directory and - allows us to bundle the root certs for the Orgs constituting our - network into the genesis block. This is a critical concept. Now any - network entity communicating with the ordering service can have its - digital signature verified. +Run the shell script +^^^^^^^^^^^^^^^^^^^^ -Generate the orderer genesis block -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +You can skip this step if you just manually generated the crypto and artifacts. +However, if you want to see this script in action, delete the ``crypto-config`` +folder and remove the four artifacts from your ``channel-artifacts`` folder. +Then proceed... -From your ``e2e`` folder first execute the following: +Make sure you are in the ```` directory where the script resides. +Decide upon a unique name for your channel and replace the parm +with a name of your choice. The script will fail if you do not supply a name. .. code:: bash - # this command will not return a response - export FABRIC_CFG_PATH=$PWD + ./generateArtifacts.sh -Then use the tool: +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 - # notice at the top of configtx.yaml we define the profile as TwoOrgs - ./../../$os_arch/bin/configtxgen -profile TwoOrgs -outputBlock orderer.block - # for example, if you are running OSX then the binary from darwin-amd64 would have been used + ########################################################## + ##### Generate certificates using cryptogen tool ######### + ########################################################## -The orderer genesis block - ``orderer.block`` - is output into the ``e2e`` directory. + ########################################################## + ######### Generating Orderer Genesis block ############## + ########################################################## -Generate the channel configuration artifact -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ################################################################# + ### Generating channel configuration transaction 'channel.tx' ### + ################################################################# -When we call the ``createChannel`` API, and send the proposal to the ordering -service, we need to pass a channel configuration artifact along with this call. -We will once again leverage the ``configtx.yaml`` and use the same profile -definition - TwoOrgs - that we used to create the orderer genesis block. In -other words, this channel we are creating is a network-wide channel. All Orgs -are included. + ################################################################# + ####### Generating anchor peer update for Org0MSP ########## + ################################################################# -Still in your ``e2e`` folder execute the following: + ################################################################# + ####### Generating anchor peer update for Org1MSP ########## + ################################################################# -.. code:: bash - # replace the parm with a name of your choosing - ./../../$os_arch/bin/configtxgen -profile TwoOrgs -outputCreateChannelTx channel.tx -channelID +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. -The channel configuration artifact - ``channel.tx`` - is output into the ``e2e`` directory. +Start the network +----------------- -Start the network (No TLS) --------------------------- - -We will leverage a docker-compose script to spin up our network. The docker-compose +We will leverage a docker-compose script to spin up our network. The docker-compose points to the images that we have already downloaded, and bootstraps the orderer -with our previously generated ``orderer.block``. Before launching the network, -open the docker-compose file and comment out the script.sh in the CLI container. -Your docker-compose should look like this: +with our previously generated orderer.block. Before launching the network, open +the ``docker-compose-cli.yaml`` file and comment out the script.sh in the CLI +container. Your docker-compose should look like this: .. code:: bash working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer - #command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; ' - volumes: + # command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT' + volumes If left uncommented, the script will exercise all of the CLI commands when the -network is started. However, we want to go through the commands manually in order to -expose the syntax and functionality of each call. +network is started. However, we want to go through the commands manually in order +to expose the syntax and functionality of each call. + +Pass in a moderately high value for the ``TIMEOUT`` variable (specified in seconds); +otherwise the CLI container, by default, will exit after 60 seconds. Start your network: .. code:: bash - # this sets our OS - export ARCH_TAG=$(uname -m) - # this starts the network in "detached" mode; enter the appropriate value for the CHANNEL_NAME parm - CHANNEL_NAME= docker-compose -f docker-compose-no-tls.yaml up -d + # make sure you are in the directory where your docker-compose script resides -If you'd like to see the realtime logs for the components, then remove the ``-d`` flag: + CHANNEL_NAME= TIMEOUT= 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. + +Environment variables +^^^^^^^^^^^^^^^^^^^^^ + +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 - CHANNEL_NAME= docker-compose -f docker-compose-no-tls.yaml up + # Environment variables for PEER0 -Now open another terminal and navigate back to ``release/samples/e2e``. + 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 & Join Channel ---------------------- +^^^^^^^^^^^^^^^^^^^^ -Go into the cli container: +Exec into the cli container: .. code:: bash - docker exec -it cli bash + docker exec -it cli bash -You should see the following: +If successful you should see the following: .. code:: bash - root@bb5e894d9668:/opt/gopath/src/github.com/hyperledger/fabric/peer# - -Create Channel -^^^^^^^^^^^^^^ + root@0d78bb69300d:/opt/gopath/src/github.com/hyperledger/fabric/peer# Recall that we used the configtxgen tool to generate a channel configuration -artifact - ``channel.tx``. We are going to pass in this artifact to the -orderer as part of the create channel request. +artifact - ``channel.tx``. We are going to pass in this artifact to the orderer +as part of the create channel request. -.. note:: For this to work, we must pass in the path of the orderer's local MSP in order to sign - this create channel call. Recall that we bootstrapped the orderer - with the root certificates (ca certs) for all the members of our - network. As a result, the orderer can verify the digital signature - of the submitting client. This call will also work if we pass in the - local MSP for Org0 or Org1. +.. note:: notice the ``-- cafile`` which we pass as part of this command. It is the + local path to the orderer's root cert, allowing us to verify the TLS handshake. -The following environment variables for the orderer must be passed: +We specify our channel name with the ``-c`` flag and our 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 - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com - CORE_PEER_LOCALMSPID="OrdererMSP" - CHANNEL_NAME= + # 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 -The syntax is as follows: + 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 -.. code:: bash +This command returns a genesis block - ```` - which we will use to join the channel. +It contains the configuration information specified in ``channel.tx``. - peer channel create -o :7050 -c -f channel.tx -So our command in its entirety would be: +.. 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``. + +Now let's join ``peer0.org1.example.com`` to the channel. .. code:: bash - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com CORE_PEER_LOCALMSPID="OrdererMSP" peer channel create -o orderer.example.com:7050 -c mychannel -f channel.tx + # By default, this joins ``peer0.org1.example.com`` only + # the .block was returned by the previous command -This command returns a genesis block - ``mychannel.block`` - which we will use -to join the channel. + peer channel join -b -Environment variables -~~~~~~~~~~~~~~~~~~~~~ +You can make other peers join the channel as necessary by making appropriate +changes in the four environment variables. + +Install & Instantiate +^^^^^^^^^^^^^^^^^^^^^ -You can see the syntax for all commands by inspecting the ``script.sh`` file in the ``scripts`` directory. +Applications interact with the blockchain ledger through chaincode. As such we need to +install the chaincode on any peer that will execute and endorse transactions, and +then instantiate the chaincode on the channel. -For the following cli commands against ``PEER0`` to work, we need to set the -values for the four global environment variables given below. Please make sure to override -the values accordingly when calling commands against other peers and the orderer. +First, install the sample go code onto one of the four peer nodes. This command +places the source code onto our peer's filesystem. .. code:: bash - # Environment variables for PEER0 - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 - CORE_PEER_LOCALMSPID="Org0MSP" - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/cacerts/org1.example.com-cert.pem + peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -These environment variables for each peer are defined in the supplied docker-compose file. +Next, instantiate the chaincode on the channel. This will initialize the chaincode +on the channel, set the endorsement policy for the chaincode, and launch a chaincode +container for the targeted peer. Take note of the ``-P`` argument. This is our policy where we specify the required +level of endorsement for a transaction against this chaincode to be validated. +In the command below you’ll notice that we specify our policy as +``-P "OR ('Org0MSP.member','Org1MSP.member')"``. This means that we need +“endorsement” from a peer belonging to Org1 OR Org2 (i.e. only one endorsement). +If we changed the syntax to ``AND`` then we would need two endorsements. -.. note:: In these examples, we are using the default ``mychannel`` for all CHANNEL_NAME arguments. - If you elect to create a uniquely named channel, be conscious to modify - your strings accordingly. +.. code:: bash -Join channel -^^^^^^^^^^^^ + # 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 -Now let's join ``PEER0`` to the channel by passing in the genesis block that was -just returned to us upon the create channel command. + 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 `__ +documentation for more details on policy implementation. + +Query +^^^^^ -The syntax is as follows: +Let's query for the value of “a” to make sure the chaincode was properly +instantiated and the state DB was populated. The syntax for query is as follows: .. code:: bash - peer channel join -b .block + # be sure to set the -C and -n flags appropriately -Remember, we need to pass the four global variables. So this command in its -entirety would be: + peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' + + +Invoke +^^^^^^ + +Now let's move "10" from "a" to "b". This transaction will cut a new block and +update the state DB. The syntax for invoke is as follows: .. code:: bash - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com CORE_PEER_ADDRESS=peer0.org1.example.com:7051 CORE_PEER_LOCALMSPID="Org0MSP" CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/cacerts/org1.example.com-cert.pem peer channel join -b mychannel.block + # be sure to set the -C and -n flags appropriately -Install -^^^^^^^ + 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"]}' -Now we will install the chaincode source onto the peer's filesystem. The syntax -is as follows: +Query +^^^^^ + +Let's confirm that our previous invocation executed properly. We initialized the +key “a” with a value of “100”. Therefore, removing “10” should return a value of +“90” when we query “a”. The syntax for query is as follows. .. code:: bash - peer chaincode install -n -v -p + # be sure to set the -C and -n flags appropriately + + peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' -This command in its entirety would be: +We should see the following: .. code:: bash - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com CORE_PEER_ADDRESS=peer0.org1.example.com:7051 CORE_PEER_LOCALMSPID="Org0MSP" CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/cacerts/org1.example.com-cert.pem peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 >&log.txt + Query Result: 90 -Instantiate -^^^^^^^^^^^ +Feel free to start over and manipulate the key value pairs and subsequent +invocations. -Now we start the chaincode container and initialize our key value pairs. The -syntax for instantiate is as follows: +Scripts +------- -.. code:: bash +We exposed the verbosity of the commands in order to provide some edification on +the underlying flow and the appropriate syntax. Entering the commands manually +through the CLI is quite onerous, therefore we provide a few scripts to do the +entirety of the heavy lifting. - peer chaincode instantiate -o :7050 -C -n -v -c '{"Args":["init","key","value"]}' -P "OR/AND (CHAINCODE_POLICY)" +Clean up +^^^^^^^^ -Take note of the ``-P`` argument. This is our policy where we specify the -required level of endorsement for a transaction against this chaincode to be -validated. In the command below you'll notice that we specify our policy as -``-P "OR ('Org0MSP.member','Org1MSP.member')"``. This means that we need -"endorsement" from a peer belonging to Org0 **OR** Org1 (i.e. only one endorsement). -If we changed the syntax to ``AND`` then we would need two endorsements. +Let's clean up first... -This command in its entirety would be: +Exit the currently-running containers: .. code:: bash - # we instantiate with the following key value pairs: "a","100","b","200" - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com CORE_PEER_ADDRESS=peer0.org1.example.com:7051 CORE_PEER_LOCALMSPID="Org0MSP" CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/cacerts/org1.example.com-cert.pem peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR ('Org0MSP.member','Org1MSP.member')" + docker rm -f $(docker ps -aq) -.. note:: The above command will only start a single chaincode container. If - you want to interact with different peers, you must first install - the source code onto that peer's filesystem. You can then send - an invoke or query to the peer. You needn't instantiate twice, this - command will propagate to the entire channel. +Execute a ``docker images`` command in your terminal to view the +chaincode images. They will look similar to the following: -Query -^^^^^ +.. code:: bash -Lets query for the value of "a" to make sure the chaincode was properly instantiated -and the state DB was populated. The syntax for query is as follows: + 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 - peer chaincode query -C -n -c '{"Args":["query","key"]}' + docker rmi -This command in its entirety would be: +For example: .. code:: bash - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com CORE_PEER_ADDRESS=peer0.org1.example.com:7051 CORE_PEER_LOCALMSPID="Org0MSP" CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/cacerts/org1.example.com-cert.pem peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' + docker rmi -f 4bc 6f2 509 -Invoke -^^^^^^ +Lastly, remove the ``crypto-config`` folder and the four artifacts within the +``channel-artifacts`` folder. + +**OR** -Lastly we will move "10" from "a" to "b". This transaction will cut a new block -and update the state DB. The syntax for invoke is as follows: +You can execute the following command which will do all of the above: .. code:: bash - peer chaincode invoke -o :7050 -C -n -c '{"Args":["invoke","key","key","value"]}' + ./network_setup.sh down -This command in its entirety would be: +.. _Network-Setup: -.. code:: bash +All in one +^^^^^^^^^^ - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com CORE_PEER_ADDRESS=peer0.org1.example.com:7051 CORE_PEER_LOCALMSPID="Org0MSP" CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/cacerts/org1.example.com-cert.pem peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}' +This script literally does it all. It calls ``generateArtifacts.sh`` to exercise +the ``cryptogen`` and ``configtxgen`` tools, followed by ``script.sh`` which +launches the network, joins peers to a generated channel and then drives +transactions. 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. -Query -^^^^^ +.. code:: bash -Lets confirm that our previous invocation executed properly. We initialized the -key "a" with a value of "100". Therefore, removing "10" should return a value -of "90" when we query "a". The syntax for query is outlined above. + ./network_setup.sh up -This query command in its entirety would be: +OR .. code:: bash - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com CORE_PEER_ADDRESS=peer0.org1.example.com:7051 CORE_PEER_LOCALMSPID="Org0MSP" CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/cacerts/org1.example.com-cert.pem peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' + ./network_setup.sh up + +Now clean up... -Start the network (TLS enabled) ------------------------------- +.. code:: bash -Use the ``script.sh`` to see the exact syntax for TLS-enabled CLI commands. + ./network_setup.sh down -Before starting, we need to modify our docker-compose file to reflect the appropriate private keys for -the orderer and peers. +Config only +^^^^^^^^^^^ -From your ``e2e`` directory execute the following: +The other option is to manually generate your crypto material and configuration +artifacts, and then use the embedded ``script.sh`` in the docker-compose files +to drive your network. Make sure this script is not commented out in your +CLI container. Before starting, make sure you've cleaned up your environment: .. code:: bash - PRIV_KEY=$(ls crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/keystore/) sed -i "s/ORDERER_PRIVATE_KEY/${PRIV_KEY}/g" docker-compose.yaml - PRIV_KEY=$(ls crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/keystore/) sed -i "s/PEER0_ORG1_PRIVATE_KEY/${PRIV_KEY}/g" docker-compose.yaml - PRIV_KEY=$(ls crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/keystore/) sed -i "s/PEER0_ORG2_PRIVATE_KEY/${PRIV_KEY}/g" docker-compose.yaml - PRIV_KEY=$(ls crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/keystore/) sed -i "s/PEER1_ORG1_PRIVATE_KEY/${PRIV_KEY}/g" docker-compose.yaml - PRIV_KEY=$(ls crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/keystore/) sed -i "s/PEER1_ORG2_PRIVATE_KEY/${PRIV_KEY}/g" docker-compose.yaml + ./network_setup.sh down -These commands will modify the TLS_KEY_FILE variables in your docker-compose. -Once you have executed all five commands, spin the network back up and begin -by creating your channel. +Next, open your ``docker-compose-cli.yaml`` and make sure the ``script.sh`` +command is not commented out in the CLI container. It should look exactly like +this: -Scripts -------- +.. code:: bash -We exposed the verbosity of the commands in order to provide some edification -on the underlying flow and the appropriate syntax. Entering the commands manually -through the CLI is quite onerous, therefore we provide a few scripts to do the -entirety of the heavy lifting. + working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer + command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT' + volumes -Clean up -^^^^^^^^ +From the ```` directory, 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 -Let's clean things up before continuing. This command will remove both the -active and exited containers: + # the TIMEOUT variable is optional + CHANNEL_NAME= TIMEOUT= 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 - docker rm -f $(docker ps -aq) + CHANNEL_NAME=abc TIMEOUT=1000 docker-compose -f docker-compose-cli.yaml up -d -Next, execute a ``docker images`` command in your terminal to view the -**chaincode** images. They will look similar to the following: +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 - REPOSITORY TAG IMAGE ID CREATED SIZE - dev-peer3-mycc-1.0 latest 13f6c8b042c6 5 minutes ago 176 MB - dev-peer0-mycc-1.0 latest e27456b2bd92 5 minutes ago 176 MB - dev-peer2-mycc-1.0 latest 111098a7c98c 5 minutes ago 176 MB + 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 -Remove these images: +If you set a moderately high ``TIMEOUT`` value, then you will see your cli +container as well. -.. code:: bash +What's happening behind the scenes? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - docker rmi +- 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. -For example: +- The output of ``createChannel`` is a genesis block - + ``.block`` - which gets stored on the peers' file systems and contains + the channel configuration specified from channel.tx. -.. code:: bash +- 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 ```` and create a chain starting with ``.block``. - docker rmi -f 13f e27 111 +- Now we have a channel consisting of four peers, and two + organizations. This is our ``TwoOrgsChannel`` profile. -Lastly, remove the `crypto-config`` folder and the two artifacts - ``channel.tx`` -& ``orderer.block``. +- ``peer0.org1.example.com`` and ``peer1.org1.example.com`` belong to Org1; + ``peer0.org2.example.com`` and ``peer1.org2.example.com`` belong to Org2 -.. code:: bash +- These relationships are defined through the ``crypto-config.yaml`` and + the MSP path is specified in our docker compose. - # from the e2e directory - rm -rf channel.tx orderer.block crypto-config +- 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. -All in one -^^^^^^^^^^ +- A chaincode - **chaincode_example02** - is installed on ``peer0.org1.example.com`` and + ``peer0.org2.example.com`` -This script will do it all for you! From the ``e2e`` directory: +- 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. -.. code:: bash +- 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? +^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ./network_setup.sh up +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. -.. note:: If you choose not to pass a channel_name value, then the default - ``mychannel`` will be used. +How do I see these transactions? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Now shut down your network and remove the chaincode images and artifacts: +Check the logs for the CLI docker container. .. code:: bash - ./network_setup.sh down + docker logs -f cli -If you want to restart: +You should see the following output: .. code:: bash - ./network_setup.sh restart + 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 ===================== -APIs only -^^^^^^^^^ + ===================== All GOOD, End-2-End execution completed ===================== -The other option is to manually generate your crypto material and configuration -artifacts, and then use the embedded ``script.sh`` in the docker-compose files -to drive your network. Make sure this script is not commented out in your -CLI container. -When the scripts complete successfully, you should see the following message -in your terminal: + _____ _ _ ____ _____ ____ _____ + | ____| | \ | | | _ \ | ____| |___ \ | ____| + | _| | \| | | | | | _____ | _| __) | | _| + | |___ | |\ | | |_| | |_____| | |___ / __/ | |___ + |_____| |_| \_| |____/ |_____| |_____| |_____| + +You can scroll through these logs to see the various transactions. + +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 - ===================== Query on PEER3 on channel 'mychannel' is successful ===================== + $ 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"} + +Understanding the docker-compose topology +----------------------------------------- - ===================== All GOOD, End-2-End execution completed ===================== +The ```__ repo for details + on running these tests. + +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. Using CouchDB ------------- @@ -546,96 +787,87 @@ 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. +procedures outlined earlier for generating the artifacts, except when starting +the network pass the couchdb docker-compose as well: .. code:: bash - # make sure you are in the fabric directory - make couchdb - -- Open the ``release/samples/e2e/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. + # make sure you are in the /e2e_cli directory where your docker-compose script resides + CHANNEL_NAME= TIMEOUT= 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 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. +.. 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 query +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 -``release/samples/chaincodes/go`` directory. +``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 execute transactions** section. After the **Join channel** step, use the -following commands to interact with the **marbles02** chaincode: +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``: +- Install and instantiate the chaincode on ``peer0.org1.example.com``: .. 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')" + # 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 - 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. + # be sure to modify the $CHANNEL_NAME variable accordingly - For containers running in a vagrant environment: + 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"]}' - ``http://localhost:15984/_utils`` - - For non-vagrant environment, use the port address that was mapped in CouchDB - container specification: +- 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`` and the documents - inside it. +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``): +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"]}' + peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["readMarble","marble2"]}' -You should see the details of ``marble2``: +The output should display the details of ``marble2``: .. code:: bash Query Result: {"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50} -Retrieve the history of ``marble1``: +You can retrieve the history of a specific marble - e.g. ``marble1``: .. code:: bash - peer chaincode query -C mychannel -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}' + peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}' -You should see the transactions on ``marble1``: +The output should display the transactions on ``marble1``: .. code:: bash @@ -645,22 +877,10 @@ You can also perform rich queries on the data content, such as querying marble f .. code:: bash - peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarblesByOwner","jerry"]}' + 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}}] - -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}}] @@ -671,14 +891,13 @@ 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: +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: @@ -687,25 +906,34 @@ container specification: volumes: - /var/hyperledger/couchdb0:/opt/couchdb/data - Troubleshooting --------------- -- Ensure you clear the file system after each run. - -- If you see docker errors, remove your containers and start again. +- Always start your network fresh. Use the following command + to remove artifacts, crypto, containers and chaincode images: .. code:: bash - docker rm -f $(docker ps -aq) + ./network_setup.sh down + +- **YOU WILL SEE ERRORS IF YOU DO NOT REMOVE CONTAINERS AND IMAGES** + +- 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 you elect to run the "All in one" option, be sure you have deleted your - crypto directory and the two artifacts. This can be achieved with the following - command: +- If they persist remove your images and start from scratch: .. code:: bash - ./network_setup.sh down + docker rm -f $(docker ps -aq) + docker rmi -f $(docker images -q) + +- If you see errors on your create, instantiate, invoke or query commands, make + sure you have properly updated the channel name and chaincode name. There + are placeholder values in the supplied sample commands. - If you see the below error: @@ -713,24 +941,23 @@ Troubleshooting 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-peer0-mycc-1.0`` or ``dev-peer1-mycc-1.0``) -from prior runs. Remove them and try again. +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 connectivity or communication errors, try restarting your Docker process. - - 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 + 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 are using the supplied binaries in the tarball file, and running -your backend against "alpha" images. +Make sure you are running your network against "alpha2" images that have been +retagged as "latest". If you see the below error: @@ -739,11 +966,15 @@ If you see the below error: [configtx/tool/localconfig] Load -> CRIT 002 Error reading configuration: Unsupported Config Type "" panic: Error reading configuration: Unsupported Config Type "" -Then you have an environment variable - ``ORDERER_CFG_PATH`` that is no longer -in use. You can manually change this value in the scripts, or re-download -the tarball file. +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. -- If you continue to see errors, share your logs on the **# fabric-questions** -channel on `Hyperledger Rocket Chat `__. +- 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 `__.