github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/docs/source/tutorial/commercial_paper.md (about) 1 # Commercial paper tutorial 2 3 **Audience:** Architects, application and smart contract developers, 4 administrators 5 6 This tutorial will show you how to install and use a commercial paper sample 7 application and smart contract. It is a task-oriented topic, so it emphasizes 8 procedures above concepts. When you’d like to understand the concepts in more 9 detail, you can read the 10 [Developing Applications](../developapps/developing_applications.html) topic. 11 12  *In this tutorial 13 two organizations, MagnetoCorp and DigiBank, trade commercial paper with each 14 other using PaperNet, a Hyperledger Fabric blockchain network.* 15 16 Once you've set up the test network, you'll act as Isabella, an employee of 17 MagnetoCorp, who will issue a commercial paper on its behalf. You'll then switch 18 roles to take the role of Balaji, an employee of DigiBank, who will buy this 19 commercial paper, hold it for a period of time, and then redeem it with 20 MagnetoCorp for a small profit. 21 22 You'll act as a developer, end user, and administrator, each in different 23 organizations, performing the following steps designed to help you understand 24 what it's like to collaborate as two different organizations working 25 independently, but according to mutually agreed rules in a Hyperledger Fabric 26 network. 27 28 * [Set up machine](#prerequisites) and [download samples](#download-samples) 29 * [Create the network](#create-the-network) 30 * [Examine the commercial paper smart contract](#examine-the-commercial-paper-smart-contract) 31 * [Deploy the smart contract to the channel](#deploy-the-smart-contract-to-the-channel) 32 by approving the chaincode definition as MagnetoCorp and Digibank. 33 * Understand the structure of a MagnetoCorp [application](#application-structure), 34 including its [dependencies](#application-dependencies) 35 * Configure and use a [wallet and identities](#wallet) 36 * Run a MagnetoCorp application to [issue a commercial paper](#issue-application) 37 * Understand how DigiBank uses the smart contract in their [applications](#digibank-applications) 38 * As Digibank, run applications that 39 [buy](#buy-application) and [redeem](#redeem-application) commercial paper 40 41 This tutorial has been tested on MacOS and Ubuntu, and should work on other 42 Linux distributions. A Windows version is under development. 43 44 ## Prerequisites 45 46 Before you start, you must install some prerequisite technology required by the 47 tutorial. We've kept these to a minimum so that you can get going quickly. 48 49 You **must** have the following technologies installed: 50 51 * [**Node**](https://github.com/hyperledger/fabric-sdk-node#build-and-test) 52 The Node.js SDK README contains the up to date list of prerequisites. 53 54 You **will** find it helpful to install the following technologies: 55 56 * A source code editor, such as 57 [**Visual Studio Code**](https://code.visualstudio.com/) version 1.28, or 58 higher. VS Code will help you develop and test your application and smart 59 contract. Install VS Code [here](https://code.visualstudio.com/Download). 60 61 Many excellent code editors are available including 62 [Atom](https://atom.io/), [Sublime Text](http://www.sublimetext.com/) and 63 [Brackets](http://www.sublimetext.com/). 64 65 You **may** find it helpful to install the following technologies as you become 66 more experienced with application and smart contract development. There's no 67 requirement to install these when you first run the tutorial: 68 69 * [**Node Version Manager**](https://github.com/creationix/nvm). NVM helps you 70 easily switch between different versions of node -- it can be really helpful 71 if you're working on multiple projects at the same time. Install NVM 72 [here](https://github.com/creationix/nvm#installation). 73 74 ## Download samples 75 76 The commercial paper tutorial is one of the samples in the `fabric-samples` 77 repository. Before you begin this tutorial, ensure that you have followed the 78 instructions to install the Fabric [Prerequisites](../prereqs.html) and 79 [Download the Samples, Binaries and Docker Images](../install.html). 80 When you are finished, you will have cloned the `fabric-samples` repository that 81 contains the tutorial scripts, smart contract, and application files. 82 83  *Download the 84 `fabric-samples` GitHub repository to your local machine.* 85 86 After downloading, feel free to examine the directory structure of `fabric-samples`: 87 88 ``` 89 $ cd fabric-samples 90 $ ls 91 92 CODEOWNERS SECURITY.md first-network 93 CODE_OF_CONDUCT.md chaincode high-throughput 94 CONTRIBUTING.md chaincode-docker-devmode interest_rate_swaps 95 LICENSE ci off_chain_data 96 MAINTAINERS.md commercial-paper test-network 97 README.md fabcar 98 ``` 99 100 Notice the `commercial-paper` directory -- that's where our sample is located! 101 102 You've now completed the first stage of the tutorial! As you proceed, you'll 103 open multiple command windows for different users and components. For example: 104 105 * To show peer, orderer and CA log output from your network. 106 * To approve the chaincode as an administrator from MagnetoCorp and as an 107 administrator from DigiBank. 108 * To run applications on behalf of Isabella and Balaji, who will use the smart 109 contract to trade commercial paper with each other. 110 111 We'll make it clear when you should run a command from particular command 112 window; for example: 113 114 ``` 115 (isabella)$ ls 116 ``` 117 118 indicates that you should run the `ls` command from Isabella's window. 119 120 ## Create the network 121 122 This tutorial will deploy a smart contract using the Fabric test network. 123 The test network consists of two peer organizations and one ordering organization. 124 The two peer organizations operate one peer each, while the ordering organization 125 operates a single node Raft ordering service. We will also use the test network 126 to create a single channel named `mychannel` that both peer organizations 127 will be members of. 128 129  130 *The Fabric test network is comprised of two peer organizations, Org1 and Org2, 131 and one ordering organization. Each component runs as a Docker container.* 132 133 Each organization runs their own Certificate Authority. The two peers, the 134 [state databases](../ledger/ledger.html#world-state-database-options), the ordering service node, 135 and each organization CA each run in their own Docker container. In production 136 environments, organizations typically use existing CAs that are shared with other 137 systems; they're not dedicated to the Fabric network. 138 139 The two organizations of the test network allow us to interact with a blockchain 140 ledger as two organizations that operate separate peers. In this tutorial, 141 we will operate Org1 of the test network as DigiBank and Org2 as MagnetoCorp. 142 143 You can start the test network and create the channel with a script provided in 144 the commercial paper directory. Change to the `commercial-paper` directory in 145 the `fabric-samples`: 146 ``` 147 cd fabric-samples/commercial-paper 148 ``` 149 Then use the script to start the test network: 150 ``` 151 ./network-starter.sh 152 ``` 153 154 While the script is running, you will see logs of the test network being deployed. 155 When the script is complete, you can use the `docker ps` command to see the 156 Fabric nodes running on your local machine: 157 ``` 158 $ docker ps 159 160 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 161 a86f50ca1907 hyperledger/fabric-peer:latest "peer node start" About a minute ago Up About a minute 7051/tcp, 0.0.0.0:9051->9051/tcp peer0.org2.example.com 162 77d0fcaee61b hyperledger/fabric-peer:latest "peer node start" About a minute ago Up About a minute 0.0.0.0:7051->7051/tcp peer0.org1.example.com 163 7eb5f64bfe5f hyperledger/fabric-couchdb "tini -- /docker-ent…" About a minute ago Up About a minute 4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp couchdb0 164 2438df719f57 hyperledger/fabric-couchdb "tini -- /docker-ent…" About a minute ago Up About a minute 4369/tcp, 9100/tcp, 0.0.0.0:7984->5984/tcp couchdb1 165 03373d116c5a hyperledger/fabric-orderer:latest "orderer" About a minute ago Up About a minute 0.0.0.0:7050->7050/tcp orderer.example.com 166 6b4d87f65909 hyperledger/fabric-ca:latest "sh -c 'fabric-ca-se…" About a minute ago Up About a minute 7054/tcp, 0.0.0.0:8054->8054/tcp ca_org2 167 7b01f5454832 hyperledger/fabric-ca:latest "sh -c 'fabric-ca-se…" About a minute ago Up About a minute 7054/tcp, 0.0.0.0:9054->9054/tcp ca_orderer 168 87aef6062f23 hyperledger/fabric-ca:latest "sh -c 'fabric-ca-se…" About a minute ago Up About a minute 0.0.0.0:7054->7054/tcp ca_org1 169 ``` 170 171 See if you can map these containers to the nodes of the test network (you may 172 need to horizontally scroll to locate the information): 173 * The Org1 peer, `peer0.org1.example.com`, is running in container `a86f50ca1907` 174 * The Org2 peer, `peer0.org2.example.com`, is running in container `77d0fcaee61b` 175 * The CouchDB database for the Org1 peer, `couchdb0`, is running in container `7eb5f64bfe5f` 176 * The CouchDB database for the Org2 peer, `couchdb1`, is running in container `2438df719f57` 177 * The Ordering node, `orderer.example.com`, is running in container `03373d116c5a` 178 * The Org1 CA, `ca_org1`, is running in container `87aef6062f23` 179 * The Org2 CA, `ca_org2`, is running in container `6b4d87f65909` 180 * The Ordering Org CA, `ca_orderer`, is running in container `7b01f5454832` 181 182 These containers all form a [Docker network](https://docs.docker.com/network/) 183 called `net_test`. You can view the network with the `docker network` command: 184 185 ``` 186 $ docker network inspect net_test 187 188 [ 189 { 190 "Name": "net_test", 191 "Id": "f4c9712139311004b8f7acc14e9f90170c5dcfd8cdd06303c7b074624b44dc9f", 192 "Created": "2020-04-28T22:45:38.525016Z", 193 "Containers": { 194 "03373d116c5abf2ca94f6f00df98bb74f89037f511d6490de4a217ed8b6fbcd0": { 195 "Name": "orderer.example.com", 196 "EndpointID": "0eed871a2aaf9a5dbcf7896aa3c0f53cc61f57b3417d36c56747033fd9f81972", 197 "MacAddress": "02:42:c0:a8:70:05", 198 "IPv4Address": "192.168.112.5/20", 199 "IPv6Address": "" 200 }, 201 "2438df719f57a597de592cfc76db30013adfdcfa0cec5b375f6b7259f67baff8": { 202 "Name": "couchdb1", 203 "EndpointID": "52527fb450a7c80ea509cb571d18e2196a95c630d0f41913de8ed5abbd68993d", 204 "MacAddress": "02:42:c0:a8:70:06", 205 "IPv4Address": "192.168.112.6/20", 206 "IPv6Address": "" 207 }, 208 "6b4d87f65909afd335d7acfe6d79308d6e4b27441b25a829379516e4c7335b88": { 209 "Name": "ca_org2", 210 "EndpointID": "1cc322a995880d76e1dd1f37ddf9c43f86997156124d4ecbb0eba9f833218407", 211 "MacAddress": "02:42:c0:a8:70:04", 212 "IPv4Address": "192.168.112.4/20", 213 "IPv6Address": "" 214 }, 215 "77d0fcaee61b8fff43d33331073ab9ce36561a90370b9ef3f77c663c8434e642": { 216 "Name": "peer0.org1.example.com", 217 "EndpointID": "05d0d34569eee412e28313ba7ee06875a68408257dc47e64c0f4f5ef4a9dc491", 218 "MacAddress": "02:42:c0:a8:70:08", 219 "IPv4Address": "192.168.112.8/20", 220 "IPv6Address": "" 221 }, 222 "7b01f5454832984fcd9650f05b4affce97319f661710705e6381dfb76cd99fdb": { 223 "Name": "ca_orderer", 224 "EndpointID": "057390288a424f49d6e9d6f788049b1e18aa28bccd56d860b2be8ceb8173ef74", 225 "MacAddress": "02:42:c0:a8:70:02", 226 "IPv4Address": "192.168.112.2/20", 227 "IPv6Address": "" 228 }, 229 "7eb5f64bfe5f20701aae8a6660815c4e3a81c3834b71f9e59a62fb99bed1afc7": { 230 "Name": "couchdb0", 231 "EndpointID": "bfe740be15ec9dab7baf3806964e6b1f0b67032ce1b7ae26ac7844a1b422ddc4", 232 "MacAddress": "02:42:c0:a8:70:07", 233 "IPv4Address": "192.168.112.7/20", 234 "IPv6Address": "" 235 }, 236 "87aef6062f2324889074cda80fec8fe014d844e10085827f380a91eea4ccdd74": { 237 "Name": "ca_org1", 238 "EndpointID": "a740090d33ca94dd7c6aaf14a79e1cb35109b549ee291c80195beccc901b16b7", 239 "MacAddress": "02:42:c0:a8:70:03", 240 "IPv4Address": "192.168.112.3/20", 241 "IPv6Address": "" 242 }, 243 "a86f50ca19079f59552e8674932edd02f7f9af93ded14db3b4c404fd6b1abe9c": { 244 "Name": "peer0.org2.example.com", 245 "EndpointID": "6e56772b4783b1879a06f86901786fed1c307966b72475ce4631405ba8bca79a", 246 "MacAddress": "02:42:c0:a8:70:09", 247 "IPv4Address": "192.168.112.9/20", 248 "IPv6Address": "" 249 } 250 }, 251 "Options": {}, 252 "Labels": {} 253 } 254 ] 255 ``` 256 257 See how the eight containers use different IP addresses, while being part of a 258 single Docker network. (We've abbreviated the output for clarity.) 259 260 Because we are operating the test network as DigiBank and MagnetoCorp, 261 `peer0.org1.example.com` will belong to the DigiBank organization while 262 `peer0.org2.example.com` will be operated by MagnetoCorp. Now that the test 263 network is up and running, we can refer to our network as PaperNet from this point 264 forward. 265 266 To recap: you've downloaded the Hyperledger Fabric samples repository from 267 GitHub and you've got a Fabric network running on your local machine. Let's now 268 start to play the role of MagnetoCorp, who wishes to issue and trade commercial paper. 269 270 ## Monitor the network as MagnetoCorp 271 272 The commercial paper tutorial allows you to act as two organizations by 273 providing two separate folders for DigiBank and MagnetoCorp. The two folders 274 contain the smart contracts and application files for each organization. Because 275 the two organizations have different roles in the trading of the commercial paper, 276 the application files are different for each organization. Open a new window in 277 the `fabric-samples` repository and use the following command to change into 278 the MagnetoCorp directory: 279 ``` 280 cd commercial-paper/organization/magnetocorp 281 ``` 282 The first thing we are going to do as MagnetoCorp is monitor the components 283 of PaperNet. An administrator can view the aggregated output from a set 284 of Docker containers using the `logspout` [tool](https://github.com/gliderlabs/logspout#logspout). 285 The tool collects the different output streams into one place, making it easy 286 to see what's happening from a single window. This can be really helpful for 287 administrators when installing smart contracts or for developers when invoking 288 smart contracts, for example. 289 290 In the MagnetoCorp directory, run the following command to run the 291 `monitordocker.sh` script and start the `logspout` tool for the containers 292 associated with PaperNet running on `net_test`: 293 ``` 294 (magnetocorp admin)$ ./configuration/cli/monitordocker.sh net_test 295 ... 296 latest: Pulling from gliderlabs/logspout 297 4fe2ade4980c: Pull complete 298 decca452f519: Pull complete 299 (...) 300 Starting monitoring on all containers on the network net_test 301 b7f3586e5d0233de5a454df369b8eadab0613886fc9877529587345fc01a3582 302 ``` 303 304 Note that you can pass a port number to the above command if the default port in `monitordocker.sh` is already in use. 305 ``` 306 (magnetocorp admin)$ ./monitordocker.sh net_test <port_number> 307 ``` 308 309 This window will now show output from the Docker containers for the remainder of the 310 tutorial, so go ahead and open another command window. The next thing we will do is 311 examine the smart contract that MagnetoCorp will use to issue to the commercial 312 paper. 313 314 ## Examine the commercial paper smart contract 315 316 `issue`, `buy` and `redeem` are the three functions at the heart of the commercial 317 paper smart contract. It is used by applications to submit transactions which 318 correspondingly issue, buy and redeem commercial paper on the ledger. Our next 319 task is to examine this smart contract. 320 321 Open a new terminal in the `fabric-samples` directory and change into the 322 MagnetoCorp folder to act as the MagnetoCorp developer. 323 ``` 324 cd commercial-paper/organization/magnetocorp 325 ``` 326 You can then view the smart contract in the `contract` directory using your chosen 327 editor (VS Code in this tutorial): 328 ``` 329 (magnetocorp developer)$ code contract 330 ``` 331 332 In the `lib` directory of the folder, you'll see `papercontract.js` file -- this 333 contains the commercial paper smart contract! 334 335  *An 336 example code editor displaying the commercial paper smart contract in `papercontract.js`* 337 338 `papercontract.js` is a JavaScript program designed to run in the Node.js 339 environment. Note the following key program lines: 340 341 * `const { Contract, Context } = require('fabric-contract-api');` 342 343 This statement brings into scope two key Hyperledger Fabric classes that will 344 be used extensively by the smart contract -- `Contract` and `Context`. You 345 can learn more about these classes in the 346 [`fabric-shim` JSDOCS](https://hyperledger.github.io/fabric-chaincode-node/). 347 348 349 * `class CommercialPaperContract extends Contract {` 350 351 This defines the smart contract class `CommercialPaperContract` based on the 352 built-in Fabric `Contract` class. The methods which implement the key 353 transactions to `issue`, `buy` and `redeem` commercial paper are defined 354 within this class. 355 356 357 * `async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime...) {` 358 359 This method defines the commercial paper `issue` transaction for PaperNet. The 360 parameters that are passed to this method will be used to create the new 361 commercial paper. 362 363 Locate and examine the `buy` and `redeem` transactions within the smart 364 contract. 365 366 367 * `let paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime...);` 368 369 Within the `issue` transaction, this statement creates a new commercial paper 370 in memory using the `CommercialPaper` class with the supplied transaction 371 inputs. Examine the `buy` and `redeem` transactions to see how they similarly 372 use this class. 373 374 375 * `await ctx.paperList.addPaper(paper);` 376 377 This statement adds the new commercial paper to the ledger using 378 `ctx.paperList`, an instance of a `PaperList` class that was created when the 379 smart contract context `CommercialPaperContext` was initialized. Again, 380 examine the `buy` and `redeem` methods to see how they use this class. 381 382 383 * `return paper;` 384 385 This statement returns a binary buffer as response from the `issue` 386 transaction for processing by the caller of the smart contract. 387 388 389 Feel free to examine other files in the `contract` directory to understand how 390 the smart contract works, and read in detail how `papercontract.js` is 391 designed in the [smart contract processing](../developapps/smartcontract.html) 392 topic. 393 394 ## Deploy the smart contract to the channel 395 396 Before `papercontract` can be invoked by applications, it must be installed onto 397 the appropriate peer nodes of the test network and then defined on the channel 398 using the [Fabric chaincode lifecycle](../chaincode_lifecycle.html#chaincode-lifecycle). The Fabric chaincode 399 lifecycle allows multiple organizations to agree to the parameters of a chaincode 400 before the chaincode is deployed to a channel. As a result, we need to install 401 and approve the chaincode as administrators of both MagnetoCorp and DigiBank. 402 403  *A MagnetoCorp 404 administrator installs a copy of the `papercontract` onto a MagnetoCorp peer.* 405 406 Smart contracts are the focus of application development, and are contained 407 within a Hyperledger Fabric artifact called [chaincode](../chaincode.html). One 408 or more smart contracts can be defined within a single chaincode, and installing 409 a chaincode will allow them to be consumed by the different organizations in 410 PaperNet. It means that only administrators need to worry about chaincode; 411 everyone else can think in terms of smart contracts. 412 413 ### Install and approve the smart contract as MagnetoCorp 414 415 We will first install and approve the smart contract as the MagnetoCorp admin. Make 416 sure that you are operating from the `magnetocorp` folder, or navigate back to that 417 folder using the following command: 418 ``` 419 cd commercial-paper/organization/magnetocorp 420 ``` 421 422 A MagnetoCorp administrator can interact with PaperNet using the `peer` CLI. However, 423 the administrator needs to set certain environment variables in their command 424 window to use the correct set of `peer` binaries, send commands to the address 425 of the MagnetoCorp peer, and sign requests with the correct cryptographic material. 426 427 You can use a script provided by the sample to set the environment variables in 428 your command window. Run the following command in the `magnetocorp` directory: 429 ``` 430 source magnetocorp.sh 431 ``` 432 433 You will see the full list of environment variables printed in your window. We 434 can now use this command window to interact with PaperNet as the MagnetoCorp 435 administrator. 436 437 The first step is to install the `papercontract` smart contract. The smart 438 contract can be packaged into a chaincode using the 439 `peer lifecycle chaincode package` command. In the MagnetoCorp administrator's 440 command window, run the following command to create the chaincode package: 441 ``` 442 (magnetocorp admin)$ peer lifecycle chaincode package cp.tar.gz --lang node --path ./contract --label cp_0 443 ``` 444 The MagnetoCorp admin can now install the chaincode on the MagnetoCorp peer using 445 the `peer lifecycle chaincode install` command: 446 ``` 447 (magnetocorp admin)$ peer lifecycle chaincode install cp.tar.gz 448 ``` 449 When the chaincode package is installed, you will see messages similar to the following 450 printed in your terminal: 451 ``` 452 2020-01-30 18:32:33.762 EST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nEcp_0:ffda93e26b183e231b7e9d5051e1ee7ca47fbf24f00a8376ec54120b1a2a335c\022\004cp_0" > 453 2020-01-30 18:32:33.762 EST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: cp_0:ffda93e26b183e231b7e9d5051e1ee7ca47fbf24f00a8376ec54120b1a2a335c 454 ``` 455 Because the MagnetoCorp admin has set `CORE_PEER_ADDRESS=localhost:9051` to 456 target its commands to `peer0.org2.example.com`, the `INFO 001 Installed remotely...` 457 indicates that `papercontract` has been successfully installed on this peer. 458 459 After we install the smart contract, we need to approve the chaincode definition 460 for `papercontract` as MagnetoCorp. The first step is to find the packageID of 461 the chaincode we installed on our peer. We can query the packageID using the 462 `peer lifecycle chaincode queryinstalled` command: 463 ``` 464 peer lifecycle chaincode queryinstalled 465 ``` 466 467 The command will return the same package identifier as the install command. You 468 should see output similar to the following: 469 ``` 470 Installed chaincodes on peer: 471 Package ID: cp_0:ffda93e26b183e231b7e9d5051e1ee7ca47fbf24f00a8376ec54120b1a2a335c, Label: cp_0 472 ``` 473 474 We will need the package ID in the next step, so we will save it as an environment 475 variable. The package ID may not be the same for all users, so you need to 476 complete this step using the package ID returned from your command window. 477 ``` 478 export PACKAGE_ID=cp_0:ffda93e26b183e231b7e9d5051e1ee7ca47fbf24f00a8376ec54120b1a2a335c 479 ``` 480 481 The admin can now approve the chaincode definition for MagnetoCorp using the 482 `peer lifecycle chaincode approveformyorg` command: 483 ``` 484 (magnetocorp admin)$ peer lifecycle chaincode approveformyorg --orderer localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name papercontract -v 0 --package-id $PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA 485 ``` 486 487 One of the most important chaincode parameters that channel members need to 488 agree to using the chaincode definition is the chaincode [endorsement policy](../endorsement-policies.html). 489 The endorsement policy describes the set of organizations that must endorse 490 (execute and sign) a transaction before it can be determined to be valid. By 491 approving the `papercontract` chaincode without the ``--policy`` flag, the 492 MagnetoCorp admin agrees to using the channel's default `Endorsement` policy, 493 which in the case of the `mychannel` test channel requires a 494 majority of organizations on the channel to endorse a transaction. All transactions, 495 whether valid or invalid, will be recorded on the [ledger blockchain](../ledger/ledger.html#blockchain), 496 but only valid transactions will update the [world state](../ledger/ledger.html#world-state). 497 498 ### Install and approve the smart contract as DigiBank 499 500 Based on the `mychannel` `LifecycleEndorsement` policy, the Fabric Chaincode lifecycle 501 will require a majority of organizations on the channel to agree to the chaincode 502 definition before the chaincode can be committed to the channel. 503 This implies that we need to approve the `papernet` chaincode as both MagnetoCorp 504 and DigiBank to get the required majority of 2 out of 2. Open a new terminal 505 window in the `fabric-samples` and navigate to the folder that contains the 506 DigiBank smart contract and application files: 507 ``` 508 (digibank admin)$ cd commercial-paper/organization/digibank/ 509 ``` 510 Use the script in the DigiBank folder to set the environment variables that will 511 allow you to act as the DigiBank admin: 512 ``` 513 source digibank.sh 514 ``` 515 516 We can now install and approve `papercontract` as the DigiBank. Run the following 517 command to package the chaincode: 518 ``` 519 (digibank admin)$ peer lifecycle chaincode package cp.tar.gz --lang node --path ./contract --label cp_0 520 ``` 521 The admin can now install the chaincode on the DigiBank peer: 522 ``` 523 (digibank admin)$ peer lifecycle chaincode install cp.tar.gz 524 ``` 525 We then need to query and save the packageID of the chaincode that was just 526 installed: 527 ``` 528 (digibank admin)$ peer lifecycle chaincode queryinstalled 529 ``` 530 Save the package ID as an environment variable. Complete this step using the 531 package ID returned from your console. 532 ``` 533 export PACKAGE_ID=cp_0:ffda93e26b183e231b7e9d5051e1ee7ca47fbf24f00a8376ec54120b1a2a335c 534 ``` 535 536 The Digibank admin can now approve the chaincode definition of `papercontract`: 537 ``` 538 (digibank admin)$ peer lifecycle chaincode approveformyorg --orderer localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name papercontract -v 0 --package-id $PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA 539 ``` 540 541 ### Commit the chaincode definition to the channel 542 543 Now that DigiBank and MagnetoCorp have both approved the `papernet` chaincode, we 544 have the majority we need (2 out of 2) to commit the chaincode definition to the 545 channel. Once the chaincode is successfully defined on the channel, the 546 `CommercialPaper` smart contract inside the `papercontract` chaincode can be 547 invoked by client applications on the channel. Since either organization can 548 commit the chaincode to the channel, we will continue operating as the 549 DigiBank admin: 550 551  *After the DigiBank administrator commits the definition of the `papercontract` chaincode to the channel, a new Docker chaincode container will be created to run `papercontract` on both PaperNet peers* 552 553 The DigiBank administrator uses the `peer lifecycle chaincode commit` command 554 to commit the chaincode definition of `papercontract` to `mychannel`: 555 ``` 556 (digibank admin)$ peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --peerAddresses localhost:7051 --tlsRootCertFiles ${PEER0_ORG1_CA} --peerAddresses localhost:9051 --tlsRootCertFiles ${PEER0_ORG2_CA} --channelID mychannel --name papercontract -v 0 --sequence 1 --tls --cafile $ORDERER_CA --waitForEvent 557 ``` 558 The chaincode container will start after the chaincode definition has been 559 committed to the channel. You can use the `docker ps` command to see 560 `papercontract` container starting on both peers. 561 562 ``` 563 (digibank admin)$ docker ps 564 565 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 566 d4ba9dc9c55f dev-peer0.org1.example.com-cp_0-ebef35e7f1f25eea1dcc6fcad5019477cd7f434c6a5dcaf4e81744e282903535-05cf67c20543ee1c24cf7dfe74abce99785374db15b3bc1de2da372700c25608 "docker-entrypoint.s…" 30 seconds ago Up 28 seconds dev-peer0.org1.example.com-cp_0-ebef35e7f1f25eea1dcc6fcad5019477cd7f434c6a5dcaf4e81744e282903535 567 a944c0f8b6d6 dev-peer0.org2.example.com-cp_0-1487670371e56d107b5e980ce7f66172c89251ab21d484c7f988c02912ddeaec-1a147b6fd2a8bd2ae12db824fad8d08a811c30cc70bc5b6bc49a2cbebc2e71ee "docker-entrypoint.s…" 31 seconds ago Up 28 seconds dev-peer0.org2.example.com-cp_0-1487670371e56d107b5e980ce7f66172c89251ab21d484c7f988c02912ddeaec 568 ``` 569 570 Notice that the containers are named to indicate the peer that started it, and 571 the fact that it's running `papercontract` version `0`. 572 573 Now that we have deployed the `papercontract` chaincode to the channel, we can 574 use the MagnetoCorp application to issue the commercial paper. Let's take a 575 moment to examine the application structure. 576 577 ## Application structure 578 579 The smart contract contained in `papercontract` is called by MagnetoCorp's 580 application `issue.js`. Isabella uses this application to submit a transaction 581 to the ledger which issues commercial paper `00001`. Let's quickly examine how 582 the `issue` application works. 583 584  *A gateway 585 allows an application to focus on transaction generation, submission and 586 response. It coordinates transaction proposal, ordering and notification 587 processing between the different network components.* 588 589 Because the `issue` application submits transactions on behalf of Isabella, it 590 starts by retrieving Isabella's X.509 certificate from her 591 [wallet](../developapps/wallet.html), which might be stored on the local file 592 system or a Hardware Security Module 593 [HSM](https://en.wikipedia.org/wiki/Hardware_security_module). The `issue` 594 application is then able to utilize the gateway to submit transactions on the 595 channel. The Hyperledger Fabric SDK provides a 596 [gateway](../developapps/gateway.html) abstraction so that applications can 597 focus on application logic while delegating network interaction to the 598 gateway. Gateways and wallets make it straightforward to write Hyperledger 599 Fabric applications. 600 601 So let's examine the `issue` application that Isabella is going to use. Open a 602 separate terminal window for her, and in `fabric-samples` locate the MagnetoCorp 603 `/application` folder: 604 605 ``` 606 (isabella)$ cd commercial-paper/organization/magnetocorp/application/ 607 (isabella)$ ls 608 609 addToWallet.js enrollUser.js issue.js package.json 610 ``` 611 612 `addToWallet.js` is the program that Isabella is going to use to load her 613 identity into her wallet, and `issue.js` will use this identity to create 614 commercial paper `00001` on behalf of MagnetoCorp by invoking `papercontract`. 615 616 Change to the directory that contains MagnetoCorp's copy of the application 617 `issue.js`, and use your code editor to examine it: 618 619 ``` 620 (isabella)$ cd commercial-paper/organization/magnetocorp/application 621 (isabella)$ code issue.js 622 ``` 623 624 Examine this directory; it contains the issue application and all its 625 dependencies. 626 627  *A code editor 628 displaying the contents of the commercial paper application directory.* 629 630 Note the following key program lines in `issue.js`: 631 632 * `const { Wallets, Gateway } = require('fabric-network');` 633 634 This statement brings two key Hyperledger Fabric SDK classes into scope -- 635 `Wallet` and `Gateway`. 636 637 638 * `const wallet = await Wallets.newFileSystemWallet('../identity/user/isabella/wallet');` 639 640 This statement identifies that the application will use `isabella` wallet when 641 it connects to the blockchain network channel. Because Isabella's X.509 certificate 642 is in the local file system, the application creates a new `FileSystemWallet`. The 643 application will select a particular identity within `isabella` wallet. 644 645 646 * `await gateway.connect(connectionProfile, connectionOptions);` 647 648 This line of code connects to the network using the gateway identified by 649 `connectionProfile`, using the identity referred to in `ConnectionOptions`. 650 651 See how `../gateway/networkConnection.yaml` and `User1@org1.example.com` are 652 used for these values respectively. 653 654 655 * `const network = await gateway.getNetwork('mychannel');` 656 657 This connects the application to the network channel `mychannel`, where the 658 `papercontract` was previously deployed. 659 660 661 * `const contract = await network.getContract('papercontract');` 662 663 This statement gives the application access to the `papercontract` chaincode. 664 Once an application has issued getContract, it can submit to any smart contract 665 transaction implemented within the chaincode. 666 667 * `const issueResponse = await contract.submitTransaction('issue', 'MagnetoCorp', '00001', ...);` 668 669 This line of code submits the a transaction to the network using the `issue` 670 transaction defined within the smart contract. `MagnetoCorp`, `00001`... are 671 the values to be used by the `issue` transaction to create a new commercial 672 paper. 673 674 * `let paper = CommercialPaper.fromBuffer(issueResponse);` 675 676 This statement processes the response from the `issue` transaction. The 677 response needs to deserialized from a buffer into `paper`, a `CommercialPaper` 678 object which can interpreted correctly by the application. 679 680 681 Feel free to examine other files in the `/application` directory to understand 682 how `issue.js` works, and read in detail how it is implemented in the 683 application [topic](../developapps/application.html). 684 685 ## Application dependencies 686 687 The `issue.js` application is written in JavaScript and designed to run in the 688 Node.js environment that acts as a client to the PaperNet network. 689 As is common practice, MagnetoCorp's application is built on many 690 external node packages --- to improve quality and speed of development. Consider 691 how `issue.js` includes the `js-yaml` 692 [package](https://www.npmjs.com/package/js-yaml) to process the YAML gateway 693 connection profile, or the `fabric-network` 694 [package](https://www.npmjs.com/package/fabric-network) to access the `Gateway` 695 and `Wallet` classes: 696 697 ```JavaScript 698 const yaml = require('js-yaml'); 699 const { Wallets, Gateway } = require('fabric-network'); 700 ``` 701 702 These packages have to be downloaded from [npm](https://www.npmjs.com/) to the 703 local file system using the `npm install` command. By convention, packages must 704 be installed into an application-relative `/node_modules` directory for use at 705 runtime. 706 707 Open the `package.json` file to see how `issue.js` identifies the packages to 708 download and their exact versions by examining the "dependencies" section of the file. 709 710 **npm** versioning is very powerful; you can read more about it 711 [here](https://docs.npmjs.com/getting-started/semantic-versioning). 712 713 Let's install these packages with the `npm install` command -- this may take up 714 to a minute to complete: 715 716 ``` 717 (isabella)$ cd commercial-paper/organization/magnetocorp/application/ 718 (isabella)$ npm install 719 720 ( ) extract:lodash: sill extract ansi-styles@3.2.1 721 (...) 722 added 738 packages in 46.701s 723 ``` 724 725 See how this command has updated the directory: 726 727 ``` 728 (isabella)$ ls 729 730 enrollUser.js node_modules package.json 731 issue.js package-lock.json 732 ``` 733 734 Examine the `node_modules` directory to see the packages that have been 735 installed. There are lots, because `js-yaml` and `fabric-network` are themselves 736 built on other npm packages! Helpfully, the `package-lock.json` 737 [file](https://docs.npmjs.com/files/package-lock.json) identifies the exact 738 versions installed, which can prove invaluable if you want to exactly reproduce 739 environments; to test, diagnose problems or deliver proven applications for 740 example. 741 742 ## Wallet 743 744 Isabella is almost ready to run `issue.js` to issue MagnetoCorp commercial paper 745 `00001`; there's just one remaining task to perform! As `issue.js` acts on 746 behalf of Isabella, and therefore MagnetoCorp, it will use identity from her 747 [wallet](../developapps/wallet.html) that reflects these facts. We now need to 748 perform this one-time activity of generating the appropriate X.509 credentials 749 to her wallet. 750 751 The MagnetoCorp Certificate Authority running on PaperNet, `ca_org2`, has an 752 application user that was registered when the network was deployed. Isabella 753 can use the identity name and secret to generate the X.509 cryptographic material 754 for the `issue.js` application. The process of using a CA to generate client side 755 cryptographic material is referred to as **enrollment**. In a real word scenario, 756 a network operator would provide the name and secret of a client identity that 757 was registered with the CA to an application developer. The developer would then 758 use the credentials to enroll their application and interact with the network. 759 760 The `enrollUser.js` program uses the `fabric-ca-client` class to generate a private 761 and public key pair, and then issues a **Certificate Signing Request** to the CA. 762 If the identiy name and secret submitted by Isabella match the credentials 763 registered with the CA, the CA will issue and sign a certificate that encodes the 764 public key, establishing that Isabella belongs to MagnetoCorp. When the signing 765 request is complete, `enrollUser.js` stores the private key and signing certificate 766 in Isabella's wallet. You can examine the `enrollUser.js` file to learn more about 767 how the Node SDK uses the `fabric-ca-client` class to complete these tasks. 768 769 In Isabella's terminal window, run the `enrollUser.js` program to add identity 770 information to her wallet: 771 772 ``` 773 (isabella)$ node enrollUser.js 774 775 Wallet path: /Users/nikhilgupta/fabric-samples/commercial-paper/organization/magnetocorp/identity/user/isabella/wallet 776 Successfully enrolled client user "isabella" and imported it into the wallet 777 ``` 778 779 We can now turn our focus to the result of this program --- the contents of the 780 wallet which will be used to submit transactions to PaperNet: 781 782 ``` 783 (isabella)$ ls ../identity/user/isabella/wallet/ 784 785 isabella.id 786 ``` 787 788 Isabella can store multiple identities in her wallet, though in our example, she 789 only uses one. The `wallet` folder contains an `isabella.id` file that provides 790 the information that Isabella needs to connect to the network. Other identities 791 used by Isabella would have their own file. You can open this file to see the 792 identity information that `issue.js` will use on behalf of Isabella inside a JSON 793 file. The output has been formatted for clarity. 794 ``` 795 (isabella)$ cat ../identity/user/isabella/wallet/* 796 797 { 798 "credentials": { 799 "certificate": "-----BEGIN CERTIFICATE-----\nMIICKTCCAdCgAwIBAgIQWKwvLG+sqeO3LwwQK6avZDAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMi5leGFtcGxlLmNvbTAeFw0yMDAyMDQxOTA5MDBaFw0zMDAyMDExOTA5MDBa\nMGwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMQ8wDQYDVQQLEwZjbGllbnQxHzAdBgNVBAMMFlVzZXIxQG9y\nZzIuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT4TnTblx0k\ngfqX+NN7F76Me33VTq3K2NUWZRreoJzq6bAuvdDR+iFvVPKXbdORnVvRSATcXsYl\nt20yU7n/53dbo00wSzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADArBgNV\nHSMEJDAigCDOCdm4irsZFU3D6Hak4+84QRg1N43iwg8w1V6DRhgLyDAKBggqhkjO\nPQQDAgNHADBEAiBhzKix1KJcbUy9ey5ulWHRUMbqdVCNHe/mRtUdaJagIgIgYpbZ\nXf0CSiTXIWOJIsswN4Jp+ZxkJfFVmXndqKqz+VM=\n-----END CERTIFICATE-----\n", 800 "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQggs55vQg2oXi8gNi8\nNidE8Fy5zenohArDq3FGJD8cKU2hRANCAAT4TnTblx0kgfqX+NN7F76Me33VTq3K\n2NUWZRreoJzq6bAuvdDR+iFvVPKXbdORnVvRSATcXsYlt20yU7n/53db\n-----END PRIVATE KEY-----\n" 801 }, 802 "mspId": "Org2MSP", 803 "type": "X.509", 804 "version": 1 805 } 806 ``` 807 808 In the file you can notice the following: 809 810 * a `"privateKey":` used to sign transactions on Isabella's behalf, but not 811 distributed outside of her immediate control. 812 813 * a `"certificate":` which contains Isabella's public key and other X.509 814 attributes added by the Certificate Authority at certificate creation. This 815 certificate is distributed to the network so that different actors at different 816 times can cryptographically verify information created by Isabella's private key. 817 818 You can Learn more about certificates [here](../identity/identity.html#digital-certificates). In practice, the 819 certificate file also contains some Fabric-specific metadata such as 820 Isabella's organization and role -- read more in the [wallet](../developapps/wallet.html) topic. 821 822 ## Issue application 823 824 Isabella can now use `issue.js` to submit a transaction that will issue 825 MagnetoCorp commercial paper `00001`: 826 827 ``` 828 (isabella)$ node issue.js 829 830 Connect to Fabric gateway. 831 Use network channel: mychannel. 832 Use org.papernet.commercialpaper smart contract. 833 Submit commercial paper issue transaction. 834 Process issue transaction response.{"class":"org.papernet.commercialpaper","key":"\"MagnetoCorp\":\"00001\"","currentState":1,"issuer":"MagnetoCorp","paperNumber":"00001","issueDateTime":"2020-05-31","maturityDateTime":"2020-11-30","faceValue":"5000000","owner":"MagnetoCorp"} 835 MagnetoCorp commercial paper : 00001 successfully issued for value 5000000 836 Transaction complete. 837 Disconnect from Fabric gateway. 838 Issue program complete. 839 ``` 840 841 The `node` command initializes a Node.js environment, and runs `issue.js`. We 842 can see from the program output that MagnetoCorp commercial paper 00001 was 843 issued with a face value of 5M USD. 844 845 As you've seen, to achieve this, the application invokes the `issue` transaction 846 defined in the `CommercialPaper` smart contract within `papercontract.js`. 847 The smart contract interacts with the ledger via the 848 Fabric APIs, most notably `putState()` and `getState()`, to represent the new 849 commercial paper as a vector state within the world state. We'll see how this 850 vector state is subsequently manipulated by the `buy` and `redeem` transactions 851 also defined within the smart contract. 852 853 All the time, the underlying Fabric SDK handles the transaction endorsement, 854 ordering and notification process, making the application's logic 855 straightforward; the SDK uses a [gateway](../developapps/gateway.html) to 856 abstract away network details and 857 [connectionOptions](../developapps/connectoptions.html) to declare more advanced 858 processing strategies such as transaction retry. 859 860 Let's now follow the lifecycle of MagnetoCorp 00001 by switching our emphasis 861 to an employee of DigiBank, Balaji, who will buy the commercial paper using a 862 DigiBank application. 863 864 ## Digibank applications 865 866 Balaji uses DigiBank's `buy` application to submit a transaction to the ledger 867 which transfers ownership of commercial paper `00001` from MagnetoCorp to 868 DigiBank. The `CommercialPaper` smart contract is the same as that used by 869 MagnetoCorp's application, however the transaction is different this time -- 870 it's `buy` rather than `issue`. Let's examine how DigiBank's application works. 871 872 Open a separate terminal window for Balaji. In `fabric-samples`, change to the 873 DigiBank application directory that contains the application, `buy.js`, and open 874 it with your editor: 875 876 ``` 877 (balaji)$ cd commercial-paper/organization/digibank/application/ 878 (balaji)$ code buy.js 879 ``` 880 881 As you can see, this directory contains both the `buy` and `redeem` applications 882 that will be used by Balaji. 883 884 885  *DigiBank's 886 commercial paper directory containing the `buy.js` and `redeem.js` 887 applications.* 888 889 DigiBank's `buy.js` application is very similar in structure to MagnetoCorp's 890 `issue.js` with two important differences: 891 892 893 * **Identity**: the user is a DigiBank user `Balaji` rather than MagnetoCorp's 894 `Isabella` 895 896 ```JavaScript 897 const wallet = await Wallets.newFileSystemWallet('../identity/user/balaji/wallet'); 898 ``` 899 900 See how the application uses the `balaji` wallet when it connects to the 901 PaperNet network channel. `buy.js` selects a particular identity within 902 `balaji` wallet. 903 904 905 * **Transaction**: the invoked transaction is `buy` rather than `issue` 906 907 ```JavaScript 908 const buyResponse = await contract.submitTransaction('buy', 'MagnetoCorp', '00001', ...); 909 ``` 910 911 A `buy` transaction is submitted with the values `MagnetoCorp`, `00001`, ..., 912 that are used by the `CommercialPaper` smart contract class to transfer 913 ownership of commercial paper `00001` to DigiBank. 914 915 Feel free to examine other files in the `application` directory to understand 916 how the application works, and read in detail how `buy.js` is implemented in 917 the application [topic](../developapps/application.html). 918 919 ## Run as DigiBank 920 921 The DigiBank applications which buy and redeem commercial paper have a very 922 similar structure to MagnetoCorp's issue application. Therefore, let’s install 923 their dependencies and set up Balaji's wallet so that he can use these 924 applications to buy and redeem commercial paper. 925 926 Like MagnetoCorp, Digibank must the install the required application packages 927 using the ``npm install`` command, and again, this make take a short time to 928 complete. 929 930 In the DigiBank administrator window, install the application dependencies: 931 932 ``` 933 (digibank admin)$ cd commercial-paper/organization/digibank/application/ 934 (digibank admin)$ npm install 935 936 ( ) extract:lodash: sill extract ansi-styles@3.2.1 937 (...) 938 added 738 packages in 46.701s 939 ``` 940 941 In Balaji's command window, run the `enrollUser.js` program to generate a 942 certificate and private key and them to his wallet: 943 ``` 944 (balaji)$ node enrollUser.js 945 946 Wallet path: /Users/nikhilgupta/fabric-samples/commercial-paper/organization/digibank/identity/user/balaji/wallet 947 Successfully enrolled client user "balaji" and imported it into the wallet 948 ``` 949 950 The `addToWallet.js` program has added identity information for `balaji`, to his 951 wallet, which will be used by `buy.js` and `redeem.js` to submit transactions to 952 `PaperNet`. 953 954 Like Isabella, Balaji can store multiple identities in his wallet, though in our 955 example, he only uses one. His corresponding id file at 956 `digibank/identity/user/balaji/wallet/balaji.id` is very similar Isabella's --- 957 feel free to examine it. 958 959 ## Buy application 960 961 Balaji can now use `buy.js` to submit a transaction that will transfer ownership 962 of MagnetoCorp commercial paper 00001 to DigiBank. 963 964 Run the `buy` application in Balaji's window: 965 966 ``` 967 (balaji)$ node buy.js 968 969 Connect to Fabric gateway. 970 Use network channel: mychannel. 971 Use org.papernet.commercialpaper smart contract. 972 Submit commercial paper buy transaction. 973 Process buy transaction response. 974 MagnetoCorp commercial paper : 00001 successfully purchased by DigiBank 975 Transaction complete. 976 Disconnect from Fabric gateway. 977 Buy program complete. 978 ``` 979 980 You can see the program output that MagnetoCorp commercial paper 00001 was 981 successfully purchased by Balaji on behalf of DigiBank. `buy.js` invoked the 982 `buy` transaction defined in the `CommercialPaper` smart contract which updated 983 commercial paper `00001` within the world state using the `putState()` and 984 `getState()` Fabric APIs. As you've seen, the application logic to buy and issue 985 commercial paper is very similar, as is the smart contract logic. 986 987 ## Redeem application 988 989 The final transaction in the lifecycle of commercial paper 00001 is for 990 DigiBank to redeem it with MagnetoCorp. Balaji uses `redeem.js` to submit a 991 transaction to perform the redeem logic within the smart contract. 992 993 Run the `redeem` transaction in Balaji's window: 994 995 ``` 996 (balaji)$ node redeem.js 997 998 Connect to Fabric gateway. 999 Use network channel: mychannel. 1000 Use org.papernet.commercialpaper smart contract. 1001 Submit commercial paper redeem transaction. 1002 Process redeem transaction response. 1003 MagnetoCorp commercial paper : 00001 successfully redeemed with MagnetoCorp 1004 Transaction complete. 1005 Disconnect from Fabric gateway. 1006 Redeem program complete. 1007 ``` 1008 1009 Again, see how the commercial paper 00001 was successfully redeemed when 1010 `redeem.js` invoked the `redeem` transaction defined in `CommercialPaper`. 1011 Again, it updated commercial paper `00001` within the world state to reflect 1012 that the ownership returned to MagnetoCorp, the issuer of the paper. 1013 1014 ## Clean up 1015 1016 When you are finished using the Commercial Paper tutorial, you can use a script 1017 to clean up your environment. Use a command window to navigate back to the root 1018 directory of the commercial paper sample: 1019 ``` 1020 cd fabric-samples/commercial-paper 1021 ``` 1022 You can then bring down the network with the following command: 1023 ``` 1024 ./network-clean.sh 1025 ``` 1026 This command will bring down the peers, CouchDB containers, and ordering node of the network, in addition to the logspout tool. It will also remove the identities that we created for Isabella and Balaji. Note that all of the data on the ledger will be lost. If you want to go through the tutorial again, you will start from a clean initial state. 1027 1028 ## Further reading 1029 1030 To understand how applications and smart contracts shown in this tutorial work 1031 in more detail, you'll find it helpful to read 1032 [Developing Applications](../developapps/developing_applications.html). This 1033 topic will give you a fuller explanation of the commercial paper scenario, the 1034 PaperNet business network, its actors, and how the applications and smart 1035 contracts they use work in detail. 1036 1037 Also feel free to use this sample to start creating your own applications and 1038 smart contracts! 1039 1040 <!--- Licensed under Creative Commons Attribution 4.0 International License 1041 https://creativecommons.org/licenses/by/4.0/ -->