Chapter 5. A Blockchain Example: Commercial Paper

In Chapter 2, we referenced the Commercial Paper scenario provided as part of the Hyperledger Fabric samples repository. In this chapter, we will examine this scenario in depth as a tutorial to better understand what it is doing. We will then extend the tutorial to create a new transaction in the smart contract and develop a new command line application to invoke it.

What Is Commercial Paper?

The Commercial Paper tutorial simulates a simple commercial paper trading network called PaperNet. Commercial paper is a type of unsecured lending called a promissory note. Paper is normally issued by large corporations to raise funds to meet short-term financial obligations at a fixed rate of interest. Once issued at a fixed price for a fixed term, another company or bank will purchase commercial paper at a cost lower than its face value, and when the term is up, it will be redeemed for its face value.

As an example, if paper was issued at a face value of $10 million for a six-month term at 2% interest, then it could be bought for $9.8 million ($10 million – 2%) by another company or bank happy to bear the risk that the issuer will not default. Once the term is up, then the paper could be redeemed or sold back to the issuer for its full face value of $10 million. Between buying and redemption, the paper can be bought or sold multiple times between different parties on a commercial paper market.

Understanding the Commercial Paper Tutorial

Previously, we looked at how we can use the idea of assets, participants, and transactions to analyze blockchain use cases.

From this description, we can see that the main asset here is the commercial paper itself, which will have multiple attributes such as the issuing company, the face value of the paper, the redemption date, and the current state (such as issued, trading, and redeemed) of the paper.

We can also see that there are multiple participants in this scenario: an issuer who will be responsible for creating or issuing commercial paper, and one or more buyers of commercial paper who will own the paper until it is either redeemed or sold on to another party.

Finally, we have the transactions: they are issue, buy and redeem, to issue new commercial paper, trade it, and redeem the face value of the paper with the issuer, respectively.

In the tutorial there are two key participants: MagnetoCorp and DigiBank. The tutorial shows MagnetoCorp initially acting as an issuer, with DigiBank taking on the role of the buyer and redeemer of the commercial paper in the PaperNet network.

Figure 5-1 shows an overview of the network, with Isabella working for MagnetoCorp, the issuer, Balaji working for an example trader (DigiBank), and the two organizations communicating over the PaperNet blockchain:

commercialpaper.png
Figure 5-1. Sample network for the Commercial Paper tutorial

Running the Commercial Paper Tutorial

Hyperledger Fabric contains a tutorial for Commercial Paper. In this section, we introduce the purpose of this tutorial and the main tasks involved.

A more detailed description of the Commercial Paper tutorial is available online; if you are a developer looking for hands-on experience of Hyperledger Fabric, then we recommend that you follow this. At the time of writing, the tutorial is available here.

Initially, the tutorial takes you through installing some prerequisite software and downloading the samples. Once this is done you take on the role of Isabella from MagnetoCorp, who will create the network that DigiBank will join. After installing and instantiating the smart contract, she will run a command-line application that will invoke the smart contract’s issue transaction.

Next, you switch to the role of Balaji from DigiBank, who will use different command-line applications to buy the paper that Isabella issued and then redeem it with another application.

The tutorial uses a command-line application for each smart contract transaction. Although this makes it very easy to see what is going on from the tutorial’s point of view, in a more realistic scenario, one application might be expected to call several smart contract transactions.

At the end of the tutorial, one commercial paper asset has been issued, bought, and redeemed in the network.

Extending the Commercial Paper Tutorial

Although the tutorial shows many aspects of smart contract development and transaction invocation, it currently does not provide a way to query for particular paper. Therefore, in this section we will look at extending the commercial paper smart contract to add a new getPaper transaction that will return a string representation of the requested paper to the caller. We will then create a new command-line application based on one of the existing ones in order to invoke it.

This will provide us with a way of looking at the different states commercial paper will go through during its lifecycle. We will then issue new paper and follow it through its lifecycle, querying it at each step along the way.

Writing the New getPaper Transaction

The new getPaper transaction follows the same model as the buy and redeem transactions, but it is much simpler as we do not need to update any properties of the paper in the world state:

/**
* Get commercial paper
* @param {Context} ctx the transaction context
* @param {String} issuer commercial paper issuer
* @param {Integer} num paper number for this issuer
*/
async getPaper(ctx, issuer, num) {
 try {
  console.log("getPaper for: " + issuer + " " + num);
  let paperKey = CommercialPaper.makeKey([issuer, num]);
  let paper = await ctx.paperList.getPaper(paperKey);
  return paper.toBuffer();
 } catch (e) {
  throw new Error('Paper does not exist' + issuer + num);
 }
}

