Hyperledger Composer: Create a Simple Blockchain Application [Beginner Tutorial]

This article shows how you can create a Simple Blockchain Application with Hyperledger Composer.

Install pre-requisites

First of all, you have to install the pre-requisites required for Hyperledger Composer. You need to install the following:

– Docker Engine
– Docker Compose
– Node
– Npm
– Git
– Python
– Code Editor

Details on pre-requisites installation can be found here: Installing pre-requisites

Install Development Tools

After installing the pre-requisites, we need to install different components (development tools) required for the application development.

Here are the steps defined in the above install development tools link:

Install CLI tools

CLI tool


npm install -g composer-cli@0.20

Utility for running REST Server on your machine to generate RESTful APIs of the business network:


npm install -g composer-rest-server@0.20

Utility to generate application assets:


npm install -g generator-hyperledger-composer@0.20

Yeamon tool used for application generation:


npm install -g yo

Install Playground


npm install -g composer-playground@0.20

Install Hyperledger Fabric

Create a directory named fabric-dev-servers in your computer’s home directory and then go inside that newly created directory:


mkdir ~/fabric-dev-servers && cd ~/fabric-dev-servers

Download the .tar.gz file that contains tools to install Hyperledger Fabric:


curl -O https://raw.githubusercontent.com/hyperledger/composer-tools/master/packages/fabric-dev-servers/fabric-dev-servers.tar.gz

OR, if you want to download .zip file instead of .tar.gz, then you can run the following command:


curl -O https://raw.githubusercontent.com/hyperledger/composer-tools/master/packages/fabric-dev-servers/fabric-dev-servers.zip

Extract the downloaded .tar.gz file:


tar -xvf fabric-dev-servers.tar.gz

OR, if you have downloaded the .zip file, then run the following command to extract it:


unzip fabric-dev-servers.zip 

Remember that, you should be inside the fabric-dev-servers folder:


mukesh:com_kilroyblockchain_riley chapagain$ cd ~/fabric-dev-servers/

mukesh:fabric-dev-servers chapagain$ pwd
/Users/mukeshchapagain/fabric-dev-servers

The .tar.gz or .zip file that you downloaded and extracted through the above commands, should be present inside the fabric-dev-servers folder.

Create Environment Variable FABRIC_VERSION


export FABRIC_VERSION=hlfv12

Download Hyperledger Fabric v1.2 runtime

To download a local Hyperledger Fabric v1.2 runtime, run the following command:


./downloadFabric.sh

You have successfully installed everything required for the development environment.

Start & Stop Hyperledger Fabric

Just be sure that you are inside the fabric-dev-servers folder where you have extracted the hyperledger fabric:


cd ~/fabric-dev-servers

Run the following command to Start Hypeledger Fabric:


./startFabric.sh

Run the following command to generate PeerAdmin Card:


./createPeerAdminCard.sh

If you want to restart the fabric server, you first need to stop it and then start it again:


./stopFabric.sh
./startFabric.sh

You can also teardown the fabric server. For that, at first you have to stop the fabric server and then teardown it.


./stopFabric.sh
./teardownFabric.sh

If you teardown the fabric server, then next time you start it, you have to create Peer Admin Card. So, after you teardown the server, you need to run the following commands to properly start it:


./startFabric.sh
./createPeerAdminCard.sh

Start the composer playground web app with the following command:


composer-playground

The Hyperledger Composer Playground provides user interface from where you can create, deploy and test the blockchain business network.

The composer playground is present here: Playground Tutorial

Create Hypeledger Composer Blockchain Application

In this section, we will not use the composer playground. We will manually create model, logics and queries files and use the command line to create the business network.

We will create a Business Network. In our blockchain solution, we define:

– data model
– transaction logic
– access control rules

Generate a skeleton business network

We will use Yeoman generator to create a skeleton business network. The following command will create a directory containing all the components required for the business network.


yo hyperledger-composer:businessnetwork

Make sure that you are inside the fabric-dev-servers directory.


mukesh:fabric-dev-servers chapagain$ pwd
/Users/mukeshchapagain/fabric-dev-servers

When you enter the Yeoman generator command, you are asked for certain things:

– Enter your network name
– Enter your network description
– Author name, which can be your own name
– Author email, which can be your own email address
– License can be Apache-2.0
– Namespace for your network can be something like org.example.mynetwork
– You are asked to either create an empty network or populated network. We will choose the populated network. The populated network contains all the necessary files auto-generated for our blockchain business network.


