Chaincode Invoke and Query

Overview

In a typical Hyperledger Fabric design, a fabric network provides the infrastructure, and application chaincode implementing the business logic is deployed on the network. When we are using this application, our actions eventually reach the fabric network and chaincode in one of the two ways: chaincode function invoke or chaincode function query. Invoking chaincode function results in new block creation and ledger update, while querying chaincode function retrieves information from ledger without ledger updating.

Command Line Interface (CLI) is one of the tools we always use during chaincode developing and testing. Inside CLI, we can issue commands to perform various tasks on fabric network and chaincode. In actual real deployment, instead of using CLI, there are always client applications front-ending the fabric network. Client application is developed in various common coding environments, such as JavaScript, Java, etc, with Software Development Kit (SDK) in these environments.

In this article we wish to achieve two objectives. First, we will observe the overall transaction processing. The transaction flow begins with the client sending a transaction proposal to selected endorsing peers, and ends in a new block received and committed in peers. By reading the logs of various components in a fabric network, we will construct back the whole flow. We use CLI to perform this observation. Secondly, we observe the difference between CLI and client application, and see how Service Discovery helps to achieve a level of high availability in fabric networks.

Quick Review

Assuming a fabric network is running and a chaincode is deployed properly. The two actions that a user (client) is interacting with this fabric network is chaincode function invoke and query. In both cases a transaction is created and sent to the fabric network. But the purpose, the flow, and result is quite different.

Chaincode Function Invoke

Chaincode function invoke is a transaction reflecting a real business transaction. A quick example is that Alice sends Bob 100 shares. It is always an execution of business logic and the result is an update in the ledger (world state), reflecting this business transaction. In fabric networks, the business logic execution is done by selected endorsers (endorsing peers). Eventually a new block is received containing the endorsement result and all peers in a channel will commit the block and update the world state.

Assuming we have a fabric network with chaincode deployed. Put aside a lot of variation and “what-if”, here is a quick flow on what happens behind

  1. Client sends a transaction proposal to selected peers for endorsement (endorsers), according to endorsement policy.
  2. Endorsers process this proposal in their chaincode container independently, and the result is a Read Write Set (RWSet). Each endorser signs the result and returns the proposal response to client.
  3. After validating the proposal response, client creates a transaction with the proposal and endorsements received from endorsers, and sends the transaction to ordering service.
  4. After validating the transaction (plus others), ordering service collects these transactions, has them ordered and packed into a block. This block is broadcast to all peers in this channel.
  5. Peers in this channel receive a new block from ordering service. Each peer validates the block and the transactions inside. Assuming everything is good, each peer commits the block and updates the ledger according to the endorsement results.
Image for post
Image for post
Transaction flow after chaincode function is invoked by a client.

You can also refer to the transaction flow described in the fabric documentation here.

Chaincode Function Query

Chaincode function query, as the name suggests, is a transaction reflecting a query on the ledger (world state). A quick example is that Alice checks her balance. It can be simply a retrieval of data from ledger, or performing some computation according to the business logic. The result is sent back to client, and the process ends here. There will be no update on the ledger, no involvement of new block creation and of ordering service.

Service Discovery

Besides these two major topics above, we will encounter another handy service provided in fabric network: Service Discovery. In a nutshell, Service Discovery gives the latest information about the fabric network and chaincode deployment. This piece of information is useful or needed in many situations, and one of them is in client application. We will see this later. For a quick introduction, refer here in the fabric documentation.

With this quick introduction, we will take a look at our setup.

Setup

Our demonstration is using First Network from fabric-samples. First Network comes with two peers for each peer organization, which is good for observation. We are using Fabcar, also from fabric-samples, to show both CLI and client applications with SDK.

Everything is being brought up using the script inside . Note that in the script,

  • The chaincode is being installed in all the four peers, and therefore each of them can perform chaincode endorsement and query.
  • The endorsement policy when chaincode is instantiated requires one endorsement from each organization.

