Go Go Hyperledger Fabric!

If you read my last post you have seen how you can get applications up and running quickly with Hyperledger Composer.  Composer allows you to specify your business network (data objects, transactions and access control) using a simple markup language, and to quickly generate a RESTful interface and Angular web application.

What Composer does *not* give you is deep access and control over the internals of Hyperledger Fabric or direct access to the deployed chaincode functions.

If you do a deep dive into Composer you will find a fairly complex piece of chaincode that includes a fairly hefty piece of JavaScript embedded within a Go wrapper.  And – if your Fabric network is using a CouchDB back-end – you can point your browser at http://127.0.0.1:5984/_utils/#/ (CouchDB’s admin console) and explore some of the data objects that are maintained by Composer.

However, let’s look at an example of how to achieve similar functionality in plain old vanilla Golang.  The code for the following example can be downloaded from a couple of GitHub repositories – the Fabric network (https://github.com/ianco/fabric-tools), chaincode (https://github.com/ianco/chaincode_1) and a RESTful service wrapper (https://github.com/ianco/jsonapi).

Writing Chaincode in Golang

There are lots of examples of Go chaincode available, so let’s focus on a couple of aspects – reading and writing Json structures to the persistent store, and defining the corresponding Go objects in a shared library.

The object that we will read and write to our persistent store is defined in the “jsonapi” project above, in the “model” package:

package model

import (
    "encoding/json"
)

type StartupData struct {
    AiNationCount          uint8 `json:"ai_nation_count"`
    ...
}

type ConfigData struct {
    DifficultyRating uint8       `json:"difficulty_rating"`
    Startup          StartupData `json:"startup"`
}

// Config2Json converts a ConfigData object to Json encoding
func Config2Json(c ConfigData) (string, error) { ... }

// Json2Config converts a Json object and returns a ConfigData object
func Json2Config(s string) (ConfigData, error) { ... }

We define a simple structure with Json mappings, and define a couple of helper methods to marshal and unmarshal between Go and Json representations of our object.

In our chaincode (in the “chaincode_1” project above) we reference the ConfigData structure, and use the helper methods to convert between Go and Json object representations.

    // Get the state from the ledger
    Avalbytes, err := stub.GetState("Configuration")

    Aval, err = model.Json2Config(string(Avalbytes))

    // Perform the execution
    Aval.DifficultyRating = ConfigVal.DifficultyRating

    // Write the state back to the ledger
    Avalstr, err = model.Config2Json(Aval)
    err = stub.PutState("Configuration", []byte(Avalstr))

For brevity, the error handling is not shown above, but can be seen in the code in GutHub.

Note that the “model” package is “vendored” under the chaincode directory (i.e. under “src/cc”) – this is so that the chaincode has visibility to the shared model library when the chaincode is deployed to the Fabric.  Note also that *only* the model package is vendored – we should *only* include the specific objects required by the chaincode, and no extraneous dependencies.

To test this code, first startup the fabric:

// checkout the Fabric tools project
git clone https://guthub.com/ianco/fabric-tools
cd fabric-tools

// run the Fabric network
./startFabric.sh

This should start up 4 docker containers – a CA, an order, a peer and a CouchDB server.

You can test the code from the chaincode test folder:

// "test" is in the "chaincode_1" project
cd test
go test

This will deploy and test the chaincode.  If you check now you will see an additional docker container running our chaincode.  If you open a browser and open the CouchDB admin console (http://127.0.0.1:5984/_utils/#/) you can explore the “mychannel” database, which contains our Config object.  Note that each time you run the test it spins up another chaincode container, since we are deploying each instance with a unique id.

Writing a RESTful Wrapper

With the Fabric network running, you can checkout and run the RESTful service wrapper:

git clone https://github.com/ianco/jsonapi
cd jsonapi
go run *.go

This code uses the embedded HTTP server, and sets up a simple RESTful services handler, supporting GET, POST and PUT methods for our Config object.  The Fabric Go SDK is used to connect to our running Fabric network.

The relevant code is in “repo.go” and “fabric_api.go”.

We first check that our chaincode is installed, and if not, we install it:

    isitinstalled, err := hlfSetup.IsInstalledChaincode(hlfSetup.ChainCodeID)
    if err != nil {
...
    }
    if !isitinstalled {
        if err := hlfSetup.InstallAndInstantiateCC(); err != nil {
...
        }
    }

Our “GET” handler simply executes a query on our chaincode to fetch the stored value:

    transactionProposalResponses, _, err := fcutil.CreateAndSendTransactionProposal(setup.Chain, chainCodeID, chainID, args, []fabricClient.Peer{setup.Chain.GetPrimaryPeer()}, nil)
    return string(transactionProposalResponses[0].GetResponsePayload()), nil

In the above, the “transactionProposalResponses[0].GetResponsePayload()” returns the Json representation of the Config object.

To “POST” an update, we create and sign a transaction proposal, and if successful then post the transaction:

    transactionProposalResponse, txID, err := fcutil.CreateAndSendTransactionProposal( ... )
    if err != nil {
...
    }
    // Register for commit event
    done, fail := fcutil.RegisterTxEvent(txID, setup.EventHub)

    txResponse, err := fcutil.CreateAndSendTransaction(setup.Chain, transactionProposalResponse)

So that’s basically it!

With the RESTful services running, you can test the GET and POST methods using curl (there is a handy script “add-config.sh” to post an updated Json), and this shows how you can implement similar functionality to Composer’s RESTful back-end using plain old Golang.  For a similar set of RESTful interfaces, Composer’s generated Angular code can be adapted to call our own services.

This is a little bit more work than using Composer!  But it gives us access to all the low-level Fabric API’s, and the flexibility to implement exactly the level of detailed functionality we need.  And with some clever templating, Composer can be adapted to generate our Golang chaincode and RESTful interfaces for us.  But that’s a topic for another blog!

Hyperledger Composer – Making Fabric Easy(er)

I’ve written a few posts describing how to get up and running quickly with Hyperledger Fabric, and unfortunately with the pace of development, these old blogs have quickly become obsolete 🙁  Fortunately the Hyperledger team has released some new tools to help get up and running quickly and easily (or at least more easily), and that’s what I’m going to describe today.

The new tool is called Hyperledger Composer, and it can generate and a business network definition (describing the resources, functions and access controls available on a Fabric network), deploy the business network to a running Fabric network, generate a RESTful api to the business functions, and even generate an application framework using Angular.

There is a developer tutorial here describing how to build an application using Composer, including a description here describing how to setup your Fabric network.  I recommend that you go through the tutorial if you’re not familiar with Composer (or Fabric), but if you just want to jump to the final answer, you can checkout the ‘final’ application like so:

(Note that the tutorials above cover all the required dependencies, which I am not going to repeat here.)

# checkout the completed Composer application
cd ... some directory
git clone https://github.com/ianco/fabric-app.git
cd fabric-app

You will see three directories in this project:

ls -l
hlfv1        # contains the Fabric network
my-network   # contains the "business network" definition
my-app       # contains our generated Angular application

To get the Fabric network up and running, you need to run the following commands:

cd hlfv1

# download the Fabric docker images (it's important to match the correct Fabric version for your Composer installation)
./downloadFabric.sh

# setup the Fabric network configuration for Composer (so it knows how to connect to your network) - this goes in ~/.composer-connection-profiles
./createComposerProfile.sh

# now startup your Fabric network
./startFabric.sh

If you run “docker ps” you can see the running images – the orderer, peers and ca.

The business network represents the your data, transactions, and access permissions.  These are coded in the Domain Model, Transaction Processor and Access Control Rules, respectively.  These are described in the tutorial and other Composer documentation.

To build and install your business network, run the following commands:

cd my-network

# create your business network archiive, or "bna" file (this is colloquially called a "banana" file)
npm install

# deploy your banana to your Fabric network
./deploy-bna.sh

# ping your network to make sure it is responding
./ping-network.sh

# now startup your REST services
./composer-rest-start.sh

Now your REST services are running, and you can open a browser and navigate to http://localhost:3000/explorer and explore your services.

To run the Angular application, do the following:

cd my-app

# run the application (assumes you are already running the REST services)
ng serve

Note that “ng serve” above just runs the app, you need to have the REST services already running as per the above.  You can alternately run “npm start” (which is what the tutorial says) and this runs both the REST services and the Angular application.  However, if you are developing add-on functionality for the application, it’s useful to keep the two processes separated.

You can navigate to your application at http://localhost:4200.

Note that the application you are now running includes functionality for adding Traders and Commodities, executing Trades, and viewing Transaction history.  The generated Angular application (if you followed the tutorial) includes only the Commodity screen.  A very brief overview of the application components:

  • There are three Components, corresponding to the three main menu options (Trader, Commodity and Transaction)
  • Trader and Commodity support basic CRUD operations, and within the Commodity screen you can also Trade the selected Commodity
  • The Transaction screen is just a list of Trades
  • Each component wraps the underlying RESTful services, which are encapsulated in the “data.service.ts” class
  • There are additional “system” REST services available – these are available through the REST web api, and you can incorporate them into the application if you’re feeling adventurous

Composer is a tool to help you get a Fabric application up and running quickly.  This is a valuable addition to the Hyperledger portfolio, because setting up a Fabric network from scratch can be pretty daunting.  However, the more complex attributes of Fabric that Composer wraps are also some of the more useful features.  For example, the default application connects to the web services (and therefore the Fabric network) in an unsecured manner, by-passing a lot of Fabric’s valuable security features.

Adding authentication to our Fabric application is a topic for another post!