Extending Fabric 2 Test Network

bukhorimuhammad

Bukhori M. Aqid

Posted on June 25, 2020

Extending Fabric 2 Test Network

What is Fabric 2
Hyperledger Fabric is a private blockchain platform that enables you to create permissioned blockchain network. The main elements in Hyperledger Fabric are:

  • Peer & Organization: Peer node hosts and execute ledger transactions and smart contracts. Peer belongs to Organization. Some peers can be endorsing peers.
  • Orderer: Orderer provides ordering service (packages transactions into blocks to be delivered to peers on a channel).
  • Channel: Channel are logical structure formed by collection of peers.
  • Chaincode / Smart Contract: Smart Contract is software that defines the business logic, contains assets and related transactions. Hyperledger Fabric smart contracts are called chaincode and may specify an endorsement policy which defines transaction validity.

The approach that is taken by Hyperledger Fabric (in my opinion) is beneficial for industrial use cases because it enables cooperation between organization (using channels) while to certain extent having a privacy inside the organization.

To explore the capabilities of Fabric, there are some examples provided that serves certain use cases. For a simple introduction, there are 2 examples that should be used: First Network and Test Network. Due to a major upgrade in Hyperledger Fabric, there are 2 major versions available 1.4.x and 2.x.x - First Network is suitable if you want to learn Fabric 1.4.x but Test Network would be preferable for Fabric 2.x.x. Also good to know that Test Network is a replacement for First Network so you should use that whenever possible.

The striking difference between First Network and Test Network is the number of nodes. First Networks comes with 2 peers for each organization, and 5 orderers while Test Network only comes with 1 peer per organization and 1 orderer. This might be limited for some scenario that you want to run. This article will help you extend the test network with some helpful bash scripts. The underlying assumption is that you already have a Test Network running with command ./network.sh up createChannel && ./network.sh deployCC

TL;DR

To extend Test Network, we need to extend fabric key with cryptogen, update system-channel definition, compose orderer nodes, compose peer nodes, join application channel and deploy the chaincode. For an easy setup, clone this repository and run ./extend-network.sh after setting up your local Test Network. Or to make things easier, just run ./setup-fabric-extended.sh that will setup local Test Network as well as extends it.


Extending Fabric Key
Before extending the network, we need to generate all the necessary key for each new orderer and peer that we want to create. The easiest way to do that is by using cryptogen command. cryptogen is an utility for generating Hyperledger Fabric key material. It is provided as a means of preconfiguring a network for testing purposes. It would normally not be used in the operation of a production network.

cryptogen extend --config=crypto-config.yaml --input="organizations"
Enter fullscreen mode Exit fullscreen mode

The --config parameter should point to the new network configuration, not the existing test network configuration. In this case, we want a total of 3 orderers, with 3 peers for each organization.

OrdererOrgs:
- Name: Orderer
  Domain: example.com
  EnableNodeOUs: true

  Specs:
    - Hostname: orderer
    - Hostname: orderer1
    - Hostname: orderer2

PeerOrgs:
- Name: Org1
  Domain: org1.example.com
  EnableNodeOUs: true

  Template:
      Count: 3
      SANS:
        - localhost
  Users:
      Count: 1

- Name: Org2
  Domain: org2.example.com
  EnableNodeOUs: true

  Template:
      Count: 3
      SANS:
        - localhost
  Users:
      Count: 1
Enter fullscreen mode Exit fullscreen mode

Extending Test Network Orderer
First, we need to update system-channel configuration so that we can run new orderer node. The steps needed to update system-channel are as follows:

  1. Fetch (and decode) latest configuration
  2. Add new orderer certificate generated by cryptogen to orderer consenters and modify the configuration
  3. Apply the change to blockchain

To fetch and decode latest configuration, we need to execute:

peer channel fetch config ./out/config_block.pb -o $ORDERER_ADDRESS -c $2 --tls --cafile $TLS_ROOT_CA

configtxlator proto_decode --input ./out/config_block.pb --type common.Block --output ./out/config_block.json

jq .data.data[0].payload.data.config ./out/config_block.json > ./out/config.json
Enter fullscreen mode Exit fullscreen mode

The commands above will get the latest config and store the result in out folder. The default orderer address is export ORDERER_ADDRESS=localhost:7050 and the TLS_ROOT_CAshould be test-network/organizations/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem

Next is adding new orderer certificate to the new configuration. We can achieve that by executing commands below:

# add new orderer certificate
echo "{\"client_tls_cert\":\"$(cat $ORDERER_TLS | base64 -w 0)\",\"host\":\"orderer$1.example.com\",\"port\":7$150,\"server_tls_cert\":\"$(cat $ORDERER_TLS | base64 -w 0)\"}" > $PWD/out/ord$1consenter.json

jq ".channel_group.groups.Orderer.values.ConsensusType.value.metadata.consenters += [$(cat ./out/ord$1consenter.json)]" ./out/config.json > ./out/modified_config.json

