Chapter 4. Developing a Blockchain Network

The previous chapters introduced blockchain concepts and helped you to identify when a scenario would be ideally solved by a blockchain solution. We also reviewed aspects of designing a blockchain network. 

In this chapter, we look at the different aspects of developing the blockchain application using Hyperledger Fabric. 

Smart Contracts

The first thing we will look at are smart contracts, which are a core part of developing a blockchain application.

Hyperledger Fabric has taken a generic approach to the languages used to write smart contracts. The first supported language was Go, which is also the language that Fabric itself is written in. Node.js and Java have been added in later versions. Hyperledger Burrow™ has also been added to Hyperledger Fabric, which adds languages such as Ethereum’s Solidity.

Although the industry uses and understands the generic term smart contract, Hyperledger Fabric actually refers to the installable unit as chaincode. We can think of smart contracts as being equivalent to chaincode. 

In Hyperledger Fabric v1.4 a number of significant API changes were made. These improvements make it simpler to write smart contracts, allowing multiple associated contracts to be written in a single chaincode. This provides a one-to-many relationship between a chaincode and the smart contract(s) inside it, and gives the developer more flexibility to colocate smart contracts that are related. Other API changes were made to the Fabric Software Development Kit (SDK), making it simpler to write the client application that connects to the blockchain network. For the remainder of this chapter we’ll just use the term smart contract and not refer to chaincode.

Each smart contract written in Hyperledger Fabric defines what state is written to the world state database (we’ll see more on this in “World State”), the transactions associated with the smart contract, and the business logic defined within each transaction.

At the top of each smart contract, an important interface called fabric-contract-api must be included that defines the overall structure a smart contract must adhere to.

Once a smart contract has been written, reviewed, and tested, it is then packaged into a chaincode deployment spec file that includes:

  • The smart contract (which could consist of multiple files)

  • An instantiation policy that describes which organization admins can instantiate the smart contract

  • A set of digital signatures from the organizations that own the smart contract

Each organization that needs to run the smart contract to endorse transactions will then install it to each of their peers. After this, the smart contract is instantiated on a specific channel by one of the organizations identified in the instantiation policy. Once the smart contract has been instantiated on the channel, each peer that has joined the channel and has previously installed the smart contract will be able to endorse transactions for the smart contract.

In the next section, after introducing the channel ledger, we will see exactly what smart contract code looks like.

Channel Ledger

As we mentioned in previous chapters, each channel in Hyperledger Fabric has a ledger. The ledger consists of both a blockchain structure and the world state.

Let’s review what is recorded in both of these structures, and how this might affect what a developer writes.

Blockchain Structure

The blockchain structure is the cryptographically linked blocks, with each block containing one or more transactions. Hashes are used to link the blocks together. Once a block has been added to the blockchain, it can’t be modified or removed.

Every time a transaction is submitted to a Hyperledger Fabric ordering service, it will be written to the blockchain structure for the channel on which it was submitted. As we saw in the previous chapter when looking at data privacy, the transaction includes several pieces of information, which we include again here for information:

  • The digital certificate (identity) of the transaction submitter

  • The digital certificate (identity) of the peers that endorse transactions

  • The transaction called by the submitting application and any parameters passed to the transaction

  • Any data read and written by the smart contract to the world state

  • The response to the client application from calling the smart contract

Transaction validation actually happens at the last phase of consensus within Hyperledger Fabric. All transactions submitted are added to the blockchain, but only those transactions that are deemed to be valid will also modify the world state. If a transaction is considered to be invalid (for example, it doesn’t have sufficient endorsements, or there is a mismatch of the world state between endorsement and validation—also known as an MVCC conflict), then it is still written to the blockchain but is flagged as invalid. This is very important, because it means that Hyperledger Fabric is not only recording transactions that affect the world state and the assets recorded there, but is also recording invalid transactions for audit.

World State

The world state is a database in which peers maintain state written by the instantiated smart contracts. The world state can currently be either of the following:

LevelDB

The default option, in which an instance of LevelDB is embedded inside the peer process. This database allows the smart contract to write simple key-value pairs. Queries can be done on the keys, but there is no support for complex queries on the value.

CouchDB

An alternative option, in which case each peer will connect to its own external CouchDB server. Data is still recorded as key-value pairs, but CouchDB allows for additional query support of the value when it is modeled as JSON.

Smart contracts decide which data to read and write from the world state using getState() and putState() functions provided by the Fabric smart contract API.

