- We are using fabric version 1.4.4 in which raft mechanism has been introduced. Raft is native in the orderer service from 1.4.1. You can verify this by checking
configtx.yaml
where orderer profile is specified asSampleMultiNodeEtcdRaft
.
This demo/tutorial is based on cluster of nodes created by docker-machine in which docker-machine uses default driver
--driver virtualbox
. So you need to install Oracle Virtual Box in order to follow this tutorial.
-
Make sure your system has docker and go language installed. If not,
- Install docker and docker compose by
sudo apt-get -y install docker-compose
- And as standard practice on docker installation
sudo usermod -aG docker $USER
- Check if docker is installed by
docker -v
anddocker-compose -v
- Install go programming language and set up environment vairables ny using following commands
wget https://golang.org/dl/go1.11.11.linux-amd64.tar.gz
sudo tar -xvf go1.11.11.linux-amd64.tar.gz
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
- Install docker and docker compose by
-
Install Hyperledger Fabric Components consisting docker images, binary tools and fabric samples using
curl -sSL http://bit.ly/2ysbOFE | bash -s 1.4.4
-
We can verify the docker images pulled by
docker images
. You can see there are two types of tag for same docker image. -
This tutorial runs on four nodes cluster. To make a four node cluster run the below commands.
docker-machine create node1
docker-machine create node2
docker-machine create node3
docker-machine create node4
-
You can ssh to these nodes by two ways. Choose either of below given methodes
docker-machine ssh <node-name>
ssh docker@<node-ip-address
which will prompt for password where password istcuser
. You can get the ip address of node bydocker-machine ip <node-name>
-
To make a swarm cluster first ssh to node1 and make it execute the below commands
docker swarm init --advertise-addr <node1-ip-address>
docker swarm join-token manager
-
The last command will give you another to command to be executed on other nodes to be joined them as manager nodes in the cluster
<output from join-token manager> --advertise-addr <node n ip address>
-
Now we will connect all swarm nodes with overlay network. To create an overlay network execute following from node1
docker network create --attachable --driver overlay first-network
wherefirst-network
is name of network. If it is successful and then you can check the network from any of the cluster nodes by executingdocker netwokr ls
. There, network scope will be swarm. -
Now copy the fabric-sample downloaded earlier from your local pc to
node1
. To do that execute the below commandscp fabric-samples/ docker@<node1-ip-address>:/home/docker/
, it will ask for a password which is tcuser
-
Now follow the below commands to copy the configuration file
cd raft-4node-swarm
cp ../first-network/crypto-config.yaml .
cp ../first-network/configtx.yaml .
-
And generate the required materials to boot up the network
../bin/cryptogen generate --config=./crypto-config.yaml
export FABRIC_CFG_PATH=$PWD
mkdir channel-artifacts
../bin/configtxgen -profile SampleMultiNodeEtcdRaft -outputBlock ./channel-artifacts/genesis.block
../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
-
Now let's deploy our docker stack. To deploy it use the following command
docker stack deploy -c docker_stack.yaml hlf
where docker_stack.yaml is docker stack config file and hlf is docker stack name.- Docker stack supports only version greater than or equals to 3.
- You can check the docker stack by
docker stack ls
- There will be 10 services running across the swarm cluster. Five of orderer, four of peer and one cli service to interact with peers.
- You can check the total replication of services by
docker service ls
- If you want to view specifics of one service you can do with
docker service ps <service-name>
- If some service is in pending state or failing you can get the extend view of it by
docker service ps --no-trunc <service-name>
- You can see the logs of the service by
docker service logs <service-name>
-
Now let's create a channel and let all peers join it
- You can do
docker ps
and can get the cli container name or id to use it further - Create channel genesis block for mychannel
docker exec <cli-container-name> peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
- Join peer0_org1 to mychannel
docker exec <cli-container-name> peer channel join -b mychannel.block
- Join peer1_org1 to mychannel
docker exec -e CORE_PEER_ADDRESS=peer1.org1.example.com:7051 -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt <cli-container-name> peer channel join -b mychannel.block
- Join peer0_org2 to mychannel
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e 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 <cli-container-name> peer channel join -b mychannel.block
- Join peer1_org2 to mychannel
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer1.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt <cli-container-name> peer channel join -b mychannel.block
- You can do
-
Now let's install and instantiate Fabcar chaincode on mychannel to test our network
- Install Fabcar chaincode to all peer nodes by following commands
- Install to peer0_org1
docker exec <cli-container-name> peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/fabcar/go/
- Install to peer1_org1
docker exec -e CORE_PEER_ADDRESS=peer1.org1.example.com:7051 -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt <cli-container-name> peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/fabcar/go/
- Install to peer0_org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e 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 <cli-container-name> peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/fabcar/go/
- Install to peer1_org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer1.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt <cli-container-name> peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/fabcar/go/
- Let's instantiate the chaincode at mychannel from one of the peers. We are doing it on peer0_org1
- Instantiate by
docker exec <cli-container-name> peer chaincode instantiate -o orderer.example.com:7050 --tls --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 -v 1.0 -c '{"Args":[]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"
-
Let's invoke Fabcar chaincode by invoking a function initLedger
- From peer0_org1,
docker exec <cli-container-name> 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":["initLedger"]}'
- Now we can query from chaincode installed peers and check the result, whether it's upto our expectation.
- From peer0_org1
docker exec <cli-container-name> peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
- From peer1_org1
docker exec -e CORE_PEER_ADDRESS=peer1.org1.example.com:7051 -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt <cli-container-name> peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
- From peer0_org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e 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 <cli-container_name> peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
- From peer1_org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer1.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt <cli-container-name> peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
- Now let invoke another function and change the owner of the one car and submit our transaction to different orderer
- From peer0_org1
docker exec <cli-container-name> peer chaincode invoke -o orderer3.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":["changeCarOwner","CAR0","KC"]}'
- Now let's see the change made by function invokation, from peer0_org1
docker exec cli peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
- From peer1_org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer1.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt <cli-container-name> peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
- From peer0_org1,
-
You have reached to the end the tutorial. If all commands are working as expected then you can pat on your back. You have done an awesome job.
-
To clean up the stack, you can do
docker stack rm hlf
and to clean up the volumes and networks, dodocker system prune
&docker volume prune