Modern Approach to Smart Contracts with Hyperledger Fabric 2.0
Hyperledger fabric has become one of the top choices for enterprise to built Blockchain solutions and has come a long way with its own evolution to build strong and smart system
With the recent 2.0 release Hyperledger fabric has raised the bar again for Blockchain systems out there, as it delivers important new features and changes for users and operators.
Fabric v2.0 includes support for new application and privacy patterns, enhanced governance around smart contracts, and new options for operating nodes. With Alpine based docker images, fabric images got much smaller, providing faster download and startup times, as well as taking up less disk space on host systems
One of the major modifications and exciting feature to this change is Chaincode lifecycle. Fabric v2.0 introduced decentralized governance for smart contracts, with a new process for installing a chaincode on your peers and starting it on a channel
In the earlier releases 1.x versions of Fabric, one organization had the ability to set parameters of a chaincode (for instance the endorsement policy) for all other channel members while instantiating chaincode, while others only had the choice to refuse to install the chaincode and therefore not take part in transactions invoking it. The new Fabric chaincode lifecycle is a process that allows multiple organizations to agree on how a chaincode will be operated before it can be used on a channel. It is more flexible since it supports both centralized trust models (such as that of the previous lifecycle model) as well as decentralized models requiring a sufficient number of organizations to agree on an endorsement policy and other details before the chaincode becomes active on a channel.
So today in this article we are going to look at the new method of deploying chaincode on a Hyperledger fabric network
To start with I am already running a byfn network with channel and anchor peers in place
So in this article we will start with the steps to install and define a chaincode on our network
With the new approach to chaincode deployment the members of the channel need to agree on a chaincode definition that establishes chaincode governance and for that we need to package the chaincode before it can be installed on our peers. For each package we create, you need to provide a chaincode package label as a description of the chaincode
Step 1: Packaging, before packaging Golang chaincode, vendoring Go dependencies is required for which we will get into the chaincode folder
cd /opt/gopath/src/github.com/hyperledger/fabric-samples/chaincode/abstore/go
GO111MODULE=on go mod vendor
GO111MODULE would handle all the packaging and dependency of our chaincode
Now lets get back to our previous directory with “cd -” and run below command
peer lifecycle chaincode package mycc.tar.gz --path github.com/hyperledger/fabric-samples/chaincode/abstore/go/ --lang golang --label mycc_1
This would package our Golang chaincode and will create a chaincode package named mycc.tar.gz, which we can use to install the chaincode on our peers
Step 2: Installing chaincode, Next we would install chaincode on peer0 of Org1 as it’s environment variables are set default in our cli
“peer lifecycle chaincode install mycc.tar.gz”
Response:
2020-02-19 12:43:18.379 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nGmycc_1:4299989154fdb5067fe54d92922003ff6281201e1a39916a9c3bfbddbf7fd3a7\022\006mycc_1" >2020-02-19 12:43:18.379 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: mycc_1:4299989154fdb5067fe54d92922003ff6281201e1a39916a9c3bfbddbf7fd3a7
The installation of chaincode on a peer would respond back with package identifier for our installed chaincode, in case missed you can also retrieve the package identifier with below command
peer lifecycle chaincode queryinstalled
“mycc_1:4299989154fdb5067fe54d92922003ff6281201e1a39916a9c3bfbddbf7fd3a7” is the package id generated for my chaincode, for you the value would something different so please make a note of it
Next, we are going to need this package ID in up coming steps so let’s store it in an environment variable using command:
CC_PACKAGE_ID=mycc_1:4299989154fdb5067fe54d92922003ff6281201e1a39916a9c3bfbddbf7fd3a7
Now let’s Install chaincode on other peers, we would set the peer environment variable for peer0 of Org2
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/mspCORE_PEER_ADDRESS=peer0.org2.example.com:9051CORE_PEER_LOCALMSPID="Org2MSP"CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
And then repeat the same command to install chaincode
Command:
peer lifecycle chaincode install mycc.tar.gz
Response:
bash-5.0# peer lifecycle chaincode install mycc.tar.gz2020-02-19 12:56:41.970 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nGmycc_1:4299989154fdb5067fe54d92922003ff6281201e1a39916a9c3bfbddbf7fd3a7\022\006mycc_1" >2020-02-19 12:56:41.970 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: mycc_1:4299989154fdb5067fe54d92922003ff6281201e1a39916a9c3bfbddbf7fd3a7
Note that the package identifier returned after this command is same as the package identifier obtained while installing chaincode on peer0 of Org1
Step 3: Approve Chaincode, After we install the package, Individual organizations are required to approve the chaincode definition that includes important parameters of chaincode governance like endorsement policy, chaincode name, version.
We’ll the below command for both peer0 of Org1 and peer0 of Org2, All organizations need to agree on the definition before they can use the chaincode
peer lifecycle chaincode approveformyorg --channelID $CHANNEL_NAME --name mycc --version 1.0 --init-required --package-id $CC_PACKAGE_ID --sequence 1 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
The approval is distributed to peers within each organization, so the command does not need to target every peer within an organization.
Step 4: Committing Chaincode, To proceed with enabling chaincode on a channel from Hyperledger fabric 2.0 instead of instantiating chaincode we have to commit chaincode and this is how it makes a difference
We can only commit a chaincode to a channel if sufficient number of channel members have approved a chaincode definition after which any one member can commit the definition to the channel.By default a majority of channel members need to approve a definition before it can be committed. We can also check approval status for a chaincode by issuing the following query:
peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name mycc --version 1.0 --init-required --sequence 1 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json
As we can see both the channel members have approved the chaincode we can proceed with committing it on the channel, again its a one time process so we can do it from either Org1 or Org2 peer
peer lifecycle chaincode commit -o orderer.example.com:7050 --channelID $CHANNEL_NAME --name mycc --version 1.0 --sequence 1 --init-required --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
As we see the commit is successful let's try interacting with the chaincode
Step 5: Invoking a chaincode
peer chaincode invoke -o orderer.example.com:7050 --isInit --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["Init","a","100","b","100"]}' --waitForEvent
This command will start the chaincode container
Now we’ll query the chaincode to make sure that the container was properly started and the state DB was populated. The syntax for query is as follows:
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
Now let’s move 10 from a to b with below command
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}' --waitForEvent
Let’s confirm that our previous invocation executed properly. We initialized the key a with a value of 100 and just removed 10 with our previous invocation. Therefore, a query against a should return 90. The syntax for query is as follows.
# be sure to set the -C and -n flags appropriately
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
We should see the following:
So this is how Hyperledger Fabric 2.0 has changed the way we set up chaincode/smart contracts on our Blockchain network, with an improved approach of approving and then hosting a chaincode it adds an additional layer of transparency and trust. Together with such continuous improvements and detailed process of setting Blockchain system Hyperledger fabric is really setting a mark for the digital era
Thanks for Reading :)