Blockchain Supply Chain Application


Hands-on Recipe for Building A Blockchain Supply Chain Using Hyperledger Fabric and Composer

Read Recipe

Building A Blockchain Supply Chain Using Hyperledger Fabric and Composer


Step-by-Step Recipe

Hyperledger is a set of open source tools and blockchain subprojects resulting from cross- industry collaboration. We will present two main components in this recipe – Hyperledger Fabric and Hyperledger Composer.

If you are not familiar with blockchain technology or Hyperledger family  reading History and Evolution of Blockchain Technology from Bitcoin, Intro to Hyperledger Family and Hyperledger Blockchain Ecosystem, Hyperledger Design Philosophy and Framework Architecture, The Survey of Hyperledger Fabric Architecture and Components for Blockchain Developers and Overview of Building Blockchain Smart Contracts in Hyperledger articles are highly recommended.

If you like to explore blockchain development with an alternative platform like Ethereum (with Solidity programming), Blockchain Developer Guide- Introduction to Ethereum Blockchain Development with DApps and Ethereum VM, Building Ethereum Financial Applications with Java and Web3j API through Blockchain Oracles, Harness the Power of Distributed Storage IPFS and Swarm in Ethereum Blockchain Applications, and Building Enterprise Blockchain-as-a-Service Applications Using Ethereum and Quorum are highly recommended.
After finishing this recipe, you can move on to Building A Blockchain for Letter of Credit Using Hyperledger Fabric and Composer and Build Blockchain Applications with Hyperledger Fabric and Composer on IBM Cloud tutorials that cover more advance topics on Hyperledger Fabric.
In this recipe, we will introduce an enterprise blockchain solution called Hyperledger Fabric. Hyperledger (or the Hyperledger project) is one of the biggest projects in the blockchain industry. It is a global collaboration, hosted by The Linux Foundation, and includes leaders in different sectors aiming to build a robust business-driven blockchain framework.

In this recipe, you will develop, from a practical standpoint, a strong grasp of core Hyperledger, understand what Fabric is and how it works, and learn key vocabulary and concepts commonly used when discussing Hyperledger.

This recipe presents a first introduction to Hyperledger by building a blockchain-based supply chain application. It will be an occasion to show how blockchain, and in particular Hyperledger, enables global business transactions with greater visibility and trust and less entanglement.
This recipe will help you to achieve the following practical goals:

  • Setting up a private Hyperledger network
  • Writing and deploying your first Chaincode (smart contract)
  •  Building a web interface to query your Chaincode

 

Food industry supply chain

The main reason for classical supply chain inefficiency is the lack of transparency
and reliable reporting. Many companies suffer from the lack of visibility regarding the entire supply chain of their products, and hence lose an immediate competitive advantage over competitors in their industries.


In the traditional supply chain models, the information about an entity is not fully transparent to others, which leads to inaccurate reports and a lack of interoperability. Emails and printed documents provide certain information, but still can’t contain fully detailed visibility and traceability information since the products across the entire supply chain are hard to trace. It is almost impossible for the consumer to know the true value of the product they purchased.
Since the blockchain is a transparent, immutable, and secure decentralized system, it is considered to be a game-changing solution for traditional supply chain industries. It can help to build an effective supply chain system by improving the following areas:

  • Tracking the products in the entire chain
  • Verifying and authenticating the products in the chain
  • Sharing the entire chain information between supply chain actors 
  • Providing better auditability

 

The food industry's supply chain use case is a difficult landscape, where multiple actors need to coordinate with each other in order to deliver the goods to their final destination, that is, the customers. The following picture depicts the actors we will consider in our example of a food supply chain (multi-echelon) network.
blockchain hyperledger fabric and composer

Every stage of the chain introduces potential security vulnerabilities, integration issues, and other inefficiency issues. The main growing threat in current food supply chains remains counterfeit food and food fraud. Given these threats, in this example we will build a food- tracking system based on the Hyperledger blockchain, which will enable full visibility, tracking, and traceability. More importantly, it will assure the authenticity of food by recording a product's details in an immutable and viable way. By sharing a product's   details over an immutable framework, we will enable the end consumer to self-verify a product's authenticity.


Now that we have an idea about the project we will build, let's take a quick overview of the Hyperledger project before we start coding.

 

Quick Hyperledger overview

There are three main types of blockchain networks; public blockchains, consortium or federated blockchains, and private blockchains. Hyperledger is a blockchain framework which aims to help companies to build private or consortium permissioned blockchain networks, where multiple organizations can share the control and the permission to operate a node within the network.

Hyperledger is a set of open source tools and blockchain subprojects resulting from cross- industry collaboration. We will present two main components in this recipe – Hyperledger Fabric and Hyperledger Composer.

 

Hyperledger Fabric

Hyperledger Fabric is the cornerstone of the Hyperledger projects hosted by the Linux Foundation. It is a permission-based blockchain, or more accurately a distributed ledger technology (DLT), which was originally created by IBM and Digital Asset. It is designed as a modular framework with different components, such as the orderer and Membership Services Provider (MSP). It is also a flexible solution, offering a pluggable consensus model, although it is currently only providing permissioned, voting-based consensus, with the assumption being that any current Hyperledger networks will be operating in a  partially trustworthy environment.
Given this, there is no need for anonymous miners to validate any transactions, there is no need either for an associated currency to act as an incentive. All participants are required to be authenticated in order to participate and transact on the blockchain. As with Ethereum, it supports smart contracts, which in Hyperledger are called Chaincode and these contracts describe and execute the application logic of the system.
Unlike Ethereum, however, Hyperledger Fabric doesn’t require expensive mining computation to commit transactions and thus can help us to build blockchains that can scale up with less latency.


Hyperledger Fabric is different from blockchains such as Ethereum or Bitcoin, not only in its type or because it is currency-agnostic, but also in terms of its internal machinery. In a typical Hyperledger network we have the following key elements:

  • Ledger: This stores a chain of blocks, which keeps all immutable historical records of all state transitions.
  • Nodes: These are the logical entities of the blockchain. There are three types of nodes :
    • Client: Clients are applications that act on behalf of a user to submit transactions to the network.
    • Peer: This is an entity that commits transactions and maintains the ledger state.
    • Orderer: This creates a shared communication channel between clients and peers, and it packages blockchain transactions into blocks and sends them to committing peers.

 

Together with these key elements, Hyperledger Fabric is based on the following key design features:

  • Chaincode: Chaincode is a similar concept to a smart contract in other networks such as Ethereum. It is a program written in a higher level language, executing against the ledger’s current state database.
  • Channels: A channel is a private communication subnet for sharing confidential information between multiple network members. Each transaction is executed on the channel which is only visible to the authenticated and authorized parties.
  • Endorsers: These validate transactions and invoke chaincode, sending back the endorsed transaction results to the calling applications.
  • MSP: This provides identity validation and authentication processes by issuing and validating certificates. It identifies which certification authorities (CAs) are trusted to define the members of a trust domain, and determines the specific roles an actor might play (member, admin, and so on).

 

End-to-end transaction flow

To understand how Hyperledger Fabric is different and how it works under the hood, let's look at how a transaction gets validated. In a typical Hyperledger network, the following figure depicts the end-to-end system flow for processing a transaction:
blockchain hyperledger fabric and composer

