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 network.sh 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 chaincode/fabcar/ to asset-transfer-basic/, if no chaincode is specified in ./network.sh deployCC. For simplicity we are using the Simple Asset Chaincode (chaincode/sacc/) 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, network.sh, 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.

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 -s couchdb 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.

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.

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 (-ccn) and chaincode path (-ccp), the asset-transfer-basic/ will be deployed. If we do not specify channel name, mychannel is the target channel.

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 peer 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: terminalorg1

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: terminalorg2

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

Terminal for Org2 (dark violet background)

source terminalorg2

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.

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

All network components are up and running.

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

And both peers have joined mychannel.

peer0.org1.example.com joined mychannel
peer0.org2.example.com joined mychannel
./network.sh deployCC -ccn mycc -ccp ../chaincode/sacc

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

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"]}'
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"]}'
peer0.org1.example.com
peer0.org2.example.com

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

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.

Two chaincode containers are running
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).

One database handling the state for one channel and one chaincode
./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.

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.

peer0.org1.example.com joined channelone and channeltwo
peer0.org2.example.com joined channelone and channeltwo

Note that the script ./network.sh deployCC 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

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
Approval for Org1 (on Terminal for Org1)
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
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
For channelone
For channeltwo

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

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"]}'

Query on channelone from both Org1 and Org2

peer chaincode query -C channelone -n mycc -c '{"Args":["get","name"]}'
Terminal for Org1
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"]}'
Terminal for Org1
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"]}'

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"]}'
Terminal for Org1
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.

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.

Two chaincode containers are running
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.

Two databases handling the state when two channels are created
./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.

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.

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.

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"]}'

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"]}'
Terminal for Org1
Terminal for Org2

Again we see state is handled separately in different chaincodes.

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.

Four chaincode containers are running
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.

Two databases handling the state when two chaincodes are deployed
./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.

--

--

--

Visit http://www.ledgertech.biz/kcarticles.html for all my works. Reach me on https://www.linkedin.com/in/ktam1/ or follow me @kctheservant in Twitter.

Love podcasts or audiobooks? Learn on the go with our new app.

Flutter-Feel the Magic in application development

Ensuring High Availability —Infrastructures Design

Upcoming News and Excitement to look forward to this week

Thanks, Vincenzo, for the great introduction to Avalanche!

Tech Deployment: CJI Piping And Fabrication Uses Morpheus.Network

Free, Zero Waste, New Computer by Revitalizing with LinuxMint

Recycle Reuse Reduce

DiffUtil Part I. How to improve your List’s Adapter

Fun and Failure with Computer Vision Tools

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
KC Tam

KC Tam

Visit http://www.ledgertech.biz/kcarticles.html for all my works. Reach me on https://www.linkedin.com/in/ktam1/ or follow me @kctheservant in Twitter.

More from Medium

Hyperledger Fabric Tools — 1

Intro to QUIC — a multiplexed transport over UDP

Working with Hyperledger Fabric v2.2

Welcome to gRPC, Please Follow Me…