Add this code to the commercial-paper/organization/magnetocorp/contract/lib/papercontract.js file and save it. It needs to sit as a top-level transaction like the other transactions, so place it after the redeem transaction almost at the bottom of the file.

We’ll now walk through the changes we made.

After the comments, there is the definition of the getPaper transaction, which takes three parameters. The first one (ctx) is of type Context and is the first parameter passed to all transactions. This allows the framework to pass extra information into the transaction function when it is called. For example, it can pass information about the identity of the caller of the contract as well as methods to query the worldstate when the transaction is called. The second and third parameters (issuer and num) are passed in from the calling application and contain the issuer and number of the paper we wish to retrieve.

After logging the parameters passed in to the console log, the transaction calls the static CommercialPaper.makeKey method. This method is defined in the ledger-api/state.js file and is a helper method to create a world state key for the paper. Remember from the last chapter that data in the world state is stored as key/value pairs, and for the commercial paper tutorial the key is defined using this method. In this example, the key is simply a concatenation of the issuer and the paper number, separated by a colon; for example, MagnetoCorp:00001.

Next, the transaction uses the paperKey return value to request a specific paper by calling ctx.paperList.getPaper and passing in the key (paperKey). As you can see, this is using the ctx parameter to access the paperList and call its getPaper method. The definition of this method is provided in the lib/paperlist.js file.

In turn, paperList.getPaper simply calls the getState method defined in ledger-api/stateList.js. It is this method that actually accesses the world state to retrieve the requested commercial paper asset.

Once we have the requested paper, we simply return it to our caller as a buffer object.

If the requested commercial paper does not exist in the world state, an exception will be thrown, informing our caller that the requested paper does not exist.

Writing the New getPaper.js Application

The getPaper.js application is based on the existing buy.js application that comes with the Commercial Paper tutorial. We can’t show you all the code here as there are over 100 lines of code. However, most of these lines remain the same—we are only going to change about 12 of them.

To get started, make a copy of the commercial-paper/organization/digibank/application/buy.js file and call the copy getPaper.js. Make sure the copy is in the same folder as buy.js.

Open the file in a code editor such as VSCode and look through the file for the console.log lines that contain the string “Buy program;” for example:

console.log('Buy program complete.');
...
console.log('Buy program exception.');

To avoid confusion, change Buy to GetPaper throughout, so that when we subsequently review these console logs we see the correct application’s output.

Next, delete the buy commercial paper and process response sections in the main method, as these are not relevant to the getPaper application:

    // buy commercial paper
    console.log('Submit commercial paper buy transaction.');

    const buyResponse = await contract.submitTransaction('buy',
      'MagnetoCorp', '00001', 'MagnetoCorp', 'DigiBank',
      '4900000', '2020-05-31');

    // process response
    console.log('Process buy transaction response.');

    let paper = CommercialPaper.fromBuffer(buyResponse);
    console.log(`${paper.issuer} commercial paper :
      ${paper.paperNumber} successfully purchased by
      ${paper.owner}`);

In place of this deleted block, just before the Transaction Complete log message, add the following code. (Note that you will be adding in a few more lines than you deleted, but that’s okay—we are doing a little more work to nicely format the returned paper object. Make sure you save the file when you are done.)

// get commercial paper
console.log('Evaluate getPaper transaction.');
const getPaperResponse = await contract.evaluateTransaction(
    'getPaper', 'MagnetoCorp', '00001');
console.log('Process getPaper transaction response.');

let paper = CommercialPaper.fromBuffer(getPaperResponse);
let paperState = "Unknown";
if (paper.isIssued()) {
 paperState = "ISSUED";
} else if (paper.isTrading()) {
 paperState = "TRADING";
} else if (paper.isRedeemed()) {
 paperState = "REDEEMED";
}

console.log(` +--------- Paper Retrieved ---------+ `);
console.log(` | Paper number: "${paper.paperNumber}"`);
console.log(` | Paper is owned by: "${paper.owner}"`);
console.log(` | Paper is currently: "${paperState}"`);
console.log(` | Paper face value: "${paper.faceValue}"`);
console.log(` | Paper is issued by: "${paper.issuer}"`);
console.log(` | Paper issue on: "${paper.issueDateTime}"`);
console.log(` | Paper matures: "${paper.maturityDateTime}"`);
console.log(` +-----------------------------------+ `);

Looking at this new code that we inserted, we can see that it starts by logging the call it is about to make on the contract to the console. It then calls the evaluateTransaction method of the contract to submit the call to the peer to run the getPaper transaction.

