Blockchain — Hyperledger implementation
In this article, we will implement blockchain with two organizations set up with one orderer. We could notice all the ledger information in hyperledger explorer and interact with blockchain using Hyperledger composer rest server.
Implement Hyperledger fabric and Hyperledger Composer Business network archive.
In this section, we will set up two orgs Hyperledger with an orderer. We will create business network archive using hyperledger composer and deploy the network on blockchain. Follow below steps.
We will use Google Cloud Platform for proof of concept.
- Create compute engine with ubuntu version 16, 50 GB disk space and 1 cpu 12 GB Memory
- Log into VM SSH console.
- Prepare VM ready with blockchain pre requisites . This will set up node, npm, git, python , docker and docker-compose
curl -O https://hyperledger.github.io/composer/v0.19/prereqs-ubuntu.shchmod u+x prereqs-ubuntu.sh./prereqs-ubuntu.shlogout
You should notice following versions.
Installation completed, versions installed are:
Node: v8.16.0
npm: 6.4.1
Docker: Docker version 19.03.1, build 74b1e89e8a
Docker Compose: docker-compose version 1.13.0, build 1719ceb
Python: Python 2.7.12
4. Re login to SSH console and run following commands for installing Hyperledger composer
// Hyper ledger composer client that is needed to install the
// network, create network cards etc
npm install -g composer-cli@0.20// Hyperledger composer generator and yo will help in creating basic // code for code chain
npm install -g generator-hyperledger-composer@0.20npm install -g yo
5. Get Hyperledger fabric sample repository. We will be using hyperledger provided artifacts for creating multi org set up.
git clone --single-branch --branch multi-org https://github.com/mahoney1/fabric-samples.git
6. We should download all the hyperledger docker images and start docker containers.
cd fabric-samplescurl -sSL http://bit.ly/2ysbOFE | bash -s 1.2.1 1.2.1 0.4.10cd first-network./byfn.sh -m generate// Above command generate artifacts that are needed for generate../byfn.sh -m up -s couchdb -a
7. Observe the log and you will notice there are transactions happened with sample chaincode. If you would like to do more transactions with same chain code, you can try this
docker exec -it cli bash
for example:
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'peer chaincode query -C mychannel -n mycc -c '{"Args":["query","b"]}'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 mychannel -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:7051 --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","20"]}'peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'peer chaincode query -C mychannel -n mycc -c '{"Args":["query","b"]}'
8. Create temporary working directories
mkdir -p /tmp/composer/org1
mkdir -p /tmp/composer/org2
9. Copy below connection details to your favorite notepad.
{
"name": "byfn-network",
"x-type": "hlfv1",
"version": "1.0.0",
"client": {
"organization": "Org1",
"connection": {
"timeout": {
"peer": {
"endorser": "300",
"eventHub": "300",
"eventReg": "300"
},
"orderer": "300"
}
}
},
"channels": {
"mychannel": {
"orderers": [
"orderer.example.com"
],
"peers": {
"peer0.org1.example.com": {
"endorsingPeer": true,
"chaincodeQuery": true,
"eventSource": true
},
"peer1.org1.example.com": {
"endorsingPeer": true,
"chaincodeQuery": true,
"eventSource": true
},
"peer0.org2.example.com": {
"endorsingPeer": true,
"chaincodeQuery": true,
"eventSource": true
},
"peer1.org2.example.com": {
"endorsingPeer": true,
"chaincodeQuery": true,
"eventSource": true
}
}
}
},
"organizations": {
"Org1": {
"mspid": "Org1MSP",
"peers": [
"peer0.org1.example.com",
"peer1.org1.example.com"
],
"certificateAuthorities": [
"ca.org1.example.com"
]
},
"Org2": {
"mspid": "Org2MSP",
"peers": [
"peer0.org2.example.com",
"peer1.org2.example.com"
],
"certificateAuthorities": [
"ca.org2.example.com"
]
}
},
"orderers": {
"orderer.example.com": {
"url": "grpcs://localhost:7050",
"grpcOptions": {
"ssl-target-name-override": "orderer.example.com"
},
"tlsCACerts": {
"pem": "INSERT_ORDERER_CA_CERT"
}
}
},
"peers": {
"peer0.org1.example.com": {
"url": "grpcs://localhost:7051",
"grpcOptions": {
"ssl-target-name-override": "peer0.org1.example.com"
},
"tlsCACerts": {
"pem": "INSERT_ORG1_CA_CERT"
}
},
"peer1.org1.example.com": {
"url": "grpcs://localhost:8051",
"grpcOptions": {
"ssl-target-name-override": "peer1.org1.example.com"
},
"tlsCACerts": {
"pem": "INSERT_ORG1_CA_CERT"
}
},
"peer0.org2.example.com": {
"url": "grpcs://localhost:9051",
"grpcOptions": {
"ssl-target-name-override": "peer0.org2.example.com"
},
"tlsCACerts": {
"pem": "INSERT_ORG2_CA_CERT"
}
},
"peer1.org2.example.com": {
"url": "grpcs://localhost:10051",
"grpcOptions": {
"ssl-target-name-override": "peer1.org2.example.com"
},
"tlsCACerts": {
"pem": "INSERT_ORG2_CA_CERT"
}
}
},
"certificateAuthorities": {
"ca.org1.example.com": {
"url": "https://localhost:7054",
"caName": "ca-org1",
"httpOptions": {
"verify": false
}
},
"ca.org2.example.com": {
"url": "https://localhost:8054",
"caName": "ca-org2",
"httpOptions": {
"verify": false
}
}
}
}
In the above json, we need to update three variables. INSERT_ORG1_CA_CERT, INSERT_ORG2_CA_CERT and INSERT_ORDERER_CA_CERT
Copy the certificate details to temporary folder.
awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt > /tmp/composer/org1/ca-org1.txtawk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt > /tmp/composer/org2/ca-org2.txtawk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt > /tmp/composer/ca-orderer.txt
Open /tmp/composer/org1/ca-org1-txt file copy the contents of the file as is and replace the “INSERT_ORG1_CA_CERT” in above json.
Open /tmp/composer/org2/ca-org2-txt file copy the contents of the file as is and replace the “INSERT_ORG2_CA_CERT” in above json.
Open /tmp/composer/ca-orderer.txt file copy the contents of the file as is and replace the “INSERT_ORDERER_CA_CERT” in above json.
Save the json as byfn-network-org1.json in “/tmp/composers/org1” folder
Change the client.organization in the nodepad to Org2 and save a copy to “/tmp/composers/org2” as byfn-network-org2.json file
10. Copy the certificates to temporary folder.
export ORG1=crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
cp -p $ORG1/signcerts/A*.pem /tmp/composer/org1
cp -p $ORG1/keystore/*_sk /tmp/composer/org1export ORG2=crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
cp -p $ORG2/signcerts/A*.pem /tmp/composer/org2
cp -p $ORG2/keystore/*_sk /tmp/composer/org2
11. Let’s create composer business network archive. We will do this in root folder.
cd ~
yo hyperledger-composer:businessnetwork
a. Enter byfn-network
for the network name, and desired information for description, author name, and author email.
b. Select Apache-2.0
as the license.
c. Select org.example.mynetwork
as the namespace.
d. Select No
when asked whether to generate an empty network or not.
Replace the contents of byfn-network/permissions.acl with below
/**
* Access control rules for tutorial-network
*/
rule Default {
description: "Allow all participants access to all resources"
participant: "ANY"
operation: ALL
resource: "org.example.mynetwork.*"
action: ALLOW
}
rule SystemACL {
description: "System ACL to permit all access"
participant: "ANY"
operation: ALL
resource: "org.hyperledger.composer.system.**"
action: ALLOW
}
cd to byfn-network and run following command to create bna file
composer archive create -t dir -n .
You can notice byfn-network@0.0.1.bna file under byfn-network folder.
12. Create network cards
composer card create -p /tmp/composer/org1/byfn-network-org1.json -u PeerAdmin -c /tmp/composer/org1/Admin@org1.example.com-cert.pem -k /tmp/composer/org1/*_sk -r PeerAdmin -r ChannelAdmin -f PeerAdmin@byfn-network-org1.cardcomposer card create -p /tmp/composer/org2/byfn-network-org2.json -u PeerAdmin -c /tmp/composer/org2/Admin@org2.example.com-cert.pem -k /tmp/composer/org2/*_sk -r PeerAdmin -r ChannelAdmin -f PeerAdmin@byfn-network-org2.card
13. Import network cards to the networks
composer card import -f PeerAdmin@byfn-network-org1.card --card PeerAdmin@byfn-network-org1composer card import -f PeerAdmin@byfn-network-org2.card --card PeerAdmin@byfn-network-org2
14. Import business network archive to the network
composer network install --card PeerAdmin@byfn-network-org1 --archiveFile byfn-network@0.0.1.bnacomposer network install --card PeerAdmin@byfn-network-org2 --archiveFile byfn-network@0.0.1.bna
15. Create endorsement file “/tmp/composer/endorsement-policy.json”
{
"identities": [
{
"role": {
"name": "member",
"mspId": "Org1MSP"
}
},
{
"role": {
"name": "member",
"mspId": "Org2MSP"
}
}
],
"policy": {
"2-of": [
{
"signed-by": 0
},
{
"signed-by": 1
}
]
}
}
16. Retrieve business network cards
composer identity request -c PeerAdmin@byfn-network-org1 -u admin -s adminpw -d alicecomposer identity request -c PeerAdmin@byfn-network-org2 -u admin -s adminpw -d bob
17. Starting the business network
composer network start -c PeerAdmin@byfn-network-org1 -n byfn-network -V 0.0.1 -o endorsementPolicyFile=/tmp/composer/endorsement-policy.json -A alice -C alice/admin-pub.pem -A bob -C bob/admin-pub.pem
This step might take 5 min. If you get error try running same command again.
18. Create business network cards in org1 and org2
composer card create -p /tmp/composer/org1/byfn-network-org1.json -u alice -n byfn-network -c alice/admin-pub.pem -k alice/admin-priv.pemcomposer card import -f alice@byfn-network.cardcomposer network ping -c alice@byfn-networkcomposer card create -p /tmp/composer/org2/byfn-network-org2.json -u bob -n byfn-network -c bob/admin-pub.pem -k bob/admin-priv.pemcomposer card import -f bob@byfn-network.cardcomposer network ping -c bob@byfn-network
Hyperledger Explorer
Hyperledger Explorer is a blockchain module and one of the Hyperledger projects hosted by The Linux Foundation. Designed to create a user-friendly Web application, Hyperledger Explorer can view, invoke, deploy or query blocks, transactions and associated data, network information (name, status, list of nodes), chain codes and transaction families, as well as any other relevant information stored in the ledger.
Install Hyperledger explorer
Get blockchain-explorer code from github
git clone https://github.com/hyperledger/blockchain-explorer.git
- Get the keystore key for org1 peer admin.
ls ~/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore
Copy the value.
2. Open first-network.json from blockchain-explorer and update the Org1MSP adminPrivateKey path with the key you copied from above step.
vi ~/blockchain-explorer/examples/net1/connection-profile/first-network.json
3. Copy the crypto keys from fabric-samples to blockchain
cp -r ~/fabric-samples/first-network/crypto-config/* ~/blockchain-explorer/examples/net1/crypto
Notice two folders (ordererOrganizations, peerOrganizations)under ~/blockchain-explorer/examples/net1/crypto
4. Now go back to ~/blockchain-explorer run follow command to start the hyperledger explorer.
docker-compose up -d
Check if dockers running successfully
docker ps
5. You can access explorer with external IP address on port 8090. Use admin/adminpw as userid and password.
Rest API to interact with the block chain
<<Explain rest api>>
Set up gitlab account.
- Move cards that can interact with blockchain to a new folder
mkdir ~/composer-repo
cp -r ~/.composer ~/composer-repo
2. Push composer-repo files to gitlab.
3. Create ubuntu 16 vm and install pre requisites
Create two files in a new docker folder. Dockerfile and startup.sh
startup.sh
cp -r ~/blockchain-blog-artifacts ~/.composer
composer-rest-server -c alice@byfn-network -n never -u true -w true
Dockerfile
FROM hyperledger/composer-rest-server
COPY startup.sh startup.sh
ENTRYPOINT ["/bin/sh","startup.sh"]
4. Get the repo to your local using git clone and update ipaddress with in connection.json file under blockchain-blog-artifacts for alice. Location of connection.json example: ~/blockchain-blog-artifacts/cards/alice@byfn-network
sed -i 's/localhost/<<EXTERNAL IP ADDRESS>>/g' connection.json
5. Build docker image and run composer rest server with the cards available
docker build --no-cache -t blockchain/composer-rest-server .docker run -v ~/blockchain-blog-artifacts:/home/composer/blockchain-blog-artifacts -p 8080:3000 -d blockchain/composer-rest-server
You can visit swagger specs at external ip : 8080/explorer . You should see rest end points
6. Create participants. Add couple of participants. For that click on SampleParticipant and post a request.
Sample Request:
{
“$class”: “org.example.mynetwork.SampleParticipant”,
“participantId”: “1”,
“firstName”: “pradeep”,
“lastName”: “batchu”
}
7. Add asset value “xrp” to assetId 1 and participant you created above
{
“$class”: “org.example.mynetwork.SampleAsset”,
“assetId”: “1”,
“owner”: “org.example.mynetwork.SampleParticipant#1”,
“value”: “xrp”
}
8. Create a transaction and change the new value to “btc”
{
“$class”: “org.example.mynetwork.SampleTransaction”,
“asset”: “org.example.mynetwork.SampleAsset#1”,
“newValue”: “btc”
}
You can see all the transactions in hyperledger explore.
All we have done were on Org1, since alice belongs to Org1. Let’s create new VM for org2.
Follow above steps except step 4 where change on external url for Bob connection instead of alice. Instantiate few transactions and observe the transactions are available on both orgs and we can see transactions clearly.
Happy Blockchain.