With the new release of Hyperledger Fabric 2.0 the lifecycle of chaincode has been changed. It implies also the changes in the chaincode deployment process – what basically means that commands used to deploy chaincode in < 2.0 release (no matter if using peer
binary or SDK) will not work.
In this article I show how to deploy chaincode to the Hyperledger Fabric 2.0.
Channel configuration changes
One of the most important changes of chaincode lifecycle in the Fabric 2.0 is that the rights to chaincode operations are now encoded in channel definition. In the most basic scenario, the change included in the configtx.yaml
indicates who has the right to endorse the chaincode changes. Fabric 2.0 ACL can specify the rights to even single blockchain operations (like querying peer if chaincode exists). We will not focus on the customization but only highlight the minimum change.
Hyperledger Fabric 2.0 chaincode deployment steps
Here are the steps in order to succeed with chaincode deployment in Hyperledger Fabric 2.0
1. Upgrade all the docker images
Upgrade the docker images tags to given values:
- peer, orderer, fabric-tools: 2.0.0 (I assume that you use Raft orderer, in case of Kafka search for the newest Kafka and Zookeeper tags)
- couch: 0.4.18
- CA: 1.4.4 (however this articles doesn’t focus on CA)
2. Update configtx.yaml
I assume you setup fresh Fabric setup otherwise you will have to update blockchain configuration rather than setup it from scratch (updating the configtx.yaml
file will allow to generate fresh blockchain configuration). Here is the change which must be done in configtx.yaml in order to apply to new 2.0 specification:
- For every organization add the
Endorsement
section in thePolicies
section with the signature of organization peer. Lack of this entry will for example not allow you to install chaincode with private collections. At least from the tests I’ve done so far, not required for orderer organization. Example:
- &Org1 Name: Org1MSP ID: Org1MSP MSPDir: crypto-config/peerOrganizations/org1/msp Policies: Readers: Type: Signature Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')" Writers: Type: Signature Rule: "OR('Org1MSP.admin', 'Org1MSP.client')" Admins: Type: Signature Rule: "OR('Org1MSP.admin')" Endorsement: Type: Signature Rule: "OR('Org1MSP.peer')" AnchorPeers: - Host: org1-peer0 Port: 7051
- Your capabilities section should look like below:
Capabilities: Channel: &ChannelCapabilities V2_0: true Orderer: &OrdererCapabilities V2_0: true Application: &ApplicationCapabilities V2_0: true
- Your application section should have added 2 new sections
LifecycleEndorsement
andEndorsement
, except the existingReaders
,Writers
,Admins
. Here below is the example section which is not very restrictive (means that every organization can apply the chaincode change). Please align it to your need:
Application: &ApplicationDefaults Organizations: Policies: Readers: Type: ImplicitMeta Rule: "ANY Readers" Writers: Type: ImplicitMeta Rule: "ANY Writers" Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" LifecycleEndorsement: Type: ImplicitMeta Rule: "ANY Endorsement" Endorsement: Type: ImplicitMeta Rule: "ANY Endorsement" Capabilities: <<: *ApplicationCapabilities
3. Regenerate configuration
The configuration must be regenerated (need new genesis block) – use configtxgen
tool. You can also regenerate crypto-config
with cryptogen
tool if you want and can but it’s not necessary. Run the blockchain with new genesis block, then also recreate your channel with channel transaction.
3. Prepare chaincode deployment container and script
This assumes you load the chaincode using fabric-tools
docker image container which has all the keys and environment vars setup. If you was using your cli before upgrade to 2.0 for chaincode deployment you can use this image, just add there the setupchaincode.sh
script and your chaincode sources with appropriate path mapping (volumes section in docker compose file definition, take a look on following docker compose file example).
This is minimal container settings for the one I use. It requires you to set your local chaincode path (on local machine). This is the file content (don’t invoke it yet, it requires you to have also the chaincode deployment setupchaincode.sh
script):
# Copyright IBM Corp. All Rights Reserved. # # SPDX-License-Identifier: Apache-2.0 # version: '2' networks: byfn: services: chaincode-deployer: container_name: chaincode-deployer image: hyperledger/fabric-tools:$IMAGE_TAG tty: true stdin_open: true environment: - GOPATH=/opt/gopath - FABRIC_LOGGING_SPEC=DEBUG working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer command: /opt/gopath/src/github.com/hyperledger/fabric/peer/setupchaincode.sh && /bin/bash volumes: # Change your local chaincode path!!! # If you change the location in container also remember to change in setupchaincode.sh - ./your/local/chaincode/path:/opt/gopath/src/github.com/chaincode/examplechaincode # Change according to your paths - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ - ./setupchaincode.sh:/opt/gopath/src/github.com/hyperledger/fabric/peer/setupchaincode.sh networks: - byfn ports: - 15050:15050
This is the setupchaincode.sh
script which does the work of chaincode deployment. Configure all the variables according to your configuration:
#!/usr/bin/env bash ## MUST BE CHANGED EVERY BUILD CHAINCODE_VERSION=1.0 ## Chaincode info - CONFIGURE ONCE CHAINCODE_LANG=node CHAINCODE_NAME=examplechaincode CHAINCODE_INIT_ARGS='{"Args":[]}' CHAINCODE_LABEL=${CHAINCODE_NAME}_${CHAINCODE_VERSION} CHAINCODE_PACKAGE_NAME=${CHAINCODE_LABEL}.tar.gz # Source path in the cli container CHAINCODE_SOURCE_PATH=/opt/gopath/src/github.com/chaincode/examplechaincode # Other info - CONFIGURE ONCE CHANNEL_NAME=mychannel ORDERER=orderer.org1.fabric ORDERER_ADDRESS=${ORDERER}:7050 ORDERER_CA_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/org1.fabric/orderers/orderer.org1.fabric/msp/tlscacerts/tlsca.org1.fabric-cert.pem export CORE_PEER_ADDRESS=peer0.org1.fabric:7051 export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ENABLED=true export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric/peers/peer0.org1.fabric/tls/server.crt export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric/peers/peer0.org1.fabric/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric/users/Admin@org1.fabric/msp # Dont change anything below, should work fine installChaincode() { PEER_ADDRESS=$1 PEER_CERT_PATH=$2 SEQUENCE=$3 echo 'Installing chaincode on peer: ' $PEER_ADDRESS peer lifecycle chaincode install $CHAINCODE_PACKAGE_NAME >&install-log.txt PACKAGE_ID=$(awk '{for(i=1;i<=NF;i++)if($i=="identifier:")print $(i+1)}' install-log.txt) peer lifecycle chaincode approveformyorg -o $ORDERER_ADDRESS --tls --cafile $ORDERER_CA_FILE --channelID $CHANNEL_NAME --name $CHAINCODE_NAME --version $CHAINCODE_VERSION --init-required --package-id $PACKAGE_ID --waitForEvent --sequence $SEQUENCE peer lifecycle chaincode commit -o $ORDERER_ADDRESS --tls --cafile $ORDERER_CA_FILE --channelID $CHANNEL_NAME --name $CHAINCODE_NAME --version $CHAINCODE_VERSION --sequence $SEQUENCE --init-required peer chaincode invoke -o $ORDERER_ADDRESS --tls --cafile $ORDERER_CA_FILE --ordererTLSHostnameOverride $ORDERER -C $CHANNEL_NAME -n $CHAINCODE_NAME --peerAddresses $PEER_ADDRESS --isInit -c $CHAINCODE_INIT_ARGS --tlsRootCertFiles $PEER_CERT_PATH echo 'Finished installing chaincode on peer: ' $PEER_ADDRESS } # Generate chaincode package - common step peer lifecycle chaincode package $CHAINCODE_PACKAGE_NAME --path $CHAINCODE_SOURCE_PATH --lang $CHAINCODE_LANG --label $CHAINCODE_LABEL # Get sequence value peer lifecycle chaincode querycommitted --channelID $CHANNEL_NAME >&sequence.txt seq=$(awk '{for(i=1;i<=NF;i++)if($i=="Sequence:")print $(i+1)}' sequence.txt) SEQUENCE=$(echo "${seq//,}") if [ -z $SEQUENCE ] ; then SEQUENCE=1 echo 'No sequence yet, initializing with 1, got: '$SEQUENCE else SEQUENCE=$(($SEQUENCE + 1)) echo 'Incrementing sequence by 1, got: '$SEQUENCE fi installChaincode $CORE_PEER_ADDRESS $CORE_PEER_TLS_ROOTCERT_FILE $SEQUENCE
4. Deploy chaincode
Prepare folder and put there:
- docker compose file for running
fabric-tools
deployment container (I’ve gave example content, please configure for your needs) - current crypto-config
- setupchaincode.sh (please configure it for your needs)
You can run it with:
docker-compose -f chaincode-deployer.yaml up
The script should install chaincode correctly only if you have the same non restrictive endorsement (single organization approval is enough to install chaincode). Otherwise you will have to repeat peer lifecycle chaincode approveformyorg
multiple times (and probably the steps before) before running peer lifecycle chaincode commit
.
Summary
Hyperledger Fabric is the permissioned blockchain which is very features rich especially allowing for very wide configuration. The new chaincode deployment model gives more flexibility in the definition of chaincode deployment permissions.
Have got any question? Feel free to ask in the comments.
Przemek