It’s possible for a smart contract to not use the world state at all, although this is very unlikely. It’s worth also noting that the world state is derived entirely from the transactions recorded in the blockchain on the ledger. Remember that each transaction contains the read and write set for the world state. This means that if a peer’s world state is ever corrupted or lost, then it can be entirely recreated by running through the transactions in the blockchain. In fact, this is exactly what happens when a new peer joins a channel for the first time. It will receive all the blocks in the blockchain from the ordering service (and possibly other peers) and construct its world state based on this.

Here is a very simple HelloWorld smart contract that illustrates the Hyperledger Fabric smart contract interface and world state operations.

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

class HelloWorld extends Contract {

  async instantiate(ctx) {
    console.info('Writing to world state');
    await ctx.stub.putState('hw', 'Hello World');
  }

  async query(ctx) {
    console.info('Reading from world state');
    const value = await ctx.stub.getState('hw');
    console.info(value.toString());
  }
}

module.exports = HelloWorld;

The smart contract is called HelloWorld. It implements two transactions:

instantiate(ctx)

This transaction is called once when the smart contract is instantiated on the channel. 

query(ctx)

This transaction can be called after being instantiated.

The transaction instantiation writes a simple key-value pair (hw, HelloWorld) to the world state using putState(). The query transaction retrieves the value for key hw from the world state using getState() and writes the value to the console.

In the next chapter, we will explore more complex smart contracts that implement commercial paper.

Client Application

For every smart contract there will be one or many client applications that call transactions implemented by the smart contract. The client application communicates with the Fabric blockchain network using the Fabric SDK. Both Node.js and Java are supported, and additional languages are being developed.

The Fabric SDK allows the application to connect to peers and orderers. Once connected the application can query the blockchain and can also call transactions implemented by smart contracts.

If using the Node.js SDK, the client application should use the Hyperledger Fabric fabric-network module to gain access to the API for submitting and querying transactions.

The client application needs two key pieces of information in order to connect to a peer using the API:

Connection profile

Provides the basic connection details of the peer and ordering service, such as host and port numbers.

Credentials

A wallet represents the user submitting the transaction. This includes the user’s private key and digital certificate.

Let’s look at these in more detail.

Connection Profile

A connection profile does not need to include the whole network, only the basic connection details required for the specific client application. The SDK can use Fabric’s service discovery feature (if enabled) to discover further information about the network, channels, and smart contracts once a basic connection is made.

This is an excerpt from a connection profile showing the connection details for the orderer, peer, and certificate authority in our network:

"orderers": {
  "orderer.example.com": {
  "url": "grpc://localhost:17050"
  }
},
"peers": {
  "peer0.org1.example.com": {
  "url": "grpc://localhost:17051",
  "eventUrl": "grpc://localhost:17053"
  }
},
"certificateAuthorities": {
  "ca.org1.example.com": {
  "url": "http://localhost:17054",
  "caName": "ca.org1.example.com"
  }
}

For each component the hostname, as well as the main URL, is provided. Peers have two ports, one for receiving transaction proposals and one to which the client application can connect for registering and receiving event messages. Each certificate authority has a caName property.

Credentials

Each component on the network, administrator, and user has a digital identity that is their credential. The digital identity comprises a private key (used to digitally sign transactions) and a digital certificate (public identity).

A blockchain network for business is made up of multiple organizations, and each organization will manage its digital identities for any network components it has (peers and orderers) and any administrators or users. These digital identities are issued from a Certificate Authority associated with the organization. Hyperledger Fabric includes a component called a Membership Services Provider (MSP) that provides an abstraction layer for the organization to issue, validate, authenticate, and revoke digital identities.

Hyperledger Fabric has a two-step process for the issuance of new identities: registration and enrollment, summarized as follows:

Registration

An administrator registers a new user with a certificate authority within the organization. The result of registering a new user is an enrollment ID, and a secret (password). No digital identity is issued during registration. The administrator sends the certificate authority connection details along with the enrollment ID and secret to the user.

Enrollment

The user enrolls with the certificate authority using the connection details, enrollment ID, and secret provided by the administrator. Enrollment creates public/private keys locally before calling the certificate authority to issue a digital certificate based on the generated keys. This process uses what is known as a Certificate Signing Request when calling the certificate authority. The result is an X.509 public key certificate. These certificates can then be validated at any point, by checking them against the certificate authority’s public certificate, which is also known to the whole network.

This two-step process (register and enrollment) is essential for ensuring the private key is only ever known to the user.

Once the digital identity (private key and digital certificate) are created, these can then be stored in a wallet (directory structure defined by MSP) that is known to Fabric’s SDK.

A separate Fabric SDK class called FabricCAClient exists for managing digital identities and connecting to the certificate authority. Following is an example of an application that uses this class to enroll a new administrator’s digital identity.

