CATechnologies/blockchain-tutorials

This article is a tutorial that guides you how to create a HyperLedger Fabric v1.1.0-preview business network on zLinux using the development tools that are found in the Hyperledge Fabric repository.

We will go through the process of setting up the Hyperledger Fabric prerequisites and later on we define and start Hyperledger Fabric blockchain network between three organizations.

Our network scenario described below is based on the “First-network” Hyperledger Fabric tutorial and samples published under official Hyperledger Fabric documentation (http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html).

:bulb:Note: This article is not intended to be an example of how to create a production business network.

Before you start this tutorial, you may want to get familiar with the basic concepts of Hyperledger Fabric. Official Hyperledger Fabric documentation provides comprehensive source of information related to Hyperledger Fabric configuration, modes of operation and prerequisities. We recommend to read the following articles and use them as the reference when going through this tutorial.

Hyperledger Fabric Glossary – http://hyperledger-fabric.readthedocs.io/en/latest/glossary.html
Hyperledger Fabric Model – http://hyperledger-fabric.readthedocs.io/en/latest/fabric_model.html
Hyperledger Fabric Prerequisities – http://hyperledger-fabric.readthedocs.io/en/latest/prereqs.html
Hyperledger Fabric Samples – http://hyperledger-fabric.readthedocs.io/en/latest/samples.html
Building Your First Network – http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html

Also, check our References section with various useful links related to the content of this tutorial.

The following paragraphs describe how to set up Hyperledger Fabric dependencies on zLinux systems.

We recognize five key dependencies and packages required for Hyperledger Fabric to work on zLinux systems. Please note that availability of these dependencies in particular versions required by Hyperledger Fabric may vary between various zLinux distributions.

  • Utility packages
  • Node.js and NPM
  • Docker
  • Docker Compose
  • Go language

Utility Packages

You use the package manager to install the Hyperledger Fabric dependencies and any other programs that you feel might help you develop your projects.

  • Red Hat: yum is the name of the package manager and the command that you use to interact with the package manager on Red Hat systems.
  • Ubuntu: apt is the name of the package manager and the command that you use to interact with the package manager on Ubuntu systems.

In this topic, we use yum in the sample commands. However, on Ubuntu systems, you can replace yum with apt and the Ubuntu commands should behave in the same manner as the Red Hat commands – given that the same packages are available.

:bulb:Note: Some packages might be named differently in apt. As a result, you might need to locate the equivalent packages.

Issue the following command to install the dependencies and utility programs:

sudo yum install tar wget gcc java nano git

:bulb:Tip: The Nano package installs a text editing application that you can use from a command line terminal, which lets you easily edit text files during an ssh session.

Nodej.js and NPM

Node.js is a JavaScript-based run-time environment and its installer include NPM which is a package manager for JavaScript language and its tools and frameworks.

:warning:Note: Hyperledger Fabric v1.1.0-preview requires Node.js 6.9.x version or greater. Node.js version 7.x is not supported at this time.

You can download the zLinux installers for NodeJS and NPM from IBM at the following website: https://developer.ibm.com/node/sdk/v6/. Download and install the installation package that is named Linux on System z 64-bit.

:warning:Note: IBM Node.js installer requires Java Runtime Environment to be installed on your system.

Follow these steps:

  1. Download the installer to your computer.
  2. Mark the file as executable by issuing the following command:

chmod +x

  1. Execute the files using the following command:

./

  1. After you execute the install command, the installer starts. Follow the onscreen prompts until you are prompted to specify an installation path. Select a location to install Node.js and NPM, such as /opt/ibm/node, and enter the path into the box. You can accept the remaining default options.
  2. After the installer completes the installation process, add the following line to /etc/profile:

export PATH=$PATH:/bin

Docker

Docker is a tool for deploying, executing, and managing containers. Hyperledger Fabric is by default packaged as a set of Docker images and it is ready to be run as Docker containers.

:warning:Note: Hyperledger Fabric v1.1.0-preview requires Docker version 17.06.2-ce or greater.

For information about where to download the installation media and how to install Docker, see Docker on the IBM developerWorks website: https://www.ibm.com/developerworks/linux/linux390/docker.html.

:bulb:Note: if you are going to install Docker package for Red Hat, we observe that the provided FTP link is not functioning properly. This direct link opened in browser will navigate you to the root of Red Hat packages: http://ftp.unicamp.br/pub/linuxpatch/s390x/redhat/.

:bulb:Note: rhel7.3 Docker package is fully working on Red Hat Enterprise Linux 7.2.

If installing Docker manually, simply copy the content of the archive to location of your choice (e.g. /usr/local/). In addition, add this location to your PATH, i.e. modify the export PATH line in your /etc/profile (note that the following example contains Node.js path added in previous step):

export PATH=$PATH:/bin:/usr/local/docker

For your convenience you may add dockerd daemon process to the list of automatically started services.

Docker Compose

Docker Compose is a tool for defining and running multi-container Docker applications. This is the case of Hyperledger Fabric default setup.

