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/