The original address: www.xuanzhangjiong.top/2019/04/16/…

Author: TopJohn

Develop your first blockchain application using Hyperledger Fabric

The examples for this article are derived from fabcar github.com/hyperledger…

In this example, we use a simple sample program to see how the Fabric application works. The application and smart contract (chain code) used in this example are collectively called FabCar. This example provides a good starting point for understanding Hyperledger Fabric. Here, you’ll learn how to develop an application and smart contract to query and update ledgers, and how to leverage CA to generate x.509 certificates that an application needs to interact with the blockchain.

We use the application SDk to perform the query and update ledger operations in the smart contract with the help of the underlying interface in the smart contract.

We will explain it in three steps:

  1. Set up the development environment. Our application needs to interact with the network, so we need a smart contract and the underlying network that the application uses.

  1. Learn a simple smart contract, FabCar. We use JavaScript to develop smart contracts. We looked at smart contracts to learn how applications use them to send transactions and to query and update ledgers.

  2. Develop a simple application using FabCar. Our application uses the FabCar smart contract to query and update the automotive assets on the ledger. We will go into the code of the application to learn how to create a transaction, including querying information about a car, querying information about a batch of cars, and creating a car.

Set up the blockchain network

Note: The following section needs to go to the first-network subdirectory of the Fabric-samples repository that you cloned locally.

If you’ve already studied Building Your First Network, you should have downloaded fabric-samples and have a Network up and running. Before you proceed with this tutorial, you need to stop the network:

./byfn.sh down
Copy the code

If you have run this tutorial before, use the following command to close any stopped or running containers. Note that this closes all containers, whether or not they are related to Fabric.

docker rm -f $(docker ps -aq)
docker rmi -f $(docker images | grep fabcar | awk '{print $3}')
Copy the code

If you do not have the Network and application-related development environment and artifacts, visit the Prerequisites page to make sure your machine has the necessary dependencies installed.

Next, if you haven’t already done so, browse the Install Samples, Binaries, and Docker Images page and follow the steps above. Return to the tutorial once you have cloned the Fabric-samples repository and downloaded the latest stable version of the Fabric image and related tools.

If you’re using Mac OS and Mojava, you’ll need to have Xcode installed.

Start the network

The following section needs to go into the Fabcar subdirectory of the Fabric-samples repository.

Use startFabric.sh to start your network. This command will start a blockchain network consisting of peer nodes, sorting nodes, certificate authorization services, and so on. We will also install and initialize the javascript version of the FabCar smart contract that our application will use to manipulate the ledger. We’ll learn more about these components through this tutorial.

./startFabric.sh javascript
Copy the code

We now have a sample network up and running and the FabCar smart contract installed and initialized. To run our application, we need to install some dependencies, and let’s see how they work in the meantime.

Installing the application

Note: The following sections need to go into the Fabcar /javascript subdirectory of the Fabric-samples repository that you cloned locally. The following command installs the fabric-related dependencies required by the application. It will take about 1 minute:

npm install
Copy the code

This directive is used to install the dependencies required by the application, which are defined in package.json. The most important of these is the fabric-Network class; It enables applications to use identities, wallets, and gateways to connect to channels, as well as to submit transactions and wait for notifications. This tutorial will also use the Fabric-ca-Client class to register users and their authorization certificates, generating a legitimate identity for use by the Fabric-Network.

Once NPM Install executes successfully, everything is ready to run the application. In this tutorial, you will mainly use javascript files in the fabcar/javascript directory to manipulate the application. Let’s take a look at what’s inside:

ls
Copy the code

You will see the following files:

enrollAdmin.js  node_modules       package.json  registerUser.js
invoke.js       package-lock.json  query.js      wallet
Copy the code

There are also files for other programming languages, such as the Fabcar /typescript directory. Once you’ve used the JavaScript examples – they’re all similar.