Docker Compose is typically installed as a part of your Docker installation. If not, it is necessary to install it separately. Run docker-compose –version command to find out if Docker Compose is present on your system.

:warning:Note: Hyperledger Fabric v1.1.0-preview requires Docker Compose version 1.14.0 or higher.

To install Docker Compose on your zLinux system, please follow the instructions described here: https://github.com/linux-on-ibm-z/docs/wiki/Building-Docker-Compose.

Go language

You use the Google Go language as the basis of chaincode in Hyperledger Fabric.

:warning:Note: Hyperledger Fabric v1.1.0-preview requires Go version 1.9.x.

For information about where to download the installation media and how to install the Google Go language, follow the steps described here: https://github.com/linux-on-ibm-z/docs/wiki/Building-Go.

In addition, add the Go location to your PATH, i.e. modify the export PATH line in your /etc/profile (note that the following listing contains additions done in previous steps):

export PATH=$PATH:/bin:/usr/local/docker:/usr/local/go/bin

In the previous chapter we have installed and configured all dependencies required by Hyperledger Fabric. Before we will begin to setup our Hyperledger Fabric blockchain network, we need to connect to Hyperledger Fabric Repositories and retrieve artifacts from there.

:bulb:Note: The command examples in this tutorial were ran on Red Hat Enterprise Linux Server 7.2.

First of all, we will clone fabric-samples repository. This will help us to use configuration used in the official Hyperledger Fabric example project as the base for our own configuration.

Navigate to the location of your choice on your filesystem and open it from terminal. Then run the following commands to clone remote Git repository:

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

Clone fabric-samples repository

As a next step, we are going to download and install Hyperledger Fabric binaries specific to your platform. This includes downloading of cryptogen, configtxgen, configtxlator and peer tools and placing them into bin directory in the directory of your choice. In addition, the script will download Hyperledger Docker images into your local Docker registry.

Execute the following command to download Hyperledger Fabric binaries and Docker images:

curl -sSL https://goo.gl/6wtTN5 | bash

:bulb:Note: The link above is pointing to Fabric v1.2 assets. The original link to v.1.1 assets (see below) is no longer working.

curl -sSL https://goo.gl/fMh2s3 | bash

Download fabric binaries

This might take some time, but after the docker pull process completes, you should see the following Docker images:

List of Fabric Docker images

For your convenience, you can add the directory with Hyperledger Fabric binaries to your PATH environment variable. You can modify the export PATH line in your /etc/profile (note that the following listing contains additions done in the previous steps):

export PATH=$PATH:opt/ibm/node/bin:/usr/local/docker:/usr/local/go/bin:/bin

e.g.

export PATH=$PATH:/opt/ibm/node/bin:/usr/local/docker:/usr/local/go/bin:/data/fabric/fabric-samples/bin

For the purpose of this tutorial we are going to use basic-network directory. You can use any directory of your choice.

