Deploy a business network on (free) IBM Blockchain Starter Plan

Written by horeaporutiu | Published 2018/04/11
Tech Story Tags: blockchain | development | hyperledger | ibm | deployment

TLDRvia the TL;DR App

I’m celebrating my 1-year anniversary with IBM today. Wow, that sounds weird when I read it in my head. Sounds like I just started dating my girlfriend or something. What better way to celebrate my first year than to write a post on how to deploy your custom 🍌(.bna) file to IBM Blockchain Starter Plan? But before we begin, let me show you a sneak peak of what you will build. I want to make sure this blog is worth your time. P.S. I haven’t written a blog since February, so excuse my rusty ⌨️.

Preview

The goal is to build an auction app. This app will be controlled by a composer-rest-server (i.e. a Swagger UI). You will add members, put up offers, and ultimately close the bidding in this app, and the UI will respond by showing the item as ‘Sold’, as shown below:

The final step in this app is to close the bidding. Commands are given using the (composer-rest-server) Swagger UI.

For each successful request you give using the composer-rest-server, the chaincode will be invoked, and you will be able to see the chaincode logs on the IBM Blockchain platform as shown below. The logs will persist as long as you have your blockchain service running on the cloud.

Checking chaincode logs after making requests with the composer-rest-server.

Context

Like my other blog posts, the underlying technology in focus is the Hyperledger Fabric framework. It’s a framework that strives to advance cross-industry blockchain technology. If you are not familiar with Hyperledger Fabric please do some research before reading this post.

What I will help you do today is deploy your custom 🍌 file to the IBM Cloud, and show you how to submit transactions to your blockchain network through a composer-rest-server. In the end of the blog, you should be able to view chaincode logs using the IBM Blockchain platform that were submitted from the composer-rest-server.

Also, from now on, when I use the 🍌 emoji, I am referring to the .bna file.

Your 🍌 file encompasses all your business logic (or smart contracts, or chaincode) into one file that is able to be installed on the peers of an organization. Once you install this file on the peers, you can start the network, and perform transactions based on the rules from the 🍌 file. If you want to learn more about creating .bna files, check out this tutorial.

Prerequisites

  1. Free IBM Cloud account
  2. NPM and Node installed (this blog is tested with node version 8.10.0)
  3. If you have used other versions of composer-cli, or have deployed a .bna file before, run these commands:

$ npm uninstall -g composer-rest-server

$ rm -rf ~/.composer

$ rm *.card

$ rm -rf credentials/

4. (Optional — if you have errors due to docker containers that are already running):

$ docker kill $(docker ps -q)

$ docker rm $(docker ps -aq)

$ docker rmi $(docker images -q)

5. This step is EXTREMELY IMPORTANT. Starter Plan ONLY works with Composer version 0.19.4. I have answered this in many posts. So I will say it again. Starter Plan ONLY works with Composer version 0.19.4. Check your composer version with this command:

$ composer -v

If you see ‘v0.19.4’ you are 👍🏼. Otherwise, uninstall Composer:

$ npm uninstall -g composer-cli

And then install Composer version 0.19.4:

$ npm install -g composer-cli@0.19.4

Step 1: create 🍌 file

First we need to clone a repo that contains the three components that are needed to make a 🍌 file: a logic file**(.js), a model file(.cto), and an access control(.acl)** file.

  1. Clone the repo which has these three files, and a fully functioning business network

$ git clone https://github.com/IBM/BlockchainEvents-CompositeJourney.git

2. go into Composer directory, and create .bna file.

$ cd BlockchainEvents-CompositeJourney/Composer

$ npm install

If this command fails, check that you have the right Node version (should be 8.10.0) and npm v 5.6.0.

3. Now you should have a 🍌 file, (events.bna), that is in your BlockchainEvents-CompositeJourney/Composer/dist directory.

Step 2: create blockchain service

  1. In your browser go to your shiny new IBM Cloud account: https://console.bluemix.net/dashboard/apps
  2. Create a blockchain service:

Create a blockchain service on IBM Cloud.

Step 3: get the secret

  1. Launch your blockchain service, and click on connection profile, and view as raw JSON
  2. Scroll all the way down until you see “registrar” and then under “enrollId” will be “enrollSecret”. Copy this secret, we will need it for the next step