If you’re using a Mac OS and running a Mojava you need to install Xcode (https://hyperledger-fabric.readthedocs.io/en/latest/tutorial/installxcode.html).

Registering administrator Users

The following sections cover the process of communicating with the CA server. It may be helpful to open a terminal and execute docker logs -f ca.example.com to view CA logs while executing the following program.

When we create the network, a user named admin has been created by the authorization server (CA) as the registrar. Our first step is to use the enrolle.js program to generate the private key, public key, and X.509 certificate for admin. The program uses a certificate Signing Request (CSR)– the private and public keys are generated locally, and the public key is sent to a CA, which publishes a certificate for use by the application. These three credentials will be kept in the wallet so that we can use the CA as an administrator.

Next we will register and enroll a new application user that we will use to interact with the blockchain through the application.

Let’s register an admin user:

node enrollAdmin.js
Copy the code

This command saves the CA administrator certificate in the Wallet directory.

Registration and registrationuser1

Now that we have the administrator’s credentials in our wallet, we can register a new user –user1– with which to query and update the ledger:

node registerUser.js
Copy the code

Similar to registering administrators, this program uses CSR to register user1 and save its certificate to admin’s wallet. Now we have two separate users –admin and user1– both of which will be used for our application.

Next up is ledger interaction time…

Query book

Each node in the blockchain network has a copy of the ledger, and the application can query the ledger operation by performing the smart contract query for the latest creep on the ledger, returning the results to the application.

Here’s a quick explanation of how to query:

The application uses a query to read data from ledger. The most common is to query the latest value in the current ledger – the state of the world. The world state is a collection of key-value pairs that an application can query for data based on one or more keys. Furthermore, when key-value pairs exist in JSON form, world states can be configured to support rich queries using databases such as CouchDB. This feature is useful for querying values that match specific keys, such as all of a person’s cars.

First, let’s use the query.js program to query all the cars on the ledger. This program uses our second identity, User1, to manipulate the ledger.

node query.js
Copy the code

The following output is displayed:

Wallet path: ... fabric-samples/fabcar/javascript/wallet Transaction has been evaluated, result is: [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}}, {"Key":"CAR1", "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}}, {"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}}, {"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}}, {"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}}, {"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}}, {"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}}, {"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}}, {"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}}, {"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}]Copy the code

Let’s take a closer look at the program. Open Query.js using a text editor such as Atom or Visual Studio.

The application starts with the introduction of two key classes FileSystemWallet and Gateway from the Fabric-Network module. These two classes will be used to locate the identity of User1 in the wallet and use this identity to connect to the network:

const { FileSystemWallet, Gateway } = require('fabric-network');
Copy the code

Applications use gateways to connect to the network:

const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'user1' });
Copy the code

This code creates a new gateway through which the application can connect to the network. CPP describes the gateway connecting to the network through user1 in the Wallet. Open.. /.. Json to see how CPP parses a JSON file: /basic-network/connection.json

const ccpPath = path.resolve(__dirname, '.. '.'.. '.'basic-network'.'connection.json');
const ccpJSON = fs.readFileSync(ccpPath, 'utf8');
const ccp = JSON.parse(ccpJSON);
Copy the code

If you want to learn more about the structure of a connection profile and how it defines a network, check out the Connection Profile Topic

A network can be split into many channels, and the next important part of the code is to connect the application to a particular channel, MyChannel:

In this channel, we can interact with the ledger via fabCar smart contract:

const contract = network.getContract('fabcar');
Copy the code

There are many different transactions in FabCar, and our application starts with queryAllCars transactions to query the world state of the ledger:

const result = await contract.evaluateTransaction('queryAllCars');
Copy the code

The evaluateTransaction method presents one of the simplest ways to interact with smart contracts in a blockchain network. It simply connects to a node as defined in the configuration file, sends a request to the node, and executes the request within the node. The smart contract queries all the cars on the node ledger and returns the results to the application. This interaction did not update the ledger.

FabCar smart contract

Let’s take a look at the transactions in FabCar smart contracts. Into the subdirectory of the fabric – samples chaincode/fabcar/javascript/lib, then use your editor opens fabcar. Js.

Take a look at how our smart Contract is defined by the Contract class:

