Hyperledger Fabric v2.3 Example Network Setup — Channels(Part II)

Anıl HELVACI
stm-blockchain
Published in
9 min readMar 9, 2021

Introduction

In the previous part we discussed identity concept in a Fabric network. Talked about MSPs, Organizational Units, Fabric CA and finally went over the deployment steps of our sample network. This time we will examine;

  • Configuration of channel.
  • Creating an application channel using osnadmin without the existence of a system channel.
  • Joining peers to that channel.
  • Explaining and demonstrating the package, install, approve, commit, invoke, query chaincode operations.

CouchDB and CLI for Peer Nodes

We mentioned about peer1.Org1.com.couchdb and cli.peer1.Org1.com docker-compose services in last part.

  • peer1.Org1.com.couchdb is state database container that a peer node puts and gets the latest state of the ledger. CouchDB is an advanced option in terms of queries compared to default GoLevelDB.

In order to operate on a couchdb server you need “admin” credentials. Above environment variables should match the username and password you specified in your peer for this couchdb server.

  • cli.peer1.Org1.com : Purpose and usage of a cli container will be explained later in this article along with necessary environment variables to configure it.

Sample Network

Let’s remember the network topology from the last part. The whole code showcased here can be found in this repo.

Sample Network From Last Part

If you are coming from the last part you should have Ordering Service, Org1 and Org2 up and running by now. In this part we will examine the code in createAndJoinChannels.sh . In order for us to create a channel we must first configure it. We do that by using a file named configtx.yaml .

Step 1

I have made three main changes to the default configtx.yaml ;

  1. Introduce the organizations in the channel:
  • Name field in the organizations should match with the name you specified in CORE_PEER_LOCALMSPID environment variable when you were starting yout peer so that the peer will authorized to join this channel.
  • MSPDir field points to msp/ directory which is placed under the root folder of the corresponding organization.
  • In the Policies section of Org1 and Org2 we used the roles which we specified via NodeOUs during the registration of users to CA servers.
  • The reason why I did not use NodeOUs in the orderingservice organization is that there was no need for that kind of logic for the orderingservice.
  • Specifying AnchorPeers in configtx.yaml file is now considered as an anti-pattern since v2.3. What is recommended is you first create the channel without AnchorPeers then update the channel with AnchorPeers. Since channel update operation is not in this article’s scope and will come as another article I decided to go this way speciy AnchorPeers in configtx.yaml .
  • You should specify the address of the ordering nodes of an organization using OrdererEndpoints.

2. Make adjustments for orderers so this channel does not need a system channel

  • OrdererType should be set to “etcdraft” for application channels that are created via osnadmin .

In the EtcdRaft configuration we need to specify “Consenter” ordering nodes

  • Host: The host machine of the ordering node.
  • Port: The port the ordering node listens on.
  • ClientTLSCert and ServerTLSCert: Orderer in this example is using the same TLS certificate for both the server and client for simplicity.

3. Define a channel profile without consortium

  • Orderder: Since there is no consortium we should define the ordering organizations of this channel in the channel profile. Other than that we went with the defaults.
  • Application: In addition to the default application configurations we added the peer organizations of this channel.

Full configtx.yaml is present in the github repo.

Step 2

Now that we have our configurations ready we can create the genesis block of our application channel.

  • FABRIC_CFG_PATH: This environment variable should point location of the folder which configtx.yaml is in.

configtxgen is a useful fabric binary that converts our configtx.yaml file into an actual block that our nodes can use to create and join the channel.

  • -profile : Refers to the Profiles section in configtx.yaml file.
  • -outputBlock : Name of the genesis block to be generated.
  • -channelID : Name of the channel.

Step 3

After our genesis block is generated we can create our chanel usind osnadmin

We talked about the mutual-TLS requirement of orderer admin server. Here we are addressing the client side TLS certificicates. By “client” we mean the one who sends the request to orderer admin server.

  • ORDERER_TLS_CA: This is the root certificate of orderingservice’s TLS CA.
  • ORDERER_ADMIN_CERT: TLS certificate issued by TLS CA Server.
  • ORDERER_ADMIN_KEY: TLS private ket issued by TLS CA Server.
  • ORDERDER_ADMIN_ADDRESS: Address of the orderer admin server.

osnadmin channel join command joins this orderer to an existing channel, if the channel does not exist it creates the channel according to the genesis block.

  • --channelID : Name of the channel.
  • --config-block : Genesis block of the channel.
  • -o : Address of the orderer admin server.
  • --ca-file : Root certificate of orderinservice TLS CA
  • --client-cert : Public key(certificate) of orderer admin client issued by orderinservice TLS CA.
  • —client-key: Private key of orderer admin client issued by orderinservice TLS CA.

Step 4

After the creation of our channel is successful we can now join our peer nodes to the channel. Here is the code for that;

CLI

peer command has these subcommands

And these subcommands have other subcommands as you can see in the picture above. We started our node using peer node start which started the peer node server. Now we have to run some operations regarding that peer. For that we will use peer channel and peer chaincode subcommands which act as a requesting client to the order and peer node servers. So we have to provide this client with some context which is the purpose of these environment variables;

  • CORE_PEER_LOCALMSPID: Name of the organzation which this requesting member belongs to.
  • CORE_PEER_ID: Name of the requesting member.
  • CORE_PEER_ADDRESS: Address of the actual peer node which will be effected as a result of this request.
  • FABRIC_CFG_PATH: peer commands expectes to be a core.yaml file present in the location pointed by this environment variable.
  • ORDERER_TLS_CA: TLS root certificate of orderer node issued by Ordering Service TLS CA.
  • CORE_PEER_TLS_ROOTCERT_FILE: TLS roo certificate of this organization issued by this organizations’s TLS CA.
  • CORE_PEER_MSPCONFIGPATH: Here we specify our actual identity in the network. In order to run operations as CLI container this MSP should belong to an “admin”. Since we enabled NodeOUs do not forget to include config.yaml inside the MSP you are using.
  • CORE_PEER_TLS_ENABLED: Enable server side TLS.
  • ORDERER_ADDRESS: Address of the orderer node.

cli.peer1.Org1.com

As you can see the environment variables of the cli container are identical to the ones we use in our createAndJoinChannel.sh script. This means you do not actually need a container to perform cli operations as long as you have connection to the nodes and the admin MSP you can run peer commands as a client. The reason I chose cli container is some cli operations need to be run on both peers and switching between peers would not be so efficient. Also this cli environmet is automated and you only need access the bash of the cli container without any preperation.

Once we our cli environment ready, we can run peer channel fetch oldest which fetches the oldest block in channel which is the genesis block. We need this block so that we will have the full ledger. In a more complex scenario where the channel is up for a while and many transactions are commited, this block will be useful for catching up the state and have the full transaction history in our local file system. There are other methods used when joining a channel like joining by snapshot or fetching last config block but in this article we are going simple. We can discuss or demonstrate those methods in another article.

peer channel fetch oldest

  • -o : Adrees of the orderer node which we will fetch the genesis block from.
  • --cafile : TLS root certificate of orderer node issued by Ordering Service TLS CA.
  • --tls : Tells the orderer node we will use TLS.
  • -c : Name of the channel.
  • $PWD/Org1/peer1/testchannel.genesis.block : Indicates the name and the location of the genesis block to be fetched.

peer channel join does the actual joining operation using the genesis block we fetched.

-b : Name and address of the genesis block.

Since we have two peers belonging to two different organizations we should run these commands for the other peer too as I did in the createAndJoinChannel.sh script. The steps are identitcal but for Org2 instead of Org1 this time.

Step 5

Now that we have joined our peers to testchannel we can start chaincode deployment process. First you need to enter the bash of either one of the cli containers. Since the install and approve operations need to be done on both peers, the commands shown in this section must be done on the other peer cli depending on which cli you enter first.

Enter cli.peer1.Org1.com;

Run docker exec -it cli.peer1.Org1.com bash . You should something like this;

A chaincode needs to be packaged in order to be install on a peer. There is a sample chaincode in the github repo that is already packaged which we will use for our demo purposes. If you want to package your own chain you can follow the steps in the official documentation. They are pretty straight forward.

Once you are in the terminal of cli container run this command;

peer lifecycle chaincode install javascript@0.0.1.tar.gz

To check if the installation successful run;

peer lifecycle chaincode queryinstalled

If successful you should see something like this;

Installed chaincodes on peer:Package ID: javascript_0.0.1:42ad3b2bf2c78d1b5330245a6e1f104b6735f81dba326239d52d13008631ff90, Label: javascript_0.0.1

This Package ID will be used to identify the chaincode. Assign this package id to the environment variable CC_PACKAGE_ID for ease of use in the following commands.

Once we have our package id now we can approve it since the defaul endorsment policy for a chaincode is MAJORITY and majority of two is two. So we must approve this chaincode on both peers. The approve command is as follows;

peer lifecycle chaincode approveformyorg -o $ORDERER_ADDRESS --channelID testchannel --name javascript --version 0.0.1 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_TLS_CA

Some of the flags I have explained before are used here as well so I will only go over the ones I haven’t explained before.

  • --name : Name of the chaincode.
  • --version : Version of the chaincode.
  • --package-id : The package id we received when we installed the chaincode succesfully.
  • --sequence : This parameter is an integer that keeps track of the number of times a chaincode has been defined or updated.

Assuming you do not get any errors after you run this command you should run the following command to check whether if every organization that needed to endorse this chaincode approved it or not.

peer lifecycle chaincode checkcommitreadiness --channelID testchannel --name javascript --version 0.0.1 --sequence 1 --tls --cafile $ORDERER_TLS_CA --output json
  • --output : Specifies the format of the output.

In order to move forward to the next step you should see this output indicating every endorser of this chaincode have been approved this chaincode and now we are ready to commit it;

{"approvals": {"Org1": true,"Org2": true}}

Do not forget to run the peer lifecycle chaincode install and peer lifecycle chaincode approve commands on both of the clis.

Step 6

Assumin every endorser peer has approved the chaincode,we can move on to commiting the chaincode. To do this run;

peer lifecycle chaincode commit -o $ORDERER_ADDRESS --channelID  testchannel --name javascript --version 0.0.1 --sequence 1 --tls  --cafile $ORDERER_TLS_CA --peerAddresses peer1.Org1.com:8054  --tlsRootCertFiles ./Org1/peer1/tls/tls-ca-cert.pem --peerAddresses  peer1.Org2.com:9054 --tlsRootCertFiles ./Org2/peer1/tls/tls-ca-cert.pem 

There are few new flags that we are not familiar;

--peerAddress : Used to target the peers to query the chaincode wheter or not it is approved by their organization.

--tlsRootCertFiles : The root TLS CA certificated which this peer is registred.

Once the above commands succeds we can finally invoke and query the methods of this chaincode. Here are the sample commands I used for testing this channel.

peer chaincode invoke -o $ORDERER_ADDRESS --tls --cafile  $ORDERER_TLS_CA -C testchannel -n javascript --peerAddresses  peer1.Org1.com:8054 --tlsRootCertFiles ./Org1/peer1/tls/tls-ca-cert.pem  --peerAddresses peer1.Org2.com:9054 --tlsRootCertFiles  ./Org2/peer1/tls/tls-ca-cert.pem -c  '{"function":"myAssetExists","Args":["1"]}'

-c : Here specifies the actual function name and parameters we use to invoke.

If success you should see this output;

2021-02-25 10:45:49.791 UTC [chaincodeCmd] chaincodeInvokeOrQuery  -> INFO 001 Chaincode invoke successful. result: status:200  payload:"false" 

You can create an asset using;

peer chaincode invoke -o $ORDERER_ADDRESS --tls --cafile  $ORDERER_TLS_CA -C testchannel -n javascript --peerAddresses  peer1.Org1.com:8054 --tlsRootCertFiles ./Org1/peer1/tls/tls-ca-cert.pem  --peerAddresses peer1.Org2.com:9054 --tlsRootCertFiles  ./Org2/peer1/tls/tls-ca-cert.pem -c  '{"function":"createMyAsset","Args":["1", "hello world"]}' 

The query it using;

peer chaincode query -C testchannel -n javascript -c '{"Args":["readMyAsset", "1"]}' 

Summary

If you have come this far, you should have the network in the topology above in your local machine. Thank you bearing with me :-) I hope these articles was useful for you.

--

--