As a first step, the client initiates a transaction by sending a request to a Hyperledger Fabric-based application client, which submits the transaction proposal to endorsing peers. These peers simulate the transaction by executing the Chaincode (using a local copy of the state) specified by the transaction and sending back the results to the application. At this point, the application combines the transaction along with the endorsements and broadcasts it to the Ordering Service. The Ordering Service checks the endorsements and creates a block of transactions for each channel before broadcasting them to all peers in the channel. Peers will then verify the transactions and commit them.

In our use case, the Hyperledger Fabric blockchain can connect participants through a transparent, permanent, and shared record of food origin data, processing data, shipping details, and more. The Chaincode we defined will be invoked by authorized participants in the food supply chain. All executed transaction records will be permanently saved in the ledger, and all entities will be able to look up this information.

Hyperledger Composer

Alongside blockchain frameworks such as Fabric or Iroha, the Hyperledger project provides us with tools such as Composer, Hyperledger Explorer, and Cello. Composer provides a tool set to help build blockchain applications more easily. It consists of CTO (a modelling language), Playground (a browser-based development tool for rapid testing and deployment), and a command-line interface (CLI) tool. Composer supports the Hyperledger Fabric runtime and infrastructure, and internally the composer's APIs utilize the underlying Fabric API. Composer runs on Fabric, meaning the business networks generated by Composer can be deployed to Hyperledger Fabric for execution.

After this short introduction to Hyperledger Fabric's main components, it's time to run the first Hyperledger blockchain network.

 

Setting up the development environment

In this project, we will use Ubuntu (16.04, 64 bits) as the lab environment, and run the Hyperledger application in a virtual machine. For that, we recommend your system to have at least 4 GB of memory. To get started with Hyperledger Fabric, we need first to meet the following prerequisites.

 

Prerequisites

Before advancing any further we need to install the following third-party tools :