Inside the blockchain platform, go to the connection profile, and get the enrollSecret and copy it.

Step 4: use secret to get certificates from the certificate authority (CA)

  1. Go back and instead of viewing as raw JSON, download the connection profile.
  2. rename the downloaded JSON file to ‘connection-profile.json’
  3. Move the connection-profile.json file to the BlockchainEvents-CompositeJourney directory
  4. Using the enrollSecret from the previous step issue this command to create a business network card for the certificate authority (CA). This command assumes my enrollSecret is ‘123456789’, but yours is likely different.

$ composer card create -f ca.card -p connection-profile.json -u admin -s 123456789

5. Import the card with this command

$ composer card import -f ca.card -c ca

6. Finally, we request certificates from the CA using the card we imported that contains our enrollSecret. The certificates are stored in the credentials directory that is created after the completion of this command.

$ composer identity request --card ca --path ./credentials -u admin -s 123456789

Step 5: Use ‘admin-pub.pem’ file to add certificates to the peers

  1. Back in the blockchain service, click on the members tab, then add certificate. Go to your BlockchainEvents-CompositeJourney/credentials directory, and copy and paste the contents of the ‘admin-pub.pem’ file in the certificate box. Submit the certificate and restart the peers. Note: restarting the peers takes a minute.

Adding certificates to members and restarting the peers.

2. Next, we need to synchronize the certificates of the channel. From our blockchain service, under ‘my network’ click on ‘Channels’ and then the three-dot button. Then click ‘Sync Certificate’.

Sync certificates of the channel.

Step 6: create admin business network card

  1. Now that we have synced certificates with our peers, we can install the Hyperledger Composer runtime and start the network by creating an admin card. Create the admin card with the channel admin and peer admin roles with the following command:

$ composer card create -f adminCard.card -p connection-profile.json -u admin -c ./credentials/admin-pub.pem -k ./credentials/admin-priv.pem --role PeerAdmin --role ChannelAdmin

2. Import the card created from the previous command:

$ composer card import -f adminCard.card -c adminCard

Step 7: install runtime and start the network

  1. Copy and paste the events.bna file to the BlockchainEvents-CompositeJourney directory.

$ cp Composer/dist/events.bna .

  1. Now we will use the admin card from the previous step to install the runtime with the following command:

$ composer network install -c adminCard -a events.bna

If you get an error at this point, wait a minute and try again.

3. Start the business network by providing the admin card, the path to the .bna file, and the credentials received from the CA. This command will issue a card which we will remove, called ‘delete_me.card’. Note: make sure the version matches up with the version provided as output from the composer network install command above.

Version here is 0.0.1, so that is what version you need to use in the step below.

$ composer network start -c adminCard -n events -V 0.0.1 -A admin -C ./credentials/admin-pub.pem -f delete_me.card

If you get an error at this point, such as below, wait a couple seconds and try again.

Docker build error.

REQUEST_TIMEOUT error.

Once your command works, you should see the output below:

Success!

Next, let’s delete delete_me.card :

$ rm delete_me.card

Step 8: create a new business network card

  1. After we have installed the runtime and started the network, we need to create a card which we will deploy to the Starter Plan:

$ composer card create -n events -p connection-profile.json -u admin -c ./credentials/admin-pub.pem -k ./credentials/admin-priv.pem

This command should have created a card called ‘adminCard.card’.

2. Import the business network card:

$ composer card import -f ./admin@events.card

Nice. You should feel pretty good at this point. We’re pretty much done…

weeeee! Stuff works!!

Step 9: create the composer-rest-server and start the web UI

  1. Let’s install the composer-rest-server:

$ npm install -g composer-rest-server@0.19.4

2. Now, let’s start up the server. Make sure you are in the same directory as your connection-profile.json

$ composer-rest-server -c admin@events -n never -w true

3. In your browser, go to http://localhost:3000/explorer

4. Open up a new terminal window and go to BlockchainEvents-CompositeJourney/Web

5. Install dependencies:

$ npm install

6. Start the server:

$ node server.js

7. In your browser go to http://localhost:8000/buyer.html

Step 10: test the network and view chaincode logs

  1. In the composer-rest-server running on port 3000, make a POST request on a ‘Seller’ with the following JSON:

{

"$class": "org.acme.product.auction.Seller",

"organisation": "ACME",

"email": "auction@acme.org",

"balance": 100,

"products": []

}

