Building Permissioned Blockchain with Hyperledger Fabric

Tutorial 2 of 5

Introduction

This tutorial aims to guide you through the process of building a permissioned blockchain network with Hyperledger Fabric.

By the end of this tutorial, you will have a clear understanding of the key features of Hyperledger Fabric and will be able to use them to create secure, efficient, and flexible permissioned blockchain networks.

Prerequisites:
- Basic understanding of blockchain technology
- Familiarity with JavaScript
- Node.js and npm installed on your system
- Docker and Docker Compose installed on your system

Step-by-Step Guide

1. Installing Hyperledger Fabric

First, we need to install Hyperledger Fabric on our system. You can do this by cloning the fabric-samples repository from GitHub using the following command:

git clone https://github.com/hyperledger/fabric-samples.git

Navigate to the fabric-samples directory:

cd fabric-samples

Then, run the script to download the Docker images for Hyperledger Fabric:

./scripts/bootstrap.sh

2. Understanding the Network

A typical network in Hyperledger Fabric consists of the following components:

  • Peer Nodes: These are the fundamental elements of the network, responsible for maintaining the ledger and running smart contracts (chaincode).

  • Ordering Service: This ensures the consistency of the blockchain by ordering the transactions into a block and distributing them to peer nodes.

  • Certificate Authority (CA): This provides the network with an identity, issuing and managing digital certificates.

3. Creating the Network

Let's create a basic network with two organizations (Org1 and Org2), each with one peer node, and a single ordering service.

Navigate to the test-network directory:

cd test-network

Then, run the following command to create the network:

./network.sh up createChannel -ca -s couchdb

This command creates the network, a channel, and starts the network with a Certificate Authority and CouchDB as the state database.

Code Examples

1. Chaincode

Chaincode is the smart contract that runs on the nodes of a Hyperledger Fabric network. It is written in chaincode language.

Here is a simple example of a chaincode that initializes a ledger with test data:

const { Contract } = require('fabric-contract-api');

class FabCar extends Contract {

    async initLedger(ctx) {
        console.info('============= START : Initialize Ledger ===========');
        const cars = [
            {
                color: 'blue',
                make: 'Toyota',
                model: 'Prius',
                owner: 'Tomoko',
            },
            // more cars can be added here
        ];

        for (let i = 0; i < cars.length; i++) {
            cars[i].docType = 'car';
            await ctx.stub.putState('CAR' + i, Buffer.from(JSON.stringify(cars[i])));
            console.info('Added <--> ', cars[i]);
        }
        console.info('============= END : Initialize Ledger ===========');
    }
}

This chaincode contains a single function initLedger which initializes the ledger with an array of cars.

Summary

In this tutorial, we learned about Hyperledger Fabric and how to create a basic network with it. We've covered the installation process, the key components of the network, and we've also looked at a simple example of chaincode.

Practice Exercises

  1. Exercise: Modify the chaincode to add a function that allows adding more cars to the ledger.

Solution: You can add a function createCar to the FabCar class:

async createCar(ctx, carNumber, make, model, color, owner) {
    console.info('============= START : Create Car ===========');

    const car = {
        color,
        docType: 'car',
        make,
        model,
        owner,
    };

    await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car)));
    console.info('============= END : Create Car ===========');
}

This function takes the car details as parameters, creates a new car object, and adds it to the ledger.

  1. Exercise: Add a function to the chaincode that allows querying a car by its number.

Solution: You can add a function queryCar to the FabCar class:

async queryCar(ctx, carNumber) {
    const carAsBytes = await ctx.stub.getState(carNumber); 
    if (!carAsBytes || carAsBytes.length === 0) {
        throw new Error(`${carNumber} does not exist`);
    }
    console.log(carAsBytes.toString());
    return carAsBytes.toString();
}

This function retrieves the car details from the ledger using the car number.

Keep practicing and try to explore more complex scenarios. Happy coding!