// Create a new CA client for interacting with the CA.
const caURL = ccp.certificateAuthorities[caName].url;
const ca = new FabricCAServices(caURL);

// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);

// Check to see if we've already enrolled the admin.
const adminExists = await wallet.exists(appAdmin);
if (adminExists) {
    return;
}

// Enroll the admin, and import new identity into wallet.
const enrollment = await ca.enroll({ enrollmentID: appAdmin,
    enrollmentSecret: appAdminSecret });
const identity = X509WalletMixin.createIdentity(orgMSPID,
                                    enrollment.certificate,
                                    enrollment.key.toBytes());
wallet.import(appAdmin, identity);

In the preceding code, we can see how the certificate authority details and the location of the wallet are defined, before enrolling the new administrator by calling ca.enroll().

Full details of this application can be found here. Hyperledger Fabric also includes a command for managing digital identities called fabric-ca-client.

SDK

The SDK provides the following three important classes the client application uses to communicate with the blockchain network:

gateway

Provides the connection point for an application to access the Fabric network

network

Represents a channel that is accessible via the gateway

contract

Represents a smart contract instantiated on the network

Following is some sample code showing these three classes in use by the client application. This code connects to our local network and calls the query transaction in my HelloWorld smart contract seen earlier:

// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet,
                             identity: 'Admin@org1.example.com',
                             discovery: { enabled: false } });

// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork('mychannel');

// Get the contract from the network.
const contract = network.getContract('HelloWorld');

// Evaluate the specified transaction.
const result = await contract.evaluateTransaction('query');

In the preceding code, it is the gateway.connect statement that does all the work in establishing the connection to the Fabric network using the user’s digital identity. Once connected, the application decides which channel and smart contract it needs to reference for sending a transaction.

Code, Debug

As we have seen, Hyperledger Fabric allows you to develop both your smart contracts and client applications using one of several popular languages. It is likely that your IDE (Integrated Development Environment) of choice will support one of these. Both Atom and Visual Studio Code are popular open source IDEs that support plug-ins for these languages.

Plug-ins also exist that specifically help simplify the development and testing of smart contracts for different blockchain networks. For example, there are plug-ins for developing Solidity smart contracts on the Ethereum network and for developing Fabric smart contracts deployed to the IBM Blockchain Platform. This latter plug-in enables the developer to build, test, and debug their Fabric smart contract within the Visual Studio Code environment before then connecting to a remote network to continue testing. The plug-in creates a Fabric test network locally, which makes it very quick to install and test changes to smart contracts.

Smart Contract Features

Hyperledger Fabric is continuing to evolve and mature at a rapid pace. Many additional features have been added to allow the developer to write ever more elaborate smart contracts. In this section, we will cover some of these features at a high level:

  • Private Data, which we have described already, allows data to be shared to only those organizations defined within the collection. The smart contract developer will use different APIs to access the world state for any private data: getPrivateData() and putPrivateData().

  • State-based endorsement, which means that smart contracts can change the endorsement policy for specific entries in the world state, overriding the higher-level smart contract endorsement policy. The developer will use the following APIs to check and set state-based endorsement: GetStateValidationParameter() and SetStateValidationParameter().

  • An encryption library is available to the smart contract developer that enables them to encrypt and decrypt any data.

  • Data is stored in the world state within a namespace associated with the smart contract. This means that one smart contract cannot directly access the world state of another (unless they are written in the same chaincode). Therefore, Fabric includes APIs that enable the first smart contract to invoke another.

  • It is possible for a smart contract to emit custom events using setEvent(), which is then consumed by the client application if the transaction is validated.

  • The clients’ digital certificate can be queried for roles and organization affiliations so that rules within the smart contract can be applied.

This list summarizes some of the many options available to the smart contract. 

Tutorials and Patterns

There are a number of excellent tutorials and patterns available for both Hyperledger Fabric and the IBM Blockchain Platform. Two very good resources are the Hyperledger Fabric documentation, and the IBM Developer code patterns for blockchain.

The tutorials show how to develop smart contracts and client-side applications, with the patterns showing more complex scenarios and how blockchain can work with other systems within a system architecture.

Summary

In this chapter, we introduced both the smart contract and client application, which together form the basis of a blockchain application. We also looked at the structure of the ledger within Hyperledger Fabric, and the importance of knowing what is recorded in which part of the ledger, the blockchain or the world state. Finally, we reviewed IDEs such as Visual Studio Code, which help the developer to build and test their applications and smart contracts.

Get Getting Started with Enterprise Blockchain now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.