2. Let’s check the chaincode logs. In your blockchain service, go to the ‘Channels’ tab. Click on ‘defaultchannel’. Click on the blue ‘>’ symbol from the latest invocation. Then, under actions, click the three-dot symbol. Then click view details. The logs will show that you have created a seller with the details from the JSON above.

Checking chaincode logs.

3. Next, let’s create a product, and add it to the auction. Let’s make a POST to ‘AddProduct’ with the following JSON:

{

"$class": "org.acme.product.auction.AddProduct",

"description": "Sample Product",

"owner": "resource:org.acme.product.auction.Seller#auction@acme.org"

}

4. Now we need to get the productId of the sample product we just created. Let’s do a GET for ‘Product’. The productId will be in the response body as shown below:

GET for ‘Product’ gets us our productId that we need to start bidding.

5. Let’s start bidding. Let’s POST to ‘StartBidding’ with the following JSON while replacing the <productId> with the productId from the previous step.

{

"$class": "org.acme.product.auction.StartBidding",

"reservePrice": 50,

"product": "resource:org.acme.product.auction.Product#<productId>"

}

The UI will update after a successful POST to ‘StartBidding’ as shown below:

The UI is updated to show that our item is ready to be bid on.

At this point, you can call yourself a blockchain developer. Bravo. Give yourself a pat on the back. If you want to continue with this app - make a few offers and close the bidding, then continue with me. Otherwise, you already learned a lot, so goodbye for now! 👋🏼 If you enjoyed this, hit the 👏🏼 to show that you found this useful.

Let’s keep grinding!! A couple more steps and we’ve completed an auction on the blockchain running in the cloud.

6. Let’s create two members that can bid on the product we’ve put on the auction, by POST’ing to ‘Member’ with the JSON below

{

"$class": "org.acme.product.auction.Member",

"firstName": "Amy",

"lastName": "Williams",

"email": "memberA@acme.org",

"balance": 1000,

"products": []

}

Let’s post one more time, but with slightly different JSON:

{

"$class": "org.acme.product.auction.Member",

"firstName": "Billy",

"lastName": "Thompson",

"email": "memberB@acme.org",

"balance": 1000,

"products": []

}

7. Now let’s make a GET on ‘ProductListing’ and copy the ‘listingId’ from there, as shown in my screenshot below:

listingId that we need to make an offer.

8. Let’s make two offers by POST’ing to ‘Offer’ with the JSON as shown below, but replacing the <listingId> with YOUR unique listingId:

{

"$class": "org.acme.product.auction.Offer",

"bidPrice": 50,

"listing": "resource:org.acme.product.auction.ProductListing#<listingId>",

"member": "resource:org.acme.product.auction.Member#memberA@acme.org"

}

Let’s make another offer, this time a bit larger than the first:

{

"$class": "org.acme.product.auction.Offer",

"bidPrice": 100,

"listing": "resource:org.acme.product.auction.ProductListing#<listingId>",

"member": "resource:org.acme.product.auction.Member#memberB@acme.org"

}

Making two offers, one from each member.

At this point, your UI should look like this:

Updated UI.

9. Let’s end the auction by POST’ing to ‘CloseBidding’ with the following JSON while replacing <listingId> with YOUR unique listingId:

{

"$class": "org.acme.product.auction.CloseBidding",

"listing": "resource:org.acme.product.auction.ProductListing#<listingId>"

}

10. You are all done! Your listing state should be ‘SOLD’, and if you make a ‘GET’ to members, you should see memberB has 100 less in the balance, and also has ‘sample product’ listed in the product[].

Member b won the auction, so he has a new product, but has a smaller balance.

The seller, who started with 100, now has 100 more, from member B, so if we make a GET to ‘Seller’, we will see his total is now 200.

The seller has a balance of 200 now.

‘//;/You are done! You have successfully spun up a composer-rest-server based on our .bna file, and interacted with our app by making requests through the Swagger UI. All of our requests are successfully logged on our channel, and we can see the details of each chaincode invocation. Thanks for reading, and if you enjoyed it, hold down that 👏🏼 button!

If you have any questions, you can reach out at horeaporutiu@gmail.com, connect with me on LinkedIn, or follow me on Twitter and Medium. Cheers!


Published by HackerNoon on 2018/04/11