This is the first part of the series of articles where we will describe how to develop applications on Hyperledger Fabric from local machine to production on AWS Managed Blockchain.
We will assume that you know Hyperledger Fabric basics to understand what is going on and have installed Docker on your machine.
Step 1. Installation
We are going to start from bare bones and install Hyperledger Fabric with docker images and samples from the official guide. We will use current stable version (1.4.1), to install it run the following command:
curl -sSL http://bit.ly/2ysbOFE | bash -s -- 1.4.1 1.4.1 0.4.15
And the expected result is:
docker images| grep hyperledger
returns list of docker images
After this step we have all necessary docker images and ready to start Hyperledger Fabric on your machine. Additionally there are some Fabric usage samples and all necessary binaries.
Step 2. Basic checks
At this step we will ensure that your Hyperledger Fabric installation is complete and ready to work. For this we are going to start a basic network.
cd fabric-samples/basic-network
bash ./start.sh
Expected result:
docker ps | grep hyperledger
returns four running images (fabric-peer, fabric-ca, fabric-orderer, fabric-couchd)
Let’s try to look deeper in what we’ve done. For this we need to open ./start.sh
script in your favorite editor. As a start we will omit all comments because they are self-descriptive and see what exactly we have. There are 4 simple commands (a little bit prettified):
docker-compose -f docker-compose.yml down
docker-compose -f docker-compose.yml up -d \
ca.example.com orderer.example.com peer0.org1.example.com couchdb
docker exec \
-e "CORE_PEER_LOCALMSPID=Org1MSP" \
-e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" \
peer0.org1.example.com peer channel create \
-o orderer.example.com:7050 \
-c mychannel \
-f /etc/hyperledger/configtx/channel.tx
docker exec \
-e "CORE_PEER_LOCALMSPID=Org1MSP" \
-e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" \
peer0.org1.example.com peer channel join \
-b mychannel.block
The first one will down your current local Hyperledeger Fabric if it’s already started. The next one is about runnning all necessary Hyperledger Fabric components:
ca.example.com
is a Certificate Authority component. It networks member organizations and their users.
orderer.example.com
is an ordering service. It orders transactions for all channel's on the network.
peer0.org1.example.com
is a peer. Basic network entity that runs chaincode and maintains ledger. Currently there are only one peer but we will fix it later.
couchdb
is a state database. The main function is to provide efficient reads and queries from chaincode.
The next two commands are related to the network initialization. The first one (peer channel create
) creates a channel named mychannel
which is the main basic network channel and uses channel.tx
file as a configuration transaction file. This file is a part of samples but later we will be able to generate it with configtxgen
. The result of executing this command is a mychannel.block
file. It's the genesis block for the channel we just created (mychannel
) . The file mychannel.block
will be used in the last command to join in the created channel.
As you can see all commands here are executed on the peer machine (peer0.org1.example.com
). It's a little bit unusual. The common practice is to use a special cli
container for it and we will do this way in the next steps. But for the "basic" configuration cli
container isn't need, so that's why the script uses peer container instead.
And the result is following: the script stops active network, creates a new one, create a channel and then joins it.
Step 3. Preparing network for local development
At this point we have already ensured that Hyperldeger Fabric is installed and works as expected. Now it’s time to tweak Hyperldeger Fabric for our needs. What’s wrong with the current setup? The main problem is that current version is running in production-like mode. Meanwhile, we need some way to interact with it as a developer. To do it we need to:
Change start.sh
script to run cli
container. This container allows to interact with the network. Simply add cli
to list of docker images to up. As result, it should look like this:
docker-compose -f docker-compose.yml up -d ca.example.com orderer.example.com peer0.org1.example.com couchdb cli
Change docker-compose.yml
to run a peer node in development node. To do it you need to comment the first command and uncomment the second command under peer0.org1.example.com
description. This one:
command: peer node start --peer-chaincodedev=true
After this your environment is ready to deploy the first smart contract (aka chaincode). We will deploy JavaScript sample chaincode which is provided by fabric-samples
. You can observe it's code in chaincode/fabcar/javascript-low-level/
.
To deploy this chaincode you need to run following commands:
docker exec cli \
peer chaincode install -n fabcar -v 1.0 -l node \
-p /opt/gopath/src/github.com/fabcar/javascript-low-level
docker exec cli \
peer chaincode instantiate -n fabcar -v 1.0 -l node --channelID mychannel \
-c '{"Args":["instantiate"]}'
Expected result:
docker exec cli peer chaincode list --instantiated -C mychannel
returns fabcar
chaincode.
At this step we’ve deployed chaincode and instantiated it. Let’s look deeply what is going on here.
On chaincode installation peer called special chaincode lscc which is responsible for working with user’s chaincode. lscc
installs the chaincode to the local peer file system. Notice, there is no channel argument in install
. It's because the chaincode isn't associated with any channel before instantiating.
Next command is much more interesting and doing really a lot. Hyperledger Fabric sees instantiate
command and understands that it need to deploy the chaincode. Hyperledger passes deploy
command to lscc
chaincode to instantiate the passed chaincode. But before doing it we need to have a running chaincode. To resolve it, Hyperledger Fabric wraps the passed chaincode into an one-time Docker container before deploy.
Yes, Hyperledger Fabric runs your chaincode in Docker. You can actually see it on docker ps
output. It looks something like:
dev-peer0.org1.example.com-fabcar-1.0 5c906e402ed29f20260ae42283216aa75549c571e2e380f3615826365d8269ba
Now everything is ready to finaly instantiate the chaincode by calling passed command ({"Args":["instantiate"]}). Pretty much for one command, isn't it?
Step 4. Call the chaincode
Now everything is ready to call the chaincode. Default fabcar
sample contains a special method to feel Hyperledger Fabric with seed data. Let’s call it.
docker exec cli \
peer chaincode invoke -n fabcar --channelID mychannel --orderer orderer.example.com:7050 \
-c '{"function":"initLedger","Args":[]}'
As you can see there are not to much difference between chaincode instantiating and calling. We provide additional information about an orderer (because peer need to send proposals to the passed orderer) and a chaincode’s command name to call with arguments as JSON.
So, what’s now? Let’s try to call a more usefull function from the chaincode.
docker exec cli \
peer chaincode query -n fabcar --channelID mychannel \
-c '{"Args":["queryCar","CAR5"]}'
# => {"color":"purple","docType":"car","make":"Peugeot","model":"205","owner":"Michel"}
Instead of invoke
we use query
here. Why? Because this request doesn't change the blockchain state and simple queries it, instead of modifying. And that's the reason why there is no orderer
flag.
You could probably receive message like Error: endorsement failure during query. response: status:500 message:"transaction returned with failure: Error: CAR5 does not exist: "
. It's because invoke
command is asyncronios and Hyperledger Fabric orderer need some time to process transaction. How much? You can find it in the configtx.yaml
under the Orderer
section. So, to solve it, you need to wait a little bit more before running query command.
Conclusion
We’ve started a new Hyperledger Fabric network, prepared it for local development, deployed basic chaincode and run it. Now everything is ready to write and deploy your first chaincode. Our next steps are to be described in the next chapter.