github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/docs/source/build_network.rst (about) 1 Building Your First Network 2 =========================== 3 4 .. note:: These instructions have been verified to work against the 5 version "1.0.3" tagged Docker images and the pre-compiled 6 setup utilities within the supplied tar file. If you run 7 these commands with images or tools from the current master 8 branch, it is possible that you will see configuration and panic 9 errors. 10 11 The build your first network (BYFN) scenario provisions a sample Hyperledger 12 Fabric network consisting of two organizations, each maintaining two peer 13 nodes, and a "solo" ordering service. 14 15 Install prerequisites 16 --------------------- 17 18 Before we begin, if you haven't already done so, you may wish to check that 19 you have all the :doc:`prereqs` installed on the platform(s) 20 on which you'll be developing blockchain applications and/or operating 21 Hyperledger Fabric. 22 23 You will also need to download and install the :doc:`samples`. You will notice 24 that there are a number of samples included in the ``fabric-samples`` 25 repository. We will be using the ``first-network`` sample. Let's open that 26 sub-directory now. 27 28 .. code:: bash 29 30 cd first-network 31 32 .. note:: The supplied commands in this documentation 33 **MUST** be run from your ``first-network`` sub-directory 34 of the ``fabric-samples`` repository clone. If you elect to run the 35 commands from a different location, the various provided scripts 36 will be unable to find the binaries. 37 38 Want to run it now? 39 ------------------- 40 41 We provide a fully annotated script - ``byfn.sh`` - that leverages these Docker 42 images to quickly bootstrap a Hyperledger Fabric network comprised of 4 peers 43 representing two different organizations, and an orderer node. It will also 44 launch a container to run a scripted execution that will join peers to a 45 channel, deploy and instantiate chaincode and drive execution of transactions 46 against the deployed chaincode. 47 48 Here's the help text for the ``byfn.sh`` script: 49 50 .. code:: bash 51 52 ./byfn.sh -h 53 Usage: 54 byfn.sh -m up|down|restart|generate [-c <channel name>] [-t <timeout>] 55 byfn.sh -h|--help (print this message) 56 -m <mode> - one of 'up', 'down', 'restart' or 'generate' 57 - 'up' - bring up the network with docker-compose up 58 - 'down' - clear the network with docker-compose down 59 - 'restart' - restart the network 60 - 'generate' - generate required certificates and genesis block 61 -c <channel name> - config name to use (defaults to "mychannel") 62 -t <timeout> - CLI timeout duration in microseconds (defaults to 10000) 63 64 Typically, one would first generate the required certificates and 65 genesis block, then bring up the network. e.g.: 66 67 byfn.sh -m generate -c <channelname> 68 byfn.sh -m up -c <channelname> 69 70 If you choose not to supply a channel name, then the 71 script will use a default name of ``mychannel``. The CLI timeout parameter 72 (specified with the -t flag) is an optional value; if you choose not to set 73 it, then your CLI container will exit upon conclusion of the script. 74 75 Generate Network Artifacts 76 ^^^^^^^^^^^^^^^^^^^^^^^^^^ 77 78 Ready to give it a go? Okay then! Execute the following command: 79 80 .. code:: bash 81 82 ./byfn.sh -m generate 83 84 You will see a brief description as to what will occur, along with a yes/no command line 85 prompt. Respond with a ``y`` to execute the described action. 86 87 .. code:: bash 88 89 Generating certs and genesis block for with channel 'mychannel' and CLI timeout of '10000' 90 Continue (y/n)?y 91 proceeding ... 92 /Users/xxx/dev/fabric-samples/bin/cryptogen 93 94 ########################################################## 95 ##### Generate certificates using cryptogen tool ######### 96 ########################################################## 97 org1.example.com 98 2017-06-12 21:01:37.334 EDT [bccsp] GetDefault -> WARN 001 Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP. 99 ... 100 101 /Users/xxx/dev/fabric-samples/bin/configtxgen 102 ########################################################## 103 ######### Generating Orderer Genesis block ############## 104 ########################################################## 105 2017-06-12 21:01:37.558 EDT [common/configtx/tool] main -> INFO 001 Loading configuration 106 2017-06-12 21:01:37.562 EDT [msp] getMspConfig -> INFO 002 intermediate certs folder not found at [/Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/intermediatecerts]. Skipping.: [stat /Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/intermediatecerts: no such file or directory] 107 ... 108 2017-06-12 21:01:37.588 EDT [common/configtx/tool] doOutputBlock -> INFO 00b Generating genesis block 109 2017-06-12 21:01:37.590 EDT [common/configtx/tool] doOutputBlock -> INFO 00c Writing genesis block 110 111 ################################################################# 112 ### Generating channel configuration transaction 'channel.tx' ### 113 ################################################################# 114 2017-06-12 21:01:37.634 EDT [common/configtx/tool] main -> INFO 001 Loading configuration 115 2017-06-12 21:01:37.644 EDT [common/configtx/tool] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx 116 2017-06-12 21:01:37.645 EDT [common/configtx/tool] doOutputChannelCreateTx -> INFO 003 Writing new channel tx 117 118 ################################################################# 119 ####### Generating anchor peer update for Org1MSP ########## 120 ################################################################# 121 2017-06-12 21:01:37.674 EDT [common/configtx/tool] main -> INFO 001 Loading configuration 122 2017-06-12 21:01:37.678 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update 123 2017-06-12 21:01:37.679 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update 124 125 ################################################################# 126 ####### Generating anchor peer update for Org2MSP ########## 127 ################################################################# 128 2017-06-12 21:01:37.700 EDT [common/configtx/tool] main -> INFO 001 Loading configuration 129 2017-06-12 21:01:37.704 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update 130 2017-06-12 21:01:37.704 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update 131 132 This first step generates all of the certificates and keys for all our various 133 network entities, the ``genesis block`` used to bootstrap the ordering service, 134 and a collection of configuration transactions required to configure a 135 :ref:`Channel`. 136 137 Bring Up the Network 138 ^^^^^^^^^^^^^^^^^^^^ 139 140 Next, you can bring the network up with the following command: 141 142 .. code:: bash 143 144 ./byfn.sh -m up 145 146 Once again, you will be prompted as to whether you wish to continue or abort. 147 Respond with a ``y``: 148 149 .. code:: bash 150 151 Starting with channel 'mychannel' and CLI timeout of '10000' 152 Continue (y/n)?y 153 proceeding ... 154 Creating network "net_byfn" with the default driver 155 Creating peer0.org1.example.com 156 Creating peer1.org1.example.com 157 Creating peer0.org2.example.com 158 Creating orderer.example.com 159 Creating peer1.org2.example.com 160 Creating cli 161 162 163 ____ _____ _ ____ _____ 164 / ___| |_ _| / \ | _ \ |_ _| 165 \___ \ | | / _ \ | |_) | | | 166 ___) | | | / ___ \ | _ < | | 167 |____/ |_| /_/ \_\ |_| \_\ |_| 168 169 Channel name : mychannel 170 Creating channel... 171 172 The logs will continue from there. This will launch all of the containers, and 173 then drive a complete end-to-end application scenario. Upon successful 174 completion, it should report the following in your terminal window: 175 176 .. code:: bash 177 178 2017-05-16 17:08:01.366 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP 179 2017-05-16 17:08:01.366 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity 180 2017-05-16 17:08:01.366 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08F1E3ECC80510...6D7963631A0A0A0571756572790A0161 181 2017-05-16 17:08:01.367 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: E61DB37F4E8B0D32C9FE10E3936BA9B8CD278FAA1F3320B08712164248285C54 182 Query Result: 90 183 2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting..... 184 ===================== Query on PEER3 on channel 'mychannel' is successful ===================== 185 186 ===================== All GOOD, BYFN execution completed ===================== 187 188 189 _____ _ _ ____ 190 | ____| | \ | | | _ \ 191 | _| | \| | | | | | 192 | |___ | |\ | | |_| | 193 |_____| |_| \_| |____/ 194 195 You can scroll through these logs to see the various transactions. If you don't 196 get this result, then jump down to the :ref:`Troubleshoot` section and let's see 197 whether we can help you discover what went wrong. 198 199 Bring Down the Network 200 ^^^^^^^^^^^^^^^^^^^^^^ 201 202 Finally, let's bring it all down so we can explore the network setup one step 203 at a time. The following will kill your containers, remove the crypto material 204 and four artifacts, and delete the chaincode images from your Docker Registry: 205 206 .. code:: bash 207 208 ./byfn.sh -m down 209 210 Once again, you will be prompted to continue, respond with a ``y``: 211 212 .. code:: bash 213 214 Stopping with channel 'mychannel' and CLI timeout of '10000' 215 Continue (y/n)?y 216 proceeding ... 217 WARNING: The CHANNEL_NAME variable is not set. Defaulting to a blank string. 218 WARNING: The TIMEOUT variable is not set. Defaulting to a blank string. 219 Removing network net_byfn 220 468aaa6201ed 221 ... 222 Untagged: dev-peer1.org2.example.com-mycc-1.0:latest 223 Deleted: sha256:ed3230614e64e1c83e510c0c282e982d2b06d148b1c498bbdcc429e2b2531e91 224 ... 225 226 If you'd like to learn more about the underlying tooling and bootstrap mechanics, 227 continue reading. In these next sections we'll walk through the various steps 228 and requirements to build a fully-functional Hyperledger Fabric network. 229 230 Crypto Generator 231 ---------------- 232 233 We will use the ``cryptogen`` tool to generate the cryptographic material 234 (x509 certs) for our various network entities. These certificates are 235 representative of identities, and they allow for sign/verify authentication to 236 take place as our entities communicate and transact. 237 238 How does it work? 239 ^^^^^^^^^^^^^^^^^ 240 241 Cryptogen consumes a file - ``crypto-config.yaml`` - that contains the network 242 topology and allows us to generate a set of certificates and keys for both the 243 Organizations and the components that belong to those Organizations. Each 244 Organization is provisioned a unique root certificate (``ca-cert``) that binds 245 specific components (peers and orderers) to that Org. By assigning each 246 Organization a unique CA certificate, we are mimicking a typical network where 247 a participating :ref:`Member` would use its own Certificate Authority. 248 Transactions and communications within Hyperledger Fabric are signed by an 249 entity's private key (``keystore``), and then verified by means of a public 250 key (``signcerts``). 251 252 You will notice a ``count`` variable within this file. We use this to specify 253 the number of peers per Organization; in our case there are two peers per Org. 254 We won't delve into the minutiae of `x.509 certificates and public key 255 infrastructure <https://en.wikipedia.org/wiki/Public_key_infrastructure>`__ 256 right now. If you're interested, you can peruse these topics on your own time. 257 258 Before running the tool, let's take a quick look at a snippet from the 259 ``crypto-config.yaml``. Pay specific attention to the "Name", "Domain" 260 and "Specs" parameters under the ``OrdererOrgs`` header: 261 262 .. code:: bash 263 264 OrdererOrgs: 265 #--------------------------------------------------------- 266 # Orderer 267 # -------------------------------------------------------- 268 - Name: Orderer 269 Domain: example.com 270 CA: 271 Country: US 272 Province: California 273 Locality: San Francisco 274 # OrganizationalUnit: Hyperledger Fabric 275 # StreetAddress: address for org # default nil 276 # PostalCode: postalCode for org # default nil 277 # ------------------------------------------------------ 278 # "Specs" - See PeerOrgs below for complete description 279 # ----------------------------------------------------- 280 Specs: 281 - Hostname: orderer 282 # ------------------------------------------------------- 283 # "PeerOrgs" - Definition of organizations managing peer nodes 284 # ------------------------------------------------------ 285 PeerOrgs: 286 # ----------------------------------------------------- 287 # Org1 288 # ---------------------------------------------------- 289 - Name: Org1 290 Domain: org1.example.com 291 292 The naming convention for a network entity is as follows - 293 "{{.Hostname}}.{{.Domain}}". So using our ordering node as a 294 reference point, we are left with an ordering node named - 295 ``orderer.example.com`` that is tied to an MSP ID of ``Orderer``. This file 296 contains extensive documentation on the definitions and syntax. You can also 297 refer to the :doc:`msp` documentation for a deeper dive on MSP. 298 299 After we run the ``cryptogen`` tool, the generated certificates and keys will be 300 saved to a folder titled ``crypto-config``. 301 302 Configuration Transaction Generator 303 ----------------------------------- 304 305 The ``configtxgen tool`` is used to create four configuration artifacts: 306 307 * orderer ``genesis block``, 308 * channel ``configuration transaction``, 309 * and two ``anchor peer transactions`` - one for each Peer Org. 310 311 Please see :doc:`configtxgen` for a complete description of the use of this 312 tool. 313 314 The orderer block is the :ref:`Genesis-Block` for the ordering service, and the 315 channel transaction file is broadcast to the orderer at :ref:`Channel` creation 316 time. The anchor peer transactions, as the name might suggest, specify each 317 Org's :ref:`Anchor-Peer` on this channel. 318 319 How does it work? 320 ^^^^^^^^^^^^^^^^^ 321 322 Configtxgen consumes a file - ``configtx.yaml`` - that contains the definitions 323 for the sample network. There are three members - one Orderer Org (``OrdererOrg``) 324 and two Peer Orgs (``Org1`` & ``Org2``) each managing and maintaining two peer nodes. 325 This file also specifies a consortium - ``SampleConsortium`` - consisting of our 326 two Peer Orgs. Pay specific attention to the "Profiles" section at the top of 327 this file. You will notice that we have two unique headers. One for the orderer genesis 328 block - ``TwoOrgsOrdererGenesis`` - and one for our channel - ``TwoOrgsChannel``. 329 330 These headers are important, as we will pass them in as arguments when we create 331 our artifacts. 332 333 .. note:: Notice that our ``SampleConsortium`` is defined in 334 the system-level profile and then referenced by 335 our channel-level profile. Channels exist within 336 the purview of a consortium, and all consortia 337 must be defined in the scope of the network at 338 large. 339 340 This file also contains two additional specifications that are worth 341 noting. Firstly, we specify the anchor peers for each Peer Org 342 (``peer0.org1.example.com`` & ``peer0.org2.example.com``). Secondly, we point to 343 the location of the MSP directory for each member, in turn allowing us to store the 344 root certificates for each Org in the orderer genesis block. This is a critical 345 concept. Now any network entity communicating with the ordering service can have 346 its digital signature verified. 347 348 Run the tools 349 ------------- 350 351 You can manually generate the certificates/keys and the various configuration 352 artifacts using the ``configtxgen`` and ``cryptogen`` commands. Alternately, 353 you could try to adapt the byfn.sh script to accomplish your objectives. 354 355 Manually generate the artifacts 356 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 357 358 You can refer to the ``generateCerts`` function in the byfn.sh script for the 359 commands necessary to generate the certificates that will be used for your 360 network configuration as defined in the ``crypto-config.yaml`` file. However, 361 for the sake of convenience, we will also provide a reference here. 362 363 First let's run the ``cryptogen`` tool. Our binary is in the ``bin`` 364 directory, so we need to provide the relative path to where the tool resides. 365 366 .. code:: bash 367 368 ../bin/cryptogen generate --config=./crypto-config.yaml 369 370 You will likely see the following warning. It's innocuous, ignore it: 371 372 .. code:: bash 373 374 [bccsp] GetDefault -> WARN 001 Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP. 375 376 Next, we need to tell the ``configtxgen`` tool where to look for the 377 ``configtx.yaml`` file that it needs to ingest. We will tell it look in our 378 present working directory: 379 380 First, we need to set an environment variable to specify where ``configtxgen`` 381 should look for the configtx.yaml configuration file: 382 383 .. code:: bash 384 385 export FABRIC_CFG_PATH=$PWD 386 387 Then, we'll invoke the ``configtxgen`` tool which will create the orderer genesis block: 388 389 .. code:: bash 390 391 ../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block 392 393 You can ignore the log warnings regarding intermediate certificates, certificate 394 revocation lists (crls) and MSP configurations. We are not using any of those 395 in this sample network. 396 397 .. code: bash 398 399 2017-06-12 21:01:37.562 EDT [msp] getMspConfig -> INFO 002 intermediate certs folder not found at [/Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/intermediatecerts]. Skipping.: [stat /Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/intermediatecerts: no such file or directory] 400 2017-06-12 21:01:37.562 EDT [msp] getMspConfig -> INFO 003 crls folder not found at [/Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/intermediatecerts]. Skipping.: [stat /Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/crls: no such file or directory] 401 2017-06-12 21:01:37.562 EDT [msp] getMspConfig -> INFO 004 MSP configuration file not found at [/Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/config.yaml]: [stat /Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/config.yaml: no such file or directory] 402 403 .. _createchanneltx: 404 405 Create a Channel Configuration Transaction 406 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 407 408 Next, we need to create the channel transaction artifact. Be sure to replace $CHANNEL_NAME or 409 set CHANNEL_NAME as an environment variable that can be used throughout these instructions: 410 411 .. code:: bash 412 413 export CHANNEL_NAME=mychannel 414 415 # this file contains the definitions for our sample channel 416 ../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME 417 418 Next, we will define the anchor peer for Org1 on the channel that we are 419 constructing. Again, be sure to replace $CHANNEL_NAME or set the environment variable 420 for the following commands: 421 422 .. code:: bash 423 424 ../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP 425 426 Now, we will define the anchor peer for Org2 on the same channel: 427 428 .. code:: bash 429 430 ../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP 431 432 Start the network 433 ----------------- 434 435 We will leverage a docker-compose script to spin up our network. The 436 docker-compose file references the images that we have previously downloaded, 437 and bootstraps the orderer with our previously generated ``genesis.block``. 438 439 .. note: Before launching the network, open the ``docker-compose-cli.yaml`` file 440 and comment out the script.sh in the CLI container. Your docker-compose 441 should be modified to look like this: 442 443 .. code:: bash 444 445 working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer 446 # command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT' 447 volumes 448 449 If left uncommented, that script will exercise all of the CLI commands when the 450 network is started, as we describe in the :ref:`behind-scenes` section. 451 However, we want to go through the commands manually in order 452 to expose the syntax and functionality of each call. 453 454 Pass in a moderately high value for the ``TIMEOUT`` variable (specified in seconds); 455 otherwise the CLI container, by default, will exit after 60 seconds. 456 457 Start your network: 458 459 .. code:: bash 460 461 CHANNEL_NAME=$CHANNEL_NAME TIMEOUT=<pick_a_value> docker-compose -f docker-compose-cli.yaml up -d 462 463 If you want to see the realtime logs for your network, then do not supply the ``-d`` flag. 464 If you let the logs stream, then you will need to open a second terminal to execute the CLI calls. 465 466 .. _peerenvvars:: 467 468 Environment variables 469 ^^^^^^^^^^^^^^^^^^^^^ 470 471 For the following CLI commands against ``peer0.org1.example.com`` to work, we need 472 to preface our commands with the four environment variables given below. These 473 variables for ``peer0.org1.example.com`` are baked into the CLI container, 474 therefore we can operate without passing them. **HOWEVER**, if you want to send 475 calls to other peers or the orderer, then you will need to provide these 476 values accordingly. Inspect the ``docker-compose-base.yaml`` for the specific 477 paths: 478 479 .. code:: bash 480 481 # Environment variables for PEER0 482 483 CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 484 CORE_PEER_ADDRESS=peer0.org1.example.com:7051 485 CORE_PEER_LOCALMSPID="Org1MSP" 486 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 487 488 .. _createandjoin: 489 490 Create & Join Channel 491 ^^^^^^^^^^^^^^^^^^^^^ 492 493 Recall that we created the channel configuration transaction using the 494 ``configtxgen`` tool in the :ref:`createchanneltx` section, above. You can 495 repeat that process to create additional channel configuration transactions, 496 using the same or different profiles in the ``configtx.yaml`` that you pass 497 to the ``configtxgen`` tool. Then you can repeat the process defined in this 498 section to establish those other channels in your network. 499 500 We will enter the CLI container using the ``docker exec`` command: 501 502 .. code:: bash 503 504 docker exec -it cli bash 505 506 If successful you should see the following: 507 508 .. code:: bash 509 510 root@0d78bb69300d:/opt/gopath/src/github.com/hyperledger/fabric/peer# 511 512 Next, we are going to pass in the generated channel configuration transaction 513 artifact that we created in the :ref:`createchanneltx` section (we called 514 it ``channel.tx``) to the orderer as part of the create channel request. 515 516 We specify our channel name with the ``-c`` flag and our channel configuration 517 transaction with the ``-f`` flag. In this case it is ``channel.tx``, however 518 you can mount your own configuration transaction with a different name. 519 520 .. code:: bash 521 522 export CHANNEL_NAME=mychannel 523 524 # the channel.tx file is mounted in the channel-artifacts directory within your CLI container 525 # as a result, we pass the full path for the file 526 # we also pass the path for the orderer ca-cert in order to verify the TLS handshake 527 # be sure to replace the $CHANNEL_NAME variable appropriately 528 529 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/tlscacerts/tlsca.example.com-cert.pem 530 531 .. note:: Notice the ``-- cafile`` that we pass as part of this command. It is 532 the local path to the orderer's root cert, allowing us to verify the 533 TLS handshake. 534 535 This command returns a genesis block - ``<channel-ID.block>`` - which we will use to join the channel. 536 It contains the configuration information specified in ``channel.tx``. 537 538 .. note:: You will remain in the CLI container for the remainder of 539 these manual commands. You must also remember to preface all commands 540 with the corresponding environment variables when targeting a peer other than 541 ``peer0.org1.example.com``. 542 543 Now let's join ``peer0.org1.example.com`` to the channel. 544 545 .. code:: bash 546 547 # By default, this joins ``peer0.org1.example.com`` only 548 # the <channel-ID.block> was returned by the previous command 549 550 peer channel join -b <channel-ID.block> 551 552 You can make other peers join the channel as necessary by making appropriate 553 changes in the four environment variables we used in the :ref:`peerenvvars` 554 section, above. 555 556 Install & Instantiate Chaincode 557 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 558 559 .. note:: We will utilize a simple existing chaincode. To learn how to write 560 your own chaincode, see the :doc:`chaincode4ade` tutorial. 561 562 Applications interact with the blockchain ledger through ``chaincode``. As 563 such we need to install the chaincode on every peer that will execute and 564 endorse our transactions, and then instantiate the chaincode on the channel. 565 566 First, install the sample Go code onto one of the four peer nodes. This command 567 places the source code onto our peer's filesystem. 568 569 .. code:: bash 570 571 peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 572 573 Next, instantiate the chaincode on the channel. This will initialize the 574 chaincode on the channel, set the endorsement policy for the chaincode, and 575 launch a chaincode container for the targeted peer. Take note of the ``-P`` 576 argument. This is our policy where we specify the required level of endorsement 577 for a transaction against this chaincode to be validated. 578 579 In the command below you’ll notice that we specify our policy as 580 ``-P "OR ('Org0MSP.member','Org1MSP.member')"``. This means that we need 581 “endorsement” from a peer belonging to Org1 **OR** Org2 (i.e. only one endorsement). 582 If we changed the syntax to ``AND`` then we would need two endorsements. 583 584 .. code:: bash 585 586 # be sure to replace the $CHANNEL_NAME environment variable 587 # if you did not install your chaincode with a name of mycc, then modify that argument as well 588 589 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/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')" 590 591 See the `endorsement 592 policies <http://hyperledger-fabric.readthedocs.io/en/latest/endorsement-policies.html>`__ 593 documentation for more details on policy implementation. 594 595 Query 596 ^^^^^ 597 598 Let's query for the value of ``a`` to make sure the chaincode was properly 599 instantiated and the state DB was populated. The syntax for query is as follows: 600 601 .. code:: bash 602 603 # be sure to set the -C and -n flags appropriately 604 605 peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' 606 607 608 Invoke 609 ^^^^^^ 610 611 Now let's move ``10`` from ``a`` to ``b``. This transaction will cut a new block and 612 update the state DB. The syntax for invoke is as follows: 613 614 .. code:: bash 615 616 # be sure to set the -C and -n flags appropriately 617 618 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/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}' 619 620 Query 621 ^^^^^ 622 623 Let's confirm that our previous invocation executed properly. We initialized the 624 key ``a`` with a value of ``100`` and just removed ``10`` with our previous 625 invocation. Therefore, a query against ``a`` should reveal ``90``. The syntax 626 for query is as follows. 627 628 .. code:: bash 629 630 # be sure to set the -C and -n flags appropriately 631 632 peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' 633 634 We should see the following: 635 636 .. code:: bash 637 638 Query Result: 90 639 640 Feel free to start over and manipulate the key value pairs and subsequent 641 invocations. 642 643 .. _behind-scenes: 644 645 What's happening behind the scenes? 646 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 647 648 .. note:: These steps describe the scenario in which 649 ``script.sh`` is not commented out in the 650 docker-compose-cli.yaml file. Clean your network 651 with ``./byfn.sh -m down`` and ensure 652 this command is active. Then use the same 653 docker-compose prompt to launch your network again 654 655 - A script - ``script.sh`` - is baked inside the CLI container. The 656 script drives the ``createChannel`` command against the supplied channel name 657 and uses the channel.tx file for channel configuration. 658 659 - The output of ``createChannel`` is a genesis block - 660 ``<your_channel_name>.block`` - which gets stored on the peers' file systems and contains 661 the channel configuration specified from channel.tx. 662 663 - The ``joinChannel`` command is exercised for all four peers, which takes as 664 input the previously generated genesis block. This command instructs the 665 peers to join ``<your_channel_name>`` and create a chain starting with ``<your_channel_name>.block``. 666 667 - Now we have a channel consisting of four peers, and two 668 organizations. This is our ``TwoOrgsChannel`` profile. 669 670 - ``peer0.org1.example.com`` and ``peer1.org1.example.com`` belong to Org1; 671 ``peer0.org2.example.com`` and ``peer1.org2.example.com`` belong to Org2 672 673 - These relationships are defined through the ``crypto-config.yaml`` and 674 the MSP path is specified in our docker compose. 675 676 - The anchor peers for Org1MSP (``peer0.org1.example.com``) and 677 Org2MSP (``peer0.org2.example.com``) are then updated. We do this by passing 678 the ``Org1MSPanchors.tx`` and ``Org2MSPanchors.tx`` artifacts to the ordering 679 service along with the name of our channel. 680 681 - A chaincode - **chaincode_example02** - is installed on ``peer0.org1.example.com`` and 682 ``peer0.org2.example.com`` 683 684 - The chaincode is then "instantiated" on ``peer0.org2.example.com``. Instantiation 685 adds the chaincode to the channel, starts the container for the target peer, 686 and initializes the key value pairs associated with the chaincode. The initial 687 values for this example are ["a","100" "b","200"]. This "instantiation" results 688 in a container by the name of ``dev-peer0.org2.example.com-mycc-1.0`` starting. 689 690 - The instantiation also passes in an argument for the endorsement 691 policy. The policy is defined as 692 ``-P "OR ('Org1MSP.member','Org2MSP.member')"``, meaning that any 693 transaction must be endorsed by a peer tied to Org1 or Org2. 694 695 - A query against the value of "a" is issued to ``peer0.org1.example.com``. The 696 chaincode was previously installed on ``peer0.org1.example.com``, so this will start 697 a container for Org1 peer0 by the name of ``dev-peer0.org1.example.com-mycc-1.0``. The result 698 of the query is also returned. No write operations have occurred, so 699 a query against "a" will still return a value of "100". 700 701 - An invoke is sent to ``peer0.org1.example.com`` to move "10" from "a" to "b" 702 703 - The chaincode is then installed on ``peer1.org2.example.com`` 704 705 - A query is sent to ``peer1.org2.example.com`` for the value of "a". This starts a 706 third chaincode container by the name of ``dev-peer1.org2.example.com-mycc-1.0``. A 707 value of 90 is returned, correctly reflecting the previous 708 transaction during which the value for key "a" was modified by 10. 709 710 What does this demonstrate? 711 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 712 713 Chaincode **MUST** be installed on a peer in order for it to 714 successfully perform read/write operations against the ledger. 715 Furthermore, a chaincode container is not started for a peer until an ``init`` or 716 traditional transaction - read/write - is performed against that chaincode (e.g. query for 717 the value of "a"). The transaction causes the container to start. Also, 718 all peers in a channel maintain an exact copy of the ledger which 719 comprises the blockchain to store the immutable, sequenced record in 720 blocks, as well as a state database to maintain a snapshot of the current state. 721 This includes those peers that do not have chaincode installed on them 722 (like ``peer1.org1.example.com`` in the above example) . Finally, the chaincode is accessible 723 after it is installed (like ``peer1.org2.example.com`` in the above example) because it 724 has already been instantiated. 725 726 How do I see these transactions? 727 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 728 729 Check the logs for the CLI Docker container. 730 731 .. code:: bash 732 733 docker logs -f cli 734 735 You should see the following output: 736 737 .. code:: bash 738 739 2017-05-16 17:08:01.366 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP 740 2017-05-16 17:08:01.366 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity 741 2017-05-16 17:08:01.366 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08F1E3ECC80510...6D7963631A0A0A0571756572790A0161 742 2017-05-16 17:08:01.367 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: E61DB37F4E8B0D32C9FE10E3936BA9B8CD278FAA1F3320B08712164248285C54 743 Query Result: 90 744 2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting..... 745 ===================== Query on PEER3 on channel 'mychannel' is successful ===================== 746 747 ===================== All GOOD, BYFN execution completed ===================== 748 749 750 _____ _ _ ____ 751 | ____| | \ | | | _ \ 752 | _| | \| | | | | | 753 | |___ | |\ | | |_| | 754 |_____| |_| \_| |____/ 755 756 You can scroll through these logs to see the various transactions. 757 758 How can I see the chaincode logs? 759 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 760 761 Inspect the individual chaincode containers to see the separate 762 transactions executed against each container. Here is the combined 763 output from each container: 764 765 .. code:: bash 766 767 $ docker logs dev-peer0.org2.example.com-mycc-1.0 768 04:30:45.947 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW] 769 ex02 Init 770 Aval = 100, Bval = 200 771 772 $ docker logs dev-peer0.org1.example.com-mycc-1.0 773 04:31:10.569 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW] 774 ex02 Invoke 775 Query Response:{"Name":"a","Amount":"100"} 776 ex02 Invoke 777 Aval = 90, Bval = 210 778 779 $ docker logs dev-peer1.org2.example.com-mycc-1.0 780 04:31:30.420 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW] 781 ex02 Invoke 782 Query Response:{"Name":"a","Amount":"90"} 783 784 Understanding the Docker Compose topology 785 ----------------------------------------- 786 787 The BYFN sample offers us two flavors of Docker Compose files, both of which 788 are extended from the ``docker-compose-base.yaml`` (located in the ``base`` 789 folder). Our first flavor, ``docker-compose-cli.yaml``, provides us with a 790 CLI container, along with an orderer, four peers. We use this file 791 for the entirety of the instructions on this page. 792 793 .. note:: the remainder of this section covers a docker-compose file designed for the 794 SDK. Refer to the `Node SDK <https://github.com/hyperledger/fabric-sdk-node>`__ 795 repo for details on running these tests. 796 797 The second flavor, ``docker-compose-e2e.yaml``, is constructed to run end-to-end tests 798 using the Node.js SDK. Aside from functioning with the SDK, its primary differentiation 799 is that there are containers for the fabric-ca servers. As a result, we are able 800 to send REST calls to the organizational CAs for user registration and enrollment. 801 802 If you want to use the ``docker-compose-e2e.yaml`` without first running the 803 byfn.sh script, then we will need to make four slight modifications. 804 We need to point to the private keys for our Organization's CA's. You can locate 805 these values in your crypto-config folder. For example, to locate the private 806 key for Org1 we would follow this path - ``crypto-config/peerOrganizations/org1.example.com/ca/``. 807 The private key is a long hash value followed by ``_sk``. The path for Org2 808 would be - ``crypto-config/peerOrganizations/org2.example.com/ca/``. 809 810 In the ``docker-compose-e2e.yaml`` update the FABRIC_CA_SERVER_TLS_KEYFILE variable 811 for ca0 and ca1. You also need to edit the path that is provided in the command 812 to start the ca server. You are providing the same private key twice for each 813 CA container. 814 815 Using CouchDB 816 ------------- 817 818 The state database can be switched from the default (goleveldb) to CouchDB. 819 The same chaincode functions are available with CouchDB, however, there is the 820 added ability to perform rich and complex queries against the state database 821 data content contingent upon the chaincode data being modeled as JSON. 822 823 To use CouchDB instead of the default database (goleveldb), follow the same 824 procedures outlined earlier for generating the artifacts, except when starting 825 the network pass ``docker-compose-couch.yaml`` as well: 826 827 .. code:: bash 828 829 CHANNEL_NAME=$CHANNEL_NAME TIMEOUT=<pick_a_value> docker-compose -f docker-compose-cli.yaml -f docker-compose-couch.yaml up -d 830 831 **chaincode_example02** should now work using CouchDB underneath. 832 833 .. note:: If you choose to implement mapping of the fabric-couchdb container 834 port to a host port, please make sure you are aware of the security 835 implications. Mapping of the port in a development environment makes the 836 CouchDB REST API available, and allows the 837 visualization of the database via the CouchDB web interface (Fauxton). 838 Production environments would likely refrain from implementing port mapping in 839 order to restrict outside access to the CouchDB containers. 840 841 You can use **chaincode_example02** chaincode against the CouchDB state database 842 using the steps outlined above, however in order to exercise the CouchDB query 843 capabilities you will need to use a chaincode that has data modeled as JSON, 844 (e.g. **marbles02**). You can locate the **marbles02** chaincode in the 845 ``fabric/examples/chaincode/go`` directory. 846 847 We will follow the same process to create and join the channel as outlined in the 848 :ref:`createandjoin` section above. Once you have joined your peer(s) to the 849 channel, use the following steps to interact with the **marbles02** chaincode: 850 851 - Install and instantiate the chaincode on ``peer0.org1.example.com``: 852 853 .. code:: bash 854 855 # be sure to modify the $CHANNEL_NAME variable accordingly for the instantiate command 856 857 peer chaincode install -n marbles -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02 858 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/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -v 1.0 -c '{"Args":["init"]}' -P "OR ('Org0MSP.member','Org1MSP.member')" 859 860 - Create some marbles and move them around: 861 862 .. code:: bash 863 864 # be sure to modify the $CHANNEL_NAME variable accordingly 865 866 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/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble1","blue","35","tom"]}' 867 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/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble2","red","50","tom"]}' 868 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/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble3","blue","70","tom"]}' 869 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/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["transferMarble","marble2","jerry"]}' 870 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/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["transferMarblesBasedOnColor","blue","jerry"]}' 871 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/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n marbles -c '{"Args":["delete","marble1"]}' 872 873 - If you chose to map the CouchDB ports in docker-compose, you can now view 874 the state database through the CouchDB web interface (Fauxton) by opening 875 a browser and navigating to the following URL: 876 877 ``http://localhost:5984/_utils`` 878 879 You should see a database named ``mychannel`` (or your unique channel name) and 880 the documents inside it. 881 882 .. note:: For the below commands, be sure to update the $CHANNEL_NAME variable appropriately. 883 884 You can run regular queries from the CLI (e.g. reading ``marble2``): 885 886 .. code:: bash 887 888 peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["readMarble","marble2"]}' 889 890 The output should display the details of ``marble2``: 891 892 .. code:: bash 893 894 Query Result: {"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50} 895 896 You can retrieve the history of a specific marble - e.g. ``marble1``: 897 898 .. code:: bash 899 900 peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}' 901 902 The output should display the transactions on ``marble1``: 903 904 .. code:: bash 905 906 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":}] 907 908 You can also perform rich queries on the data content, such as querying marble fields by owner ``jerry``: 909 910 .. code:: bash 911 912 peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesByOwner","jerry"]}' 913 914 The output should display the two marbles owned by ``jerry``: 915 916 .. code:: bash 917 918 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}}] 919 920 921 Why CouchDB 922 ------------- 923 CouchDB is a kind of NoSQL solution. It is a document oriented database where document fields are stored as key-value mpas. Fields can be either a simple key/value pair, list, or map. 924 In addition to keyed/composite-key/key-range queries which are supported by LevelDB, CouchDB also supports full data rich queries capability, such as non-key queries against the whole blockchain data, 925 since its data content is stored in JSON format and fully queryable. Therefore, CouchDB can meet chaincode, auditing, reporting requirements for many use cases that not supported by LevelDB. 926 927 CouchDB can also enhance the security for compliance and data protection in the blockchain. As it is able to implement field-level security through the filtering and masking of individual attributes within a transaction, and only authorizing the read-only permission if needed. 928 929 In addition, CouchDB falls into the AP-type (Availability and Partition Tolerance) of the CAP theorem. It uses a master-master replication model with ``Eventual Consistency``. 930 More information can be found on the 931 `Eventual Consistency page of the CouchDB documentation <http://docs.couchdb.org/en/latest/intro/consistency.html>`__. 932 However, under each fabric peer, there is no database replicas, writes to database are guaranteed consistent and durable (not ``Eventual Consistency``). 933 934 CouchDB is the first external pluggable state database for Fabric, and there could and should be other external database options. For example, IBM enables the relational database for its blockchain. 935 And the CP-type (Consistency and Partition Tolerance) databases may also in need, so as to enable data consistency without application level guarantee. 936 937 938 A Note on Data Persistence 939 -------------------------- 940 941 If data persistence is desired on the peer container or the CouchDB container, 942 one option is to mount a directory in the docker-host into a relevant directory 943 in the container. For example, you may add the following two lines in 944 the peer container specification in the ``docker-compose-base.yaml`` file: 945 946 .. code:: bash 947 948 volumes: 949 - /var/hyperledger/peer0:/var/hyperledger/production 950 951 For the CouchDB container, you may add the following two lines in the CouchDB 952 container specification: 953 954 .. code:: bash 955 956 volumes: 957 - /var/hyperledger/couchdb0:/opt/couchdb/data 958 959 .. _Troubleshoot: 960 961 Troubleshooting 962 --------------- 963 964 - Always start your network fresh. Use the following command 965 to remove artifacts, crypto, containers and chaincode images: 966 967 .. code:: bash 968 969 ./byfn.sh -m down 970 971 .. note:: You **will** see errors if you do not remove old containers 972 and images. 973 974 - If you see Docker errors, first check your docker version (:doc:`prereqs`), 975 and then try restarting your Docker process. Problems with Docker are 976 oftentimes not immediately recognizable. For example, you may see errors 977 resulting from an inability to access crypto material mounted within a 978 container. 979 980 If they persist remove your images and start from scratch: 981 982 .. code:: bash 983 984 docker rm -f $(docker ps -aq) 985 docker rmi -f $(docker images -q) 986 987 - If you see errors on your create, instantiate, invoke or query commands, make 988 sure you have properly updated the channel name and chaincode name. There 989 are placeholder values in the supplied sample commands. 990 991 992 - If you see the below error: 993 994 .. code:: bash 995 996 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) 997 998 You likely have chaincode images (e.g. ``dev-peer1.org2.example.com-mycc-1.0`` or 999 ``dev-peer0.org1.example.com-mycc-1.0``) from prior runs. Remove them and try 1000 again. 1001 1002 .. code:: bash 1003 1004 docker rmi -f $(docker images | grep peer[0-9]-peer[0-9] | awk '{print $3}') 1005 1006 - If you see something similar to the following: 1007 1008 .. code:: bash 1009 1010 Error connecting: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure 1011 Error: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure 1012 1013 Make sure you are running your network against the "1.0.0" images that have 1014 been retagged as "latest". 1015 1016 - If you see the below error: 1017 1018 .. code:: bash 1019 1020 [configtx/tool/localconfig] Load -> CRIT 002 Error reading configuration: Unsupported Config Type "" 1021 panic: Error reading configuration: Unsupported Config Type "" 1022 1023 Then you did not set the ``FABRIC_CFG_PATH`` environment variable properly. The 1024 configtxgen tool needs this variable in order to locate the configtx.yaml. Go 1025 back and execute an ``export FABRIC_CFG_PATH=$PWD``, then recreate your 1026 channel artifacts. 1027 1028 - To cleanup the network, use the ``down`` option: 1029 1030 .. code:: bash 1031 1032 ./byfn.sh -m down 1033 1034 - If you see an error stating that you still have "active endpoints", then prune 1035 your Docker networks. This will wipe your previous networks and start you with a 1036 fresh environment: 1037 1038 .. code:: bash 1039 1040 docker network prune 1041 1042 You will see the following message: 1043 1044 .. code:: bash 1045 1046 WARNING! This will remove all networks not used by at least one container. 1047 Are you sure you want to continue? [y/N] 1048 1049 Select ``y``. 1050 1051 .. note:: If you continue to see errors, share your logs on the 1052 **fabric-questions** channel on 1053 `Hyperledger Rocket Chat <https://chat.hyperledger.org/home>`__ 1054 or on `StackOverflow <https://stackoverflow.com/questions/tagged/hyperledger-fabric>`__. 1055 1056 .. Licensed under Creative Commons Attribution 4.0 International License 1057 https://creativecommons.org/licenses/by/4.0/