- Virtual box available at https://www.virtualbox.org/wiki/Downloads or native Linux (Ubuntu)
- Git (https://git-scm.com/)
- Go Language (https://golang.org/dl/)
- Docker engine available at https://docs.docker.com/install/linux/docker- ce/ubuntu/ (version +17.03)
- Docker Compose available https://docs.docker.com/compose/install/
( version +1.8)
- Curl (https://curl.haxx.se/)


Node available at https://nodejs.org/en/ (version 8.x < 9) NPM (version 5.x)
- Python 2.7.x and Pip

 

You can refer to their official documentation for further installation instructions.

 

Installing Hyperledger Fabric

The next step is to build a local Hyperledger Fabric runtime to deploy your business networks to.

Make sure you have installed all the dependencies required for us to make the Fabric environment run. Then, create a folder with the name food-supply-chain/, which will host our Fabric project and network configurations files.

Enter the project's directory and install the platform-specific binaries:

curl -sSL
ttps://raw.githubusercontent.com/hyperledger/fabric/release-1.2/scripts/bo otstrap.sh | bash

As a result, you'll preload all of the requisite Docker images for Hyperledger Fabric 1.2 in one shot.


Fabric's Chaincode

Now, let's begin the fun part of the recipe – writing smart contracts.

Chaincode is the smart contract that handles the business logic agreed to by members of the network. It is a piece of code that performs the logic operation in the blockchain network, and can be written in any conventional programming language and executed in a   container. Currently, since Fabric 1.1, Golang and Javascript are the supported Chaincode languages. In this example, we will use Golang (Go) as the Chaincode language to implement our food supply chain example. Therefore, I recommend learning about the Go lanauge before starting. You can refer to the official documentation, or to Go playground (https://play.golang.org/), which is a web-based IDE where you can learn to code in Go online.

As creating the entire supply chain logic may not be within the scope of this recipe, we will implement some very simple logic for our food industry supply chain example.

 

Writing Chaincode

Before we start coding, you can choose to use an IDE for Go, or you may choose the old- fashioned route of Vim or Notepad. There are many popular IDEs which support Go development, for example Visual Studio Code (VSC) (https://code.visualstudio.com/ docs/languages/go), JetBrains Goland, or Eclipse with the goEclipse plugin. Here, we recommend using VSC. You can refer to the official VSC documentation for setup and configuration instructions.

To start writing Chaincode. There is a starter project called food- supply-chain_start. You can import this project to your VSC and open
the foodcontract.go file located under food-supply- chain_start/chaincode/foodcontract.
When writing the Chaincode, we first need to import the necessary Go dependencies –
the shim, peer, and protobuf packages – as follows:
package main import (
"encoding/json" "fmt"
"strconv" "time"
"github.com/hyperledger/fabric/core/Chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer"
)

All Chaincode implements the following interface (from the shim package at https:// godoc.org/github.com/hyperledger/fabric/core/chaincode/shim#Chaincode), which declares these three core functions with the following signatures:

type Chaincode interface {
Init(stub *ChaincodeStub, function string, args []string) ([]byte, error)
Invoke(stub *ChaincodeStub, function string, args []string) ([]byte, error)
Query(stub *ChaincodeStub, function string, args []string) ([]byte, error)
}

Therefore, any Chaincode should define these main functions in its code. For our first Chaincode, FoodContract, along with the previous package, we will import the following structure:

type FoodContract struct{}
// We declare chaincode objects and variables
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success([]byte("Init called"))
}

func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success([]byte("Invoke called"))
}

// We declare other functions func main() {
err := shim.Start(new(FoodContract)) if err != nil {
fmt.Printf("Error creating new Food Contract: %s", err)
}
}
We now need to fill in this empty Chaincode. Let’s start by implementing the Init()
function.

 

The Init function

The Init function is called when the Chaincode is instantiated by the blockchain network for the first time to initialize its internal data. You can think of it as a constructor in other languages (though Go doesn't support constructors).

As we are building Chaincode to manage a food supply chain, we need to start by defining a struct called Food to represent a food asset. The following picture shows the UML representation of a given asset:
blockchain hyperledger fabric and composer

As you may guess, OrderId is the order-tracking ID for the entire supply chain. Besides, each entity in the chain will have its unique entity ID and timestamp when it starts processing the transaction. For example, the raw food producer entity has FoodId and RawFoodProcessDate, and retailers have RetailerId and RetailProcessDate. Each step will update the current status, the entity-related ID, and the process date in the food supply chain.

By querying orderId, we can easily track the current transaction information and status. In the final step, the blockchain will update deliverDate and mark the status as completed once the consumer has received the order.

Here is the equivalent food struct code in our chaincode:

type FoodContract struct {} type food struct {
OrderId                                     string
FoodId                                       string
ConsumerId                             string
ManufactureId                     string
WholesalerId                       string
RetailerId                             string
LogisticsId                          string
status                                       string
RawFoodProcessDate       string ManufactureProcessDate string WholesaleProcessDate string ShippingProcessDate string RetailProcessDate          string
OrderPrice                             int
ShippingPrice                     int
DeliveryDate                       string
}

We then define our Init function as follows:
func (t *FoodContract) Init(stub shim.ChaincodeStubInterface) pb.Response { return setupFoodSupplyChainOrder(stub)
}

As you may notice, the Init function takes a ChaincodeStubInterface stub as an argument and calls setupFoodSupplyChainOrder for initializing the object attributes. The best practice when writing Chaincode is to have the initialization process in a separate function:

func setupFoodSupplyChainOrder(stub shim.ChaincodeStubInterface) pb.Response {
_, args := stub.GetFunctionAndParameters() orderId := args[0]
consumerId := args[1]
orderPrice, _ := strconv.Atoi(args[2]) shippingPrice, _ := strconv.Atoi(args[3]) foodContract := food{
OrderId:               orderId, ConsumerId:       consumerId, OrderPrice:       orderPrice, ShippingPrice: shippingPrice, Status:                 "order initiated"
}
foodBytes, _ := json.Marshal(foodContract) stub.PutState(foodContract.OrderId, foodBytes) return shim.Success(nil)
}

ChaincodeStub provides us with the GetFunctionAndParameters() to read the arguments passed to the Chaincode when Init() or Invoke() are called. These arguments can be used to pass the function (defined within the Chaincode) to execute, along with other arguments used to initialize local variables. These parameters are passed when we initialize our foodContract with predefined values from the client application. For instance, when the consumer places an order with the product price and shipment price, the order ID is generated to track the entire order process for the blockchain. The newly generated foodContract data is converted to a byte stream using the json.Marshal method. The contract data is then recorded in the Fabric ledger using the ChaincodeStubInterface.putstate method, with orderId as a key. Finally, the method returns the success status by returning shim.success(nil).

 

The Invoke function

The Invoke() function, as its name implies, is executed when an application wants to invoke a specific function in the Chaincode. The calling application will pass the particular function name to be executed, with the needed arguments. In our code we will define the following Invoke() function:
func (t *FoodContract) Invoke(stub shim.ChaincodeStubInterface) pb.Response
{
function, args := stub.GetFunctionAndParameters() if function == "createRawFood" {
return t.createRawFood(stub, args)
} else if function == "manufactureProcessing" { return t.manufactureProcessing(stub, args)
} else if function == "wholesalerDistribute" { return t.wholesalerDistribute(stub, args)
} else if function == "initiateShipment" { return t.initiateShipment(stub, args)
} else if function == "deliverToRetail" { return t.deliverToRetail(stub, args)
} else if function == "completeOrder" { return t.completeOrder(stub, args)
} else if function == "query" { return t.query(stub, args)
}
return shim.Error("Invalid function name")
}

The Invoke function is called per transaction on the Chaincode, with ChaincodeStubInterface being passed as an argument, and
the GetFunctionAndParameters returning the function name and arguments. Based on the received function name, it invokes the appropriate Chaincode application method.

To keep it simple, and to avoid any irrelevant Golang coding details, we will present a      single example of an invoked Chaincode function—createRawFood. The other Chaincode functions associated with subsequent steps in the chain will be similar to this method:

func (f *FoodContract) createRawFood(stub shim.ChaincodeStubInterface, args []string) pb.Response {
orderId := args[0]
foodBytes, _ := stub.GetState(orderId) fd := food{}
json.Unmarshal(foodBytes, &fd)
if fd.Status == "order initiated" { fd.FoodId = "FISH_1"
currentts := time.Now()
fd.RawFoodProcessDate = currentts.Format("2006-01-02 15:04:05") fd.Status = "raw food created"
} else {
fmt.Printf("Order not initiated yet")
}
foodBytes, _ = json.Marshal(fd) stub.PutState(orderId, foodBytes) return shim.Success(nil)
}

As you will notice, the createRawFood method accepts a ChaincodeStubInterface stub and command-line inputs as arguments. We set orderId to the value of the first command- line argument. Then, we query food data from the Fabric and convert encoded data to a readable JSON format by using jsonUnmarshal. We check using the returned data, if the current status is "order initiated" before updating the food asset process using a system date with the format YYYY-mm-dd hh:mm:dd. In Go, we use currentts.Format("2006-01-02 15:04:05") to return the date timestamp in the specified format. We also update the food status as raw food created. At the end, we commit food to the blockchain data by calling the stub.PutState method, and we return a successful response to the client using shim.Success.
As we discussed, in the food industry supply chain example, we have six kinds of actor: the raw food producers, the manufacturing processors, wholesalers, logistics operators, retailers, and consumers. Consequently, for a complete Chaincode, we will define an associated function to each actor representing their roles and interactions with the blockchain as follows:

- createRawFood: function called to produce the food
- manufatureProcessing: function called to send the food to the manufacturing processor
- wholesaleDistribute: function called to transport the food product to the wholesaler for distribution
- nitiateShipment: function called to initiate the shipment process from wholesalers
- deliverToRetail: function called to deliver the food product to the retailers from logistics
- completeOrder: function called to complete the order process after the consumers can pick up their products. The overall process is shown in the following sequence diagram:

blockchain hyperledger fabric and composer

Once the customer receives the product, the order is completed and, per consequence, we update the status as completed by calling completeOrder, which is defined as follows:
func (f *FoodContract) completeOrder(stub shim.ChaincodeStubInterface, args []string) pb.Response {
orderId := args[0]


foodBytes, err := stub.GetState(orderId) fd := food{}
err = json.Unmarshal(foodBytes, &fd) if err != nil {
return shim.Error(err.Error())
}
if fd.Status == "Retailer started" { currentts := time.Now()
fd.DeliveryDate = currentts.Format("2006-01-02 15:04:05") fd.Status = "Consumer received order"
} else {
fmt.Printf("Retailer not initiated yet")
}
foodBytes0, _ := json.Marshal(fd)
err = stub.PutState(orderId, foodBytes0) if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}

Hyperledger data storage

At this level, let's introduce an important concept in Hyperledger—the world state.
As you will have noticed, at the end of the createRawFood function we called
the putState(key, value) method to store or update any validated state values on the ledger.

Here, a question can be raised about data immutability: Does the putState function change the data in the blockchain? In Hyperledger Fabric we need to make a distinction between two parts of the ledger—the world state and the blockchain.
The world state is a database that stores (as a key value pair) the current values of all ledger states (all Chaincode states). It is populated when each peer validates and commits a transaction. Fabric supports two database infrastructure options for state databases including LevelDB, as used by Ethereum, and CouchDB. The former is the default state database, which supports key value storage, while the latter is a more advanced choice  used to store complex data types to support business functions. However, Fabric provides a flexible pluggable design for state databases, meaning it can be configured to use other types of database.

The second part is the blockchain. It represents a transaction log that records all historical changes of the world state, and is a file-based ledger which stores an immutable sequence of blocks, and contains a set of ordered transaction data.
hyperledger fabric and composeer development

Given that, we understand now that putState(key, value) will update the ledger state data in the world state, and the transaction log will keep the entire state data as an immutable record visible only to permitted nodes in the blockchain.

 

The Query function

The final important function to define is the Query function. It is called when the application queries the Chaincode state. In our case Query definition is straightforward: we just need to pass a key—orderId—to get, in result, the corresponding food struct, as follows :

func (f *FoodContract) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var ENIITY string var err error
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expected ENIITY
Name")
}
ENIITY = args[0]
Avalbytes, err := stub.GetState(ENIITY) if err != nil {
sonResp := "{\"Error\":\"Failed to get state for " + ENIITY + "\"}" return shim.Error(jsonResp)
}
if Avalbytes == nil {
jsonResp := "{\"Error\":\"Nil order for " + ENIITY + "\"}"

return shim.Error(jsonResp)
}
return shim.Success(Avalbytes)
}

The important part in the code above is the call to the GetState(ENIITY) method, which reads the values from the world state corresponding to the given key.

 

Error handling

Interestingly, Hyperledger Fabric has its own error-handling
package, github.com/pkg/errors, which allows you to handle errors in a much better way than the built-in error handling provided by Go. For example:

import (
"fmt" "github.com/pkg/errors"
)

//wrapping error with stack func wrapWithStack() error {
err := displayError ()
return errors.Wrap(err, "wrapping an application     error with stack trace")
}
func displayError() error {
return errors.New("example error message")
}
func main() {
err := displayError()
fmt.Printf("print error without stack trace: %s\n\n", err) fmt.Printf("print error with stack trace: %+v\n\n", err) err = wrapWithStack()
fmt.Printf("%+v\n\n", err)
}

The aforementioned package provides several helpful functions. For instance, error.wrap is used to generate a call stack trace for a given error (the standard error handling does not come with stack traces), which is very helpful for debugging, while error.New generates a new error with the supplied message and records the stack trace at the point it was
called. The shim package also provides an error-handling method, shim.error(), which returns an error message with a serialized response to the client.


As an example, we can define the initiateShipment function as the following, with the ability to warn the client if an error occurs using shim.error as follows:
func (f *FoodContract) initiateShipment(stub shim.ChaincodeStubInterface, args []string) pb.Response {
orderId := args[0]
foodBytes, err := stub.GetState(orderId) fd := food{}
err = json.Unmarshal(foodBytes, &fd) if err != nil {
return shim.Error(err.Error())
}
if fd.Status == "wholesaler distribute" { fd.LogisticsId = "LogisticsId_1" currentts := time.Now()
fd.ShippingProcessDate = currentts.Format("2006-01-02 15:04:05") fd.Status = "initiated shipment"
} else {
fmt.Printf("Wholesaler not initiated yet")
}
foodBytes0, _ := json.Marshal(fd)
err = stub.PutState(orderId, foodBytes0) if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}

At this level, we have successfully written the main parts of our first Chaincode using the Golang language. Next, we need to build a local Hyperledger network to deploy the Chaincode and start tracking the food along the supply chain.

 

Building a business network

Hyperledger Fabric has a built-in docker image to run peer nodes, and in order to set up a supply chain network we would typically use Docker Composer to launch various Fabric component containers. Before we run the Fabric network, we need to design the food supply chain network topology properly. In the chain, we have six types of entity: the raw food producer, a manufacturing processor, wholesalers, logistics operators, retailers, and consumers. For demonstration purposes we will define three different organizations to contain these entities, a single orderer, and a channel in our business network. The entities will interact with the blockchain application by invoking Chaincode in the Fabric network, updating the ledger world state, and writing transaction logs.

Hyperledgr supply chain

In this design, the organisation ORG1 hosts two peer nodes (peer0.org1.fsc.com and peer1.org1.fsc.com) representing the consumer and retailer peers, and handles the interaction involved in the consumer ordering food through the retailer store. Elsewhere, ORG2 hosts two peer nodes (peer0.org2.fsc.com and peer1.org2.fsc.com) representing the logistic and wholesaler peers, and handles the wholesaler's initial  shipment request to the logistical entity. Meanwhile, ORG3 hosts two peer nodes (peer0.org3.fsc.com and peer1.org3.fsc.com) representing the manufacturing processor and raw food producer peers, and handles the interaction of sending raw food to manufacturers for processing and packaging.

Privacy in Hyperledger

Hyperledger is a permissioned blockchain, meaning all participants and components in the network have identities which are assigned to a certificate such as x.509. The main element behind this schema, is the MSP which ensures the privacy of all members in the network. It has the ability to identify each participant's roles within the organization they represent, and set access privileges for the context of a network and channel. There are three types of MSPs:

- Network MSP: Defines members in the network
- Channel MSP: Defines who can participate in certain actions on a given channel according to channel policies
- Peer/Orderer MSP: Defined as the local MSP for a single peer or orderer, for identifying members of the same organization
hyperledger fabric and composeer development

In the preceding example, there are two channels for two groups of members. CHANNEL 1 is for ORG5 and ORG6, and CHANNEL 2 is for ORG2, ORG3, ORG4, and ORG5. Two different channel MSPs apply to these groups separately. ORG5 and ORG6 can see transactions in CHANNEL 1, while ORG2, ORG3, ORG4, and ORG5 can see transactions in CHANNEL 2. ORG5 participates in both channels, and can see both sets of transactions, but ORG6 can’t see transactions in CHANNEL 1. Similarly, ORG2, ORG3, and ORG4 can’t see transactions in CHANNEL 1 .

Define services in a compose file

After presenting the business network's logical architecture, we will now adopt something similar for our food supply chain. We’ll be using Docker Compose to launch the corresponding Fabric containers, and as a first step we will define the services run in the container using a docker-compose.yml file.
Before we start to define our config files, let's have a look at the project's structure. You should remember that you can get the project code from the Packt website. We have a root folder food-supply-chain/ structured as follows:
hyperledger fabric and composeer development

There is a base/ folder which contains two base files — peer-base.yaml and docker- compose-base.yaml — which are needed to configure the Docker containers as fabric peers. The chaincode/ folder contains a subfolder foodcontract/ which hosts the Chaincode files.

As we will discover later, the configtxgen tool will generate the output in the channel- artifacts/ folder, as configured in configtx.yaml. Finally, the scripts/ folder contains script.sh and utils.sh, which sets up the Hyperledger network and defines a Chaincode execution scenario, while fscn.sh will be be the script which triggers the execution of the others.

That said, let's start configuring Docker. To make it easy for you, copy the file
and base/ directory, along with the docker-compose-cli.yaml file, to your working directory from the Packt source code or fabric-samples/first-network directory (https://github.com/hyperledger/fabric-samples/tree/release-1.2/first-network). Here is an example defining the parameters of the orderer service and a network peer:

# Blockchain by example version: '2'
services: orderer.fsc.com:
container_name: orderer.fsc.com image: hyperledger/fabric-orderer environment:

  1. ORDERER_GENERAL_LOGLEVEL=debug
  2. ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
  3. ORDERER_GENERAL_GENESISMETHOD=file

-
ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block

  1. ORDERER_GENERAL_LOCALMSPID=OrdererMSP
  2. ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
  3. ORDERER_GENERAL_TLS_ENABLED=true

-
ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
-
ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt

  1. ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] working_dir: /opt/gopath/src/github.com/hyperledger/fabric

command: orderer volumes:

    1. ../channel- artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
    2. ../crypto- config/ordererOrganizations/fsc.com/orderers/orderer.fsc.com/msp:/var/hyper ledger/orderer/msp
    3. ../crypto- config/ordererOrganizations/fsc.com/orderers/orderer.fsc.com/tls/:/var/hype rledger/orderer/tls

ports:
- 7050:7050
peer0.org1.fsc.com:
container_name: peer0.org1.fsc.com extends:
file: peer-base.yaml service: peer-base
environment:

      1. CORE_PEER_ID=peer0.org1.fsc.com
      2. CORE_PEER_ADDRESS=peer0.org1.fsc.com:7051
      1. CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.fsc.com:7051
      2. CORE_PEER_LOCALMSPID=Org1MSP

volumes:

        1. /var/run/:/host/var/run/
        2. ../crypto- config/peerOrganizations/org1.fsc.com/peers/peer0.org1.fsc.com/msp:/etc/hyp erledger/fabric/msp
        3. ../crypto- config/peerOrganizations/org1.fsc.com/peers/peer0.org1.fsc.com/tls:/etc/hyp erledger/fabric/tls

ports:
- 7051:7051
- 7053:7053

peer1.org1.fsc.com:
container_name: peer1.org1.fsc.com extends:
file: peer-base.yaml service: peer-base
...

You can define the other peers, peer*.org*.fsc.com, in the same way as we did
for peer0.org1.fsc.com using their corresponding domain names. For a more complete example, you can have a look at the example listed in the Hyperledger GitHub repository (https://github.com/hyperledger/composer/blob/master/packages/composer-tests- functional/hlfv1/docker-compose.yml). As you may notice, the docker-compose.yml file extends a peer-base.yaml configuration, which can be used as the configuration file for each node:

# Peer network configuration for food Supply Chain version: '2'
services: peer-base:
image: hyperledger/fabric-peer environment:

      1. CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      2. CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_fscn
      3. CORE_LOGGING_LEVEL=DEBUG
      4. CORE_PEER_TLS_ENABLED=true
      5. CORE_PEER_GOSSIP_USELEADERELECTION=true
      6. CORE_PEER_GOSSIP_ORGLEADER=false
      7. CORE_PEER_PROFILE_ENABLED=true
      8. CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
      9. CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
      10. CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer command: peer node start

The most important part of the previous file is the line starting with command, which specifies the command that is issued when the container starts.

 

Resources and profiles

The next step is to edit the configtx.yaml file, which represents an exhaustive list of all the internal resources defined by Fabric. It will be used later to create a channel and related artifacts. Here's the configuration we need for our network:

# Blockchain by example. Profiles:
FSCOrgsOrdererGenesis: Orderer:
<<: *OrdererDefaults Organizations:

        1. *OrdererOrg Consortiums:

FoodSupplyChainConsortium: Organizations:

          1. *Org1
          2. *Org2
          3. *Org3

FSCOrgsChannel:
Consortium: FoodSupplyChainConsortium Application:
<<: *ApplicationDefaults Organizations:

        1. *Org1
        2. *Org2
        3. *Org3 ########################################################################### #####

#       Section: Organizations
#       - This section defines the different organizational identities which will
#       be referenced later in the configuration. ########################################################################### #####
Organizations:

    1. &OrdererOrg

Name: OrdererOrg ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/fsc.com/msp

    1. &Org1

Name: Org1MSP ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1.fsc.com/msp AnchorPeers:

      1. Host: peer0.org1.fsc.com Port: 7051
    1. &Org2

Name: Org2MSP ID: Org2MSP
MSPDir: crypto-config/peerOrganizations/org2.fsc.com/msp AnchorPeers:

      1. Host: peer0.org2.fsc.com Port: 7051
    1. &Org3

Name: Org3MSP ID: Org3MSP
MSPDir: crypto-config/peerOrganizations/org3.fsc.com/msp AnchorPeers:

      1. Host: peer0.org3.fsc.com Port: 7051

Orderer: &OrdererDefaults OrdererType: solo Addresses:
- orderer.fsc.com:7050 BatchTimeout: 2s BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 20 MB
PreferredMaxBytes: 512 KB Kafka:
Brokers:
- 127.0.0.1:9092
Organizations:
Application: &ApplicationDefaults Organizations:

We define, among other things, the path which contains the MSP configuration for every organization.

You can refer to the sample configtx.yaml shipped with Fabric (https://github.com/ hyperledger/fabric-test/blob/master/feature/configs/configtx.yaml) for all possible configuration options.


Fabric channel and Genesis block

We can use the configrxgen tool to create important artifacts for the food supply chain network, namely: the Genesis block, channel, and anchor peer transactions. To achieve that goal, we run the following commands:

> configtxgen -profile FSCOrgsOrdererGenesis -outputBlock ./channel- artifacts/genesis.block

> export CHANNEL_NAME="fscchannel"
> configtxgen -profile FSCOrgsChannel -outputCreateChannelTx ./channel- artifacts/channel.tx -channelID $CHANNEL_NAME

The first command creates the orderer Genesis block, whereas the last command initiates a channel configuration transaction, channel.tx. At each step we supply to
the configtxgen tool the profiles defined earlier in the configtx.yaml file.
After creating a channel with multiple organizations, we need to define AnchorPeers to initiate gossip communication between peers from different organizations. As stated in
the official documentation at https://hyperledger-fabric.readthedocs.io/en/release- 1.2/glossary.html#anchor-peer, an anchor node serves as the entry point for another organization's peer on the same channel to communicate with each of the peers in the anchor peer’s organization.
Next, we need to use configtxgen to create a configuration update transaction to include those anchor peers for the different Orgs:
configtxgen -profile FSCOrgsChannel -outputAnchorPeersUpdate ./channel- artifacts/Org1MSPanchors.tx -asOrg Org1MSP -channelID $CHANNEL_NAME
configtxgen -profile FSCOrgsChannel -outputAnchorPeersUpdate ./channel- artifacts/Org2MSPanchors.tx -asOrg Org2MSP -channelID $CHANNEL_NAME
configtxgen -profile FSCOrgsChannel -outputAnchorPeersUpdate ./channel- artifacts/Org3MSPanchors.tx -asOrg Org3MSP -channelID $CHANNEL_NAME

To update an anchor peer in the FSCOrgsChannel channel, run the following commands:
peer channel update -f ./channel-artifacts/Org${ORG}MSPanchors.tx -c
$CHANNEL_NAME -o orderer.fsc.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile
$ORDERER_CA >&log.txt


As a result, you should see output similar to the following screenshot:
develop blockchain supply chain

 

Generate peers and orderer certificates

As stated earlier, nodes are allowed to access business networks using an MSP, which is typically a Certificate Authority (CA).

In this section, we will generate, for all the components that we need to run in the network, the required X.509 certificates using the cryptogen tool, which uses the crypto- config.yaml file as its configuration input. Here is an example which defines the orderer and peer organizations:

OrdererOrgs:
# -----------------------------------------------------------------------
----
# Orderer
# -----------------------------------------------------------------------
----
- Name: Orderer Domain: fsc.com Specs:
- Hostname: orderer
# -------------------------------------------------------------------------
--
# "PeerOrgs" - Definition of organizations managing peer nodes
# -------------------------------------------------------------------------
--
PeerOrgs:
# -----------------------------------------------------------------------
----
# Org1

# -----------------------------------------------------------------------
----
- Name: Org1
Domain: org1.fsc.com Template:
Count: 2 Users:
Count: 2
# -----------------------------------------------------------------------
----
# Org2
# -----------------------------------------------------------------------
----
- Name: Org2
Domain: org2.fsc.com Template:
Count: 2 Users:
Count: 2
# -----------------------------------------------------------------------
----
# Org3
# -----------------------------------------------------------------------
----
- Name: Org3
Domain: org3.fsc.com Template:
Count: 2 Users:
Count: 2

We have now defined three organizations for peers and single orderer organization. You can use the sample file provided by Hyperledger sample projects at https://github.com/ hyperledger/fabric-samples. Afterward, we run the following command to generate the certificates for the peers and the orderer:

cryptogen generate --config=./crypto-config.yaml

As a result, you should see the following output in the console:
develop blockchain supply chain

 

Start the Docker containers

We are now ready to run our network, but first we need to perform one last step—editing the compose-cli.yaml.
This file defines the networks and services including the peer, order, and cli containers, the last of which is where you issue commands that interact with the peers (creating channels, deploying Chaincode, and so on).

Below is an example of a docker-compose-cli.yaml:
version: '2'
networks: #Define blockchain network name fscn:
#service section define all peers service and related container services: #name of service will serve as an orderer in the fabric network orderer.fsc.com:
extends:
file: base/docker-compose-base.yaml service: orderer.fsc.com container_name: orderer.fsc.com networks:

  1. fscn peer0.org1.fsc.com:

container_name: peer0.org1.fsc.com extends:
file: base/docker-compose-base.yaml service: peer0.org1.fsc.com networks:

  1. fscn peer1.org1.fsc.com:

container_name: peer1.org1.fsc.com extends:
file: base/docker-compose-base.yaml service: peer1.org1.fsc.com networks:

  1. fscn

....
#client section cli:
container_name: cli
image: hyperledger/fabric-tools tty: true

Defining environment variable environment:

  1. GOPATH=/opt/gopath
  2. CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
  3. CORE_LOGGING_LEVEL=DEBUG #- CORE_LOGGING_LEVEL=INFO
  4. CORE_PEER_ID=cli
  5. CORE_PEER_ADDRESS=peer0.org1.fsc.com:7051
  6. CORE_PEER_LOCALMSPID=Org1MSP
  7. CORE_PEER_TLS_ENABLED=true

-
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/ crypto/peerOrganizations/org1.fsc.com/peers/peer0.org1.fsc.com/tls/server.c rt
-
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/c rypto/peerOrganizations/org1.fsc.com/peers/peer0.org1.fsc.com/tls/server.ke y
-
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/p eer/crypto/peerOrganizations/org1.fsc.com/peers/peer0.org1.fsc.com/tls/ca.c rt
-
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/ crypto/peerOrganizations/org1.fsc.com/users/Admin@org1.fsc.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME} ${DELAY}; sleep
$TIMEOUT'

Mapping the directories that are being used in the environment configurations:

volumes:

  1. /var/run/:/host/var/run/
  2. ./Chaincode/:/opt/gopath/src/github.com/Chaincode
  3. ./crypto- config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
  4. ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
  5. ./channel- artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel- artifacts

depends_on:

  1. orderer.fsc.com
  2. peer0.org1.fsc.com
  3. peer1.org1.fsc.com
  4. peer0.org2.fsc.com
  5. peer1.org2.fsc.com
  6. peer0.org3.fsc.com
  7. peer1.org3.fsc.com networks:

We define the following environment variables:

CHANNEL_NAME=$CHANNEL_NAME TIMEOUT=$CLI_TIMEOUT DELAY=$CLI_DELAY

The first variable, CHANNEL_NAME, holds the name of the channel that was specified earlier as an input for the configtxgen tool. For the timeout, you can provide a value (specified in seconds), otherwise the CLI container, by default, will exit after 60 seconds.

Finally, we can launch our network by calling the docker-compose command with the docker-compose-cli.yaml file, as follows:
sudo docker-compose -f docker-compose-cli.yaml up

If we run the command, it will launch our network, shown as follows:
develop blockchain supply chain

 

Join the channel and install Chaincode

Once we have started the Fabric network, we need to execute a series of commands to interact with the blockchain. You may already notice that we have a command configuration in the CLI section of the docker-compose-cli.yaml:
/bin/bash -c './scripts/script.sh ${CHANNEL_NAME} ${DELAY}; sleep $TIMEOUT'

Since there are six peers and three organizations, when we call the above commands, we don’t want to hardcode the peers and organizations inside any functions. To avoid ending with a cumbersome script, we can simply pass the peer and organization parameters to a script function and trigger the peer-related Fabric command. Here is an example of scripts/script.sh to join all peers to a channel and install Chaincode for the consumer and retailer peer nodes.
#check script.sh utils.sh joinChannel () {
for org in 1 2 3; do
for peer in 0 1; do joinChannelWithRetry $peer $org
echo "======= peer${peer}.org${org} joined on the channel
\"$CHANNEL_NAME\" ============ "
sleep $DELAY echo
done done
}

joinChannelWithRetry () { PEER=$1
ORG=$2
setGlobals $PEER $ORG
peer channel join -b $CHANNEL_NAME.block >&log.txt
..
}

echo "Installing Chaincode on consumer peer: peer0.org1..." installChaincode 0 1
echo "Installing Chaincode on retailer peer: peer1.org1..." installChaincode 1 1
..

#function for install Chaincode, check utils.sh installChaincode () {
PEER=$1 ORG=$2
setGlobals $PEER $ORG

peer Chaincode install -n fsccc -v 1.0 -l ${LANGUAGE} -p github.com/Chaincode/foodcontract >&log.txt
res=$?
cat log.txt
verifyResult $res "Chaincode installation on peer${PEER}.org${ORG} has Failed"
echo "================== Chaincode is installed on remote peer${PEER}.org${ORG} ================= "
echo
}

