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
- our network name is
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.