What is Hyperledger
"Hyperledger Fabric is a modular blockchain framework that acts as a foundation for developing blockchain-based products using plug-and-play components that are aimed for use within private enterprises" - Investopedia
Why Hyperledger
While you may have heard of ethereum, polygon and solana being commonly used for blockchain development, these are public blockchains. As public blockchains, all the code, data and activities are available for anyone to access. For large companies like Walmart, a lot of whose code is IP and not publicly available, this maybe a problem.
Hyperledger allows large enterprises to set up their own copy of the blockchain whether its for just collaboration within a team, within a company or across a fixed set of companies. This gives them more control on their processes within the blockchain.
Several other benefits of Hyperledger are:
- Privacy: Hyperledger fabric is a permissioned, private blockchain where organizations can cooperate with other authorized organizations while sharing resources, away from the public view.
- Modularity and Reusability: Everything a developer builds on Fabric is reusable.
- Scalability: Thanks to the plug-and-play approach, scaling an application becomes a delight.
- Support and Credibility: Hyperledger is built under the Linux Foundation, One of the most well-respected communities of developers, and comes with extensive, well-written documentation.
An example of a practical use case: "A B2B Contract"
Suppose business A wants a service from business B, then there is a requirement for a contract to be agreed upon by both the parties. The businesses can join a channel on the fabric network, deploy a chain code that both agree upon, and automate the contract.
Since the blockchain is permissioned, only the two businesses involved can see the contract and interact with it. At the same time, no third party has access to any sensitive/private business information shared over the blockchain.
Installation Steps
In this blog, we will install Hyperledger Fabric on macOS along with Fabric Samples.
Channel is a private 'subnet' of communication between two or more specific network members. Think of it as a private group on the network.
Chaincode is a program, written in Go, node.js, or Java that runs in a secured Docker container on the network. It manages the ledger and implements business logic.
We will be using fabric-samples/test-network scripts and doing the following:
- Create a test network.
- Create two example orgs on this test-network.
- Create a channel and have the two orgs join it.
- Deploy a chaincode onto the channel after both the orgs approve it.
Step 1: Install pre-requisites.
Homebrew
Install the latest version of Homebrew:
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Along with Homebrew installation, Xcode cli tools are installed (if not already installed).
Ensure Homebrew is installed:
$ brew --version
Homebrew 3.3.12
Homebrew/homebrew-core (git revision b81bc29e8a1; last commit 2022-01-24)
Homebrew/homebrew-cask (git revision 7792a6e065; last commit 2022-01-24)
Git
Install the latest version of Git
$ brew install git
Ensure Git is installed:
$ git --version
git version 2.35.1
cURL
Install the latest version of cURL:
$ brew install curl
Ensure cURL is installed:
$ curl --version
curl 7.64.1 (x86_64-apple-darwin20.0) libcurl/7.64.1 (SecureTransport) LibreSSL/2.8.3 zlib/1.2.11 nghttp2/1.41.0
Release-Date: 2019-03-27
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS GSS-API HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM NTLM_WB SPNEGO SSL UnixSockets
Docker
Download docker desktop from here
Ensure docker and docker-compose is installed:
$ docker --version
Docker version 20.10.12, build e91ed57
$ docker-compose --version
Docker Compose version v2.2.3
Go
(for Go chaincode or SDK applications)
Install the latest supported version of go:
$ brew install go@1.17.5
Ensure go is installed:
$ go version
go1.17.5 darwin/amd64
JQ
(for channel configuration transactions)
Install the latest version of jq:
$ brew install jq
Ensure jq is installed:
$ jq --version
jq-1.6
Step 2: Install Fabric and Fabric Samples
Download fabric samples, docker images, and binaries
Make a directory to clone the fabric samples to and cd into it:
$ mkdir -p $HOME/go/src/hyperledger && cd $HOME/go/src/hyperledger
Download the latest version of fabric samples, docker images and binaries:
$ curl -sSL https://bit.ly/2ysbOFE | bash -s
Step 3: Run a test network
Bring up the network along with two example orgs
cd into the test-network
directory containing the main network.sh
script:
$ cd fabric-samples/test-network
run the following command to bring up a fresh test-network:
$ ./network.sh down && ./network.sh up
run the following command to see the running docker-containers:
$ docker ps -a
You should see 4 containers with the following names:
hyperledger/fabric-tools:latest
: 1 container
hyperledger/fabric-orderer:latest
: 1 container
hyperledger/fabric-peer:latest
: 2 containers
Create a channel and have the two example orgs join it
$ ./network.sh createChannel
You should see the following message at the end of the output:
Channel 'mychannel' joined
Step 4: Deploy a smart contract on the
network
Package the smart contract
Firstly we want to package our go lang smart contract code into a binary file to deploy it onto the network.
Go to the folder containing the golang Chaincode and install golang dependencies there, then return to the current directory:
$ cd ../chaincode/fabcar/go && GO111MODULE=on go mod vendor && cd ../../../test-network
Now add the following variables to your cli:
$ export PATH=${PWD}/../bin:${PWD}:$PATH
$ export FABRIC_CFG_PATH=$PWD/../config/
Finally, create the package for the smart contract:
$ peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/go/ --lang golang --label fabcar_1
Run the following command to ensure that the package has been created:
$ ls | grep fabcar.tar.gz
fabcar.tar.gz
Install the chaincode package on both the orgs
First, let's take up the role of org 1:
$ export CORE_PEER_TLS_ENABLED=true
$ export CORE_PEER_LOCALMSPID="Org1MSP"
$ export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
$ export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
$ export CORE_PEER_ADDRESS=localhost:7051
Install the chaincode onto the peer (org1):
$ peer lifecycle chaincode install fabcar.tar.gz
Next, let's take up the role of org 2:
$ export CORE_PEER_LOCALMSPID="Org2MSP"
$ export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
$ export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
$ export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
$ export CORE_PEER_ADDRESS=localhost:9051
Install the chaincode onto the peer (org2):
$ peer lifecycle chaincode install fabcar.tar.gz
Approve the chaincode on both the orgs
First, let's take up the role of org 1:
$ export CORE_PEER_TLS_ENABLED=true
$ export CORE_PEER_LOCALMSPID="Org1MSP"
$ export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
$ export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
$ export CORE_PEER_ADDRESS=localhost:7051
Ensure that the chaincode is installed on org1:
$ peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: fabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276, Label: fabcar_1
Copy the Package ID from the result in the previous command, and set the following variable equal to it:
$ CC_PACKAGE_ID=fabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276
Approve the chaincode for org1:
$ peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
Next, let's take up the role of org 2:
$ export CORE_PEER_LOCALMSPID="Org2MSP"
$ export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
$ export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
$ export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
$ export CORE_PEER_ADDRESS=localhost:9051
Ensure that the chaincode is installed onto org 2:
$ peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: fabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276, Label: fabcar_1
Copy the Package ID from the result in the previous command, and set the following variable equal to it:
$ CC_PACKAGE_ID=fabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276
Now approve the chaincode for org2:
$ peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
Commit the chaincode to the channel
Check if the chaincode is ready to be committed:
$ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --version 1.0 --sequence 1 --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json
{
"approvals": {
"Org1MSP": true,
"Org2MSP": true
}
}
As you can see, both the orgs have approved the chaincode. Hence, it is ready to be committed to the channel.
Commit the chaincode to the channel:
$ peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --sequence 1 --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
Check if the chaincode is committed:
$ peer lifecycle chaincode querycommitted --channelID mychannel --name fabcar --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
Committed chaincode definition for chaincode 'fabcar' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Invoke the chaincode
Now that we have committed the chaincode onto the channel, finally it's time to have some fun!
Let's invoke various functions of the committed chaincode:
Call the queryAllCars
function:
$ peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'
[]
As we can see by the empty array, there are no cars onto the ledger, so let's try adding some.
Call the initLedger
function:
$ peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n fabcar --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"initLedger","Args":[]}'
This should add some cars to the ledger, let's check it by querying all cars again.
Call the queryAllCars
function:
$ peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'
[{"Key":"CAR0","Record":{"make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}},{"Key":"CAR1","Record":{"make":"Ford","model":"Mustang","colour":"red","owner":"Brad"}},{"Key":"CAR2","Record":{"make":"Hyundai","model":"Tucson","colour":"green","owner":"Jin Soo"}},{"Key":"CAR3","Record":{"make":"Volkswagen","model":"Passat","colour":"yellow","owner":"Max"}},{"Key":"CAR4","Record":{"make":"Tesla","model":"S","colour":"black","owner":"Adriana"}},{"Key":"CAR5","Record":{"make":"Peugeot","model":"205","colour":"purple","owner":"Michel"}},{"Key":"CAR6","Record":{"make":"Chery","model":"S22L","colour":"white","owner":"Aarav"}},{"Key":"CAR7","Record":{"make":"Fiat","model":"Punto","colour":"violet","owner":"Pari"}},{"Key":"CAR8","Record":{"make":"Tata","model":"Nano","colour":"indigo","owner":"Valeria"}},{"Key":"CAR9","Record":{"make":"Holden","model":"Barina","colour":"brown","owner":"Shotaro"}}]
As we can see, the cars were added to the ledger which confirms that our smart contract (Chaincode) is working!
That's it for this tutorial! You can check out more functions in the Chaincode by heading over to ../chaincode/fabcar/go/fabar.go
and try invoking/querying them.
Make sure to run $ ./network.sh down
to kill any containers related to fabric samples once you are done.
Thanks for reading!
-This article was written by Smith Pereira, Software Developer at DisruptX
Top comments (0)