We can also define additional important environment variables such as the following (an example when interacting with Peer 0 of Organization 2):

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/ crypto/peerOrganizations/org2.fsc.com/users/Admin@org2.fsc.com/msp CORE_PEER_ADDRESS=peer0.org2.fsc.com:7051
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/p eer/crypto/peerOrganizations/org2.fsc.com/peers/peer0.org2.fsc.com/tls/ca.c rt

However, to automate the process and to avoid handling environment variables from the CLI, I have defined a utils.sh script located under the scripts/ folder which we will be using later in this recipe.

 

Chaincode compilation and deployment

After setting up the network and writing the Chaincode, it's time to deploy the Chaincode. For that, we start by building and compiling the Chaincode using the following   command: go build.

Many developers directly compile and install Chaincode from the project Chaincode folder, which isn't the best practice. Typically, we define GOPATH at /opt/gopath in the docker-compose-cli.yaml file, under the cli section:
cli:
container_name: cli
image: hyperledger/fabric-tools tty: true
environment:
- GOPATH=/opt/gopath

  1. CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
  2. CORE_LOGGING_LEVEL=DEBUG

....
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME} ${DELAY}; sleep
$TIMEOUT'
volumes:

  1. /var/run/:/host/var/run/

- ./Chaincode/:/opt/gopath/src/github.com/Chaincode
- ./crypto- config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/

