How to deploy and test system chaincodes on Hyperledger Fabric effectively
--
I have been working on a project that requires me to implement custom system chaincodes(SCC) on Hyperlerledger Fabric, I’ve spent the good part of January 2019 working on it and trying to understand how fabric works and what is the best way to test and deploy system chaincode. In this process I interacted with some members of the hyperledger community who were very helpful in explaining the non-obvious practices. In this post I will try to explain the best steps and practices to effectively deploy system chaincode while testing. This tutorial will not go into detail about writing system chaincodes as they are covered in detail by the documentation.
Why use System Chaincode ?
If you just started looking at Fabric and ask this question in most cases regular chaincode would suffice. However, you would need to use a system chaincode if you need something which has to be done in the peer directly instead of in a restricted docker container. An example of this is having a separate communication medium (i.e direct socket communication between peers) instead of using channels.
How to write System Chaincode ?
Writing the actual system chaincode is not very different from regular chaincodes, there is the “shim.Chaincode” interface which defines a few methods which need to be implemented by the chaincode. I won’t go in too much detail here, the hyperledger docs do a good job explaining it.
For something like a peer ip lookup system chaincode, the following would do
package mainimport (
“fmt”“github.com/hyperledger/fabric/core/chaincode/shim”
pb “github.com/hyperledger/fabric/protos/peer”
)// New returns an implementation of the chaincode interface.
func New() shim.Chaincode {
fmt.Println(“Hello”) peer1org1, err := net.LookupHost("peer1.org1.example.com")
if err != nil {
log.Fatalf("net.LookupHost peer1.org1.example.com failed with %s\n", err)
}
fmt.Println(peer1org1)
return &helloworldscc{}
}type helloworldscc struct{}// Init implements the chaincode shim interface
func (s *helloworldscc) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
}// Invoke implements the chaincode shim interface
func (s *helloworldscc) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
}
Deploying the SCC
There are two options for deploying SCC. You can deploy it in the standard format like how the query system chaincode and the other in built ones are deployed i.e they are linked statically. The option is using Go plugins and dynamically link the SCC to the peer.
The issues with the first approach is the requirement to rebuild the docker image for every change in the system chaincode. This takes anywhere between 6–10 minutes.
In the second approach only the Go plugin needs to be built and the linking configurations is provided. I will go through the steps required for this approach and how to run the end to end test .
Building the SCC plugin
The system chaincode plugin can be built with the following flags.
go build -buildmode=plugin
For running end to end tests we need to build this to be in the same platform as the fabric peer docker image. The following command mounts the plugin into a docker container of fabric-baseimage and builds the plugin there.
docker run -i --rm -v PATH_TO_PLUGIN:/opt/gopath/src/github.com/PLUGIN_NAME -w /opt/gopath/src/github.com/PLUGIN_NAME \
-v PATH_TO_FABRIC:/opt/gopath/src/github.com/hyperledger/fabric \
hyperledger/fabric-baseimage:amd64-0.4.14 \
go build -buildmode=plugin -tags
Setting up Fabric to allow dynamic linking of SCC plugins:
We need to add information about the plugin and enable it in the core.yaml file.
system:
cscc: enable
lscc: enable
escc: enable
vscc: enable
qscc: enable
helloworldscc: enable
systemPlugins:
- enabled: true
name: helloworldscc
path: /opt/lib/helloworld.so
invokableExternal: true
invokableCC2CC: true
In version 1.4 of fabric SCC plugins were disabled, but they added a secret flag to allow this for faster development. The jira to this issue has further information about why they disabled it.
The peer has to be built with the following flags
GO_TAGS+=" pluginsenabled" make peer
End-to-End tests utilize docker containers hence the containers should also be built with
DOCKER_DYNAMIC_LINK=true GO_TAGS+=" pluginsenabled" make peer-docker
Running end to end tests:
I like using the first network environment present in fabric-samples repository. Make sure to modify the docker image of the peer to mount a volume pointing to the path which was supplied in the earlier core.yaml entry.
About me :
I am a Computer Science Masters student at UIUC. I work in the Decentralized Systems Lab headed by Prof. Andrew Miller
Disclaimer:
I am not a developer of hyperledger fabric and my knowledge and views are limited to my use case.