mukesh:fabric-dev-servers chapagain$ yo hyperledger-composer:businessnetwork
Welcome to the business network generator
? Business network name: my-business-network
? Description: My Blockchain Business Network
? Author name:  Mukesh Chapagain
? Author email: mukesh.chapagain@example.com
? License: Apache-2.0
? Namespace: org.example.mynetwork
? Do you want to generate an empty template network? No: generate a populated sample network
   create package.json
   create README.md
   create models/org.example.mynetwork.cto
   create permissions.acl
   create .eslintrc.yml
   create features/sample.feature
   create features/support/index.js
   create test/logic.js
   create lib/logic.js

Define the business network

A blockchain business network is made of the following:

– assets
– participants
– access control rules
– events (optional)
– queries (optional)

Some of the important files in the business network are:

  • Model (models/org.example.mynetwork.cto)
    • contains class definition of all assistants, participants, and transactions

namespace org.example.mynetwork

participant SampleParticipant identified by participantId {
  o String participantId
  o String firstName
  o String lastName
}

asset SampleAsset identified by assetId {
  o String assetId
  --> SampleParticipant owner
  o String value
}

transaction SampleTransaction {
  --> SampleAsset asset
  o String newValue
}

event SampleEvent {
  --> SampleAsset asset
  o String oldValue
  o String newValue
}
  • Access Control (ACL) file (permissions.acl)
    • contains the basic access control rules

/**
 * Sample access control list.
 */
rule EverybodyCanReadEverything {
    description: "Allow all participants read access to all resources"
    participant: "org.example.mynetwork.SampleParticipant"
    operation: READ
    resource: "org.example.mynetwork.*"
    action: ALLOW
}

rule EverybodyCanSubmitTransactions {
    description: "Allow all participants to submit transactions"
    participant: "org.example.mynetwork.SampleParticipant"
    operation: CREATE
    resource: "org.example.mynetwork.SampleTransaction"
    action: ALLOW
}

rule OwnerHasFullAccessToTheirAssets {
    description: "Allow all participants full access to their assets"
    participant(p): "org.example.mynetwork.SampleParticipant"
    operation: ALL
    resource(r): "org.example.mynetwork.SampleAsset"
    condition: (r.owner.getIdentifier() === p.getIdentifier())
    action: ALLOW
}

rule SystemACL {
  description:  "System ACL to permit all access"
  participant: "org.hyperledger.composer.system.Participant"
  operation: ALL
  resource: "org.hyperledger.composer.system.**"
  action: ALLOW
}

rule NetworkAdminUser {
    description: "Grant business network administrators full access to user resources"
    participant: "org.hyperledger.composer.system.NetworkAdmin"
    operation: ALL
    resource: "**"
    action: ALLOW
}

rule NetworkAdminSystem {
    description: "Grant business network administrators full access to system resources"
    participant: "org.hyperledger.composer.system.NetworkAdmin"
    operation: ALL
    resource: "org.hyperledger.composer.system.**"
    action: ALLOW
}
  • Logic script (lib/logic.js)
    • transaction processor functions

'use strict';
/**
 * Write your transction processor functions here
 */

/**
 * Sample transaction
 * @param {org.example.mynetwork.SampleTransaction} sampleTransaction
 * @transaction
 */
async function sampleTransaction(tx) {
    // Save the old value of the asset.
    const oldValue = tx.asset.value;

    // Update the asset with the new value.
    tx.asset.value = tx.newValue;

    // Get the asset registry for the asset.
    const assetRegistry = await getAssetRegistry('org.example.mynetwork.SampleAsset');
    // Update the asset in the asset registry.
    await assetRegistry.update(tx.asset);

    // Emit an event for the modified asset.
    let event = getFactory().newEvent('org.example.mynetwork', 'SampleEvent');
    event.asset = tx.asset;
    event.oldValue = oldValue;
    event.newValue = tx.newValue;
    emit(event);
}
  • package.json
    • contains the business network metadata