The configuration will map the project Chaincode/ folder to
/opt/gopath/src/github.com/Chaincode, and when we start to bring up the Fabric network through our Composer command, the Chaincode will be copied to the preceding- mapped address with the compiled Chaincode file. Afterwards, we start the Docker CLI using: docker exec -it cli bash.
From here, we deploy Chaincode on the default peer (Peer 0 of Organization 1) using:

peer Chaincode install -n fsccc -v 1.0                                                                                                -p github.com/Chaincode/foodcontract

Here the -n argument specifies the network name and -v the Chaincode version. When this command executes successfully you will see a response indicating a status of 200.

Interacting with Chaincode

Once the Chaincode is deployed and installed, we can then instantiate the Chaincode as follows:

peer Chaincode instantiate -o orderer.fsc.com:7050 -C $CHANNEL_NAME -n fsccc -v 1.0 -c '{"Args":["init","order_001","John_1","100","5"]}' -P "OR('Org1MSP.member','Org2MSP.member','Org3MSP.member')"

Here we pass a JSON array of arguments to trigger the Init function defined earlier, using the -c option (lowercase). If you remember, when Init is executed it calls
the setupFoodSupplyChainOrder function internally, which initiates the order details.
Along with this, we assign the values order_001, John_1, 100, and 5 to the
variables orderId , consumerId , orderPrice and shippingPrice respectively. The -P
flag represents the endorsement policy associated with this Chaincode.

 

