Fabric Network Extensibility

Dinesh Rivankar
5 min readNov 30, 2019

--

Application extensibility is a software principle for further growth of the application. Growth can be in terms of adding new functionality or to enhance the existing. In blockchain, extensibility is not limited to adding new rules to the smart contract but also need to accommodate network growth. Network growth can be a little tricky and need to have a good governance model associated with it. Initially the network might consist of few organizations, however, there should be provision where one organization can leave or join the business network.

Hyperledger Fabric allows us to add multiple peers to any given organization, this makes it unique and can be used to achieve high availability. Till now adding or removing organization was the top consideration in terms of network growth, but peer becomes a wise candidate. Let’s focus on adding new peer and organization to the existing network.

For exploration we will be using the below GitHub repository.

git clone https://github.com/dineshrivankar/fabric-network-extensibility.git

For network setup follow the instruction on https://github.com/dineshrivankar/fabric-network-extensibility/blob/master/docs/network-setup.md

Adding new peers to existing organization on network is a simple process. First, we need to create new crypto material by extending the current material for organization. Secondly, deploy the new peer with newly created crypto material and join the existing channels.

# Step 1

After successfully deploying the network, edit the “crypto-config.yaml” file from the root directory to add new peer. Change Org1 template count to 3

- Name: Org1
Domain: org1.example.com
EnableNodeOUs: false
Template:
Count: 3
Users:
Count: 1

# Step 2

Generate crypto material for new peer by using the “cryptogen extend parameter.

cryptogen extend --config=crypto-config.yaml

# Step 3

Copy new crypto material to standard place for deploying docker container.

# Step 4

Join new peer to existing channel on the network.

# Step 5

Testing time!!! Compare the block height on old peers and new peer.

# ------------------------------------------------------------------
# Check block height on old Peer (Peer0)
# ------------------------------------------------------------------
[channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
Blockchain info: {"height":5,"currentBlockHash":"VOj7s0h6YA78R1pkLnipEIpTFKl793Mb2RjrAALiZBg=","previousBlockHash":"7YFlyn+CxvONFUyOo4Tu3YD7CQGWTMbZFIDmWHkkcm0="}
# ------------------------------------------------------------------
# Check block height on new Peer (Peer2)
# ------------------------------------------------------------------
[channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
Blockchain info: {"height":5,"currentBlockHash":"VOj7s0h6YA78R1pkLnipEIpTFKl793Mb2RjrAALiZBg=","previousBlockHash":"7YFlyn+CxvONFUyOo4Tu3YD7CQGWTMbZFIDmWHkkcm0="}

Run the “add-new-peer.sh” script to perform all the above actions.

./add-new-peer.sh

Adding new peer is simple as it dose not include any modification to the channel configuration.

Adding new organization is bit long process and involves multiple steps, below script will automate everything.

cd new-org/
./deploy.sh

Script explanation

# Step 1

Generate crypto material for new organization.

cryptogen extend --config=crypto-config.yaml

# Step 2

Print new Org specific configuration material in JSON file (org3.json)

configtxgen -printOrg Org3MSP > org3.json

# Step 3

Update the network to include new org configuration.

a) Fetch the latest configuration block from ledger (config_block.pb)

docker exec "$CLI_NAME" peer channel fetch config config_block.pb -o "$ORDERER_NAME":7050 --tls --cafile $ORDERER_CA_LOCATION -c $CHANNEL_NAME

b) Convert the “config_block.pb” from protobuf to JSON (config.json) and remove extra headers from the JSON.

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

c) Add the new org crypto material to new JSON (config.json + org3.json = modified_config.json). Note that we are using jq tool for filtering JSON data.

jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json org3.json > modified_config.json

d) Translate config.json back into a protobuf (config.pb)

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

e) Encode modified_config.json to modified_config.pb (modified_config.pb)

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

f) Calculate the delta between these two config protobufs (config.pb + modified_config.pb = org3_update.pb)

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

g) Decode this object into editable JSON (org3_update.json)

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

h) Wrap org3 update.json in an envelope message (org3_update_in_envelope.json).Add header field that we stripped away earlier.

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

i) Convert org3_update_in envelope.json into the fully fledged protobuf format (org3_update_in_envelope.json)

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

j) Org 1 & Org 2 will sign and submit the configuration update

docker exec "$CLI_NAME" peer channel signconfigtx -f org3_update_in_envelope.pb

# Step 4

Deploy new organization peers and join the existing channel.

# Step 5

Perform chaincode operation by installing new version of chaincode and upgrade endorsement policy to include new org.

Adding new organization to a given channel requires to install new version of the chaincode with change in the endorsement policy to include new organization.

Removing organization from the network follows the similar steps like adding new organization. The only change here is no extra crypto material is required. Below is the automated script.

cd remove-org/
./remove-org.sh

Script explanation

# Step 1

Update the network to remove new org.

a) Fetch the latest configuration block from ledger (config_block.pb)

docker exec "$CLI_NAME" peer channel fetch config config_block.pb -o "$ORDERER_NAME":7050 --tls --cafile $ORDERER_CA_LOCATION -c $CHANNEL_NAME

b) Convert the “config_block.pb” from protobuf to JSON (config.json), remove extra headers from the JSON.

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

c) Remove org crypto material from JSON (config.json = modified_config.json)

jq 'del(.channel_group.groups.Application.groups.Org3MSP)' config.json > modified_config.json

d) Translate config.json back into a protobuf (config.pb)

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

e) Encode modified_config.json to modified_config.pb (modified_config.pb)

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

f) Calculate the delta between these two config protobufs (config.pb + modified_config.pb = update.pb)

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

g) Decode this object into editable JSON (update.json)

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

h) Wrap update.json in an envelope message (update_in_envelope.json).Add header field that we stripped away earlier.

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

i) Convert update_in_envelope.json into the fully fledged protobuf format (update_in_envelope.json)

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

j) Org 1 & Org 2 will sign and submit the configuration update

docker exec "$CLI_NAME" peer channel signconfigtx -f update_in_envelope.pb

# Step 2

Perform chaincode operation by installing new version of chaincode and upgrade endorsement policy to remove new org.

After removing the organization for the existing channel, we can still query the chaincode(if containers are active), however the data received by the peer is old and there will be no further updates.

# ------------------------------------------------------------------
# Invoking chaincode : Move 10 from A to B (A=80,B=220)
# ------------------------------------------------------------------
[chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
# ------------------------------------------------------------------
# Query chaincode: Query A
# ------------------------------------------------------------------
70
# ------------------------------------------------------------------
# Query chaincode from org3: Query A - will fetch old value
# ------------------------------------------------------------------
80

# Step 3

Remove organization peers container.

docker stack rm org3

That’s it!!

Feel free to shout out for any suggestions or improvements.
Happy Learning !!!

--

--

Dinesh Rivankar

Architect, Blockchain Innovation Group. #TOGAF #ConfidentialComputing #Corda #Hyperledger #SmartContract