The demonstration is done with Fabric v1.4. The choice is just due to demonstration consideration. In Fabric v2.0 much material is being rewritten. And the script in Fabcar in v2.0 is using Test Network, not First Network. Test Network comes with only one peer in one peer organization. This does not give us the best result, as we wish to see two peers in each organization. Therefore we choose Fabric v1.4 for demonstration. Nevertheless, the transaction flow is not changed a lot between v1.4 and v2.0, and what we observe here is largely applicable to v2.0.

Instead of focusing the general output, in this demonstration we will trace the logs from various containers in order to capture the full picture. This helps us understand the transaction flow. The command to get logs from each container is

docker logs -f <container_name for peers and orderer>

Chaincode Invoke and Query Using CLI

Setup

cd fabric-samples/fabcar
./startFabric.sh

The script

  • brings up First Network,
  • installs Fabcar chaincode into all the four peers,
  • instantiates Fabcar into channel with endorsement policy requiring one peer from each organizations (an AND operation),
  • performs a chaincode invoke on initLedger, which preloads 10 car records.

With this we can start performing chaincode query.

Chaincode Query

Use command. Here we use queryAllCars for demonstration.

docker exec cli peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'

The command is read like this,

  • channel name: mychannel
  • chaincode name: fabcar
  • arguments: [“queryAllCars”]

We repeat issuing this command, and find that all queries go to . And here is the log we see in the container.

Image for post
Image for post
Logs from peer0.org1.example.com

The reason behind is that CLI is by default targeting commands to (). For demonstration purpose, if we wish to use , we will see the log now in .

docker exec -e CORE_PEER_ADDRESS=peer1.org1.example.com:8051 -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt cli peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'

Chaincode Invoke

Use command. Here we use createCar for demonstration.

docker exec cli peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n fabcar --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt  -c '{"Args":["createCar", "CAR12", "Honda", "Accord", "black", "Tom"]}'

The command is read like this,

  • orderer: orderer.example.com (and its TLS root certificate)
  • channel name: mychannel
  • chaincode name: fabcar
  • endorsing peers: peer0.org1.example.com and peer0.org2.example.com (and their TLS root certificates)
  • arguments: [“createCar”, “CAR12”, “Honda”, “Accord”, “black”, “Tom”]

First, we see two more items in chaincode function invoke: orderer and endorsing peers. Endorsing peers are where the transaction proposal to be sent for endorsement, and orderer is where the transaction with endorsement to be sent for new block creation.

As endorsement policy requires one from each organization, here in this command we specify and . This satisfies the endorsement policy.

Without going into detail on the result, let’s focus on the logs of all components again. I am arranging them in a time sequence to show the flow.

Endorsing

Image for post
Image for post

Image for post
Image for post

Ordering

Image for post
Image for post

Block commit and Ledger update

Image for post
Image for post

Image for post
Image for post

Image for post
Image for post

Image for post
Image for post

This follows the flow we introduce in the quick review. Endorsement is done by those selected endorsing peers in the peer chaincode invoke command ( ), and all peers will receive the new block containing that transaction, and commit the block after validation.

You can try to specify other peers as endorsers by changing the options. Any combination of one peer from each peer organization should work well.

Clean Up

Use these commands to clean up everything after testing Fabcar.

cd fabric-samples/first-network
./byfn.sh down
docker rm $(docker ps -aq)
docker rmi $(docker images dev-* -q)

Using Client Application (SDK)

We will observe similar things in CLI. Here we highlight the difference, in particular how peer(s) for chaincode function query and invoke is (are) selected.

Setup

cd fabric-samples/fabcar
./startFabric.sh

After the script is executed completely, we need to prepare user credentials for client application.

cd javascript
npm install (if not done before)
rm -rf wallet
node enrollAdmin.js
node registerUser.js

With these, we can start using the client applications.

Chaincode Query

To perform chaincode query, we are using with the chaincode function name and required argument(s). Here is what we see in .