Running the project

Throughout the previous sections we have gone over Chaincode deployment, network setup and many other Fabric features. In this section, we will use the Fabric tool to run an end-to-end application for our food supply chain application. I assume here that you have already downloaded the project code from the Packt website.

To run the network we provide a bash script—fscn.sh—that leverages the Docker images to bootstrap a Hyperledger Fabric network quickly. You can run it using: sudo ./fscn.sh
–m up.
Once up, the script script.sh defined earlier will be executed. As a consequence, a series of events will be set in motion, including channel creation, the joining of all peers into the channel, the installation and instantiation of Chaincode in all peers, and the execution of different queries. These are all defined in script.sh, which is associated with utils.sh.

The following picture shows the execution results of the first part of the script, ending with the creation of the channel, fscchannel:
develop blockchain supply chain

All the functions defined in the Chaincode will be called within script.sh. For the sake of brevity, we present here the output showing the result of the invocation of
the createRawFood method:
develop blockchain supply chain

This is the result of the execution of chaincodeInvokeCreateRawFood defined in the
utils.sh script as follows:
#create rawfood by invoke chaincode chaincodeInvokeCreateRawFood() {
PEER=$1 ORG=$2
setGlobals $PEER $ORG
if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false"
]; then
peer chaincode invoke -o orderer.fsc.com:7050 -C $CHANNEL_NAME -n fsccc -c '{"Args":["createRawFood","order_001"]}' >&log.txt
else
peer chaincode invoke -o orderer.fsc.com:7050    --tls
$CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n fsccc -c '{"Args":["createRawFood","order_001"]}' >&log.txt
fi res=$?
cat log.txt
verifyResult $res "Invoke:CreateRawFood execution on PEER$PEER failed " echo "Invoke:CreateRawFood transaction on PEER $PEER on channel
'$CHANNEL_NAME' is successful. " echo
}
At the end, we can see the result of querying the Chaincode for the current food state data:
develop blockchain supply chain