class FabCar extends Contract {...
Copy the code

In this class structure, you will see the following transactions defined: initLedger, queryCar, queryAllCars, createCar, and changeCarOwner. Such as:

asyncqueryCar(ctx, carNumber) {... }asyncqueryAllCars(ctx) {... }Copy the code

Let’s take a closer look at queryAllCars and see how it interacts with the ledger.

async queryAllCars(ctx) {

  const startKey = 'CAR0';
  const endKey = 'CAR999';

  const iterator = await ctx.stub.getStateByRange(startKey, endKey);
Copy the code

This code defines the range of cars that queryAllCars will fetch from the ledger. Every car from CAR0 to CAR999 — a total of 1,000 cars, assuming each key is properly anchored — will be returned as a result of the query. The rest of the code is iterated to package the query results into JSON and return them to the application.

The following shows how the application invokes the different transactions in the smart contract. Each transaction uses a set of apis such as getStateByRange to interact with the ledger. For more information about the API, see detail.

You can see our queryAllCars deal, and another one called createCar. We’ll use them later in the tutorial to update the ledger and add new blocks.

But before that, go back to the Query program and change the request for evaluateTransaction to be queried as CAR4. The query program now looks like this:

const result = await contract.evaluateTransaction('queryCar'.'CAR4');
Copy the code

Save the program and return to the fabcar/javascript directory. Now run the query program again:

node query.js
Copy the code

You should see something like this:

Wallet path: ... fabric-samples/fabcar/javascript/wallet Transaction has been evaluated, result is: {"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}Copy the code

If you look at the results of the previous queryAllCars transaction, you will see that CAR4 is Adriana’s black Tesla Model S, which is the result returned here, which is the same.

We can use queryCar transactions to query any car, using its keys (such as CAR0) to get information about the make, model, color and owner of the car.

Very good. You should now understand the basic query transactions in smart contracts and have manually modified the parameters in the query program.

It’s time to update the books.

Update the books

Now that we’ve done some querying of the ledger and added some code, we’re ready to update the ledger. There’s a lot of updating we can do, but we start by creating a new car.

From an application perspective, updating a ledger is simple. The application submits a transaction to the blockchain network, and when the transaction is validated and submitted, the application receives a reminder that the transaction was successful. But underneath, the different consensus programs in each component of the blockchain network work together to ensure that every proposal to update the ledger is legal and in an agreed-upon order.

In the figure above, we can see the main components that accomplish this task. At the same time, each of the multiple nodes has a copy of the ledger, and optionally a copy of the smart contract, and there is a sorting service in the network. Sorting service ensures the consistency of transactions in the network. It also generates blocks in a defined order for transactions connected to different applications in the network.

Our first update to the ledger was to create a new car. We have a separate program called invoke.js that updates the ledger. As with queries, use an editor opener to locate the snippet of code where we build and submit transactions to the network:

await contract.submitTransaction('createCar'.'CAR12'.'Honda'.'Accord'.'Black'.'Tom');
Copy the code

Take a look at how the application invokes the smart contract transaction createCar to create a black Honda Accord car owned by Tom. We use CAR12 as the key here, which also shows that we don’t have to use consecutive keys.

Save and run the program:

node invoke.js
Copy the code

If the execution succeeds, you should see something like:

Wallet path: ... Fabric samples/fabcar/javascript/wallet T14:2018-12-11 at 11:40. 935 z - info: [TransactionEventHandler] : _strategySuccess: strategy success for transaction "9076cd4279a71ecf99665aed0ed3590a25bba040fa6b4dd6d010f42bb26ff5d1" Transaction has been  submittedCopy the code

Note that inovke uses the submitTransactionAPI to interact with the blockchain network, not evaluateTransaction.

await contract.submitTransaction('createCar'.'CAR12'.'Honda'.'Accord'.'Black'.'Tom');
Copy the code

SubmitTransaction is much more complex than evaluateTransaction. Instead of just interacting with individual nodes, the SDK will send submitTransaction proposals to nodes of every necessary organization in the blockchain network. Each node will execute the requested smart contract based on this proposal and generate a transaction response signed by the node and sent back to the SDK. The SDK collects all signed transaction responses into a single transaction, which is sent to the sorting node. The sort node collects and sorts each application’s transactions and puts them into a transaction block. The sorting nodes then distribute these blocks to nodes in the network, where each transaction is validated and committed. Finally, the SDK alerts you after the session and returns control to the application.

SubmitTransaction also includes a listener to ensure that the transaction has been validated and committed to the ledger. The application needs to utilize listeners or use the submitTransaction interface, which already implements listeners internally. Without a listener, you may not be able to determine whether a transaction is sorted, verified and committed.

This work in the application is done by submitTransaction! A program in which applications, smart contracts, nodes, and sorting services work together to ensure ledger consistency across a network is called consensus.

To see the transaction being written to the ledger, go back to Query.js and change the parameter CAR4 to CAR12.

In other words:

const result = await contract.evaluateTransaction('queryCar'.'CAR4');
Copy the code

To:

const result = await contract.evaluateTransaction('queryCar'.'CAR12');
Copy the code

Save again and query:

node query.js
Copy the code

Returns:

Wallet path: ... fabric-samples/fabcar/javascript/wallet Transaction has been evaluated, result is: {"colour":"Black","make":"Honda","model":"Accord","owner":"Tom"}Copy the code

Congratulations. You created a car and verified it on the ledger!

Now that we’re done, let’s say Tom is generous and wants to give his Honda Accord to someone named Dave.

To do this, return to invoke.js and change the smart contract transaction from createCar to changeCarOwner using the input parameters:

await contract.submitTransaction('changeCarOwner'.'CAR12'.'Dave');
Copy the code

The first parameter, CAR12, indicates the vehicle to be changed ownership. The second parameter, Dave, represents the new owner of the car.

Save and execute the program again:

node invoke.js
Copy the code

Now let’s query the ledger again to make sure Dave and CAR12 are associated:

node query.js
Copy the code

The following result is returned:

Wallet path: ... fabric-samples/fabcar/javascript/wallet Transaction has been evaluated, result is: {"colour":"Black","make":"Honda","model":"Accord","owner":"Dave"}Copy the code

CAR12’s owner has changed from Tom to Dave.

In practice, smart contracts have permission control logic. For example, only authorized users can create new cars, and only car owners can transfer ownership.

conclusion

Now that we’ve finished querying and updating the ledgers, you should have a good understanding of how to query and update the ledgers using smart contracts and blockchain interactions. Smart contracts for querying and updating, apis, and SDKS have been covered in this tutorial, so you have a good understanding of other business scenarios as well.

Using the FabCar example, we can quickly learn how to develop applications based on the Node SDK.