github.com/true-sqn/fabric@v2.1.1+incompatible/docs/source/write_first_app.rst (about) 1 Writing Your First Application 2 ============================== 3 4 .. note:: If you're not yet familiar with the fundamental architecture of a 5 Fabric network, you may want to visit the :doc:`key_concepts` section 6 prior to continuing. 7 8 It is also worth noting that this tutorial serves as an introduction 9 to Fabric applications and uses simple smart contracts and 10 applications. For a more in-depth look at Fabric applications and 11 smart contracts, check out our 12 :doc:`developapps/developing_applications` section or the 13 :doc:`tutorial/commercial_paper`. 14 15 This tutorial provides an introduction to how Fabric applications interact 16 with deployed blockchain networks. The tutorial uses sample programs built using the 17 Fabric SDKs -- described in detail in the :doc:`/developapps/application` topic -- 18 to invoke a smart contract which queries and updates the ledger with the smart 19 contract API -- described in detail in :doc:`/developapps/smartcontract`. 20 We will also use our sample programs and a deployed Certificate Authority to generate 21 the X.509 certificates that an application needs to interact with a permissioned 22 blockchain. The sample applications and the smart contract they invoke are 23 collectively known as FabCar. 24 25 We’ll go through three principle steps: 26 27 **1. Setting up a development environment.** Our application needs a network 28 to interact with, so we'll deploy a basic network for our smart contracts and 29 application. 30 31 .. image:: images/AppConceptsOverview.png 32 33 **2. Explore a sample smart contract.** 34 We’ll inspect the sample Fabcar smart contract to learn about the transactions within them, 35 and how they are used by applications to query and update the ledger. 36 37 **3. Interact with the smart contract with a sample application.** Our application will 38 use the FabCar smart contract to query and update car assets on the ledger. 39 We'll get into the code of the apps and the transactions they create, 40 including querying a car, querying a range of cars, and creating a new car. 41 42 After completing this tutorial you should have a basic understanding of how Fabric 43 applications and smart contracts work together to manage data on the distributed 44 ledger of a blockchain network. 45 46 Before you begin 47 ---------------- 48 49 In addition to the standard :doc:`prereqs` for Fabric, this tutorial leverages the Hyperledger Fabric SDK for Node.js. See the Node.js SDK `README <https://github.com/hyperledger/fabric-sdk-node#build-and-test>`__ for a up to date list of prerequisites. 50 51 - If you are using macOS, complete the following steps: 52 53 1. Install `Homebrew <https://brew.sh/>`_. 54 2. Check the Node SDK `prerequisties <https://github.com/hyperledger/fabric-sdk-node#build-and-test>`_ to find out what level of Node to install. 55 3. Run ``brew install node`` to download the latest version of node or choose a specific version, for example: ``brew install node@10`` according to what is supported in the prerequisites. 56 4. Run ``npm install``. 57 58 - If you are on Windows, you can install the `windows-build-tools <https://github.com/felixrieseberg/windows-build-tools#readme>`_ with npm which installs all required compilers and tooling by running the following command: 59 60 .. code:: bash 61 62 npm install --global windows-build-tools 63 64 - If you are on Linux, you need to install `Python v2.7 <https://www.python.org/download/releases/2.7/>`_, `make <https://www.gnu.org/software/make/>`_, and a C/C++ compiler toolchain such as `GCC <https://gcc.gnu.org/>`_. You can run the following command to install the other tools: 65 66 .. code:: bash 67 68 sudo apt install build-essentials 69 70 Set up the blockchain network 71 ----------------------------- 72 73 If you've already run through :doc:`test_network` tutorial and have a network up 74 and running, this tutorial will bring down your running network before 75 bringing up a new one. 76 77 78 Launch the network 79 ^^^^^^^^^^^^^^^^^^ 80 81 .. note:: This tutorial demonstrates the JavaScript versions of the FabCar 82 smart contract and application, but the ``fabric-samples`` repo also 83 contains Go, Java and TypeScript versions of this sample. To try the 84 Go, Java or TypeScript versions, change the ``javascript`` argument 85 for ``./startFabric.sh`` below to either ``go``, ``java`` or ``typescript`` 86 and follow the instructions written to the terminal. 87 88 Navigate to the ``fabcar`` subdirectory within your local clone of the 89 ``fabric-samples`` repo. 90 91 .. code:: bash 92 93 cd fabric-samples/fabcar 94 95 Launch your network using the ``startFabric.sh`` shell script. 96 97 .. code:: bash 98 99 ./startFabric.sh javascript 100 101 This command will deploy the Fabric test network with two peers and an ordering 102 service. Instead of using the cryptogen tool, we will bring up the test network 103 using Certificate Authorities. We will use one of these CAs to create the certificates 104 and keys that will be used by our applications in a future step. The ``startFabric.sh`` 105 script will also deploy and initialize the JavaScript version of the FabCar smart 106 contract on the channel ``mychannel``, and then invoke the smart contract to 107 put initial data on the ledger. 108 109 Install the application 110 ^^^^^^^^^^^^^^^^^^^^^^^ 111 112 From the ``fabcar`` directory inside ``fabric-samples``, navigate to the 113 ``javascript`` folder. 114 115 .. code:: bash 116 117 cd javascript 118 119 This directory contains sample programs that were developed using the Fabric 120 SDK for Node.js. Run the following command to install the application dependencies. 121 It will take about a minute to complete: 122 123 .. code:: bash 124 125 npm install 126 127 This process is installing the key application dependencies defined in 128 ``package.json``. The most important of which is the ``fabric-network`` class; 129 it enables an application to use identities, wallets, and gateways to connect to 130 channels, submit transactions, and wait for notifications. This tutorial also 131 uses the ``fabric-ca-client`` class to enroll users with their respective 132 certificate authorities, generating a valid identity which is then used by 133 ``fabric-network`` class methods. 134 135 Once ``npm install`` completes, everything is in place to run the application. 136 Let's take a look at the sample JavaScript application files we will be using 137 in this tutorial: 138 139 .. code:: bash 140 141 ls 142 143 You should see the following: 144 145 .. code:: bash 146 147 enrollAdmin.js node_modules package.json registerUser.js 148 invoke.js package-lock.json query.js wallet 149 150 There are files for other program languages, for example in the 151 ``fabcar/java`` directory. You can read these once you've used the 152 JavaScript example -- the principles are the same. 153 154 Enrolling the admin user 155 ------------------------ 156 157 .. note:: The following two sections involve communication with the Certificate 158 Authority. You may find it useful to stream the CA logs when running 159 the upcoming programs by opening a new terminal shell and running 160 ``docker logs -f ca_org1``. 161 162 When we created the network, an admin user --- literally called ``admin`` --- 163 was created as the **registrar** for the certificate authority (CA). Our first 164 step is to generate the private key, public key, and X.509 certificate for 165 ``admin`` using the ``enroll.js`` program. This process uses a **Certificate 166 Signing Request** (CSR) --- the private and public key are first generated 167 locally and the public key is then sent to the CA which returns an encoded 168 certificate for use by the application. These credentials are then stored 169 in the wallet, allowing us to act as an administrator for the CA. 170 171 Let's enroll user ``admin``: 172 173 .. code:: bash 174 175 node enrollAdmin.js 176 177 This command stores the CA administrator's credentials in the ``wallet`` directory. 178 You can find administrator's certificate and private key in the ``wallet/admin.id`` 179 file. 180 181 Register and enroll an application user 182 --------------------------------------- 183 184 Our ``admin`` is used to work with the CA. Now that we have the administrator's 185 credentials in a wallet, we can create a new application user which will be used 186 to interact with the blockchain. Run the following command to register and enroll 187 a new user named ``appUser``: 188 189 .. code:: bash 190 191 node registerUser.js 192 193 Similar to the admin enrollment, this program uses a CSR to enroll ``appUser`` and 194 store its credentials alongside those of ``admin`` in the wallet. We now have 195 identities for two separate users --- ``admin`` and ``appUser`` --- that can be 196 used by our application. 197 198 Querying the ledger 199 ------------------- 200 201 Each peer in a blockchain network hosts a copy of the `ledger <./ledger/ledger.html>`_. An application 202 program can view the most recent data from the ledger using read only invocations of 203 a smart contract running on your peers called a query. 204 205 Here is a simplified representation of how a query works: 206 207 .. image:: tutorial/write_first_app.diagram.1.png 208 209 The most common queries involve the current values of data in the ledger -- its 210 `world state <./ledger/ledger.html#world-state>`_. The world state is 211 represented as a set of key-value pairs, and applications can query data for a 212 single key or multiple keys. Moreover, you can use complex queries to read the 213 data on the ledger when you use CouchDB as your state database and model your data in JSON. 214 This can be very helpful when looking for all assets that match certain keywords 215 with particular values; all cars with a particular owner, for example. 216 217 First, let's run our ``query.js`` program to return a listing of all the cars on 218 the ledger. This program uses our second identity -- ``appUser`` -- to access the 219 ledger: 220 221 .. code:: bash 222 223 node query.js 224 225 The output should look like this: 226 227 .. code:: json 228 229 Wallet path: ...fabric-samples/fabcar/javascript/wallet 230 Transaction has been evaluated, result is: 231 [{"Key":"CAR0","Record":{"color":"blue","docType":"car","make":"Toyota","model":"Prius","owner":"Tomoko"}}, 232 {"Key":"CAR1","Record":{"color":"red","docType":"car","make":"Ford","model":"Mustang","owner":"Brad"}}, 233 {"Key":"CAR2","Record":{"color":"green","docType":"car","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}}, 234 {"Key":"CAR3","Record":{"color":"yellow","docType":"car","make":"Volkswagen","model":"Passat","owner":"Max"}}, 235 {"Key":"CAR4","Record":{"color":"black","docType":"car","make":"Tesla","model":"S","owner":"Adriana"}}, 236 {"Key":"CAR5","Record":{"color":"purple","docType":"car","make":"Peugeot","model":"205","owner":"Michel"}}, 237 {"Key":"CAR6","Record":{"color":"white","docType":"car","make":"Chery","model":"S22L","owner":"Aarav"}}, 238 {"Key":"CAR7","Record":{"color":"violet","docType":"car","make":"Fiat","model":"Punto","owner":"Pari"}}, 239 {"Key":"CAR8","Record":{"color":"indigo","docType":"car","make":"Tata","model":"Nano","owner":"Valeria"}}, 240 {"Key":"CAR9","Record":{"color":"brown","docType":"car","make":"Holden","model":"Barina","owner":"Shotaro"}}] 241 242 Let's take a closer look at how `query.js` program uses the APIs provided by the 243 `Fabric Node SDK <https://hyperledger.github.io/fabric-sdk-node/>`__ to 244 interact with our Fabric network. Use an editor (e.g. atom or visual studio) to 245 open ``query.js``. 246 247 The application starts by bringing in scope two key classes from the 248 ``fabric-network`` module; ``Wallets`` and ``Gateway``. These classes 249 will be used to locate the ``appUser`` identity in the wallet, and use it to 250 connect to the network: 251 252 .. code:: bash 253 254 const { Gateway, Wallets } = require('fabric-network'); 255 256 First, the program uses the Wallet class to get our application user from our file system. 257 258 .. code:: bash 259 260 const identity = await wallet.get('appUser'); 261 262 Once the program has an identity, it uses the Gateway class to connect to our network. 263 264 .. code:: bash 265 266 const gateway = new Gateway(); 267 await gateway.connect(ccpPath, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } }); 268 269 ``ccpPath`` describes the path to the connection profile that our application will use 270 to connect to our network. The connection profile was loaded from inside the 271 ``fabric-samples/test network`` directory and parsed as a JSON file: 272 273 .. code:: bash 274 275 const ccpPath = path.resolve(__dirname, '..', '..', 'test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json'); 276 277 If you'd like to understand more about the structure of a connection profile, 278 and how it defines the network, check out 279 `the connection profile topic <./developapps/connectionprofile.html>`_. 280 281 A network can be divided into multiple channels, and the next important line of 282 code connects the application to a particular channel within the network, 283 ``mychannel``, where our smart contract was deployed: 284 285 .. code:: bash 286 287 const network = await gateway.getNetwork('mychannel'); 288 289 Within this channel, we can access the FabCar smart contract to interact 290 with the ledger: 291 292 .. code:: bash 293 294 const contract = network.getContract('fabcar'); 295 296 Within FabCar there are many different **transactions**, and our application 297 initially uses the ``queryAllCars`` transaction to access the ledger world state 298 data: 299 300 .. code:: bash 301 302 const result = await contract.evaluateTransaction('queryAllCars'); 303 304 The ``evaluateTransaction`` method represents one of the simplest interactions 305 with a smart contract in blockchain network. It simply picks a peer defined in 306 the connection profile and sends the request to it, where it is evaluated. The 307 smart contract queries all the cars on the peer's copy of the ledger and returns 308 the result to the application. This interaction does not result in an update the 309 ledger. 310 311 The FabCar smart contract 312 ------------------------- 313 314 Let's take a look at the transactions within the FabCar smart contract. Open a 315 new terminal and navigate to the JavaScript version of the FabCar Smart contract 316 inside the ``fabric-samples`` repository: 317 318 .. code:: bash 319 320 cd fabric-samples/chaincode/fabcar/javascript/lib 321 322 Open the ``fabcar.js`` file in a text editor editor. 323 324 See how our smart contract is defined using the ``Contract`` class: 325 326 .. code:: bash 327 328 class FabCar extends Contract {... 329 330 Within this class structure, you'll see that we have the following 331 transactions defined: ``initLedger``, ``queryCar``, ``queryAllCars``, 332 ``createCar``, and ``changeCarOwner``. For example: 333 334 335 .. code:: bash 336 337 async queryCar(ctx, carNumber) {...} 338 async queryAllCars(ctx) {...} 339 340 Let's take a closer look at the ``queryAllCars`` transaction to see how it 341 interacts with the ledger. 342 343 .. code:: bash 344 345 async queryAllCars(ctx) { 346 347 const startKey = 'CAR0'; 348 const endKey = 'CAR999'; 349 350 const iterator = await ctx.stub.getStateByRange(startKey, endKey); 351 352 353 This code defines the range of cars that ``queryAllCars`` will retrieve from the 354 ledger. Every car between ``CAR0`` and ``CAR999`` -- 1,000 cars in all, assuming 355 every key has been tagged properly -- will be returned by the query. The 356 remainder of the code iterates through the query results and packages them into 357 JSON for the application. 358 359 Below is a representation of how an application would call different 360 transactions in a smart contract. Each transaction uses a broad set of APIs such 361 as ``getStateByRange`` to interact with the ledger. You can read more about 362 these APIs in `detail 363 <https://hyperledger.github.io/fabric-chaincode-node/>`_. 364 365 .. image:: images/RunningtheSample.png 366 367 We can see our ``queryAllCars`` transaction, and another called ``createCar``. 368 We will use this later in the tutorial to update the ledger, and add a new block 369 to the blockchain. 370 371 But first, go back to the ``query`` program and change the 372 ``evaluateTransaction`` request to query ``CAR4``. The ``query`` program should 373 now look like this: 374 375 .. code:: bash 376 377 const result = await contract.evaluateTransaction('queryCar', 'CAR4'); 378 379 Save the program and navigate back to your ``fabcar/javascript`` directory. 380 Now run the ``query`` program again: 381 382 .. code:: bash 383 384 node query.js 385 386 You should see the following: 387 388 .. code:: json 389 390 Wallet path: ...fabric-samples/fabcar/javascript/wallet 391 Transaction has been evaluated, result is: 392 {"color":"black","docType":"car","make":"Tesla","model":"S","owner":"Adriana"} 393 394 If you go back and look at the result from when the transaction was 395 ``queryAllCars``, you can see that ``CAR4`` was Adriana’s black Tesla model S, 396 which is the result that was returned here. 397 398 We can use the ``queryCar`` transaction to query against any car, using its 399 key (e.g. ``CAR0``) and get whatever make, model, color, and owner correspond to 400 that car. 401 402 Great. At this point you should be comfortable with the basic query transactions 403 in the smart contract and the handful of parameters in the query program. 404 405 Time to update the ledger... 406 407 Updating the ledger 408 ------------------- 409 410 Now that we’ve done a few ledger queries and added a bit of code, we’re ready to 411 update the ledger. There are a lot of potential updates we could make, but 412 let's start by creating a **new** car. 413 414 From an application perspective, updating the ledger is simple. An application 415 submits a transaction to the blockchain network, and when it has been 416 validated and committed, the application receives a notification that 417 the transaction has been successful. Under the covers this involves the process 418 of **consensus** whereby the different components of the blockchain network work 419 together to ensure that every proposed update to the ledger is valid and 420 performed in an agreed and consistent order. 421 422 .. image:: tutorial/write_first_app.diagram.2.png 423 424 Above, you can see the major components that make this process work. As well as 425 the multiple peers which each host a copy of the ledger, and optionally a copy 426 of the smart contract, the network also contains an ordering service. The 427 ordering service coordinates transactions for a network; it creates blocks 428 containing transactions in a well-defined sequence originating from all the 429 different applications connected to the network. 430 431 Our first update to the ledger will create a new car. We have a separate program 432 called ``invoke.js`` that we will use to make updates to the ledger. Just as with 433 queries, use an editor to open the program and navigate to the code block where 434 we construct our transaction and submit it to the network: 435 436 .. code:: bash 437 438 await contract.submitTransaction('createCar', 'CAR12', 'Honda', 'Accord', 'Black', 'Tom'); 439 440 See how the applications calls the smart contract transaction ``createCar`` to 441 create a black Honda Accord with an owner named Tom. We use ``CAR12`` as the 442 identifying key here, just to show that we don't need to use sequential keys. 443 444 Save it and run the program: 445 446 .. code:: bash 447 448 node invoke.js 449 450 If the invoke is successful, you will see output like this: 451 452 .. code:: bash 453 454 Wallet path: ...fabric-samples/fabcar/javascript/wallet 455 Transaction has been submitted 456 457 Notice how the ``invoke`` application interacted with the blockchain network 458 using the ``submitTransaction`` API, rather than ``evaluateTransaction``. 459 460 .. code:: bash 461 462 await contract.submitTransaction('createCar', 'CAR12', 'Honda', 'Accord', 'Black', 'Tom'); 463 464 ``submitTransaction`` is much more sophisticated than ``evaluateTransaction``. 465 Rather than interacting with a single peer, the SDK will send the 466 ``submitTransaction`` proposal to every required organization's peer in the 467 blockchain network. Each of these peers will execute the requested smart 468 contract using this proposal, to generate a transaction response which it signs 469 and returns to the SDK. The SDK collects all the signed transaction responses 470 into a single transaction, which it then sends to the orderer. The orderer 471 collects and sequences transactions from every application into a block of 472 transactions. It then distributes these blocks to every peer in the network, 473 where every transaction is validated and committed. Finally, the SDK is 474 notified, allowing it to return control to the application. 475 476 .. note:: ``submitTransaction`` also includes a listener that checks to make 477 sure the transaction has been validated and committed to the ledger. 478 Applications should either utilize a commit listener, or 479 leverage an API like ``submitTransaction`` that does this for you. 480 Without doing this, your transaction may not have been successfully 481 ordered, validated, and committed to the ledger. 482 483 ``submitTransaction`` does all this for the application! The process by which 484 the application, smart contract, peers and ordering service work together to 485 keep the ledger consistent across the network is called consensus, and it is 486 explained in detail in this `section <./peers/peers.html>`_. 487 488 To see that this transaction has been written to the ledger, go back to 489 ``query.js`` and change the argument from ``CAR4`` to ``CAR12``. 490 491 In other words, change this: 492 493 .. code:: bash 494 495 const result = await contract.evaluateTransaction('queryCar', 'CAR4'); 496 497 To this: 498 499 .. code:: bash 500 501 const result = await contract.evaluateTransaction('queryCar', 'CAR12'); 502 503 Save once again, then query: 504 505 .. code:: bash 506 507 node query.js 508 509 Which should return this: 510 511 .. code:: bash 512 513 Wallet path: ...fabric-samples/fabcar/javascript/wallet 514 Transaction has been evaluated, result is: 515 {"color":"Black","docType":"car","make":"Honda","model":"Accord","owner":"Tom"} 516 517 Congratulations. You’ve created a car and verified that its recorded on the 518 ledger! 519 520 So now that we’ve done that, let’s say that Tom is feeling generous and he 521 wants to give his Honda Accord to someone named Dave. 522 523 To do this, go back to ``invoke.js`` and change the smart contract transaction 524 from ``createCar`` to ``changeCarOwner`` with a corresponding change in input 525 arguments: 526 527 .. code:: bash 528 529 await contract.submitTransaction('changeCarOwner', 'CAR12', 'Dave'); 530 531 The first argument --- ``CAR12`` --- identifies the car that will be changing 532 owners. The second argument --- ``Dave`` --- defines the new owner of the car. 533 534 Save and execute the program again: 535 536 .. code:: bash 537 538 node invoke.js 539 540 Now let’s query the ledger again and ensure that Dave is now associated with the 541 ``CAR12`` key: 542 543 .. code:: bash 544 545 node query.js 546 547 It should return this result: 548 549 .. code:: bash 550 551 Wallet path: ...fabric-samples/fabcar/javascript/wallet 552 Transaction has been evaluated, result is: 553 {"color":"Black","docType":"car","make":"Honda","model":"Accord","owner":"Dave"} 554 555 The ownership of ``CAR12`` has been changed from Tom to Dave. 556 557 .. note:: In a real world application the smart contract would likely have some 558 access control logic. For example, only certain authorized users may 559 create new cars, and only the car owner may transfer the car to 560 somebody else. 561 562 Clean up 563 -------- 564 565 When you are finished using the FabCar sample, you can bring down the test 566 network using ``networkDown.sh`` script. 567 568 569 .. code:: bash 570 571 ./networkDown.sh 572 573 This command will bring down the CAs, peers, and ordering node of the network 574 that we created. It will also remove the ``admin`` and ``appUser`` crypto material stored 575 in the ``wallet`` directory. Note that all of the data on the ledger will be lost. 576 If you want to go through the tutorial again, you will start from a clean initial state. 577 578 Summary 579 ------- 580 581 Now that we’ve done a few queries and a few updates, you should have a pretty 582 good sense of how applications interact with a blockchain network using a smart 583 contract to query or update the ledger. You’ve seen the basics of the roles 584 smart contracts, APIs, and the SDK play in queries and updates and you should 585 have a feel for how different kinds of applications could be used to perform 586 other business tasks and operations. 587 588 Additional resources 589 -------------------- 590 591 As we said in the introduction, we have a whole section on 592 :doc:`developapps/developing_applications` that includes in-depth information on 593 smart contracts, process and data design, a tutorial using a more in-depth 594 Commercial Paper `tutorial <./tutorial/commercial_paper.html>`_ and a large 595 amount of other material relating to the development of applications. 596 597 .. Licensed under Creative Commons Attribution 4.0 International License 598 https://creativecommons.org/licenses/by/4.0/