At this level, we are able to communicate with the deployed Chaincode through Linux scripts and commands. I know you might find it a bit tricky, therefore, in the following sections, we will use a more abstract approach using RESTful calls.

 

Interacting over REST API/JSON-RPC

So far, we have successfully run the end-to-end food supply chain via a script, simulating the entire business flow. In this section, we will explore using the Fabric RESTful API to demonstrate how a web page can interact with Fabric through a web application. We will demo how a CA can join the network and query the ledger data. We will use a previous food supply chain example to demonstrate how we can utilize the Fabric RESTful API to get information from the blockchain.

Setting up the development environment

Get the source code of this from the PacktPub GitHub repository if you haven’t already done so. Once you download the source code, navigate to the directory blockchain-by- example/fsc-restful. The example we will run here is based on a Fabric sample project, located at github: https://github.com/hyperledger/fabric-samples.
To run the web application, we first need to bring up the Fabric network. We make sure that no other active container is running by using:
sudo ./script.sh m down

Then, clear any unused networks:

docker network prune

Navigate to the webapp/ folder and run:
npm install

You'll have to wait for npm to install a few packages. Once the operation is successfully finished, navigate back to the fsc-restful folder, and launch the Fabric network by running:
sudo ./script m up

Install the Chaincode, and instantiate it with initial customer order data, before invoking
createRowfoodChaincode:
peer Chaincode install -n fsccc -v 1.0 -p "$CC_SRC_PATH" -l "$LANGUAGE" peer Chaincode instantiate -o orderer.example.com:7050 -C mychannel -n fsccc -l "$LANGUAGE" -v 1.0 -c '{"Args":["init","order_001","John_1","100","5"]}'
peer Chaincode invoke -o orderer.example.com:7050 -C mychannel -n fsccc -c '{"Args":["createRawFood","order_001"]}'


Register users

As the Chaincode is instantiated and the needed dependencies are installed, launch the Node.js server using node server.js. Once the server is running, open the web browser by navigating to http://yourserverip:3000. You will see a web page similar to the one here:
Blockchain dev with Hyperledger Fabric


You can start by assigning the admin to the Fabric client. For that, click the Register Admin
button, which will register you in Fabric as the admin client user:
Blockchain dev with Hyperledger Fabric

In this step, we send a request for an admin as the authorized user and register with the CA. The certificate-related folder, hrc-key-store, should be generated.

 

Let's take a look at how server.js registers admin users in a Fabric blockchain.
The client application uses fabric-ca-client, fabric-client, and GRpc node libraries to interact with the Fabric network.

The fabric-ca-client manages Fabric's user certificate life cycles, including registering, enrolling through API, and interacting with the Fabric CA.

The fabric-client interacts with peers and orderers to install and instantiate Chaincodes, send transactions, and perform queries.

 

Here are a few steps to register admin users:

  1. Set up hfc-key-store for Fabric_Client
  2. Initialize Fabric client—new Fabric_CA_Client('http://localhost:7054', tlsOptions , 'ca.example.com', crypto_suite)
  3. Get admin user—context - fabric_client.getUserContext('admin', true)

 

  1. Create admin user—fabric_client.createUser

Here is some sample code, serving to register an admin:

app.get('/registerAdmin',function(req,res) { var fabric_client = new Fabric_Client(); var fabric_ca_client = null;
var admin_user = null; var member_user = null;
var store_path = path.join( dirname, 'hfc-key-store'); Fabric_Client.newDefaultKeyValueStore({ path: store_path
}).then((state_store) => {
// assign the store to the fabric client fabric_client.setStateStore(state_store);
var crypto_suite = Fabric_Client.newCryptoSuite();
var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path});
crypto_suite.setCryptoKeyStore(crypto_store); fabric_client.setCryptoSuite(crypto_suite); var         tlsOptions = {
trustedRoots: [], verify: false
};
fabric_ca_client = new Fabric_CA_Client('http://localhost:7054', tlsOptions
, 'ca.example.com',crypto_suite);
return fabric_client.getUserContext('admin', true);
}).then((user_from_store) => {
if (user_from_store && user_from_store.isEnrolled()) { console.log('Successfully loaded admin from persistence'); admin_user = user_from_store;
return null;
} else {
// need to enroll it with CA server return fabric_ca_client.enroll({
enrollmentID: 'admin', enrollmentSecret: 'adminpw'

 

'Org1MSP',


}).then((enrollment) => {
console.log('Successfully enrolled admin user "admin"'); return fabric_client.createUser({username: 'admin',mspid:

cryptoContent: { privateKeyPEM: enrollment.key.toBytes(),

signedCertPEM: enrollment.certificate }});
}).then((user) => { admin_user = user;
return fabric_client.setUserContext(admin_user);
}).catch((err) => {
});

.. });


}
}).then(() => {

}).catch((err) => {
});
Once the admin is registered, we register a user as the Fabric client by clicking the Register User button. This step is similar to the precedent, and the user will be registered with the CA server and enrolled as a new user with an assigned identity, which can query and update the ledger. This authority is granted and authorized by the admin user through the Fabric network:
Blockchain dev with Hyperledger Fabric

 

Querying the Chaincode from UI