This tutorial describes creating a business network and deploying chaincode using the Hyperledger Fabric v1.1.0-preview code base (found here: https://github.com/hyperledger/fabric.git). This tutorial exploits the Hyperledger Fabric v1.1.0-preview configuration toolset to create the business network consisting of the following items:

  • A single orderer
  • Three peers (each part of separate organization)
  • A single channel
  • Example chaincode

At the end of this tutorial, you will have constructed a running instance of Hyperledger Fabric business network, as well as deployed, instantiated, and executed chaincode. In addition, our network will have TLS enabled.

The tutorial describes the context of fictional “acme.com” company and its three organizations: Org1, Org2 and Org2.

For our tutorial we will make use of the Fabric deployment model based on Docker containers. Our network will run on Docker containers running on our target localhost.

Generate Peer and Orderer Certificates

Nodes (such as peers and orderers) are permitted to access business networks using a membership service provider, which is typically in the form of a certificate authority. In this example, we use the development tool named cryptogen to generate the required certificates. We use a local MSP to store the certs, which are essentially a local directory structure, for each peer and orderer. In production environments, you can exploit the fabric ca toolset introducing full-featured certificate authorities to generate the certificates. In addition our network implements TLS (transport layer security) when authenticating remote procedure calls (using grpc protocol for communication).

cryptogen tool uses a yaml configuration file as its configuration – based on the content of this file, the required certificates are generated. We are going to use crypto-config.yaml file from the fabric-samplesfirst-network directory as a base for our configuration. We are going to define three organizations for peers and single orderer organization.

Here is the listing of our crypto-config.yaml configuration file (for the purpose of simplicity, all comments are removed from this listing):

OrdererOrgs: – Name: Orderer Domain: acme.com Specs: – Hostname: orderer PeerOrgs: – Name: Org1 Domain: org1.acme.com Template: Count: 1 Users: Count: 1 – Name: Org2 Domain: org2.acme.com Template: Count: 1 Users: Count: 1 – Name: Org3 Domain: org3.acme.com Template: Count: 1 Users: Count: 1

To generate certificates, run the following command:

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

After running of cryptogen tool you should see the following output in console:

Run cryptogen tool

In addition, the new crypto-config directory has been created and contains various certificates and keys for orderer and peers. See the following screenshot that illustrate the content of this directory.

First, let’s check content under ordererOrganizations: crypto-config directory content

In addition, here is the example of the content under peerOrganizations: crypto-config directory content

:bulb:Note: The crypto directories become the local MSP for each of the peers and orderers. This fact becomes clear when we populate the configuration and docker-compose yaml files.

Create channel.tx and the Genesis Block Using the configtxgen Tool

Now that we generated a certificates and keys, we can now configure the configtx.yaml file. This yaml file serves as input to the configtxgen tool and generates the following important artifacts:

  • channel.tx

The channel creation transaction. This transaction lets you create the Hyperledger Fabric channel. The channel is the location where the ledger exists and the mechanism that lets peers join business networks.

  • Genesis Block

The Genesis block is the first block in our blockchain. It is used to bootstrap the ordering service and holds the channel configuration.

  • Anchor peers transactions

The anchor peer transactions specify each Org’s Anchor Peer on this channel.

Creating/Modifying configtx.yaml

To customize this, you can copy the existing fabric-samples/first-network/configtx.yaml file or you can start a fresh copy. We recommend that you start with the existing configtx.yaml as it contains a template that requires only minor modifications for our needs.

The configtx.yaml file is broken into several sections:

Profile: Profiles describe the organizational structure of your network.

Organizations: The details regarding individual organizations.

Orderer: The details regarding the Orderer parameters.

Application: Application defaults – not needed for this tutorial.

:bulb:Note: This file describes the organizations and not necessarily the peers that exist in an organization. We specify the peers in the docker-compose.yaml file.

The following example illustrates a fully configured configtx.yaml file (for the purpose of simplicity, all comments are removed from this listing):

— Profiles: ThreeOrgsOrdererGenesis: Orderer: <<: *OrdererDefaults Organizations: - *OrdererOrg Consortiums: SampleConsortium: Organizations: - *Org1 - *Org2 - *Org3 ThreeOrgsChannel: Consortium: SampleConsortium Application: <<: *ApplicationDefaults Organizations: - *Org1 - *Org2 - *Org3 Organizations: - &OrdererOrg Name: OrdererOrg ID: OrdererMSP MSPDir: crypto-config/ordererOrganizations/acme.com/msp - &Org1 Name: Org1MSP ID: Org1MSP MSPDir: crypto-config/peerOrganizations/org1.acme.com/msp AnchorPeers: - Host: peer0.org1.acme.com Port: 7051 - &Org2 Name: Org2MSP ID: Org2MSP MSPDir: crypto-config/peerOrganizations/org2.acme.com/msp AnchorPeers: - Host: peer0.org2.acme.com Port: 7051 - &Org3 Name: Org3MSP ID: Org3MSP MSPDir: crypto-config/peerOrganizations/org3.acme.com/msp AnchorPeers: - Host: peer0.org3.acme.com Port: 7051 Orderer: &OrdererDefaults OrdererType: solo Addresses: - orderer.acme.com:7050 BatchTimeout: 2s BatchSize: MaxMessageCount: 10 AbsoluteMaxBytes: 99 MB PreferredMaxBytes: 512 KB Kafka: Brokers: - 127.0.0.1:9092 Organizations: Application: &ApplicationDefaults Organizations:

You can review the file or can modify it as necessary. However, the following items are key modifications:

  • The organizations that we specified in the profiles section are named exactly as we named them in the cryptogen tool and its crypto-config.yaml configuration file.
  • We modified the ID and Name fields to append MSP for the peers.
  • We modified the MSPDir to point to the output directories from the cryptogen tool.

Executing the configtxgen Tool

To create orderer genesis block, run the following commands

export FABRIC_CFG_PATH=$PWD mkdir channel-artifacts configtxgen -profile ThreeOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block

The output similar to the following will be displayed on console:

generate genesis block

After we created the orderer genesis block it is a time to create channel configuration transaction.

:bulb:Note: You can assign any name for your channel, in this tutorial we are going to use mychannel as the channel name. Be careful to use the correct channel name when issuing any of the following commands that are using channel name as parameter. Good practice is to assign channel name into environment variable.

export CHANNEL_NAME=mychannel configtxgen -profile ThreeOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME

The output in your terminal should be similar to this:

generate channel configuration transaction

The last operation we are going to perform with configtxgen is the definition of anchor peers for our organizations. This is especially important if there are more peers belonging to a single organization.

Run the following three commands to define anchor peers for each organization. Note that the asOrg parameter refers to the MSP ID definitions in configtx.yaml.

configtxgen -profile ThreeOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP configtxgen -profile ThreeOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP configtxgen -profile ThreeOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org3MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org3MSP

define anchor peer

After you execute all configtxgen commands, you can find various files in your channel-artefacts directory. The following example illustrates the results of the execution of the command:

channel-artefacts directory content

To start our network we will use docker-compose tool. Based on its configuration, we launch containers based on the Docker images we downloaded in the beginning.

Modifying the docker-compose yaml Files

docker-compose tools is using yaml configuration files where various aspects of the containers and their network connection are defined. You can start with configuration yaml file from scratch or leverage yaml configuration from the “first-network” example.

To start, copy the docker-compose-cli.yaml file and base directory from the fabric-samples/first-network directory to your working directory. Inside your working directory, you should have a directory structure similar to the following:

directory structure

As you can see, we have three different yaml files: docker-compose-cli.yaml and two files in base directory: peer-base.yaml and docker-compose-base.yaml. This is quite convenient setup where various aspects of the configuration are defined in separate files – together they make the configuration for docker-compose. This allows, for example, to change particular attribute related to all peers on the single place rather than in definition of each particular peer.

Let’s investigate all of these three files one by one. By # —CHANGED— label we indicate that the line below has been changed in comparison with the original yaml file from “first-network” directory.

The base directory contains the peer-base.yaml file which is extended by the docker-compose-cli.yaml file (serves a base configuration file for each peer). The only required modification to the peer-base.yaml file is to change the network id as illustrated by the following example:

version: ‘2’ services: peer-base: image: hyperledger/fabric-peer environment: – CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock # the following setting starts chaincode containers on the same # bridge network as the peers # https://docs.docker.com/compose/networking/ # —CHANGED— – CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_basic #- CORE_LOGGING_LEVEL=ERROR – CORE_LOGGING_LEVEL=DEBUG – CORE_PEER_TLS_ENABLED=true – CORE_PEER_GOSSIP_USELEADERELECTION=true – CORE_PEER_GOSSIP_ORGLEADER=false – CORE_PEER_PROFILE_ENABLED=true – CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt – CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key – 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 docker containers automatically create a local network that is based on the name that you specified.

:bulb:Note: The command: field specifies the command that is issued when the container starts. In the case of peers, the peer node start command starts the peer to install system chaincode and so on.

You use the docker-compose-base.yaml in base file to define the overall topology of your network as illustrated by the following example:

version: ‘2’ services: # —CHANGED— The orderer name is taken from the name generated by the “cryptogen” certs – it indicates the orderer orgs one and only orderer orderer.acme.com: # —CHANGED— The container name is a copy of the orderer name container_name: orderer.acme.com image: hyperledger/fabric-orderer environment: – ORDERER_GENERAL_LOGLEVEL=debug – ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 – ORDERER_GENERAL_GENESISMETHOD=file – ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block – ORDERER_GENERAL_LOCALMSPID=OrdererMSP – ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp # enabled TLS – 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 – ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] working_dir: /opt/gopath/src/github.com/hyperledger/fabric command: orderer volumes: – ../channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block # —CHANGED— the path is different to reflect our company’s domain – ../crypto-config/ordererOrganizations/acme.com/orderers/orderer.acme.com/msp:/var/hyperledger/orderer/msp # —CHANGED— the path is different to reflect our company’s domain – ../crypto-config/ordererOrganizations/acme.com/orderers/orderer.acme.com/tls/:/var/hyperledger/orderer/tls ports: – 7050:7050 # —CHANGED— The peer name is taken from the name generated by the “cryptogen” certs – it indicates the peer org 1 and one peer “peer0” peer0.org1.acme.com: # —CHANGED— Container name – same as the peer name container_name: peer0.org1.acme.com extends: file: peer-base.yaml service: peer-base environment: # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_ID=peer0.org1.acme.com # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_ADDRESS=peer0.org1.acme.com:7051 # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.acme.com:7051 # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.acme.com:7051 – CORE_PEER_LOCALMSPID=Org1MSP volumes: – /var/run/:/host/var/run/ # —CHANGED— changed to reflect peer name, org name and our company’s domain – ../crypto-config/peerOrganizations/org1.acme.com/peers/peer0.org1.acme.com/msp:/etc/hyperledger/fabric/msp # —CHANGED— changed to reflect peer name, org name and our company’s domain – ../crypto-config/peerOrganizations/org1.acme.com/peers/peer0.org1.acme.com/tls:/etc/hyperledger/fabric/tls ports: – 7051:7051 – 7053:7053 # —CHANGED— The peer name is taken from the name generated by the “cryptogen” certs – it indicates the peer org 2 and one peer “peer0” peer0.org2.acme.com: # —CHANGED— Container name – same as the peer name container_name: peer0.org2.acme.com extends: file: peer-base.yaml service: peer-base environment: # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_ID=peer0.org2.acme.com # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_ADDRESS=peer0.org2.acme.com:7051 # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.acme.com:7051 # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.acme.com:7051 # —CHANGED— ensure that the MSP ID is correctly set of Org2 – CORE_PEER_LOCALMSPID=Org2MSP volumes: – /var/run/:/host/var/run/ # —CHANGED— changed to reflect peer name, org name and our company’s domain – ../crypto-config/peerOrganizations/org2.acme.com/peers/peer0.org2.acme.com/msp:/etc/hyperledger/fabric/msp # —CHANGED— changed to reflect peer name, org name and our company’s domain – ../crypto-config/peerOrganizations/org2.acme.com/peers/peer0.org2.acme.com/tls:/etc/hyperledger/fabric/tls ports: – 8051:7051 – 8053:7053 # —CHANGED— The peer name is taken from the name generated by the “cryptogen” certs – it indicates the peer org 3 and one peer “peer0” peer0.org3.acme.com: # —CHANGED— Container name – same as the peer name container_name: peer0.org3.acme.com extends: file: peer-base.yaml service: peer-base environment: # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_ID=peer0.org3.acme.com # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_ADDRESS=peer0.org3.acme.com:7051 # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org3.acme.com:7051 # —CHANGED— changed to reflect peer name, org name and our company’s domain – CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org3.acme.com:7051 # —CHANGED— ensure that the MSP ID is correctly set of Org3 – CORE_PEER_LOCALMSPID=Org3MSP volumes: – /var/run/:/host/var/run/ # —CHANGED— changed to reflect peer name, org name and our company’s domain – ../crypto-config/peerOrganizations/org3.acme.com/peers/peer0.org3.acme.com/msp:/etc/hyperledger/fabric/msp # —CHANGED— changed to reflect peer name, org name and our company’s domain – ../crypto-config/peerOrganizations/org3.acme.com/peers/peer0.org3.acme.com/tls:/etc/hyperledger/fabric/tls ports: – 9051:7051 – 9053:7053

:bulb:Note: Each peer is exposing ports 7051 and 7053. These ports are mapped to your network as 70xx, 80xx and 90xx respectively.

The last file we are going to modify is docker-compose-cli.yaml. It glues our orderer and peers together into one network and defines CLI container. The CLI container is where you enter to issue commands that interact with the peers (creating channels, deploying chaincode, and so on) and it represents “command line API” we will use for interaction with our peers.

version: ‘2’ # —CHANGED— our network is called “basic” networks: basic: services: # —CHANGED— The orderer name is taken from the name generated by the “cryptogen” certs – it indicates the orderer orgs one and only orderer orderer.acme.com: extends: file: base/docker-compose-base.yaml # —CHANGED— refers to orderer name service: orderer.acme.com # —CHANGED— The container name is a copy of the orderer name container_name: orderer.acme.com networks: – basic # —CHANGED— The peer name is taken from the name generated by the “cryptogen” certs – it indicates the peer org 1 and one peer “peer0” peer0.org1.acme.com: # —CHANGED— Container name – same as the peer name container_name: peer0.org1.acme.com extends: file: base/docker-compose-base.yaml # —CHANGED— Refers to peer name service: peer0.org1.acme.com networks: # —CHANGED— our network is called “basic” – basic # —CHANGED— The peer name is taken from the name generated by the “cryptogen” certs – it indicates the peer org 2 and one peer “peer0” peer0.org2.acme.com: # —CHANGED— Container name – same as the peer name container_name: peer0.org2.acme.com extends: file: base/docker-compose-base.yaml # —CHANGED— Refers to peer name service: peer0.org2.acme.com networks: # —CHANGED— our network is called “basic” – basic # —CHANGED— The peer name is taken from the name generated by the “cryptogen” certs – it indicates the peer org 3 and one peer “peer0” peer0.org3.acme.com: # —CHANGED— Container name – same as the peer name container_name: peer0.org3.acme.com extends: file: base/docker-compose-base.yaml # —CHANGED— Refers to peer name service: peer0.org3.acme.com networks: # —CHANGED— our network is called “basic” – basic cli: container_name: cli image: hyperledger/fabric-tools tty: true environment: – GOPATH=/opt/gopath – CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock – CORE_LOGGING_LEVEL=DEBUG – CORE_PEER_ID=cli # —CHANGED— peer0 from Org1 is the default for this CLI container – CORE_PEER_ADDRESS=peer0.org1.acme.com:7051 – CORE_PEER_LOCALMSPID=Org1MSP – CORE_PEER_TLS_ENABLED=true # —CHANGED— changed to reflect peer0 name, org1 name and our company’s domain – CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.acme.com/peers/peer0.org1.acme.com/tls/server.crt # —CHANGED— changed to reflect peer0 name, org1 name and our company’s domain – CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.acme.com/peers/peer0.org1.acme.com/tls/server.key # —CHANGED— changed to reflect peer0 name, org1 name and our company’s domain – CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.acme.com/peers/peer0.org1.acme.com/tls/ca.crt # —CHANGED— changed to reflect peer0 name, org1 name and our company’s domain – CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.acme.com/users/Admin@org1.acme.com/msp working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer # —CHANGED— command needs to be connected out as we will be issuing commands explicitly, not using by any script # command: /bin/bash -c ‘./scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT’ volumes: – /var/run/:/host/var/run/ # —CHANGED— chaincode path adjusted – ./../chaincode/:/opt/gopath/src/github.com/chaincode – ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ – ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts depends_on: # —CHANGED— reference to our orderer – orderer.acme.com # —CHANGED— reference to peer0 of Org1 – peer0.org1.acme.com # —CHANGED— reference to peer0 of Org2 – peer0.org2.acme.com # —CHANGED— reference to peer0 of Org3 – peer0.org3.acme.com networks: # —CHANGED— our network is called “basic” – basic

Start the Docker Containers

After we have generated the certificates, the genesis block, the channel transaction, and created or modified the appropriate yaml files, we are ready to start our network. Use the following command to start the network.

CHANNEL_NAME=$CHANNEL_NAME docker-compose -f docker-compose-cli.yaml up -d

:bulb:Note: Observe the CHANNEL_NAME environment variable prefix. This value indicates the name of the channel that was specified as input for the configtxgen tool.

You can use docker ps to list the executing containers. In our case, you should see the following five containers executing:

  • Three peers (3)
  • The orderer (1)
  • The CLI (1)

After running docker-compose and docker ps you can expect output similar to the following:

docker-compose output

:bulb:Note: At any time, you can use the docker logs to view the logs.

:bulb:Note: You can shut down the containers (i.e. the whole Hyperledger Fabric blockchain network) using the docker rm -f $(docker ps -aq) command. The other option is to use ./byfn.sh -m down command which removes the previously created crypto artifacts as well.

As a verification, you should review the logs of the orderer to verify that it started properly. You should see no errors in the log, and the final message should indicate that it is ready to serve requests:

Orderer log

Reviewing the logs in depth, observe that the orderer creates a testchainid and installs system chaincode, which serves as the foundation of our network and gives the orderer and peers the capability to serve command line requests.

The channel

After the Docker containers start, you can enter the CLI container using the following command:

docker exec -it cli bash

Accessing CLI container

After you enter the CLI container, you can interact with the other peers by prefixing our peer commands with the appropriate environment variables. Usually, this means pointing to the certificates for that peer. You don`t need to do that when interacting with peer0 of Org1 which is set as the default one in CLI container.

Here is the list of environment variables that need to be used as the prefix for peer commands when interacting with peer0 of Org2 and Org3 respectively.

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.acme.com/users/Admin@org2.acme.com/msp CORE_PEER_ADDRESS=peer0.org2.acme.com:7051 CORE_PEER_LOCALMSPID=”Org2MSP” CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.acme.com/peers/peer0.org2.acme.com/tls/ca.crt CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.acme.com/users/Admin@org3.acme.com/msp CORE_PEER_ADDRESS=peer0.org3.acme.com:7051 CORE_PEER_LOCALMSPID=”Org3MSP” CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.acme.com/peers/peer0.org3.acme.com/tls/ca.crt

Create channel

The first command that we issue is the peer create channel command. This command targets the orderer (where the channels must be created) and uses the channel.tx and the channel name that is created using the configtxgen tool. As we are in the context of CLI container command line we define CHANNEL_NAME environment variable with our channel name.

export CHANNEL_NAME=mychannel peer channel create -o orderer.acme.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx –tls –cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/acme.com/orderers/orderer.acme.com/msp/tlscacerts/tlsca.acme.com-cert.pem

Creating channel

The peer channel create command returns a genesis block which will be used to join the channel. You can check that by running ls command to review that the file mychannel.block has been created.

review output of peer channel create command

Join channel

After the orderer creates the channel, we can have the peers join the channel, again using the peer CLI:

peer channel join -b mychannel.block

Observe in this case, we issued the peer channel join command for peer0 of Org1 (which is the default peer of our CLI container) and specified the mychannel.block, which is the genesis block. There is not much output, but you can see a message that peer joined the channel.

review output of peer channel join command

Now, we will make our peers of Org2 and Org3 join the channel as well. Note, the in this case we prefix the command with respective variables for each peer.

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.acme.com/users/Admin@org2.acme.com/msp CORE_PEER_ADDRESS=peer0.org2.acme.com:7051 CORE_PEER_LOCALMSPID=”Org2MSP” CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.acme.com/peers/peer0.org2.acme.com/tls/ca.crt peer channel join -b mychannel.block CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.acme.com/users/Admin@org3.acme.com/msp CORE_PEER_ADDRESS=peer0.org3.acme.com:7051 CORE_PEER_LOCALMSPID=”Org3MSP” CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.acme.com/peers/peer0.org3.acme.com/tls/ca.crt peer channel join -b mychannel.block

We expect the similar output as we got for peer of Org1:

review output of peer channel join command

review output of peer channel join command

When you review the logs of the peers, you can see the channel creation messages and the system chaincode being deployed as illustrated by the following example. Run the following command from a separate terminal:

docker logs peer0.org1.acme.com

join channel log

Update anchor peers

Now, going back to our main terminal, as the last step before we will interact with our network is to update the anchor peers. The following three commands are channel updates and they will become a part of the definition of the channel:

peer channel update -o orderer.acme.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx –tls –cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/acme.com/orderers/orderer.acme.com/msp/tlscacerts/tlsca.acme.com-cert.pem CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.acme.com/users/Admin@org2.acme.com/msp CORE_PEER_ADDRESS=peer0.org2.acme.com:7051 CORE_PEER_LOCALMSPID=”Org2MSP” CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.acme.com/peers/peer0.org2.acme.com/tls/ca.crt peer channel update -o orderer.acme.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org2MSPanchors.tx –tls –cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/acme.com/orderers/orderer.acme.com/msp/tlscacerts/tlsca.acme.com-cert.pem CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.acme.com/users/Admin@org3.acme.com/msp CORE_PEER_ADDRESS=peer0.org3.acme.com:7051 CORE_PEER_LOCALMSPID=”Org3MSP” CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.acme.com/peers/peer0.org3.acme.com/tls/ca.crt peer channel update -o orderer.acme.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org3MSPanchors.tx –tls –cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/acme.com/orderers/orderer.acme.com/msp/tlscacerts/tlsca.acme.com-cert.pem

In the screenshot below, we can see example output of the first command:

Update anchor peers

Install chaincode

Right now, we have fully configured and running Hyperledger Fabric network. However, the network does not contain any business logic – from this perspective, we can consider it as “empty” and as of now we have no way how to enter data there. Hyperledger Fabric blockchain applications interact with the ledger through the chaincode and its methods. So as a next step we need to install (deploy) chaincode on each peer.

:bulb:Note: Throughout this tutorial we are using the sample chaincode methods.

You can deploy chaincode on each peer using the following command:

peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/

In this case, if the command succeed, you should see a response indicating a status of 200 and a payload of OK, as illustrated by the following example:

Install chaincode

:bulb:Note: Interactions with our Hyperledger Fabric blockchain network are internally multi-step operations. It might take some time for commands to finish their execution.

Using the above command we have installed chaincode on peer0 of the Org1 organization. In order to let other peers from other organizations to interact with the ledger as well, we need to install chaincode there as well.

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.acme.com/users/Admin@org2.acme.com/msp CORE_PEER_ADDRESS=peer0.org2.acme.com:7051 CORE_PEER_LOCALMSPID=”Org2MSP” CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.acme.com/peers/peer0.org2.acme.com/tls/ca.crt peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/ CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.acme.com/users/Admin@org3.acme.com/msp CORE_PEER_ADDRESS=peer0.org3.acme.com:7051 CORE_PEER_LOCALMSPID=”Org3MSP” CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.acme.com/peers/peer0.org3.acme.com/tls/ca.crt peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/

Instantiate chaincode

After we installed the chaincode, we need to instantiate it. This will initialize the chaincode on the channel – the init function of chaincode will be called.

:bulb:Note: In the Hyperledger Fabric setup the chaincode instantiation creates (for the peer specified) a new docker container that is known as a chaincode container. The chaincode is deployed in this container and accessible from the peer.

Use the following command to instantiate the chaincode from one of the peers:

peer chaincode instantiate -o orderer.acme.com:7050 –tls –cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/acme.com/orderers/orderer.acme.com/msp/tlscacerts/tlsca.acme.com-cert.pem -C $CHANNEL_NAME -n mycc -v 1.0 -c ‘{“Args”:[“init”,”a”, “100”, “b”,”200″]}’ -P “OR (‘Org1MSP.member’,’Org2MSP.member’,’Org3MSP.member’)”

This command causes the following actions to occur:

  • Spawns a chaincode Docker container to house the chaincode.
  • Invokes the init function of the chaincode.

:bulb:Note: The init function (in this case) primes the ledger with the initial values for a and b (a = 100, b = 200). These can be thought of as our available assets.

  • Defines the endorsement policy for our channel. In this example, the [-P “OR (‘Org1MSP.member’,’Org2MSP.member’,’Org3MSP.member’)”] statement indicates that one (OR) of the peers (members of organizations) is enough to endorse a transaction for it to be valid.

When the command completes, you should see the “exiting…” message for the CLI, as illustrated by the following example (note the initial values specified for a and b as a parameter of peer chaincode instantiate command):

Instantiate chaincode

Execute tutorial scenario

Our Hyperledger Fabric blockchain network is now finally ready – it contains initial data and provide read/write data capabilities through the chaincode.

What we are going to do now is a series of read and writes to the ledger to demonstrate how to query the ledger and how to invoke chaincode in order to change the data in the ledger.

Query for initial state of the ledger

To quickly verify what data are in our ledger we can query the ledger for the value of a:

peer chaincode query -C $CHANNEL_NAME -n mycc -c ‘{“Args”:[“query”,”a”]}’

As expected, the value of 100 is being returned:

Initial query

Invoke chaincode

You can invoke the chaincode to transfer assets. In our example, we issue the following commands on each peer to transfer assets from a to b. In particular, we are taking 10 from a and transferring it to b.

Let’s start with peer0 of Org1:

peer chaincode invoke -o orderer.acme.com:7050 –tls –cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/acme.com/orderers/orderer.acme.com/msp/tlscacerts/tlsca.acme.com-cert.pem -C $CHANNEL_NAME -n mycc -c ‘{“Args”:[“invoke”,”a”,”b”,”10″]}’

As this command completes, you should see response message indicating status:200 and message:OK:

Invoke chaincode

We will continue with chaincode invocation from peer0 of Org2 and Org3:

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.acme.com/users/Admin@org2.acme.com/msp CORE_PEER_ADDRESS=peer0.org2.acme.com:7051 CORE_PEER_LOCALMSPID=”Org2MSP” CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.acme.com/peers/peer0.org2.acme.com/tls/ca.crt peer chaincode invoke -o orderer.acme.com:7050 –tls –cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/acme.com/orderers/orderer.acme.com/msp/tlscacerts/tlsca.acme.com-cert.pem -C $CHANNEL_NAME -n mycc -c ‘{“Args”:[“invoke”,”a”,”b”,”10″]}’ CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.acme.com/users/Admin@org3.acme.com/msp CORE_PEER_ADDRESS=peer0.org3.acme.com:7051 CORE_PEER_LOCALMSPID=”Org3MSP” CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.acme.com/peers/peer0.org3.acme.com/tls/ca.crt peer chaincode invoke -o orderer.acme.com:7050 –tls –cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/acme.com/orderers/orderer.acme.com/msp/tlscacerts/tlsca.acme.com-cert.pem -C $CHANNEL_NAME -n mycc -c ‘{“Args”:[“invoke”,”a”,”b”,”10″]}’

Query for the new values

We did some changes to the values of our assets a and b. If you recall, we instantiated a to be 100 and invoked the 3 times by transferring 10 from a to b. So we expect the queries return the value of 70 for a and 230 for b.

:bulb:Note: The following queries could be run from any peer. Remember, to run it from the context of different peers, you need to prefix the command with the respective environment variables.

Query for a:

peer chaincode query -C $CHANNEL_NAME -n mycc -c ‘{“Args”:[“query”,”a”]}’

As shown in the following screenshot, the value of a is 70 as expected:

Query chaincode

And let’s query for b:

peer chaincode query -C $CHANNEL_NAME -n mycc -c ‘{“Args”:[“query”,”b”]}’

Again, the result meets our expectation – value of b is 230:

Query chaincode

At this point, our network is fully operational and this concludes our tutorial.

Here is a summary of the tasks that we completed:

  • We installed all dependencies required to run Hyperledger Fabric v1.1 on zLinux.
  • We retrieved Hyperledger Fabric v1.1 artificats and binaries.
  • We used the cryptogen tool to generate certificates and keys for the local MSP.
  • We used the configtxgen tool to create our channel transaction and genesis block.
  • We configured the docker-compose.yaml files to describe our networks and peers.
  • We used the CLI container to perform the following tasks:
    • Create the channel
    • Deploy chaincode
    • Initialize chaincode
    • Invoke chaincode
    • Query chaincode

Our tutorial describes how to setup simple Hyperledger Fabric blockchain network on zLinux instance. There are advanced topics that might be covered in the future tutorials build on top of this one:

  • Use the fabric ca and fabric ca server to generate the certificates (instead of the cryptogen tool).
  • Setup Hyperledger Fabric blockchain network on physical nodes across the network.
  • Describe chaincode development.
  • Build a client application on top of your network using available Fabric SDKs.

Links

Topic Location
HyperLedger Fabric Documentation Home http://hyperledger-fabric.readthedocs.io/en/latest/
Hyperledger Fabric Glossary http://hyperledger-fabric.readthedocs.io/en/latest/glossary.html
Hyperledger Fabric Model http://hyperledger-fabric.readthedocs.io/en/latest/fabric_model.html
Hyperledger Fabric Prerequisities http://hyperledger-fabric.readthedocs.io/en/latest/prereqs.html
Hyperledger Fabric Samples http://hyperledger-fabric.readthedocs.io/en/latest/samples.html
Building Your First Network http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html
Hyperledger Fabric GitHub https://github.com/hyperledger/fabric
Hyperledger Fabric Samples GitHub https://github.com/hyperledger/fabric-samples
HyperLedger Fabric youtube channel https://www.youtube.com/channel/UCCFdgCWH_1vCndMPVqQlwZw
IBM Blockchain 101 https://www.ibm.com/developerworks/cloud/library/cl-ibm-blockchain-101-quick-start-guide-for-developers-bluemix-trs/index.html
Node.js http://nodejs.org/
Node.js on Linux on z https://developer.ibm.com/node/sdk/v6/
Docker https://docs.docker.com
Docker on Linux on z https://www.ibm.com/developerworks/linux/linux390/docker.html
Docker Compose https://docs.docker.com/compose/
Docker Compose on Linux on z https://github.com/linux-on-ibm-z/docs/wiki/Building-Docker-Compose
Golang https://golang.org/
Golang on Linux on z https://github.com/linux-on-ibm-z/docs/wiki/Building-Go

Useful Docker Commands

docker ps -a – Show all docker processes.

docker-compose -f up -d – Start docker containers that are described by docker-compose.yaml.

docker rm -f $(docker ps -aq) – Shut down/remove all docker processes.

docker network ls – Shows docker networks.

docker logs – Show the logs for a docker container. Logs are useful for debugging problems.

docker exec -it bash – Enter the docker container and start an interactive bash terminal.

Leave a Comment

Your email address will not be published. Required fields are marked *