|
| 1 | +Getting Started |
| 2 | +=============== |
| 3 | + |
| 4 | +The getting started scenario provisions a sample Fabric network consisting of |
| 5 | +two organizations, each maintaining two peers, and a "solo" ordering service. |
| 6 | + |
| 7 | +Prior to launching the network, we will demonstrate the usage of two fundamental tools: |
| 8 | + |
| 9 | +- cryptogen - generates the x509 certificates used to identify and authenticate |
| 10 | + the various components in the network. |
| 11 | +- configtxgen - generates the requisite configuration artifacts for orderer |
| 12 | + bootstrap and channel creation. |
| 13 | + |
| 14 | +In no time we'll have a fully-functioning transactional network with a shared |
| 15 | +ledger and digital signature verification. Let's get going... |
| 16 | + |
| 17 | +Prerequisites and setup |
| 18 | +----------------------- |
| 19 | + |
| 20 | +- `Docker <https://www.docker.com/products/overview>`__ - v1.12 or higher |
| 21 | +- `Docker Compose <https://docs.docker.com/compose/overview/>`__ - v1.8 or higher |
| 22 | +- `Docker Toolbox <https://docs.docker.com/toolbox/toolbox_install_windows/>`__ - Windows users only |
| 23 | +- `Go <https://golang.org/>`__ - 1.7 or higher |
| 24 | +- `Git Bash <https://git-scm.com/downloads>`__ - Windows users only; provides a better alternative to the Windows command prompt |
| 25 | + |
| 26 | +Curl the artifacts and binaries |
| 27 | +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 28 | + |
| 29 | +.. note:: If you are running on Windows you will want to make use of your Git |
| 30 | + Bash shell for the upcoming terminal commands. |
| 31 | + |
| 32 | +- Download the `cURL <https://curl.haxx.se/download.html>`__ tool if not already installed. |
| 33 | +- Determine a location on your machine where you want to place the artifacts and binaries. |
| 34 | + |
| 35 | +.. code:: bash |
| 36 | +
|
| 37 | + mkdir fabric-sample |
| 38 | + cd fabric-sample |
| 39 | +
|
| 40 | +Next, execute the following command: |
| 41 | + |
| 42 | +.. code:: bash |
| 43 | +
|
| 44 | + curl -L https://logs.hyperledger.org/sandbox/vex-yul-hyp-jenkins-2/fabric-verify-x86_64_1/5/release.tar.gz -o release.tar.gz 2> /dev/null; tar -xvf release.tar.gz Has conversations. Original line has conversations. |
| 45 | +
|
| 46 | +This command pulls and extracts all of the necessary artifacts to set up your |
| 47 | +network and places them into a folder titled ``release``. It also retrieves the |
| 48 | +two binaries - cryptogen and configtxgen - which are briefly described at the top |
| 49 | +of this page. |
| 50 | + |
| 51 | +Pulling the docker images |
| 52 | +^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 53 | + |
| 54 | +Change directories into ``release``. You should see the following: |
| 55 | + |
| 56 | +.. code:: bash |
| 57 | +
|
| 58 | + jdoe-mbp:release johndoe$ ls |
| 59 | + darwin-amd64 linux-amd64 linux-ppc64le linux-s390x samples templates windows-amd64 |
| 60 | +
|
| 61 | +You will notice that there are platform-specific folders. Each folder contains the |
| 62 | +corresponding binaries for that platform, along with a script that we will use |
| 63 | +to download the Fabric images. Right now we're only interested in the script. |
| 64 | +Navigate into the folder matching your machine's OS and then into ``install``. |
| 65 | +For example, if you were running on OSX: |
| 66 | + |
| 67 | +.. code:: bash |
| 68 | +
|
| 69 | + cd darwin-amd64/install |
| 70 | +
|
| 71 | +Now run the shell script to download the docker images. This will take a few |
| 72 | +minutes so remember that patience is a virtue: |
| 73 | + |
| 74 | +.. code:: bash |
| 75 | +
|
| 76 | + ./get-docker-images.sh |
| 77 | +
|
| 78 | +Execute a ``docker images`` command to view your images. Assuming you had no |
| 79 | +images on your machine prior to running the script, you should see the following: |
| 80 | + |
| 81 | +.. code:: bash |
| 82 | +
|
| 83 | + jdoe-mbp:install johndoe$ docker images |
| 84 | + REPOSITORY TAG IMAGE ID CREATED SIZE |
| 85 | + hyperledger/fabric-couchdb x86_64-1.0.0-alpha f3ce31e25872 5 weeks ago 1.51 GB |
| 86 | + hyperledger/fabric-kafka x86_64-1.0.0-alpha 589dad0b93fc 5 weeks ago 1.3 GB |
| 87 | + hyperledger/fabric-zookeeper x86_64-1.0.0-alpha 9a51f5be29c1 5 weeks ago 1.31 GB |
| 88 | + hyperledger/fabric-orderer x86_64-1.0.0-alpha 5685fd77ab7c 5 weeks ago 182 MB |
| 89 | + hyperledger/fabric-peer x86_64-1.0.0-alpha 784c5d41ac1d 5 weeks ago 184 MB |
| 90 | + hyperledger/fabric-javaenv x86_64-1.0.0-alpha a08f85d8f0a9 5 weeks ago 1.42 GB |
| 91 | + hyperledger/fabric-ccenv x86_64-1.0.0-alpha 91792014b61f 5 weeks ago 1.29 GB |
| 92 | +
|
| 93 | +Look at the names for each image; these are the components that will ultimately |
| 94 | +comprise our Fabric network. |
| 95 | + |
| 96 | +Using the cryptogen tool |
| 97 | +------------------------ |
| 98 | + |
| 99 | +First, let's set the environment variable for our platform. This command |
| 100 | +will detect your OS and use the appropriate binaries for the subsequent steps: |
| 101 | + |
| 102 | +.. code:: bash |
| 103 | +
|
| 104 | + # for power or z |
| 105 | + os_arch=$(echo "$(uname -s)-$(uname -m)" | awk '{print tolower($0)}') |
| 106 | + # for linux, osx or windows |
| 107 | + os_arch=$(echo "$(uname -s)-amd64" | awk '{print tolower($0)}') |
| 108 | +
|
| 109 | +Ok now for the fun stuff - generating the crypto material. Pop into the ``e2e`` folder: |
| 110 | + |
| 111 | +.. code:: bash |
| 112 | +
|
| 113 | + cd ../../samples/e2e |
| 114 | +
|
| 115 | +We are going to pass in the ``crypto-config.yaml`` file as an argument for the |
| 116 | +upcoming command. This file contains the definition/structure of our network |
| 117 | +and lists the components that we are generating certs for. If you open the file |
| 118 | +you will see that our network will consist of - one ``OrdererOrg`` and two |
| 119 | +``PeerOrgs`` each maintaining two peers. You can easily modify this file to |
| 120 | +generate certs for a more elaborate network, however we will leave the sample configuration |
| 121 | +for the sake of simplicity. Got it? Let's run the tool now: |
| 122 | + |
| 123 | +.. code:: bash |
| 124 | +
|
| 125 | + # this syntax requires you to be in the e2e directory |
| 126 | + # notice that we will pass in the $os_arch variable in order to use the correct binary |
| 127 | + ./../../$os_arch/bin/cryptogen generate --config=./crypto-config.yaml |
| 128 | +
|
| 129 | +If the tool runs successfully, you will see the various KeyStores churn out in |
| 130 | +your terminal. The certs are then parked into a ``crypto-config`` folder that |
| 131 | +is generated when you run the tool. |
| 132 | + |
| 133 | +Using the configtxgen tool |
| 134 | +-------------------------- |
| 135 | + |
| 136 | +We will now use our second tool - configtxgen - to create our ordering service |
| 137 | +genesis block and a channel configuration artifact. As the abbreviation suggests, |
| 138 | +this tool is a configuration transaction generator. More info on the configtxgen |
| 139 | +tool can be found `here <http://hyperledger-fabric.readthedocs.io/en/latest/configtxgen.html>`__ |
| 140 | +However, at this stage (and for the sake of brevity) we will simply make use of |
| 141 | +the tool to generate our two artifacts. |
| 142 | + |
| 143 | +.. note:: The ``configtx.yaml`` file contains the definitions for our sample |
| 144 | + network and presents the topology of the network components - three members |
| 145 | + (OrdererOrg, Org0 & Org1), and the anchor peers for each PeerOrg |
| 146 | + (peer0 and peer2). You will notice |
| 147 | + that it is structured similarly to the ``crypto-config.yaml`` that we |
| 148 | + just passed to generate our certs. The main difference is that we can |
| 149 | + now point to the locations of those certs. You'll recall that in the |
| 150 | + previous step we created a new folder called ``crypto-config`` and parked |
| 151 | + the certs there. The ``configtx.yaml`` points to that directory and |
| 152 | + allows us to bundle the root certs for the Orgs constituting our |
| 153 | + network into the genesis block. This is a critical concept. Now any |
| 154 | + network entity communicating with the ordering service can have its |
| 155 | + digital signature verified. |
| 156 | + |
| 157 | +Generate the orderer genesis block |
| 158 | +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 159 | + |
| 160 | +From your ``e2e`` folder first execute the following: |
| 161 | + |
| 162 | +.. code:: bash |
| 163 | +
|
| 164 | + # this command will not return a response |
| 165 | + export ORDERER_CFG_PATH=$PWD |
| 166 | +
|
| 167 | +Then use the tool: |
| 168 | + |
| 169 | +.. code:: bash |
| 170 | +
|
| 171 | + # notice at the top of configtx.yaml we define the profile as TwoOrgs |
| 172 | + ./../../$os_arch/bin/configtxgen -profile TwoOrgs -outputBlock orderer.block |
| 173 | + # for example, if you are running OSX then the binary from darwin-amd64 would have been used |
| 174 | +
|
| 175 | +The orderer genesis block - ``orderer.block`` - is output into the ``e2e`` directory. |
| 176 | + |
| 177 | +Generate the channel configuration artifact |
| 178 | +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 179 | + |
| 180 | +When we call the ``createChannel`` API, and send the proposal to the ordering |
| 181 | +service, we need to pass a channel configuration artifact along with this call. |
| 182 | +We will once again leverage the ``configtx.yaml`` and use the same profile |
| 183 | +definition - TwoOrgs - that we used to create the orderer genesis block. In |
| 184 | +other words, this channel we are creating is a network-wide channel. All Orgs |
| 185 | +are included. |
| 186 | + |
| 187 | +Still in your ``e2e`` folder execute the following: |
| 188 | + |
| 189 | +.. code:: bash |
| 190 | +
|
| 191 | + # replace the <CHANNEL_NAME> parm with a name of your choosing |
| 192 | + ./../../$os_arch/bin/configtxgen -profile TwoOrgs -outputCreateChannelTx channel.tx -channelID <CHANNEL_NAME> |
| 193 | +
|
| 194 | +The channel configuration artifact - ``channel.tx`` - is output into the ``e2e`` directory. |
| 195 | + |
| 196 | +Start the network (No TLS) |
| 197 | +-------------------------- |
| 198 | + |
| 199 | +We will leverage a docker-compose script to spin up our network. The docker-compose |
| 200 | +points to the images that we have already downloaded, and bootstraps the orderer |
| 201 | +with our previously generated ``orderer.block``. Before launching the network, |
| 202 | +open the docker-compose file and comment out the script.sh in the CLI container. |
| 203 | +Your docker-compose should look like this: |
| 204 | + |
| 205 | +.. code:: bash |
| 206 | +
|
| 207 | + working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer |
| 208 | + #command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; ' |
| 209 | + volumes: |
| 210 | +
|
| 211 | +If left uncommented, the script will exercise all of the CLI commands when the |
| 212 | +network is started. However, we want to go through the commands manually in order to |
| 213 | +expose the syntax and functionality of each call. |
| 214 | + |
| 215 | +Start your network: |
| 216 | + |
| 217 | +.. code:: bash |
| 218 | +
|
| 219 | + # this sets our OS |
| 220 | + export ARCH_TAG=$(uname -m) |
| 221 | + # this starts the network in "detached" mode; enter the appropriate value for the CHANNEL_NAME parm |
| 222 | + CHANNEL_NAME=<CHANNEL_NAME> docker-compose -f docker-compose-no-tls.yaml up -d |
| 223 | +
|
| 224 | +If you'd like to see the realtime logs for the components, then remove the ``-d`` flag: |
| 225 | + |
| 226 | +.. code:: bash |
| 227 | +
|
| 228 | + CHANNEL_NAME=<CHANNEL_NAME> docker-compose -f docker-compose-no-tls.yaml up |
| 229 | +
|
| 230 | +Now open another terminal and navigate back to ``release/samples/e2e``. |
| 231 | + |
| 232 | +Create & Join Channel |
| 233 | +--------------------- |
| 234 | + |
| 235 | +Go into the cli container: |
| 236 | + |
| 237 | +.. code:: bash |
| 238 | +
|
| 239 | + docker exec -it cli bash |
| 240 | +
|
| 241 | +You should see the following: |
| 242 | + |
| 243 | +.. code:: bash |
| 244 | +
|
| 245 | + root@bb5e894d9668:/opt/gopath/src/github.com/hyperledger/fabric/peer# |
| 246 | +
|
| 247 | +Create Channel |
| 248 | +^^^^^^^^^^^^^^ |
| 249 | + |
| 250 | +Recall that we used the configtxgen tool to generate a channel configuration |
| 251 | +artifact - ``channel.tx``. We are going to pass in this artifact to the |
| 252 | +orderer as part of the create channel request. |
| 253 | + |
| 254 | +.. note:: For this to work, we must pass in the path of the orderer's local MSP in order to sign |
| 255 | + this create channel call. Recall that we bootstrapped the orderer |
| 256 | + with the root certificates (ca certs) for all the member's of our |
| 257 | + network. As a result, the orderer can verify the digital signature |
| 258 | + of the submitting client. This call will also work if we pass in the |
| 259 | + local MSP for Org0 or Org1. |
| 260 | + |
| 261 | +The following environment variables for the orderer must be passed: |
| 262 | + |
| 263 | +.. code:: bash |
| 264 | +
|
| 265 | + CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com |
| 266 | + CORE_PEER_LOCALMSPID="OrdererMSP" |
| 267 | + CHANNEL_NAME=<YOUR_CHANNEL_NAME> |
| 268 | +
|
| 269 | +The syntax is as follows: |
| 270 | + |
| 271 | +.. code:: bash |
| 272 | +
|
| 273 | + peer channel create -o <ORDERER_NAME>:7050 -c <CHANNEL_NAME> -f channel.tx |
| 274 | +
|
| 275 | +So our command in its entirety would be: |
| 276 | + |
| 277 | +.. code:: bash |
| 278 | +
|
| 279 | + 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 |
| 280 | +
|
| 281 | +This command returns a genesis block - ``mychannel.block`` - which we will use |
| 282 | +to join the channel. |
| 283 | + |
| 284 | +Environment variables |
| 285 | +~~~~~~~~~~~~~~~~~~~~~ |
| 286 | + |
| 287 | +You can see the syntax for all commands by inspecting the ``script.sh`` file in the ``scripts`` directory. |
| 288 | + |
| 289 | +For the following cli commands against ``PEER0`` to work, we need to set the |
| 290 | +values for the four global environment variables given below. Please make sure to override |
| 291 | +the values accordingly when calling commands against other peers and the orderer. |
| 292 | + |
| 293 | +.. code:: bash |
| 294 | +
|
| 295 | + # Environment variables for PEER0 |
| 296 | + CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com |
| 297 | + CORE_PEER_ADDRESS=peer0.org1.example.com:7051 |
| 298 | + CORE_PEER_LOCALMSPID="Org0MSP" |
| 299 | + 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 |
| 300 | +
|
| 301 | +These environment variables for each peer are defined in the supplied docker-compose file. |
| 302 | + |
| 303 | +.. note:: In these examples, we are using the default ``mychannel`` for all CHANNEL_NAME arguments. |
| 304 | + If you elect to create a uniquely named channel, be conscious to modify |
| 305 | + your strings accordingly. |
| 306 | + |
| 307 | +Join channel |
| 308 | +^^^^^^^^^^^^ |
| 309 | + |
| 310 | +Now let's join ``PEER0`` to the channel by passing in the genesis block that was |
| 311 | +just returned to us upon the create channel command. |
| 312 | + |
| 313 | +The syntax is as follows: |
| 314 | + |
| 315 | +.. code:: bash |
| 316 | +
|
| 317 | + peer channel join -b <CHANNEL_NAME>.block |
| 318 | +
|
| 319 | +Remember, we need to pass the four global variables. So this command in its |
| 320 | +entirety would be: |
| 321 | + |
| 322 | +.. code:: bash |
| 323 | +
|
| 324 | + 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 |
| 325 | +
|
| 326 | +Install |
| 327 | +^^^^^^^ |
| 328 | + |
| 329 | +Now we will install the chaincode source onto the peer's filesystem. The syntax |
| 330 | +is as follows: |
| 331 | + |
| 332 | +.. code:: bash |
| 333 | +
|
| 334 | + peer chaincode install -n <CHAINCODE_NAME> -v <CHAINCODE_VERSION> -p <CHAINCODE_PATH> |
| 335 | +
|
| 336 | +This command in its entirety would be: |
| 337 | + |
| 338 | +.. code:: bash |
| 339 | +
|
| 340 | + 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 |
| 341 | +
|
| 342 | +Instantiate |
| 343 | +^^^^^^^^^^^ |
| 344 | + |
| 345 | +Now we start the chaincode container and initialize our key value pairs. The |
| 346 | +syntax for instantiate is as follows: |
| 347 | + |
| 348 | +.. code:: bash |
| 349 | +
|
| 350 | + peer chaincode instantiate -o <ORDERER_NAME>:7050 -C <CHANNEL_NAME> -n <CHAINCODE_NAME> -v <VERSION> -c '{"Args":["init","key","value"]}' -P "OR/AND (CHAINCODE_POLICY)" |
| 351 | +
|
| 352 | +Take note of the ``-P`` argument. This is our policy where we specify the |
| 353 | +required level of endorsement for a transaction against this chaincode to be |
| 354 | +validated. In the command below you'll notice that we specify our policy as |
| 355 | +``-P "OR ('Org0MSP.member','Org1MSP.member')"``. This means that we need |
| 356 | +"endorsement" from a peer belonging to Org0 **OR** Org1 (i.e. only one endorsement). |
| 357 | +If we changed the syntax to ``AND`` then we would need two endorsements. |
| 358 | + |
| 359 | +This command in its entirety would be: |
| 360 | + |
| 361 | +.. code:: bash |
| 362 | +
|
| 363 | + # we instantiate with the following key value pairs: "a","100","b","200" |
| 364 | + 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')" |
| 365 | +
|
| 366 | +.. note:: The above command will only start a single chaincode container. If |
| 367 | + you want to interact with different peers, you must first install |
| 368 | + the source code onto that peer's filesystem. You can then send |
| 369 | + an invoke or query to the peer. You needn't instantiate twice, this |
| 370 | + command will propagate to the entire channel. |
| 371 | + |
| 372 | +Query |
| 373 | +^^^^^ |
| 374 | + |
| 375 | +Lets query for the value of "a" to make sure the chaincode was properly instantiated |
| 376 | +and the state DB was populated. The syntax for query is as follows: |
| 377 | + |
| 378 | +.. code:: bash |
| 379 | +
|
| 380 | + peer chaincode query -C <CHANNEL_NAME> -n <CHAINCODE_NAME> -c '{"Args":["query","key"]}' |
| 381 | +
|
| 382 | +This command in its entirety would be: |
| 383 | + |
| 384 | +.. code:: bash |
| 385 | +
|
| 386 | + 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"]}' |
| 387 | +
|
| 388 | +Invoke |
| 389 | +^^^^^^ |
| 390 | + |
| 391 | +Lastly we will move "10" from "a" to "b". This transaction will cut a new block |
| 392 | +and update the state DB. The syntax for invoke is as follows: |
| 393 | + |
| 394 | +.. code:: bash |
| 395 | +
|
| 396 | + peer chaincode invoke -o <ORDERER_NAME>:7050 -C <CHANNEL_NAME> -n <CHAINCODE_NAME> -c '{"Args":["invoke","key","key","value"]}' |
| 397 | +
|
| 398 | +This command in its entirety would be: |
| 399 | + |
| 400 | +.. code:: bash |
| 401 | +
|
| 402 | + 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"]}' |
| 403 | +
|
| 404 | +Query |
| 405 | +^^^^^ |
| 406 | + |
| 407 | +Lets confirm that our previous invocation executed properly. We initialized the |
| 408 | +key "a" with a value of "100". Therefore, removing "10" should return a value |
| 409 | +of "90" when we query "a". The syntax for query is outlined above. |
| 410 | + |
| 411 | +.. code:: bash |
| 412 | +
|
| 413 | +This query command in its entirety would be: |
| 414 | + |
| 415 | + 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"]}' |
| 416 | + |
| 417 | +Start the network (TLS enabled) |
| 418 | +------------------------------ |
| 419 | + |
| 420 | +Use the ``script.sh`` to see the exact syntax for TLS-enabled CLI commands. |
| 421 | + |
| 422 | +Before starting, we need to modify our docker-compose file to reflect the appropriate private keys for |
| 423 | +the orderer and peers. |
| 424 | + |
| 425 | +From your ``e2e`` directory execute the following: |
| 426 | + |
| 427 | +.. code:: bash |
| 428 | +
|
| 429 | + 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 |
| 430 | + 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 |
| 431 | + 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 |
| 432 | + 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 |
| 433 | + 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 |
| 434 | +
|
| 435 | +These commands will modify the TLS_KEY_FILE variables in your docker-compose. |
| 436 | +Once you have executed all five commands, spin the network back up and begin |
| 437 | +by creating your channel. |
| 438 | + |
| 439 | +Scripts |
| 440 | +------- |
| 441 | + |
| 442 | +We exposed the verbosity of the commands in order to provide some edification |
| 443 | +on the underlying flow and the appropriate syntax. Entering the commands manually |
| 444 | +through the CLI is quite onerous, therefore we provide a few scripts to do the |
| 445 | +entirety of the heavy lifting. |
| 446 | + |
| 447 | +Clean up |
| 448 | +^^^^^^^^ |
| 449 | + |
| 450 | +Let's clean things up before continuing. First, kill your containers: |
| 451 | + |
| 452 | +.. code:: bash |
| 453 | +
|
| 454 | + docker rm -f $(docker ps -aq) |
| 455 | +
|
| 456 | +Next, execute a ``docker images`` command in your terminal to view the |
| 457 | +**chaincode** images. They will look similar to the following: |
| 458 | + |
| 459 | +.. code:: bash |
| 460 | +
|
| 461 | + REPOSITORY TAG IMAGE ID CREATED SIZE |
| 462 | + dev-peer3-mycc-1.0 latest 13f6c8b042c6 5 minutes ago 176 MB |
| 463 | + dev-peer0-mycc-1.0 latest e27456b2bd92 5 minutes ago 176 MB |
| 464 | + dev-peer2-mycc-1.0 latest 111098a7c98c 5 minutes ago 176 MB |
| 465 | +
|
| 466 | +Remove these images: |
| 467 | + |
| 468 | +.. code:: bash |
| 469 | +
|
| 470 | + docker rmi <IMAGE ID> <IMAGE ID> <IMAGE ID> |
| 471 | +
|
| 472 | +For example: |
| 473 | + |
| 474 | +.. code:: bash |
| 475 | +
|
| 476 | + docker rmi -f 13f e27 111 |
| 477 | +
|
| 478 | +Lastly, remove the `crypto-config`` folder and the two artifacts - ``channel.tx`` |
| 479 | +& ``orderer.block``. |
| 480 | + |
| 481 | +.. code:: bash |
| 482 | +
|
| 483 | + # from the e2e directory |
| 484 | + rm -rf channel.tx orderer.block crypto-config |
| 485 | +
|
| 486 | +All in one |
| 487 | +^^^^^^^^^^ |
| 488 | + |
| 489 | +This script will do it all for you! From the ``e2e`` directory: |
| 490 | + |
| 491 | +.. code:: bash |
| 492 | +
|
| 493 | + ./network_setup.sh up <channel_name> |
| 494 | +
|
| 495 | +.. note:: If you choose not to pass a channel_name value, then the default |
| 496 | + ``mychannel`` will be used. |
| 497 | + |
| 498 | +APIs only |
| 499 | +^^^^^^^^^ |
| 500 | + |
| 501 | +The other option is to manually generate your crypto material and configuration |
| 502 | +artifacts, and then use the embedded ``script.sh`` in the docker-compose files |
| 503 | +to drive your network. Make sure this script is not commented out in your |
| 504 | +CLI container. |
| 505 | + |
| 506 | +When the scripts complete successfully, you should see the following message |
| 507 | +in your terminal: |
| 508 | + |
| 509 | +.. code:: bash |
| 510 | +
|
| 511 | + ===================== Query on PEER3 on channel 'mychannel' is successful ===================== |
| 512 | +
|
| 513 | + ===================== All GOOD, End-2-End execution completed ===================== |
| 514 | +
|
| 515 | +Using CouchDB |
| 516 | +------------- |
| 517 | + |
| 518 | +The state database can be switched from the default (goleveldb) to CouchDB. |
| 519 | +The same chaincode functions are available with CouchDB, however, there is the |
| 520 | +added ability to perform rich and complex queries against the state database |
| 521 | +data content contingent upon the chaincode data being modeled as JSON. |
| 522 | + |
| 523 | +To use CouchDB instead of the default database (goleveldb), follow the same |
| 524 | +procedure in the **Prerequisites** section, and additionally perform the |
| 525 | +following two steps to enable the CouchDB containers and associate each peer |
| 526 | +container with a CouchDB container: |
| 527 | + |
| 528 | +- Make the CouchDB image. |
| 529 | + |
| 530 | +.. code:: bash |
| 531 | +
|
| 532 | + # make sure you are in the fabric directory |
| 533 | + make couchdb |
| 534 | +
|
| 535 | +- Open the ``release/samples/e2e/docker-compose.yaml`` and un-comment |
| 536 | + all commented statements relating to CouchDB containers and peer container |
| 537 | + use of CouchDB. These instructions are are also outlined in the |
| 538 | + same ``docker-compose.yaml`` file. Search the file for 'couchdb' (case insensitive) references. |
| 539 | + |
| 540 | +**chaincode_example02** should now work using CouchDB underneath. |
| 541 | + |
| 542 | +.. note:: If you choose to implement mapping of the fabric-couchdb container |
| 543 | + port to a host port, please make sure you are aware of the security |
| 544 | + implications. Mapping of the port in a development environment allows the |
| 545 | + visualization of the database via the CouchDB web interface (Fauxton). |
| 546 | + Production environments would likely refrain from implementing port mapping in |
| 547 | + order to restrict outside access to the CouchDB containers. |
| 548 | + |
| 549 | +You can use **chaincode_example02** chaincode against the CouchDB state database |
| 550 | +using the steps outlined above, however in order to exercise the query |
| 551 | +capabilities you will need to use a chaincode that has data modeled as JSON, |
| 552 | +(e.g. **marbles02**). You can locate the **marbles02** chaincode in the |
| 553 | +``release/samples/chaincodes/go`` directory. |
| 554 | + |
| 555 | +Install, instantiate, invoke, and query **marbles02** chaincode by following the |
| 556 | +same general steps outlined above for **chaincode_example02** in the |
| 557 | +**Manually execute transactions** section. After the **Join channel** step, use the |
| 558 | +following commands to interact with the **marbles02** chaincode: |
| 559 | + |
| 560 | +- Install and instantiate the chaincode on ``PEER0``: |
| 561 | + |
| 562 | +.. code:: bash |
| 563 | +
|
| 564 | + peer chaincode install -o orderer0:7050 -n marbles -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02 |
| 565 | + 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')" |
| 566 | +
|
| 567 | +- Create some marbles and move them around: |
| 568 | + |
| 569 | +.. code:: bash |
| 570 | +
|
| 571 | + 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"]}' |
| 572 | + 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"]}' |
| 573 | + 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"]}' |
| 574 | + 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"]}' |
| 575 | + 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"]}' |
| 576 | + 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"]}' |
| 577 | +
|
| 578 | +
|
| 579 | +- If you chose to activate port mapping, you can now view the state database |
| 580 | + through the CouchDB web interface (Fauxton) by opening a browser and |
| 581 | + navigating to one of the two URLs below. |
| 582 | + |
| 583 | + For containers running in a vagrant environment: |
| 584 | + |
| 585 | + ``http://localhost:15984/_utils`` |
| 586 | + |
| 587 | + For non-vagrant environment, use the port address that was mapped in CouchDB |
| 588 | + container specification: |
| 589 | + |
| 590 | + ``http://localhost:5984/_utils`` |
| 591 | + |
| 592 | + You should see a database named ``mychannel`` and the documents |
| 593 | + inside it. |
| 594 | + |
| 595 | +- You can run regular queries from the cli (e.g. reading ``marble2``): |
| 596 | + |
| 597 | +.. code:: bash |
| 598 | +
|
| 599 | + peer chaincode query -C mychannel -n marbles -c '{"Args":["readMarble","marble2"]}' |
| 600 | +
|
| 601 | +You should see the details of ``marble2``: |
| 602 | + |
| 603 | +.. code:: bash |
| 604 | +
|
| 605 | + Query Result: {"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50} |
| 606 | +
|
| 607 | +Retrieve the history of ``marble1``: |
| 608 | + |
| 609 | +.. code:: bash |
| 610 | +
|
| 611 | + peer chaincode query -C mychannel -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}' |
| 612 | +
|
| 613 | +You should see the transactions on ``marble1``: |
| 614 | + |
| 615 | +.. code:: bash |
| 616 | +
|
| 617 | + 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":}] |
| 618 | +
|
| 619 | +You can also perform rich queries on the data content, such as querying marble fields by owner ``jerry``: |
| 620 | + |
| 621 | +.. code:: bash |
| 622 | +
|
| 623 | + peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarblesByOwner","jerry"]}' |
| 624 | +
|
| 625 | +The output should display the two marbles owned by ``jerry``: |
| 626 | + |
| 627 | +.. code:: bash |
| 628 | +
|
| 629 | + 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}}] |
| 630 | +
|
| 631 | +Query by field ``owner`` where the value is ``jerry``: |
| 632 | + |
| 633 | +.. code:: bash |
| 634 | +
|
| 635 | + peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarbles","{\"selector\":{\"owner\":\"jerry\"}}"]}' |
| 636 | +
|
| 637 | +The output should display: |
| 638 | + |
| 639 | +.. code:: bash |
| 640 | +
|
| 641 | + 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}}] |
| 642 | +
|
| 643 | +A Note on Data Persistence |
| 644 | +-------------------------- |
| 645 | + |
| 646 | +If data persistence is desired on the peer container or the CouchDB container, |
| 647 | +one option is to mount a directory in the docker-host into a relevant directory |
| 648 | +in the container. For example, you may add the following two lines in |
| 649 | +the peer container specification in the ``docker-compose.yaml`` file: |
| 650 | + |
| 651 | +.. code:: bash |
| 652 | +
|
| 653 | + volumes: |
| 654 | + - /var/hyperledger/peer0:/var/hyperledger/production |
| 655 | +
|
| 656 | +
|
| 657 | +For the CouchDB container, you may add the following two lines in the CouchDB |
| 658 | +container specification: |
| 659 | + |
| 660 | +.. code:: bash |
| 661 | +
|
| 662 | + volumes: |
| 663 | + - /var/hyperledger/couchdb0:/opt/couchdb/data |
| 664 | +
|
| 665 | +
|
| 666 | +Troubleshooting |
| 667 | +--------------- |
| 668 | + |
| 669 | +- Ensure you clear the file system after each run |
| 670 | + |
| 671 | +- If you see docker errors, remove your containers and start again. |
| 672 | + |
| 673 | +.. code:: bash |
| 674 | +
|
| 675 | + docker rm -f $(docker ps -aq) |
| 676 | +
|
| 677 | +- If you elect to run the "All in one" option, be sure you have deleted your |
| 678 | + crypto directory and the two artifacts. |
| 679 | + |
| 680 | +- If you see the below error: |
| 681 | + |
| 682 | +.. code:: bash |
| 683 | +
|
| 684 | + 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) |
| 685 | +
|
| 686 | +You likely have chaincode images (e.g. ``dev-peer0-mycc-1.0`` or ``dev-peer1-mycc-1.0``) |
| 687 | +from prior runs. Remove them and try again. |
| 688 | + |
| 689 | +.. code:: bash |
| 690 | +
|
| 691 | + docker rmi -f $(docker images | grep peer[0-9]-peer[0-9] | awk '{print $3}') |
| 692 | +
|
| 693 | +- To cleanup the network, use the ``down`` option: |
| 694 | + |
| 695 | +.. code:: bash |
| 696 | +
|
| 697 | + ./network_setup.sh down |
| 698 | +
|
| 699 | +------------------------------------------------------------------------------- |