Note that in getPaper we are using evaluateTransaction rather than the submitTransaction method that the other transactions use; the difference is that evaluateTransaction does not record the transaction on the ledger, and as we are not changing any state when returning the paper—this is okay.

The parameters passed to evaluateTransaction indicate that we want to get MagnetoCorp’s paper 00001, which was the one issued when you ran the tutorial. Once the paper has been returned, we find out which state the paper is in (ISSUED, TRADING, or REDEEMED) and then print this out along with the other information contained within the paper such as its paper number, issuer, owner, and face value.

Upgrading the Smart Contract

Now that we have edited the smart contract to add the new transaction and created the new getPaper command line application, it is time to test them both out. To do this, we first have to install the modified smart contract on to the peer. From the magnetocorp console window, which you should have open from running the tutorial, issue this command to install the new version 2 of the contract:

(magnetocorp admin)$ docker exec cliMagnetoCorp peer chaincode
install -n papercontract -v 2 -p /opt/gopath/src/github.com/co
ntract -l node

When it completes, you should see output like this:

2019-02-21 13:32:23.824 UTC [chaincodeCmd] checkChaincodeCmdPa
rams -> INFO 001 Using default escc
2019-02-21 13:32:23.824 UTC [chaincodeCmd] checkChaincodeCmdPa
rams -> INFO 002 Using default vscc
2019-02-21 13:32:23.832 UTC [chaincodeCmd] install -> INFO 003
Installed remotely response:<status:200 payload:"OK" >

Next, we have to upgrade the version 2 smart contract on the peer to make it live:

(magnetocorp admin)$ docker exec cliMagnetoCorp peer chaincode
upgrade -n papercontract -v 2 -l node -c '{"Args":["org.papern
et.commercialpaper:instantiate"]}' -C mychannel -P "AND ('Org1
MSP.member')"

When it completes (which can take a few minutes), you should see output like this:

2019-02-21 13:32:35.508 UTC [chaincodeCmd] InitCmdFactory ->
INFO 001 Retrieved channel (mychannel) orderer endpoint:
orderer.example.com:7050
2019-02-21 13:32:35.511 UTC [chaincodeCmd] checkChaincodeCmdPar
ams -> INFO 002 Using default escc
2019-02-21 13:32:35.511 UTC [chaincodeCmd] checkChaincodeCmdPar
ams -> INFO 003 Using default vscc

Invoking the New getPaper.js Application

Now we are ready to invoke the getPaper.js application and test out the new smart contract transaction. First, check that the console window for Balaji from DigiBank, which you should have open from running the tutorial, is currently in the commercial-paper/organization/digibank/application directory. If it is not, just use cd to change to this directory. This is where the new getPaper.js application is located.

Issue this command to run the application:

(balaji)$ node getPaper.js

You should expect to see output like this:

Connect to Fabric gateway.
Use network channel: mychannel.
Use org.papernet.commercialpaper smart contract.
Submit commercial paper getPaper transaction.
Process getPaper transaction response.

 +--------- Paper Retrieved ---------+
 | Paper number: "00001"
 | Paper is owned by: "MagnetoCorp"
 | Paper is currently: "REDEEMED"
 | Paper face value: "5000000"
 | Paper is issued by: "MagnetoCorp"
 | Paper issue on: "2020-05-31"
 | Paper matures on: "2020-11-20"
 +-----------------------------------+

Transaction complete.
Disconnect from Fabric gateway.
GetPaper program complete.

Assuming that you have completed the tutorial successfully earlier, you should now see the final REDEEMED state of paper number 00001 that MagnetoCorp issued after it was bought and then redeemed by DigiBank.

Testing with New Paper

Now let’s go through this one more time, issuing, buying, and redeeming a second paper (number 00002). But this time, we will look at the output from getPaper each step along the way.

To do this we will need to edit all four programs to use the new paper. We’ll start with one of the easiest: getPaper.js. Open up getPaper.js in your editor and find this line of code:

const getPaperResponse = await contract.evaluateTransaction(
  'getPaper', 'MargetoCorp', '00001');

Change the paper number from 00001 to 00002 and save the change to the file. Although you could run getPaper.js at this point, it would return an error as there is currently no paper with the number 00002. So, let’s create one.

Open up issue.js from the organization/magnetocorp/application directory and find this line:

const issueResponse = await contract.submitTransaction(
  'issue', 'MagnetoCorp','00001','2020-05-31',
  '2020-11-20','5000000');

Change the paper number from 00001 to 00002, and so we can see more differences, change the amount from 5000000 to 6000000. You can change the dates as well as if you wish. Your changed line should look something like this:

const issueResponse = await contract.submitTransaction('issue',
  'MagnetoCorp','00002','2019-06-30','2019-12-30','6000000');

From the MagnetoCorp console window, issue this command to issue paper 00002:

(magnetocorp admin)$ node issue.js

You should see output indicating that the paper was issued successfully, with output of the form:

MagnetoCorp commercial paper : 00002 successfully issued for
value 6000000

Next, from Balaji’s console window run the getPaper application:

(balaji)$ node getPaper.js

The output should contain:

+--------- Paper Retrieved ---------+
 | Paper number: "00002"
 | Paper is owned by: "MagnetoCorp"
 | Paper is currently: "ISSUED"
 | Paper face value: "6000000"
 | Paper is issued by: "MagnetoCorp"
 | Paper issue on: "2019-06-30"
 | Paper matures on: "2019-12-30"
 +-----------------------------------+

Now we can see the paper has now been issued, but it is still owned by MagnetoCorp as it has not yet been sold. Let’s now buy this new paper as DigiBank. Open up buy.js from the organization/digibank/application folder and find this line:

const buyResponse = await contract.submitTransaction(
'buy', 'MagnetoCorp', '00001', 'MagnetoCorp', 'DigiBank',
'4900000', '2020-05-31');

If we look at the buy transaction in the papercontract.js smart contract, we can see the parameters representing the transaction to call (buy), the issuer, the paper number, the current owner, the new owner, the price, and the purchase date and time. Edit the line to update the parameters for the new paper to look like this:

const buyResponse = await contract.submitTransaction(
'buy', 'MagnetoCorp', '00002', 'MagnetoCorp', 'DigiBank',
'5880000', '2019-10-30');

When you are done, save the file and from Balaji’s console window run the buy command:

(balaji)$ node buy.js

You should see output stating that the transaction was successful:

MagnetoCorp commercial paper : 00002 successfully purchased
by DigiBank

Next, let’s run getPaper again:

(balaji)$ node getPaper.js

The output should include this:

+--------- Paper Retrieved ---------+
 | Paper number: "00002"
 | Paper is owned by: "DigiBank"
 | Paper is currently: "TRADING"
 | Paper face value: "6000000"
 | Paper is issued by: "MagnetoCorp"
 | Paper issue on: "2019-06-31"
 | Paper matures on: "2019-12-30"
 +-----------------------------------+

As we can see, the paper is now owned by DigiBank and is now in the TRADING state.

Finally, let’s change redeem.js, which is alongside buy.js in the DigiBank application folder. Open the file in your editor and find this line:

const redeemResponse = await contract.submitTransaction(
  'redeem', 'MagnetoCorp', '00001', 'DigiBank', '2020-11-30');

Here we need to change the paper number and the redeeming date for completeness, so edit the line to look like this:

const redeemResponse = await contract.submitTransaction(
  'redeem', 'MagnetoCorp', '00002', 'DigiBank', '2019-11-30');

When you are done, save the file and from Balaji’s console window run the redeem command:

(balaji)$ node redeem.js

You should see output stating that the transaction was successful:

MagnetoCorp commercial paper : 00002 successfully redeemed with
MagnetoCorp

Next, let’s run getPaper one last time:

(balaji)$ node getPaper.js

The output should look like this:

+--------- Paper Retrieved ---------+
 | Paper number: "00002"
 | Paper is owned by: "MagnetoCorp"
 | Paper is currently: "REDEEMED"
 | Paper face value: "6000000"
 | Paper is issued by: "MagnetoCorp"
 | Paper issue on: "2019-06-30"
 | Paper matures on: "2019-12-30"
 +-----------------------------------+

Here we can see the paper is now redeemed and the cycle is complete. At this point, feel free to experiment on your own, maybe by extending the smart contract further to improve error checking or by writing a new command-line application to find all TRADING or REDEEMED papers. Or, you could try and make the applications easier to use by taking arguments from the command line for the parameters such as paperNumber to save having to edit the files manually to work with a new asset.

Summary

We have taken a whirlwind tour of the Commercial Paper tutorial, and have updated its smart contract to include a new getPaper transaction. We have installed and upgraded the PaperNet network to the new version of the contract, and we have even written a new command-line application to execute the new getPaper transaction. Finally, we issued a new commercial paper asset and followed it on its lifecycle, looking at the state changes made to it on its journey.

If you are a developer of smart contracts, there is a free-to-use tool available to make your smart contract development much easier. The IBM Blockchain Platform Extension for VSCode helps Hyperledger Fabric developers to develop and test smart contracts and client applications on their local machines, as well as package their projects for deployment into IBM Blockchain Platform runtimes.

In the final chapter, we will take a look at the shape of things to come and where the future lies for blockchain technology.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset