Observing Channel and Chaincode in Hyperledger Fabric

Overview

What happens if we deploy the same chaincode to two channels? How about if the same chaincode is deployed twice in a channel? Through observing these different scenarios we can know more about how Hyperledger Fabric is working. Thanks for the latest v2.2, Test Network gives us an easy way to create these setup and make such observations.

First introduced in v2.0, the Test Network setup is simple: one orderer organization serving ordering service (solo), and two peer organizations (Org1 and Org2), each of which has one peer (peer0). The script is “upgraded” with full flexibility. Now we can easily create multiple channels and deploy multiple chaincodes onto this Test Network. This gives us an easy way to make observation, as we do not have to generate a lot of material and deal with many files. The script is well coded to build these setup for us.

The purpose of this article is to observe the system behaviour of Hyperledger Fabric when dealing with channel and chaincode. We begin with a baseline setup, in which one channel is created and one chaincode is deployed. Later we will work on two variations. They are,

  • Same chaincode deployed in two channels
  • Same chaincode deployed twice in a channel

Our observation point is on how ledger is being handled across channels and/or across chaincode deployed. Also we will take a look at chaincode containers and the worldstate database.

Note in Fabric v2.2, the default chaincode is changed from to , if no chaincode is specified in . For simplicity we are using the Simple Asset Chaincode () in this article. This provides a simple asset recorded in ledger, with get and set chaincode functions on the assets.

Quick Review on Test Network Script

Test Network in v2.2 comes with a very handy and user friendly script, , with a lot of flexibility. You can find more detail about Test Network in the readthedoc. Here we show a summary of the commands we use in this article.

Bring Up Containers

To bring up all the required components for the Test Network.

./network.sh up -s couchdb

This will bring up the three nodes: one orderer and two peers. When option is specified, two more Couch DB containers are running, one for each peer. We will see totally five containers once the command is executed.

Create Channels

To build channel artifacts, create channel genesis block, join peers, and update anchor peers for a specific channel.

./network.sh createChannel -c <channel_name>

If no channel name is specified, it is by default mychannel.

Note this command can be combined with the previous. For example,

./network.sh up createChannel

Then mychannel is created after all containers are up and running.

Deploy Chaincodes

To deploy chaincode using lifecycle chaincode,

./network.sh deployCC -ccn <chaincode name> -ccp <chaincode path> -c <channel_name>

If we do not specify chaincode name () and chaincode path (), the will be deployed. If we do not specify channel name, mychannel is the target channel.

Tear Down Test Network

To tear down everything

./network.sh down

This will stop and kill all the running containers, and remove the chaincode container images built during chaincode deployment. It helps when you need a clean setup for testing.

Prepare Two Terminals

As Test Network does not come with a CLI container, we are using localhost to issue commands to the two peers. The easiest way is to prepare two terminals, one for each peer (organization). What we need is to make sure the environment variables are properly set in these terminals.

We prepare two files keeping the environment variables:

file:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
export PATH=$PATH:$PWD/../bin/export FABRIC_CFG_PATH=$PWD/../config/
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

file:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
export PATH=$PATH:$PWD/../bin/export FABRIC_CFG_PATH=$PWD/../config/
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

Here I change the background for the two terminals.

Terminal for Org1 (blue background)

source terminalorg1
Image for post
Image for post

Terminal for Org2 (dark violet background)

source terminalorg2
Image for post
Image for post

With this we can begin with our baseline setup.

Baseline Setup: One Channel and One Chaincode

We begin with one channel (mychannel) and one chaincode (mycc). Here is the baseline setup.

Image for post
Image for post

Bring up Test Network and mychannel

cd fabric-samples/test-network
./network.sh up createChannel -s couchdb

All network components are up and running.

Image for post
Image for post
Five containers are running: one orderer, two peers, and one Couch DB for each peer

And both peers have joined mychannel.

Image for post
Image for post
peer0.org1.example.com joined mychannel
Image for post
Image for post
peer0.org2.example.com joined mychannel

Deploy chaincode

./network.sh deployCC -ccn mycc -ccp ../chaincode/sacc

After the script is completely executed, we can test the chaincode functions.

Test chaincode

Invoke from either one terminal

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls true --cafile $ORDERER_CA -C mychannel -n mycc --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["set","name","Alice"]}'
Image for post
Image for post
Invoke chaincode function to set value for “name”

Query from both Org1 and Org2

peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'
Image for post
Image for post
peer0.org1.example.com
Image for post
Image for post
peer0.org2.example.com

The basic setup for single channel and single chaincode deployment is working well. Both peers see the same asset.

Observation

Chaincode container

There are only two chaincode containers running, one for each peer. From the name of container image we learn that it is associated to the peer and the chaincode name, not a channel name. We do not see mychannel shown in the name. Later we can see it supports many channels as far as the name remains.

Image for post
Image for post
Two chaincode containers are running
Image for post
Image for post
Each chaincode container is pairing to a peer, associated to the chaincode name.

Worldstate database

We see a database for this deployment. The database is named with channel (mychannel) and chaincode (mycc).

Image for post
Image for post
One database handling the state for one channel and one chaincode

Clean up deployment

./network.sh down

Two channels with the same chaincode

Here we will bring up two channels, channelone and channeltwo, and deploy chaincode to both channels. We will demonstrate that the state is kept in two different ledgers, and stored separately even if the same chaincode is deployed and same asset name is used.

Image for post
Image for post

Bring up Test Network and two channels

cd fabric-samples/test-network
./network.sh up -s couchdb
./network.sh createChannel -c channelone
./network.sh createChannel -c channeltwo

After two channels are created, we can check each peer has joined them all.

Image for post
Image for post
peer0.org1.example.com joined channelone and channeltwo
Image for post
Image for post
peer0.org2.example.com joined channelone and channeltwo

Deploy chaincode to the two channels

Note that the script performs the whole process (packaging, installation, approval and committing). After we use script to deploy chaincode in channelone, which should be straightforward, our attempt to repeat this in channeltwo will fail, as chaincode is already installed in both peers. As a result, we will use peer command to approve and commit chaincode definition on channeltwo.

Deploy chaincode using script for channelone

We first use script to deploy sacc on channelone.

./network.sh deployCC -ccn mycc -ccp ../chaincode/sacc -c channelone

Obtain chaincode package ID

As we need manual approval on channeltwo. First we need the package ID after chaincode is installed in the peer.

peer lifecycle chaincode queryinstalled
Image for post
Image for post

Approve chaincode for both Org1 and Org2 to channeltwo

Approval is required for both organizations. Same command for both terminals.

peer lifecycle chaincode approveformyorg --tls --cafile $ORDERER_CA -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID channeltwo --name mycc --version 1 --sequence 1 --waitForEvent --package-id mycc_1.0:366663ea5345d035a3a8aca36db3abe45806c5be6cce5f30fdf9ce81410d7fa5
Image for post
Image for post
Approval for Org1 (on Terminal for Org1)
Image for post
Image for post
Approval for Org2 (on Terminal for Org2)

Commit chaincode for channeltwo

On either terminal

peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile $ORDERER_CA --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations//peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --channelID channeltwo --name mycc --version 1 --sequence 1
Image for post
Image for post
Commit chaincode to channeltwo

With this, we have deployed sacc on channeltwo. We can do a quick check.

On either terminal

peer lifecycle chaincode querycommitted --channelID channelone --name mycc --output jsonpeer lifecycle chaincode querycommitted --channelID channeltwo --name mycc --output json
Image for post
Image for post
For channelone
Image for post
Image for post
For channeltwo

Although everything is largely identical (we made that), they are on different channels.

Test chaincode

Invoke on channelone on either terminal

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls true --cafile $ORDERER_CA -C channelone -n mycc --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["set","name","Alice"]}'
Image for post
Image for post

Query on channelone from both Org1 and Org2

peer chaincode query -C channelone -n mycc -c '{"Args":["get","name"]}'
Image for post
Image for post
Terminal for Org1
Image for post
Image for post
Terminal for Org2

We see the asset “name” found in channelone.

Query on channeltwo from both Org1 and Org2

peer chaincode query -C channeltwo -n mycc -c '{"Args":["get","name"]}'
Image for post
Image for post
Terminal for Org1
Image for post
Image for post
Terminal for Org2

We see the asset “name” not found in channeltwo.

Invoke on channeltwo on either terminal

For demonstration we invoke sacc with the same asset “name” with a different state value.

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls true --cafile $ORDERER_CA -C channeltwo -n mycc --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["set","name","Bob"]}'
Image for post
Image for post

Query the same asset “name” on both channels, both Org1 and Org2

peer chaincode query -C channelone -n mycc -c '{"Args":["get","name"]}'peer chaincode query -C channeltwo -n mycc -c '{"Args":["get","name"]}'
Image for post
Image for post
Terminal for Org1
Image for post
Image for post
Terminal for Org2

We see that the ledger for each channel is operating separately, even though the same chaincode is deployed and the same asset name is used.

Observation

Chaincode container

Similar to the baseline setup, there are two chaincode containers running, one for each peer. We see that as long as the chaincode name remains the same, the same chaincode container is processing endorsement request and/or query, no matter which channels it is specified.

Image for post
Image for post
Two chaincode containers are running
Image for post
Image for post
Each chaincode container is pairing to a peer, associated to the chaincode name, without channel specific information

Worldstate database

From the worldstate database we see two different databases are handling the two channels, even the chaincode name is the same.

Image for post
Image for post
Two databases handling the state when two channels are created

Clean up deployment

./network.sh down

Same chaincode deployed twice in a channel

Here we will deploy sacc twice in mychannel. To differentiate the two deployments, we are using different chaincode names: mycc1 and mycc2.

Image for post
Image for post

Note: We have to specify different names for chaincodes if they are from the same source. If we are using the same name, we need version to distinguish them. But we can only specify one version in the chaincode definition during approving and committing. This is not what we are demonstrating in this setup.

Bring up Test Network and mychannel

cd fabric-samples/test-network
./network.sh up createChannel -s couchdb

Deploy chaincode

./network.sh deployCC -ccn mycc1 -ccp ../chaincode/sacc./network.sh deployCC -ccn mycc2 -ccp ../chaincode/sacc

After the script is completely executed, we can test the chaincode functions.

Test chaincode

For both chaincodes, invoke from either one terminal

Again we are using the same asset name “name” and different values to different chaincodes.

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls true --cafile $ORDERER_CA -C mychannel -n mycc1 --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["set","name","Alice"]}'peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls true --cafile $ORDERER_CA -C mychannel -n mycc2 --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["set","name","Bob"]}'
Image for post
Image for post

Query both chaincodes

peer chaincode query -C mychannel -n mycc1 -c '{"Args":["get","name"]}'peer chaincode query -C mychannel -n mycc2 -c '{"Args":["get","name"]}'
Image for post
Image for post
Terminal for Org1
Image for post
Image for post
Terminal for Org2

Again we see state is handled separately in different chaincodes.

Observation

Chaincode container

Now we see there are two different chaincode containers for each peer, that means, there are totally four containers. It is because the chaincode name is different, and so is the package ID, despite the fact that both are from the same source.

Image for post
Image for post
Four chaincode containers are running
Image for post
Image for post
Each chaincode container is pairing to a peer and a chaincode name. Therefore we have four here.

Worldstate database

From the worldstate database we see two different databases are handling the two chaincodes in the same channel.

Image for post
Image for post
Two databases handling the state when two chaincodes are deployed

Clean up deployment

./network.sh down

Summary

The purpose of this article is to help understanding some internal operation of Hyperledger Fabric when handling channel and chaincode. With fabric v2.2 we can easily build an environment to test our objectives. It also shows how easy it is to use script to deploy and test chaincode in the Test Network. Hope you learn something about Hyperledger Fabric and make good use of the script.

Written by

Happy to share what I learn on blockchain. Visit http://www.ledgertech.biz/kcarticles.html for my works. or reach me on https://www.linkedin.com/in/ktam1/.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store