Now, it is time to query the Chaincode status using the authorized user, who can read the data from the ledger, which is returned in JSON format.

By clicking Query Chaincode, the node server triggers the query Chaincode API to get the current ledger state information. We can see that orderId, orderPrice, shippingPrice, and rawFoodProcessDate are returned from the ledger and shown on the page:
Blockchain dev with Hyperledger Fabric

Similarly to what we did before, the queryChaincode uses the fabric_client API to connect to a channel with peer and query data as follows:

app.get('/queryChaincode',function(req,res){
// setup the fabric network
var fabric_client = new Fabric_Client();
var channel = fabric_client.newChannel('mychannel');
var peer = fabric_client.newPeer('grpc://localhost:7051'); channel.addPeer(peer);
var member_user = null;
var store_path = path.join( dirname, 'hfc-key-store'); var tx_id = null; Fabric_Client.newDefaultKeyValueStore({ path: store_path
}).then((state_store) => {
...
return fabric_client.getUserContext('user1', true);
}).then((user_from_store) => {
....
const request = { chaincodeId: 'fsccc', fcn: 'query',
args: ['order_001']
};
// send the query proposal to the peer return channel.queryByChaincode(request);

Congratulations! We just used our application and queried it via Hyperledger Fabric. At this level, you should get a good sense for how web applications can be integrated with the Fabric blockchain.

 

Hyperledger Composer

You have witnessed how difficult it can be to build a Hyperledger network and to deploy and interact with the Chaincode. This situation will change with Composer.

As mentioned earlier, Hyperledger Composer is based on Hyperldeger Fabric. It is an open development tool set and a framework for making the development of blockchain applications much easier. Hyperledger Composer was built with JavaScript, making it very easy to define your business network, create assets, and run transactions.

Get Hyperledger Composer and Playground

In this project we will make use of the Hyperledger Composer development
tools. Hyperledger Composer is an application development framework, which helps us in getting started quickly, and which simplifies the creation of Hyperledger Fabric (https:// hyperledger-fabric.readthedocs.io/en/latest/) blockchain applications.

We start by installing the most important utility, composer-cli, which will help us to perform administrative, operational, and development tasks:

npm install -g composer-cli@0.19

Next, we'll also pick up generator-hyperledger-composer and composer-rest- server. We start by installing the first package, which is a Yeoman module that creates project templates for using with Hyperledger Composer:
npm install g generator-hyperledger-composer

Then, we install the Hyperledger Composer REST server, which allows for RESTful interactions between our deployed business network and a web client:

npm install -g composer-rest-server

Afterwards, we install Yeoman, which is a tool for generating skeleton web applications. We install it in order to use the previously installed generator, generator-hyperledger- composer :
npm install g yo

We need then to install Hyperledger Playground, which provides you with a user interface for viewing and demonstrating your business networks, as follows:
npm install g composer-playground

Composer Playground

As Composer Playground has already been installed, we can start the corresponding container using:

sudo docker run --name composer-playground --publish 8080:8080 --detach hyperledger/composer-playground

Once the container has started, open a browser and navigate to localhost:8080, where you should see the following welcome page:
Blockchain dev with Hyperledger Fabric

You can shut down playground at any time, using:

sudo docker rm --force composer-playground

If everything is ready, let’s start to play!

First, let's create a new business network by clicking on Deploy a new business network. Afterwards you'll need to provide some details about your new business
network, for example a name—fsn-business-network. Then select empty-business- network, and click Deploy.
Blockchain dev with Hyperledger Fabric

Once created, you have to connect to the fsn-business-network by clicking Connect now:
Blockchain dev with Hyperledger Fabric

You'll get a few files, and among them will be a model file. Hyperledger Composer provides an object-oriented-like modeling language, which allows us to define the domain model for a business network definition in a .cto file. You can learn more about this modeling language and this file's structure from the official documentation at: https:// hyperledger.github.io/composer/v0.19/reference/cto_language. For the sake of our example, let's adopt the following sample:
Blockchain dev with Hyperledger Fabric

After that, we need to define your transaction processor script file by adding a JavaScript file with the following content:

hyperledger

Then, we need to define the access control policy. We use the default network administrator to give full access to the business network and system-level operations:
Blockchain dev with Hyperledger Fabric

Once you have finished, click Deploy changes in the bottom left to upgrade the business network, and click Test to get a test started.
We should add a participant to our business network. To do that, create a participant by selecting the left menu's Consumer tab, and clicking Create new participant in the upper right. Modify the value with your details, then click Create new to create the new participant.
Blockchain dev with Hyperledger Fabric

Now, we need to create an asset. This can be done by selecting the left menu Food tab under assets, and clicking Create new asset in the upper right. Enter or modify the value you need to test. Then click Create new to create the new asset.
You should see the newly created asset in the Food tab:
Blockchain dev with Hyperledger Fabric

At this level, you can submit a transaction by entering the corresponding orderId and
consumerId defined in previous steps:
Blockchain dev with Hyperledger Fabric

Once submitted, you can view the log of your transactions by clicking All transactions on the left. Click View record to inspect the transaction details. You can see the transaction ID and when this transaction was processed:
Blockchain dev with Hyperledger Fabric


By checking the food asset value, we can see that the consumer data is updated:
Blockchain dev with Hyperledger Fabric

Now, you have an idea how Composer works and how easy it is to work with such a tool, instead of using the native Fabric infrastructure directly.

 

Conclusion

In this recipe, we have learned a lot about the Hyperledger project and, in particular, about Fabric. We have introduced, among other things, how to write and deploy a smart contract using Golang. You should now be comfortable enough to start writing your own smart contracts. We have also discovered how to build a web application that can interact with the Hyperledger Fabric API using the RPC protocol. At the end, we introduced an important tool—Hyperledger Composer—which can help us to build Fabric
applications easily.

I hope you are not tired, since, in the next recipe, we will continue discovering Hyperledger by building another project—a letter of credit.

For more hands-on tutorials and exercises on other projects of Hyperledger like Sawtooth or Iroha, visit Comprehensive Hyperledger Training Tutorials page to get the outline of our Hyperledger articles.
To conclude this recipe, we like to recommend Blockchain Hyperledger Development in 30 hours, Learn Hands-on Blockchain Ethereum Development & Get Certified in 30 Hrs, and Become Blockchain Certified Security Architect in 30 hours courses to those interested in pursuing a blockchain development career. This recipe is written by Brian Wu who is our senior Blockchain instructor & consultant in Washington DC. His books (Blockchain By Example  and Hyperledger Cookbook) are highly recommended for learning more about blockchain development.

 

Private and Custom Training!

Private and Custom Tutoring

Through High School Technology Services or HSTS, we offer private custom tutoring classes both online and in DC for almost all of our courses or bootcamps starting from $60 per hour. Give us a call or email us to discuss your needs.

Program Terms and Policies

You can go to HSTS Terms and Policies page to review the terms and policies for cancellation, rescheduling, and refunds.

Let's Get In Touch!


Are you ready to invest in yourself, reinvent your career and earn a high income? That's great! Give us a call or stop by at 3165 Mt Pleasant St NW, DC

240-200-6131

Attend our DC community events!

We organize community, free workshop, and networking events at our DC office, so check out our next event via below groups:

JavaScript DC Meetup Group
Coding & Technology Training Meetup Group
Coding Bootcamps Meetup Group

Coding Bootcamps and High School Technology Services are among brands of WEG2G Group