{
  "engines": {
    "composer": "^0.20.0"
  },
  "name": "my-business-network",
  "version": "0.0.1",
  "description": "My Blockchain Business Network",
  "scripts": {
    "prepublish": "mkdirp ./dist && composer archive create --sourceType dir --sourceName . -a ./dist/my-business-network.bna",
    "pretest": "npm run lint",
    "lint": "eslint .",
    "test": "nyc mocha -t 0 test/*.js && cucumber-js"
  },
  "keywords": [
    "composer",
    "composer-network"
  ],
  "author": "Mukesh Chapagain",
  "email": "mukesh.chapagain@example.com",
  "license": "Apache-2.0",
  "devDependencies": {
    "composer-admin": "^0.20.0",
    "composer-cli": "^0.20.0",
    "composer-client": "^0.20.0",
    "composer-common": "^0.20.0",
    "composer-connector-embedded": "^0.20.0",
    "composer-cucumber-steps": "^0.20.0",
    "chai": "latest",
    "chai-as-promised": "latest",
    "cucumber": "^2.2.0",
    "eslint": "latest",
    "nyc": "latest",
    "mkdirp": "latest",
    "mocha": "latest"
  }
}
  • queries.qry
    • contain a WHERE clause, which defines the criteria by which assets or participants are selected
    • queries.qry file is not created by default with the yoeman generator command
    • hence, we have to create this file mannually inside the business network folder that is created with the yoeman generator command

Based on the assets, participants, transactions defined in the model file, the queries.qry file can be something like this:

queries.qry


query getSampleParticipantById {
  description: "Get participant by participant id"
  statement:
      SELECT org.example.mynetwork.SampleParticipant
      WHERE ( _$participantId == participantId )
}

Queries tutorial can be found here: Queries Tutorial using the Composer Query language and REST APIs

Create a deployable Business Network Archive (.bna) file

As you can see above, we have created a business network with the name my-business-network. Therefore, a folder named my-business-network is created inside the fabric-dev-servers directory.

Go into your newly created business network directory.


mukesh:fabric-dev-servers chapagain$ cd ~/fabric-dev-servers/my-business-network/

mukesh:my-business-network chapagain$ pwd
/Users/mukeshchapagain/fabric-dev-servers/my-business-network

Now, run the following command to create the business network archive:


composer archive create -t dir -n .

Here’s the output of the command:


mukesh:my-business-network chapagain$ composer archive create -t dir -n .
Creating Business Network Archive

Looking for package.json of Business Network Definition
    Input directory: /Users/mukeshchapagain/fabric-dev-servers/my-business-network

Found:
    Description: My Blockchain Business Network
    Name: my-business-network
    Identifier: my-business-network@0.0.1

Written Business Network Definition Archive file to
    Output file: my-business-network@0.0.1.bna

Command succeeded
  • This will create an business network archive (.bna) file.
  • The file will be created in the same directory from where you ran this command. So, the file will be created in the “my-business-network” directory.
  • The name of the file will be like this: your-business-network-name@version-specified-in-package.json-file.bna
  • In our case,
    • our network name is my-business-network
    • version in our package.json file is 0.0.1
    • therefore, the bna file name will be my-business-network@0.0.1.bna

mukesh:my-business-network chapagain$ ls
README.md           models              permissions.acl
features            my-business-network@0.0.1.bna   queries.qry
lib             package.json            test

The archive creation command can also be written as below. Here, we have manually specified the BNA file name.


composer archive create --sourceType dir --sourceName . -a my-business-network@0.0.1.bna

Deploy / Install the business network

Fabric administrator credentials is required to install the business network. We have already created the PeerAdmin card above during the development environment installation. So, we will be using that PeerAdmin business network card to deploy the business network to Hyperledger Fabric.

If you run the “composer card list” command, you will see the list of card for the business network:


mukesh:my-business-network chapagain$ composer card list
The following Business Network Cards are available:

Connection Profile: hlfv1
┌────────────────────────┬───────────┬──────────────────┐
│ Card Name              │ UserId    │ Business Network │
├────────────────────────┼───────────┼──────────────────┤
│ PeerAdmin@hlfv1        │ PeerAdmin │                  │
└────────────────────────┴───────────┴──────────────────┘

Issue composer card list --card <Card Name> to get details a specific card

Command succeeded

Install the business network

Run the following command to install the business network:


composer network install --card PeerAdmin@hlfv1 --archiveFile my-business-network@0.0.1.bna

Here’s the output of the command:


mukesh:my-business-network chapagain$ composer network install --card PeerAdmin@hlfv1 --archiveFile my-business-network@0.0.1.bna
✔ Installing business network. This may take a minute...
Successfully installed business network my-business-network, version 0.0.1

Command succeeded

Start the business network

The networkVersion number should be same your business network version number, i.e. the version number present in the package.json file of your business network.


composer network start --networkName my-business-network --networkVersion 0.0.1 --networkAdmin admin --networkAdminEnrollSecret adminpw --card PeerAdmin@hlfv1 --file networkadmin.card

