Creating Custom network and deploy chain code with Hyperledger Fabric

In this tutorial we will create a hyperledger fabric network with two custom organization and one orderer and one channel.

First we have to setup the Prerequisite for the hyperledger fabric in the system. We are using the latest release for this tutorial v 1.4. You can setup the prerequisite from this link:

After the setting up the prerequisite you have to keep in mind that fabric ledger sample must be downloaded in the gopath you specified. This command will download the latest stable release of the fabric.

curl -sSL | bash -s

After that we will start the process of designing our own custom network with 2 organizations one peer each and one orderer node and connecting them through one channel. The organization will be shuru and beyond. Our channel will be channel demo and the network will be shuru-network.

Create a folder named shuru-network inside the fabtic-samples directory. Our first step will be to generate all the certificates and keys for the organisations and peers inside them. In our network, everyone will have to prove who they claim to be. The certificates we will generate will prove their identities and allow them to sign and verify transactions. Transactions will be signed by an entity’s private key and verified by a public one.

To generate these materials, we will use the cryptogen tool. We got this tool by downloading the platform-specific binaries ( you have a file called cryptogen in the bin folder ). The cryptogen tool consumes a crypto-config.yaml file. So, inside our shuru-network folder, go ahead and create this file. You can copy and paste the following inside and I’ll explain what is going on:

There are two parts in this file: OrdererOrgs and PeerOrgs. Before we study this file we must explain what Orderers are.

In Fabric, the Ordering Service is a collection of network entities. The orderers make sure that the transactions are dealt with in the right order ( first-come-first-serve ). The orderer is then responsible for packaging transactions into blocks.

So, what do we have in this file? We first define the Orderer Service. We give it a name, a domain and a hostname under the specs key. The naming convention goes like this: {Hostname}.{Domain}. So, our orderer will be named

Next, we define our 2 organisations. We define their names and domains. The key EnableNodeOUs is set to true. This is outside the scope of this article but setting this to true will allow us to define additional policies for the network members. Finally, we have a Count key set to 1 for each organisation. This means that there will be two peers per organisation. Why? Because each organisation will have an Admin by default. So, the number of peers in an organisation will be [Count + 1].

Everything is now in place for us to generate our certificates and keys. Make sure you are inside the shuru-network folder and run:

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

The cryptogen tool has a generate method that will do the job for us. We provide a config file and an output folder. You should see the following in your terminal:

And a crypto-config file just appeared in your shuru-network folder! This is where all the certificates and keys for the orderers, organisations and peers are stored.

Next, we will use the configtxgen tool. This tool will do three important things:

  • create the orderer genesis block
  • create the channel configuration transaction
  • create the anchor peer transactions, one for each peer organisation

Channel: In Fabric, you have the possibility to create channels. These channels allow organisations to create private sub-networks inside the greater network. In our case, we could imagine a channel that only Shuru and Beyond would be a part of..

Anchor peer: An anchor peer on a channel is a public peer that all others peers can discover and communicate with. Each organisation on a channel has an anchor peer.

Creating the file

The configtxgen tool consumes a configtx.yaml file. Create it and copy-paste the following:

There are a few different sections here. The most important Profiles and Organizations for now. In Profiles, we describe the orderer genesis block, our channel ( with the two organisations ) and we also defined a Consortium. Pay attention to the headers ( OrdererGenesis and channeldemoorgs) as they will be used later. In Organizations, we specify where are stored the certificates for each organisation. We just created these certificates with cryptogen. We also specify the anchor peers for each organisation. ( MSP means Membership Service Provider )

The ordererType key in the Orderer section is set to solo. Because we are in a development environment, we have only one orderer. If we were in a production environment, we would define several orderers in case one or several of them were faulty. For now, this will do just fine.

Running configtxgen:

First, create a folder called channel-artifacts to hold our artifacts.

We can now run the configtxgen tool. Run the following command:

../bin/configtxgen -profile OrdererGenesis -outputBlock ./channel-artifacts/genesis.block

The output will be like this:

Next, we must run a command to create our channel configuration transaction:

../bin/configtxgen -profile ChannelDemo -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID channeldemo

Next, we must create our anchor peers transactions. We will have two commands to run, one for each organisation. For Shuru:

../bin/configtxgen -profile ChannelDemo -outputAnchorPeersUpdate ./channel-artifacts/ShuruAnchor.tx -channelID channeldemo -asOrg ShuruMSP

Great! Now run that following command for Beyond:

../bin/configtxgen -profile ChannelDemo -outputAnchorPeersUpdate ./channel-artifacts/BeyondAnchor.tx -channelID channeldemo -asOrg BeyondMSP

Creating peer-base and docker-compose files:

We are almost there, we now need to specify a few docker files to tell our network where to find some images, how to be configured.

First, create a base folder. In this folder, create two files, one called docker-compose-base.yaml and another called peer-base.yaml.

These files set up the base for our network, with some fabric images along with some environments variables.Take special notice of the volume portion of the docker-compose-base.yaml file where we mount volume of the folder containing msp and other important things for the network.


Finally, the last file we will add is a docker-compose-cli.yaml file. This file will be in the root of our shuru-network project. The file creates a cli container and bootstrap all of our organisations declared in our base folder.

Take note of -CORE_PEER_TLS_CERT_FILE,- CORE_PEER_TLS_KEY_FILE, — CORE_PEER_TLS_ROOTCERT_FILE,- CORE_PEER_MSPCONFIGPATH path also the volumes mounted on the cli as we specefy the path for various important things needed for the network to start and function.

Finally prepare the .env containing the variable used in docker-compose-cli.yaml.


echo COMPOSE_PROJECT_NAME=net > .env

Great, now we can run:

docker-compose -f docker-compose-cli.yaml up -d

You should see something like this is your terminal:

You can check the containers by using this command:

docker ps -a

Now we have the containers running. We start configuring the channel on the peers.

All the commands are issued from CLI containers with docker exec. For easy access, we will launch two new terminals, each of which for the peer of organizations. Our commands will later be issued on Terminal. For shuru org peer0:

docker exec -e "CORE_PEER_LOCALMSPID=ShuruMSP" -e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/fabric-samples/shuru-network/crypto-config/peerOrganizations/" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/fabric-samples/shuru-network/crypto-config/peerOrganizations/" -e "" -it cli bash


For peer0.beyond:

docker exec -e "CORE_PEER_LOCALMSPID=BeyondMSP" -e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/fabric-samples/shuru-network/crypto-config/peerOrganizations/" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/fabric-samples/shuru-network/crypto-config/peerOrganizations/" -e "" -it cli bash


For easy access, export this parameter ORDERER_CA in all two terminals.


export ORDERER_CA=/opt/gopath/fabric-samples/shuru-network/crypto-config/ordererOrganizations/

Create the channel block file (any Terminal):

peer channel create -o -c channeldemo -f /opt/gopath/fabric-samples/shuru-network/channel-artifacts/channel.tx --tls --cafile $ORDERER_CA


Now join the channel to the peers using this command,input it in both terminals:

peer channel join -b channeldemo.block --tls --cafile $ORDERER_CA

Output for each terminal :

Now we will update the anchor peer for each peer.

For peer0.beyond,command:

peer channel update -o -c channeldemo -f /opt/gopath/fabric-samples/shuru-network/channel-artifacts/BeyondAnchor.tx --tls --cafile $ORDERER_CA


For peer0.shuru,Command:

peer channel update -o -c channeldemo -f /opt/gopath/fabric-samples/shuru-network/channel-artifacts/ShuruAnchor.tx --tls --cafile $ORDERER_CA


We can check if the peer has joined the channel using this command:

peer channel list

The output will be this for all terminal:

Now our network is up and running, ready for deploying chaincode.

We are using the SACC coming with in the fabric-samples. Here is the chaincode:

The logic of this chaincode is quite straight forward.

  • When chaincode is instantiated, the Init() is executed. Two arguments are expected, which corresponding to a “key” and a “value”.
  • This key/value pair is stored in the ledger (using PutState).
  • After instantiated, transactions are handled by Invoke(). The parameter is composed of a function (or command) and argument(s).
  • If function = set, two arguments are expected. it is either a brand-new key/value, or overrides the value if key exists. Function set() is called, and the result is stored in the ledger (using PutState)
  • If function = anything (e.g. get), one argument is expected as key. Function get() is called. GetState is used to obtain the state from the ledger. If key exists then the value is returned. Otherwise it is shown “Asset not found”.

By installing the chaincode, it loads the chaincode onto each peer. Note that chaincode is not yet useable until it is being instantiated.

In this step you must take notice of the docker-compose-cli file you wrote earlier. In the volume section there is portion where we have specified the location for the chaincode,we have to keep that in mind when issuing the command for chaincode installation.

I have positioned the chaincode inside the mediumchaincode folder inside the folder specified in the volume section.

For installing the chaincode in peer0.beyond : peer chaincode install -n sacc -p chain/mediumchaincode -v 1.0


For installing the chaincode in peer0.shuru : peer chaincode install -n sacc -p chain/mediumchaincode -v 1.0


Now all the nodes have the chaincode installed. We are ready for instantiating this chaincode.We can check the if the chaincode is installed using this command:

peer chaincode list --installed


On peer0.shuru Terminal, we instantiate the code on channeldemoorgs.


peer chaincode instantiate -o -C channeldemo -n sacc -v 1.0 -l golang   -c  '{"Args":["a", "100"]}' -P "OR('ShuruMSP.peer', 'BeyondMSP.peer')" --tls true --cafile $ORDERER_CA


Now we will check if the code is instantiated using this command:

peer chaincode -C channeldemo list --instantiated


We have set the initial key/value pair as a/100. Beside we specify the endorsing policy: one of the three organizations needed (OR is used).

We will query the value of key “a” in channeldemoorgs.In both terminal:


peer chaincode query -C channeldemo -n sacc -c '{"Args":["get","a"]}'

We get the same output both time:

We now see that the two peers has the same value obtained. They are sharing the same ledger.

After everything is complete, it is good practice to clean up everything, including the docker containers and those files generated for this demo.

To shutdown all containers and remove them, we use docker-compose to remove those created through the configuration files.

docker-compose -f docker-compose-cli.yaml down

There are still some stopped containers (see it from docker ps -a). They are the chaincode after instantiation. We will remove them all as well.

$ docker ps -a$ docker rm $(docker ps -aq)$ docker volume prune 

A noob software engineer. Always interested to learn new things.