Hyperledger Fabric — Updating Channel Configs

Hyperledger Fabric Image

Introduction

This is a step-by-step tutorial for updating channel configs in Hyperledger Fabric. Those steps are demonstrated using Hyperledger Fabric “Build Your First Network” (BYFN). We use Hyperledger Fabric v1.4.

If you don’t know how to start a BYFN, I will also provide steps in this tutorial, no worry!
Channel in Hyperledger Fabric is a private group in a Blockchain network. And each Blockchain network could contain multiple Channels, where each Channel is independent to other Channels, has its own ledger, and contains (multiple) organisation(s).

Each Channel is independent, thus there is an independent configurations set for each Channel, such as some policies, how many transactions in one block, etc. We would discuss how to update a Channel’s configurations set.


The Steps – Overview

Since steps of updating channel configurations could make people lost easily (there are so many files!), I list the steps overview here:

  1. Setup a BYFN (our Blockchain network)
  2. Fetch the current channel configurations for mychannel – output: config_block.pb, which is a block file
  3. Transform the config_block.pb configurations to an understandable JSON file – output: config.json
  4. Make a copy of config.json to modified_config.json, which we will modify it according to what we need to update
  5. Install vim for the modification of JSON file
  6. Modify configurations in modified_config.json
  7. Transform modified_config.json to a block file – output: modified_config.pb
  8. Transform config.json to a block file — output: config.pb
  9. Compute the difference between modified_config.pb and config.json – output:diff_config.pb
  10. Transform the diff_config.pb configurations to an understandable JSON file – output: diff_config.json
  11. Add envelope text in diff_config.json— output: diff_config_envelope.json
  12. Transform diff_config_envelope.json to a block file — output: diff_config_envelope.pb
  13. Sign diff_config_envelope.pb as OrdererOrg admin (depending on policy)
  14. Send channel update transaction

Some Q&A:

Q: In step 2, why are those configurations obtained by fetching a block?
A: It is because in Hyperledger Fabric, channel configurations are encoded in Blockchain ledger, they are just information in the Blockchain.
Q: In step 9, why do we need to compute the difference?
A: According to Hyperledger Fabric document, “we are able to forgo the extensive MSP material and modification policy information for Org1 and Org2 because this data is already present within the channel’s genesis block. As such, we only need the delta between the two configurations”.
Q: In step 13, why do we need to sign the config block as OrdererOrg admin?
A: It depends on the policy. For more details about Hyperledger Fabric policy, you might take a look:
(1) https://hyperledger-fabric.readthedocs.io/en/release-1.4/policies.html?highlight=policy
(2) https://medium.com/@reasdom/hyperledger-fabric-damn-implicitmetapolicy-44cc9cc5c472

Step 1 — Setup a BYFN (our Blockchain network)

1.1 Install Prerequisites

We use Hyperledger Fabric v1.4 in this tutorial.

First of all, you could install prerequisites by following the official instructions:

  1. Install prerequisites
  2. Install samples, programs, and docker images from Hyperledger Fabric

1.2 Switch to the BYFN Directory

Let’s switch to BYFN directory (*supposed that you finish the prerequisite part, you should have all needed files and directories):

cd fabric-samples/first-network

1.3 Bring Up the Network!

There is a script to bring up the network easily, just run it. Thanks, Hyperledger.

./byfn.sh up
After running this script, you might need to wait for a moment…
Also, remember to start Docker, before you run the command above.
*In case you make something wrongly, you can run the following commands to turn down the network, and bring up again (and be careful):
./byfn.sh down
./byfn.sh up

1.4 Access the Cli

There is a cli Docker container created automatically, it is a command line interface to control the nodes.

Let’s get access to the cli:

docker exec -it cli bash

Then, set up environment variables used by some programs:

export CHANNEL_NAME=mychannel
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
You could just copy all of them, then paste to your terminal and press “enter”.
A little bit messy, sorry for that :P.

Step 2 — Fetch the current channel configurations for mychannel — output: config_block.pb, which is a block file

peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA

Step 3 — Transform the config_block.pb configurations to an understandable JSON file — output: config.json

configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json

Step 4 — Make a copy of config.json to modified_config.json, which we will modify it according to what we need to update

cp config.json modified_config.json

Step 5 — Install vim for the modification of JSON file

vim is a famous editing tool in Linux.

