github.com/kaituanwang/hyperledger@v2.0.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 In this tutorial we'll be looking at a handful of sample programs to see how 16 Fabric apps work. These applications and the smart contracts they use are 17 collectively known as ``FabCar``. They provide a great starting point to 18 understand a Hyperledger Fabric blockchain. You'll learn how to write an 19 application and smart contract to query and update a ledger, and how to use a 20 Certificate Authority to generate the X.509 certificates used by applications 21 which interact with a permissioned blockchain. 22 23 We will use the application SDK --- described in detail in the 24 :doc:`/developapps/application` topic -- to invoke a smart contract which 25 queries and updates the ledger using the smart contract SDK --- described in 26 detail in section :doc:`/developapps/smartcontract`. 27 28 We’ll go through three principle steps: 29 30 **1. Setting up a development environment.** Our application needs a network 31 to interact with, so we'll get a basic network our smart contracts and 32 application will use. 33 34 .. image:: images/AppConceptsOverview.png 35 36 **2. Learning about a sample smart contract, FabCar.** 37 We’ll inspect the smart contract to learn about the transactions within them, 38 and how they are used by applications to query and update the ledger. 39 40 **3. Develop a sample application which uses FabCar.** Our application will 41 use the FabCar smart contract to query and update car assets on the ledger. 42 We'll get into the code of the apps and the transactions they create, 43 including querying a car, querying a range of cars, and creating a new car. 44 45 After completing this tutorial you should have a basic understanding of how an 46 application is programmed in conjunction with a smart contract to interact with 47 the ledger hosted and replicated on the peers in a Fabric network. 48 49 .. note:: These applications are also compatible with :doc:`discovery-overview` 50 and :doc:`private-data/private-data`, though we won't explicitly show 51 how to use our apps to leverage those features. 52 53 Set up the blockchain network 54 ----------------------------- 55 56 .. note:: This next section requires you to be in the ``first-network`` 57 subdirectory within your local clone of the ``fabric-samples`` repo. 58 59 If you've already run through :doc:`build_network`, you will have downloaded 60 ``fabric-samples`` and have a network up and running. Before you run this 61 tutorial, you must stop this network: 62 63 .. code:: bash 64 65 ./byfn.sh down 66 67 If you have run through this tutorial before, use the following commands to 68 kill any stale or active containers. Note, this will take down **all** of your 69 containers whether they're Fabric related or not. 70 71 .. code:: bash 72 73 docker rm -f $(docker ps -aq) 74 docker rmi -f $(docker images | grep fabcar | awk '{print $3}') 75 76 If you don't have a development environment and the accompanying artifacts for 77 the network and applications, visit the :doc:`prereqs` page and ensure you have 78 the necessary dependencies installed on your machine. 79 80 Next, if you haven't done so already, visit the :doc:`install` page and follow 81 the provided instructions. Return to this tutorial once you have cloned the 82 ``fabric-samples`` repository, and downloaded the latest stable Fabric images 83 and available utilities. 84 85 If you are using Mac OS and running Mojave, you will need to `install Xcode 86 <./tutorial/installxcode.html>`_. 87 88 Launch the network 89 ^^^^^^^^^^^^^^^^^^ 90 91 .. note:: This next section requires you to be in the ``fabcar`` 92 subdirectory within your local clone of the ``fabric-samples`` repo. 93 94 This tutorial demonstrates the JavaScript versions of the ``FabCar`` 95 smart contract and application, but the ``fabric-samples`` repo also 96 contains Go, Java and TypeScript versions of this sample. To try the 97 Go, Java or TypeScript versions, change the ``javascript`` argument 98 for ``./startFabric.sh`` below to either ``go``, ``java`` or ``typescript`` 99 and follow the instructions written to the terminal. 100 101 Launch your network using the ``startFabric.sh`` shell script. This command will 102 spin up a blockchain network comprising peers, orderers, certificate 103 authorities and more. It will also install and instantiate a JavaScript version 104 of the ``FabCar`` smart contract which will be used by our application to access 105 the ledger. We'll learn more about these components as we go through the 106 tutorial. 107 108 .. code:: bash 109 110 ./startFabric.sh javascript 111 112 Alright, you’ve now got a sample network up and running, and the ``FabCar`` 113 smart contract installed and instantiated. Let’s install our application 114 pre-requisites so that we can try it out, and see how everything works together. 115 116 Install the application 117 ^^^^^^^^^^^^^^^^^^^^^^^ 118 119 .. note:: The following instructions require you to be in the 120 ``fabcar/javascript`` subdirectory within your local clone of the 121 ``fabric-samples`` repo. 122 123 Run the following command to install the Fabric dependencies for the 124 applications. It will take about a minute to complete: 125 126 .. code:: bash 127 128 npm install 129 130 This process is installing the key application dependencies defined in 131 ``package.json``. The most important of which is the ``fabric-network`` class; 132 it enables an application to use identities, wallets, and gateways to connect to 133 channels, submit transactions, and wait for notifications. This tutorial also 134 uses the ``fabric-ca-client`` class to enroll users with their respective 135 certificate authorities, generating a valid identity which is then used by 136 ``fabric-network`` class methods. 137 138 Once ``npm install`` completes, everything is in place to run the application. 139 For this tutorial, you'll primarily be using the application JavaScript files in 140 the ``fabcar/javascript`` directory. Let's take a look at what's inside: 141 142 .. code:: bash 143 144 ls 145 146 You should see the following: 147 148 .. code:: bash 149 150 enrollAdmin.js node_modules package.json registerUser.js 151 invoke.js package-lock.json query.js wallet 152 153 There are files for other program languages, for example in the 154 ``fabcar/typescript`` directory. You can read these once you've used the 155 JavaScript example -- the principles are the same. 156 157 If you are using Mac OS and running Mojave, you will need to `install Xcode 158 <./tutorial/installxcode.html>`_. 159 160 Enrolling the admin user 161 ------------------------ 162 163 .. note:: The following two sections involve communication with the Certificate 164 Authority. You may find it useful to stream the CA logs when running 165 the upcoming programs by opening a new terminal shell and running 166 ``docker logs -f ca.example.com``. 167 168 When we created the network, an admin user --- literally called ``admin`` --- 169 was created as the **registrar** for the certificate authority (CA). Our first 170 step is to generate the private key, public key, and X.509 certificate for 171 ``admin`` using the ``enroll.js`` program. This process uses a **Certificate 172 Signing Request** (CSR) --- the private and public key are first generated 173 locally and the public key is then sent to the CA which returns an encoded 174 certificate for use by the application. These three credentials are then stored 175 in the wallet, allowing us to act as an administrator for the CA. 176 177 We will subsequently register and enroll a new application user which will be 178 used by our application to interact with the blockchain. 179 180 Let's enroll user ``admin``: 181 182 .. code:: bash 183 184 node enrollAdmin.js 185 186 This command has stored the CA administrator's credentials in the ``wallet`` 187 directory. 188 189 Register and enroll ``user1`` 190 ----------------------------- 191 192 Now that we have the administrator's credentials in a wallet, we can enroll a 193 new user --- ``user1`` --- which will be used to query and update the ledger: 194 195 .. code:: bash 196 197 node registerUser.js 198 199 Similar to the admin enrollment, this program uses a CSR to enroll ``user1`` and 200 store its credentials alongside those of ``admin`` in the wallet. We now have 201 identities for two separate users --- ``admin`` and ``user1`` --- and these are 202 used by our application. 203 204 Time to interact with the ledger... 205 206 Querying the ledger 207 ------------------- 208 209 Each peer in a blockchain network hosts a copy of the ledger, and an application 210 program can query the ledger by invoking a smart contract which queries the most 211 recent value of the ledger and returns it to the application. 212 213 Here is a simplified representation of how a query works: 214 215 .. image:: tutorial/write_first_app.diagram.1.png 216 217 Applications read data from the `ledger <./ledger/ledger.html>`_ using a query. 218 The most common queries involve the current values of data in the ledger -- its 219 `world state <./ledger/ledger.html#world-state>`_. The world state is 220 represented as a set of key-value pairs, and applications can query data for a 221 single key or multiple keys. Moreover, the ledger world state can be configured 222 to use a database like CouchDB which supports complex queries when key-values 223 are modeled as JSON data. This can be very helpful when looking for all assets 224 that match certain keywords with particular values; all cars with a particular 225 owner, for example. 226 227 First, let's run our ``query.js`` program to return a listing of all the cars on 228 the ledger. This program uses our second identity -- ``user1`` -- to access the 229 ledger: 230 231 .. code:: bash 232 233 node query.js 234 235 The output should look like this: 236 237 .. code:: json 238 239 Wallet path: ...fabric-samples/fabcar/javascript/wallet 240 Transaction has been evaluated, result is: 241 [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}}, 242 {"Key":"CAR1", "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}}, 243 {"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}}, 244 {"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}}, 245 {"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}}, 246 {"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}}, 247 {"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}}, 248 {"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}}, 249 {"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}}, 250 {"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}] 251 252 Let's take a closer look at this program. Use an editor (e.g. atom or visual 253 studio) and open ``query.js``. 254 255 The application starts by bringing in scope two key classes from the 256 ``fabric-network`` module; ``FileSystemWallet`` and ``Gateway``. These classes 257 will be used to locate the ``user1`` identity in the wallet, and use it to 258 connect to the network: 259 260 .. code:: bash 261 262 const { FileSystemWallet, Gateway } = require('fabric-network'); 263 264 The application connects to the network using a gateway: 265 266 .. code:: bash 267 268 const gateway = new Gateway(); 269 await gateway.connect(ccp, { wallet, identity: 'user1' }); 270 271 This code creates a new gateway and then uses it to connect the application to 272 the network. ``ccp`` describes the network that the gateway will access with the 273 identity ``user1`` from ``wallet``. See how the ``ccp`` has been loaded from 274 ``../../first-network/connection.json`` and parsed as a JSON file: 275 276 .. code:: bash 277 278 const ccpPath = path.resolve(__dirname, '..', '..', 'first-network', 'connection.json'); 279 const ccpJSON = fs.readFileSync(ccpPath, 'utf8'); 280 const ccp = JSON.parse(ccpJSON); 281 282 If you'd like to understand more about the structure of a connection profile, 283 and how it defines the network, check out 284 `the connection profile topic <./developapps/connectionprofile.html>`_. 285 286 A network can be divided into multiple channels, and the next important line of 287 code connects the application to a particular channel within the network, 288 ``mychannel``: 289 290 .. code:: bash 291 292 const network = await gateway.getNetwork('mychannel'); 293 294 Within this channel, we can access the smart contract ``fabcar`` to interact 295 with the ledger: 296 297 .. code:: bash 298 299 const contract = network.getContract('fabcar'); 300 301 Within ``fabcar`` there are many different **transactions**, and our application 302 initially uses the ``queryAllCars`` transaction to access the ledger world state 303 data: 304 305 .. code:: bash 306 307 const result = await contract.evaluateTransaction('queryAllCars'); 308 309 The ``evaluateTransaction`` method represents one of the simplest interaction 310 with a smart contract in blockchain network. It simply picks a peer defined in 311 the connection profile and sends the request to it, where it is evaluated. The 312 smart contract queries all the cars on the peer's copy of the ledger and returns 313 the result to the application. This interaction does not result in an update the 314 ledger. 315 316 The FabCar smart contract 317 ------------------------- 318 319 Let's take a look at the transactions within the ``FabCar`` smart contract. 320 Navigate to the ``chaincode/fabcar/javascript/lib`` subdirectory at the root of 321 ``fabric-samples`` and open ``fabcar.js`` in your editor. 322 323 See how our smart contract is defined using the ``Contract`` class: 324 325 .. code:: bash 326 327 class FabCar extends Contract {... 328 329 Within this class structure, you'll see that we have the following 330 transactions defined: ``initLedger``, ``queryCar``, ``queryAllCars``, 331 ``createCar``, and ``changeCarOwner``. For example: 332 333 334 .. code:: bash 335 336 async queryCar(ctx, carNumber) {...} 337 async queryAllCars(ctx) {...} 338 339 Let's take a closer look at the ``queryAllCars`` transaction to see how it 340 interacts with the ledger. 341 342 .. code:: bash 343 344 async queryAllCars(ctx) { 345 346 const startKey = 'CAR0'; 347 const endKey = 'CAR999'; 348 349 const iterator = await ctx.stub.getStateByRange(startKey, endKey); 350 351 352 This code defines the range of cars that ``queryAllCars`` will retrieve from the 353 ledger. Every car between ``CAR0`` and ``CAR999`` -- 1,000 cars in all, assuming 354 every key has been tagged properly -- will be returned by the query. The 355 remainder of the code iterates through the query results and packages them into 356 JSON for the application. 357 358 Below is a representation of how an application would call different 359 transactions in a smart contract. Each transaction uses a broad set of APIs such 360 as ``getStateByRange`` to interact with the ledger. You can read more about 361 these APIs in `detail 362 <https://hyperledger.github.io/fabric-chaincode-node/>`_. 363 364 .. image:: images/RunningtheSample.png 365 366 We can see our ``queryAllCars`` transaction, and another called ``createCar``. 367 We will use this later in the tutorial to update the ledger, and add a new block 368 to the blockchain. 369 370 But first, go back to the ``query`` program and change the 371 ``evaluateTransaction`` request to query ``CAR4``. The ``query`` program should 372 now look like this: 373 374 .. code:: bash 375 376 const result = await contract.evaluateTransaction('queryCar', 'CAR4'); 377 378 Save the program and navigate back to your ``fabcar/javascript`` directory. 379 Now run the ``query`` program again: 380 381 .. code:: bash 382 383 node query.js 384 385 You should see the following: 386 387 .. code:: json 388 389 Wallet path: ...fabric-samples/fabcar/javascript/wallet 390 Transaction has been evaluated, result is: 391 {"colour":"black","make":"Tesla","model":"S","owner":"Adriana"} 392 393 If you go back and look at the result from when the transaction was 394 ``queryAllCars``, you can see that ``CAR4`` was Adriana’s black Tesla model S, 395 which is the result that was returned here. 396 397 We can use the ``queryCar`` transaction to query against any car, using its 398 key (e.g. ``CAR0``) and get whatever make, model, color, and owner correspond to 399 that car. 400 401 Great. At this point you should be comfortable with the basic query transactions 402 in the smart contract and the handful of parameters in the query program. 403 404 Time to update the ledger... 405 406 Updating the ledger 407 ------------------- 408 409 Now that we’ve done a few ledger queries and added a bit of code, we’re ready to 410 update the ledger. There are a lot of potential updates we could make, but 411 let's start by creating a **new** car. 412 413 From an application perspective, updating the ledger is simple. An application 414 submits a transaction to the blockchain network, and when it has been 415 validated and committed, the application receives a notification that 416 the transaction has been successful. Under the covers this involves the process 417 of **consensus** whereby the different components of the blockchain network work 418 together to ensure that every proposed update to the ledger is valid and 419 performed in an agreed and consistent order. 420 421 .. image:: tutorial/write_first_app.diagram.2.png 422 423 Above, you can see the major components that make this process work. As well as 424 the multiple peers which each host a copy of the ledger, and optionally a copy 425 of the smart contract, the network also contains an ordering service. The 426 ordering service coordinates transactions for a network; it creates blocks 427 containing transactions in a well-defined sequence originating from all the 428 different applications connected to the network. 429 430 Our first update to the ledger will create a new car. We have a separate program 431 called ``invoke.js`` that we will use to make updates to the ledger. Just as with 432 queries, use an editor to open the program and navigate to the code block where 433 we construct our transaction and submit it to the network: 434 435 .. code:: bash 436 437 await contract.submitTransaction('createCar', 'CAR12', 'Honda', 'Accord', 'Black', 'Tom'); 438 439 See how the applications calls the smart contract transaction ``createCar`` to 440 create a black Honda Accord with an owner named Tom. We use ``CAR12`` as the 441 identifying key here, just to show that we don't need to use sequential keys. 442 443 Save it and run the program: 444 445 .. code:: bash 446 447 node invoke.js 448 449 If the invoke is successful, you will see output like this: 450 451 .. code:: bash 452 453 Wallet path: ...fabric-samples/fabcar/javascript/wallet 454 2018-12-11T14:11:40.935Z - info: [TransactionEventHandler]: _strategySuccess: strategy success for transaction "9076cd4279a71ecf99665aed0ed3590a25bba040fa6b4dd6d010f42bb26ff5d1" 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 orderered, 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 {"colour":"Black","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 {"colour":"Black","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 Summary 563 ------- 564 565 Now that we’ve done a few queries and a few updates, you should have a pretty 566 good sense of how applications interact with a blockchain network using a smart 567 contract to query or update the ledger. You’ve seen the basics of the roles 568 smart contracts, APIs, and the SDK play in queries and updates and you should 569 have a feel for how different kinds of applications could be used to perform 570 other business tasks and operations. 571 572 Additional resources 573 -------------------- 574 575 As we said in the introduction, we have a whole section on 576 :doc:`developapps/developing_applications` that includes in-depth information on 577 smart contracts, process and data design, a tutorial using a more in-depth 578 Commercial Paper `tutorial <./tutorial/commercial_paper.html>`_ and a large 579 amount of other material relating to the development of applications. 580 581 .. Licensed under Creative Commons Attribution 4.0 International License 582 https://creativecommons.org/licenses/by/4.0/