Image for post
Image for post
extract from query.js
node query.js

Try several times and keep an eye on the logs of all peers and orderer. We see nothing in peers of Org2 and orderer, and output is found in peers of Org1. Among them we observe two outcomes:

Outcome 1: Discovery and chaincode query done on

Image for post
Image for post

Outcome 2: Discovery done on , and chaincode query on .

Image for post
Image for post

Image for post
Image for post

We see that Service Discovery is first performed on , and the chaincode function query is done on either or . It is not evenly distributed between the two peers. Nevertheless we see the queries are seen and done in both of them.

Chaincode Invoke

To perform chaincode invoke, we are using with the chaincode function and required argument(s). Here is what we see in .

Image for post
Image for post
extract from invoke.js
node invoke.js

The overall flow is similar to what we see in CLI. Here we only focus on the endorsing stage: which peers are selected.

If you perform several times, we will see endorsement is done in one of the following patterns

  • and
  • and
  • and
  • and

Any pattern above satisfies the endorsement policy. It is obvious that after service discovery (done on ), one peer in each organization is selected for endorsement. Again, it is not an even distribution, but we see different patterns after we try several times.

After endorsement, the ordering and block commit is the same as CLI. Here we skip the details.

So far we see a difference in CLI and using client application. We do not specify the target peer or endorsing peers, and qualified peers are selected. Here is what the Service Discovery provides.

Service Discovery

Service Discovery provides the updated network information. This is introduced in v1.2, and one of the prominent uses is by client application. We can specify in the client application code that service discovery is used before processing the transaction. With this information SDK can make decisions which peers are selected for query or endorsement.

Without going into detail, here is a result of service discovery on chaincode and endorsement. You can do some practice on service delivery here.

# inside CLI container
discover --configFile conf.yaml endorsers --channel mychannel --server peer0.org1.example.com:7051 --chaincode fabcar
Image for post
Image for post
Output when we query the endorsement in Service Discovery

A quick observation showing that the distribution of endorsers. They are grouped according to Organizations (Org1 and Org2), and the layout tells us that one (1) from each group is needed. This is the same as what we specify the endorsement policy in chaincode instantiation as in .

Update of Service Discovery

Here we perform some actions and see the update of service discovery.

First let’s tear down a peer

docker-compose -f docker-compose-cli.yaml -f docker-compose-couch.yaml rm -v -f -s couchdb2 peer0.org2.example.com
Image for post
Image for post

Here is the result after a peer is taken out.

Image for post
Image for post
Service Discovery gets updated once the peer is removed.

Now we see is removed.

The Service Discovery is updated immediately. As a result, when client application performs service discovery, is no longer in the list. The transaction proposal is always reaching the remaining peer in the service discovery.

Try to perform several times and we see everything is still working well. This is a level of high availability (HA) design within a fabric network, and transparent to application users.

Client Application using Service Discovery

Finally, to use discovery in client application, we specify it when calling .

In both and , discovery is set enabled.

Image for post
Image for post

Clean Up

Use these commands to clean up everything after testing Fabcar.

cd fabric-samples/first-network
./byfn.sh down
docker rm $(docker ps -aq)
docker rmi $(docker images dev-* -q)

Summary

We have made two observations in this article. First, by observing the container logs from all peers and the orderer, we trace back the flow of a transaction when a client issues chaincode function invoke: endorsement of transaction proposal, transaction to ordering service, and commit new block received. This is simpler in chaincode function query as no ledger update happens. Second, we also note the difference in both CLI and client application when using the network. In CLI we specify the target peer and endorsing peers for chaincode function invoke. In client applications with SDK, we can use Service Discovery to get the latest view of the fabric network. This provides a level of high availability when a client application is using the fabric network.

Written by

Happy to share what I learn on blockchain. Visit http://www.ledgertech.biz/kcarticles.html for my works. or reach me on https://www.linkedin.com/in/ktam1/.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store