sudo apt-get update -y
sudo apt-get install vim -y

Step 6 — Modify configurations in modified_config.json

vim modified_config.json

In this tutorial let’s edit BatchSize, that is about how many transactions in one block (default is 10 txs/block). We are going to modify max_message_count.

  1. Press “/” to start searching text
  2. Type “max_message_count”
  3. Then your cursor should be located at the start of text “max_message_count

Do you see the texts above?

  1. Now, Press “i” to enter insert mode in vim (thus we can start editing), after pressing, you should see that there is “-- Insert --” on the left bottom of the terminal
  2. Locate your cursor on “10” (line 6 above)
  3. Change it from “10” to “11”:

Notice line 6. Do we have the same texts? We just change the number of transactions per block from 10 to 11.

Tips (optional to this tutorial):
Generally speaking, increasing this number could lead to higher throughput (in TPS, transactions per second), but too much could lead to larger latency. Personally, I use 100 (you might need to adjust “absolute_max_bytes”, “preferre_max_bytes”, some Kafka settings if any, and block release timeout). In case you have very powerful machines, this number could be even larger. I could reach over 2xxx TPS in my load test (GOLang Chaincode with basic getState() and putState() operations, and with LevelDB, v1.4 network).
Remember to perform load/performance test yourself to verify for production case. More details you might take a look: https://arxiv.org/pdf/1805.11390.pdf
  1. Then, press “esc” to exit insert mode of vim
  2. Press “shift + :”, type “wq!”, and press “enter”. You should now leave vim and the modification is saved.

Step 7 — Transform modified_config.json to a block file — output: modified_config.pb

configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb

Step 8 — Transform config.json to a block file — output: config.pb

configtxlator proto_encode --input config.json --type common.Config --output config.pb

Step 9 — Compute the difference between modified_config.pb and config.pb — output: diff_config.pb

configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_config.pb --output diff_config.pb

Step 10 — Transform the diff_config.pb configurations to an understandable JSON file — output: diff_config.json

configtxlator proto_decode --input diff_config.pb --type common.ConfigUpdate | jq . > diff_config.json

Step 11 — Add envelope text in diff_config.json — output: diff_config_envelope.json

echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat diff_config.json)'}}}' | jq . > diff_config_envelope.json

Step 12 — Transform diff_config_envelope.json to a block file — output: diff_config_envelope.pb

configtxlator proto_encode --input diff_config_envelope.json --type common.Envelope --output diff_config_envelope.pb

Step 13 — Sign diff_config_envelope.pb as OrdererOrg admin (depending on policy)

In step 1, under “Access the Cli”, our cli is representing Peer0 in Org1 via environment variables.

In this step 13, we are going to switch to OrdererOrg admin to perform the signing, because our policy requires OrdererOrg admin to sign this update transaction.

For details of Hyperledger Fabric policy, please refer to two links provided at the end of section “The Steps — Overview”
export CORE_PEER_ADDRESS=orderer.example.com:7050
export CORE_PEER_LOCALMSPID="OrdererMSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/users/Admin\@example.com/msp
You could just copy all of them, then paste to your terminal and press “enter”.
A little bit messy (again), sorry for that (again) :P :P.

Now, we do signing:

peer channel signconfigtx -f diff_config_envelope.pb
If you are careful enough, you should observe that the file size of diff_config_envelope.pb before signing is smaller than that after signing.
And it is okay to sign multiple times, let’s try it yourself.

Step 14 — Send channel update transaction

It is time to update the channel!

peer channel update -f diff_config_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA
In fact, this command also performs signing. We still sign it in step 13 because I would like to make the steps explicit and it is also for teaching purpose — in some cases, where the policy requires more than one admin to sign, you might need to use the command in step 13 multiple times before the final signer submits the channel update transaction.

Well, we are done!


Bonus Step 15 — Verify the channel update

How could we know that we have really updated the configurations?

One possible way is to fetch the configuration block again and transform it into JSON file. Finally, we check whether max_message_count is 11.

peer channel fetch config config_block2.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
configtxlator proto_decode --input config_block2.pb --type common.Block | jq .data.data[0].payload.data.config > config2.json
vim config2.json

Next, I don’t provide further steps to verify, let’s try yourself as a practice.


Thanks! If you like my stories, please follow me for new updates!