Working on a project using Hyperledger Firefly with Fabconnect Gateway, I struggled to make tests when developing the chaincode against a Firefly instance. I wanted immediate feedback and testing on my code, without a complex setup, the possibility to reset the instance etc ... Most online documentation only show how to deploy the chaincode using the regular heavy deploy process (install / approve / commit), or using the test-network only like the official CCAAS doc. But I wanted to have a Firefly setup with Fabconnect as Gateway, so none were a solution.
The best and up-to-date documentation on fullstack chaincode development is here https://github.com/hyperledger/fabric-samples/tree/main/full-stack-asset-transfer-guide The others part of the repo are too old or have only sparse documentation.
After taking too much time to find an efficient way to do, here is my current setup I'm really satisfied with:
Tech stack we will use
- Blockchain: Fabric
- Firefly + Fabconnect
- Chaincode: Node + Typescript
We are going to use the CCAAS (Chaincode As A Service) builder, available since Fabric 2.2. There are a few gotchas, so let's go straight to the steps:
Prerequisites
Dependencies
- A chaincode project in Nodejs + TS (I used the one from the samples' repo)
docker
anddocker-compose
.- Fabric binaries (not mandatory, but useful)
- Firefly
Install Fabric
We will need the peer
command to work. In order to get binaries without downloading the full repo, choose a folder and use the official script:
mkdir fabric-binaries && cd fabric-binaries
curl -sSLO https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh && chmod +x install-fabric.sh
Then run ./install-fabric.sh binary
.
Next add the generated bin
folder to your $PATH
.
Install Firefly CLI
Use instructions on https://hyperledger.github.io/firefly/gettingstarted/firefly_cli.html
Initial Setup
Setup Firefly with Fabric:
ff init fabric dev 3
If you have problems pulling the images, you may need to docker login. Documentation here
The environnement will create compose files in ~/.firefly/stacks/dev
.
Now I will override some docker settings:
- (May be optional) I needed a more up-to-date peer and orderer versions, since they are only at v2.2 by default. v2.4 brings a better CCAAS support and some goodies.
- The extra_hosts part is mandatory and will be useful in the next part.
Replace the ~/.firefly/stacks/dev/docker-compose.override.yml
with
version: "2.1"
services:
fabric_orderer:
image: hyperledger/fabric-orderer:2.4.7
fabric_peer:
image: hyperledger/fabric-peer:2.4.7
extra_hosts:
- "host.docker.internal:host-gateway"
Now we can start the stack
ff start dev
Creating the CCAAS
I won't explain all the steps here, check the doc if you want to deep dive about CCAAS:
You can also use the scripts in ./builders/ccaas/bin/{build, detect, release}
, but the process is simple enough
Create two files:
{
"type": "ccaas",
"label": "asset-transfer"
}
{
"address":"host.docker.internal:9999",
"dial_timeout":"15s"
}
Here we are outside the docker network, so the host.docker.internal
will bridge us
with the docker internal network we exposed earlier in extra_hosts
.
Now we can build the package, which is a simple archive in archive:
#!/usr/bin/env bash
tar -czf code.tar.gz connection.json
tar -czf asset-transfer.tgz code.tar.gz metadata.json
rm code.tar.gz
Now we just need to install the fake chaincode one for good. Easiest way is to use the ff deploy
command
Why can't we use ff deploy
to update chaincode ? Because ff deploy
was designed for CI/CD, and can't update chaincode.
ff deploy fabric dev asset-transfert.tgz firefly asset-transfert.tgz 1.0.0
Easy ! Now the setup is complete. Let's connect our chaincode.
Setting up the chaincode
If you have copied the default chaincode, you should already have these lines in your package.json
, if not, add them:
{
// ...
"scripts": {
// ...
"start:server-nontls": "set -x && fabric-chaincode-node server --chaincode-address=$CHAINCODE_SERVER_ADDRESS --chaincode-id=$CHAINCODE_ID",
"start:server-debug": "set -x && NODE_OPTIONS='--inspect=0.0.0.0:9229' fabric-chaincode-node server --chaincode-address=$CHAINCODE_SERVER_ADDRESS --chaincode-id=$CHAINCODE_ID",
"start:server": "set -x && fabric-chaincode-node server --chaincode-address=$CHAINCODE_SERVER_ADDRESS --chaincode-id=$CHAINCODE_ID --chaincode-tls-key-file=/hyperledger/privatekey.pem --chaincode-tls-client-cacert-file=/hyperledger/rootcert.pem --chaincode-tls-cert-file=/hyperledger/cert.pem"
},
// ...
}
Now we need to set the vars and run the server, I wrote a small bash script, but you can i.e. hardcode them in your shell vars.
#!/usr/bin/env bash
export CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999
export CHAINCODE_ID=$(peer lifecycle chaincode calculatepackageid asset-transfert.tgz)
npm run start:server-debug
Now we want to reload the chaincode every time a file is changed. The easiest thing I found is tsc-watch
.
npm i --save-dev tsc-watch
then add to your package.json
scripts:
"start:dev": "tsc-watch --outDir ./dist --onSuccess './scripts/runLocally.sh'",
And we are done ! Just start your chaincode with npm run start:dev
, edit some files, and enjoy realtime chaincode changes on Firefly !