# calculate config differences
configtxlator proto_encode --input ./out/config.json --type common.Config --output ./out/config.pb

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

configtxlator compute_update --channel_id $2 --original ./out/config.pb --updated ./out/modified_config.pb --output ./out/config_update.pb
Enter fullscreen mode Exit fullscreen mode

$1 refers to our orderer address, $2 refer to channel name (system-channel) and $ORDERER_TLS should refer to TLS certificate for the corresponding orderer.

The final step before starting the node is applying the changes via update transaction

# "applying changes"
configtxlator proto_decode --input ./out/config_update.pb --type common.ConfigUpdate --output ./out/config_update.json

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

configtxlator proto_encode --input ./out/config_update_in_envelope.json --type common.Envelope --output ./out/config_update_in_envelope.pb

# "submit update transaction"
peer channel update -f ./out/config_update_in_envelope.pb -c $2 -o $ORDERER_ADDRESS --tls --cafile $TLS_ROOT_CA
Enter fullscreen mode Exit fullscreen mode

The final step is actually creating and running the orderer node. The easiest way is to use docker compose and add the service definition below

  orderer1.example.com:
    container_name: orderer1.example.com
    extends: 
      file: orderer-base.yaml
      service: orderer-base
    environment: 
      - ORDERER_GENERAL_LISTENPORT=7150
    volumes:
      - ${FABRIC_SAMPLES_DIR}/test-network/system-genesis-block/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
      - ${FABRIC_SAMPLES_DIR}/test-network/organizations/ordererOrganizations/example.com/orderers/orderer1.example.com/msp:/var/hyperledger/orderer/msp
      - ${FABRIC_SAMPLES_DIR}/test-network/organizations/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/:/var/hyperledger/orderer/tls
      - orderer1.example.com:/var/hyperledger/production/orderer
    ports:
      - 7150:7150
Enter fullscreen mode Exit fullscreen mode

with orderer-base.yaml defined below

version: '2'

services:
  orderer-base:
      image: hyperledger/fabric-orderer:$IMAGE_TAG
      environment:
        - FABRIC_LOGGING_SPEC=INFO
        - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
        - ORDERER_GENERAL_GENESISMETHOD=file
        - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
        - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
        - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
        # enabled TLS
        - ORDERER_GENERAL_TLS_ENABLED=true
        - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
        - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
        - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
        - ORDERER_KAFKA_TOPIC_REPLICATIONFACTOR=1
        - ORDERER_KAFKA_VERBOSE=true
        - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
        - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
        - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
      working_dir: /opt/gopath/src/github.com/hyperledger/fabric
      command: orderer
      networks:
        - net_test # docker network for Test Network
Enter fullscreen mode Exit fullscreen mode

Extending Test Network Peer
Extending peer node is easier. After you've generated all the required key, you can directly compose the node. One of the sample configuration for your node container is given below

  peer1.org1.example.com:
    container_name: peer1.org1.example.com
    extends:
      file: peer-base.yaml
      service: peer-base
    environment:
      # Peer specific variabes
      - CORE_PEER_ID=peer1.org1.example.com
      - CORE_PEER_ADDRESS=peer1.org1.example.com:7151
      - CORE_PEER_LISTENADDRESS=0.0.0.0:7151
      - CORE_PEER_CHAINCODEADDRESS=peer1.org1.example.com:7152
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7152
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:7151
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:7151
      - CORE_PEER_LOCALMSPID=Org1MSP
    volumes:
      - /var/run/:/host/var/run/
      - ${FABRIC_SAMPLES_DIR}/test-network/organizations/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/fabric/msp
      - ${FABRIC_SAMPLES_DIR}/test-network/organizations/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls:/etc/hyperledger/fabric/tls
      - peer1.org1.example.com:/var/hyperledger/production
    ports:
      - 7151:7151
Enter fullscreen mode Exit fullscreen mode

with peer-base.yaml defined below

version: '2'

services:
    peer-base:
        image: hyperledger/fabric-peer:$IMAGE_TAG
        environment:
            # Generic peer variables
            - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
            - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_test
            - FABRIC_LOGGING_SPEC=WARN:cauthdsl=info:policies=debug:msp=info
            - CORE_PEER_TLS_ENABLED=true
            - CORE_PEER_GOSSIP_USELEADERELECTION=true
            - CORE_PEER_GOSSIP_ORGLEADER=false
            - CORE_PEER_PROFILE_ENABLED=true
            - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
            - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
            - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
        working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
        command: peer node start
        networks:
            - net_test # docker network for Test Network
Enter fullscreen mode Exit fullscreen mode

That's basically it. Make sure that all certificates and keys are pointing in the correct and existing folder and you're good to go.

Enjoy your new network!

💖 💪 🙅 🚩
bukhorimuhammad
Bukhori M. Aqid

Posted on June 25, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Extending Fabric 2 Test Network
blockchain Extending Fabric 2 Test Network

June 25, 2020