This command will take some time to complete. Here’s the output of the command:


mukesh:my-business-network chapagain$ composer network start --networkName my-business-network --networkVersion 0.0.1 --networkAdmin admin --networkAdminEnrollSecret adminpw --card PeerAdmin@hlfv1 --file networkadmin.card
Starting business network my-business-network at version 0.0.1

Processing these Network Admins:
    userName: admin

✔ Starting business network definition. This may take a minute...
Successfully created business network card:
    Filename: networkadmin.card

Command succeeded

Import the network administrator identity as a usable business network card


composer card import --file networkadmin.card

Here’s the output of the command:


mukesh:my-business-network chapagain$ composer card import --file networkadmin.card

Successfully imported business network card
    Card file: networkadmin.card
    Card name: admin@my-business-network

Command succeeded

Now, you can see your network’s card listed when you run the composer card list command:


mukesh:my-business-network chapagain$ composer card list
The following Business Network Cards are available:

Connection Profile: hlfv1
┌───────────────────────────┬───────────┬─────────────────────┐
│ Card Name                 │ UserId    │ Business Network    │
├───────────────────────────┼───────────┼─────────────────────┤
│ admin@my-business-network │ admin     │ my-business-network │
├───────────────────────────┼───────────┼─────────────────────┤
│ PeerAdmin@hlfv1           │ PeerAdmin │                     │
└───────────────────────────┴───────────┴─────────────────────┘

Issue composer card list --card <Card Name> to get details a specific card

Command succeeded

Ping the business network

To check if the business network has been deployed successfully or not, we can ping the business network with the following command:


composer network ping --card admin@my-business-network

Here’s the sample output of the command:


mukesh:my-business-network chapagain$ composer network ping --card admin@my-business-network
The connection to the network was successfully tested: my-business-network
    Business network version: 0.0.1
    Composer runtime version: 0.20.0
    participant: org.hyperledger.composer.system.NetworkAdmin#admin
    identity: org.hyperledger.composer.system.Identity#xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Command succeeded

Generate REST Server

To generate and access the REST Server and RESTful APIs, you need to run the following command:


composer-rest-server

The command will ask for certain things which you can specify as:

– Name of the business card = admin@my-business-network
– Namespaces in the REST API = never use namespaces
– API key to secure REST API = No
– Enable authentication for the REST API using Passport = No
– Enable event publication over WebSockets = Yes
– Enable TLS security for the REST API = No

Here’s the ouput of the command:


mukesh:my-business-network chapagain$ composer-rest-server
? Enter the name of the business network card to use: admin@my-business-network
? Specify if you want namespaces in the generated REST API: never use namespaces
? Specify if you want to use an API key to secure the REST API: No
? Specify if you want to enable authentication for the REST API using Passport: No
? Specify if you want to enable event publication over WebSockets: Yes
? Specify if you want to enable TLS security for the REST API: No

To restart the REST server using the same options, issue the following command:
   composer-rest-server -c admin@my-business-network -n never -w true

Discovering types from business network definition ...
Discovering the Returning Transactions..
Discovered types from business network definition
Generating schemas for all types in business network definition ...
Generated schemas for all types in business network definition
Adding schemas for all types to Loopback ...
Added schemas for all types to Loopback
Web server listening at: http://localhost:3000
Browse your REST API at http://localhost:3000/explorer

You can now browse the REST API server with the following URL: http://localhost:3000/explorer

If you want to directly run the completed command, i.e. without specifying the business network name, and other options of namespace, security, authentication, etc. then you can run the following command directly:


composer-rest-server -c admin@my-business-network -n never -w true

By default, the REST Sever will run on port number 3000.

If you want to set a different port then you can run the following command. Here, I have set the port as 8000.


composer-rest-server -c admin@my-business-network -n never -w true -p 8000

The output of the command will be:


mukesh:my-business-network chapagain$ composer-rest-server -c admin@my-business-network -n never -w true -p 8000
Discovering types from business network definition ...
Discovering the Returning Transactions..
Discovered types from business network definition
Generating schemas for all types in business network definition ...
Generated schemas for all types in business network definition
Adding schemas for all types to Loopback ...
Added schemas for all types to Loopback
Web server listening at: http://localhost:8000
Browse your REST API at http://localhost:8000/explorer

You can now browse the REST API server with the following URL: http://localhost:8000/explorer

Read more on the Hyperledger Composer Developer Tutorial: Developer tutorial for creating a Hyperledger Composer solution

Hope this helps. Thanks.