Current chaincode development best practices and application samples leverages JSON data model, simple chaincode method routing and
REST API architecture as the de-facto technology stack. This article proposes methods and tools for blockchain application development with well known specification formats like Protocol Buffers messages and
gRPC services definitions.
Hyperledger Fabric network services
Blockchain network consists of multiple services, on-chain (chaincodes) and off-chain (API’s, oracles and other external applications, interacts with smart contracts).
For example, official Commercial paper chaincode example includes smart contract implementation and cli tools for interacting with deployed сhaincodes. With external applications, implemented with different technologies and programming languages, it is important to have a standard way to define service interfaces and underlying message interchange formats.
Chaincode development tools
CCKit, library for Hyperledger Fabric Golang application development, addresses several aspects of Hyperledger Fabric application development:
- Chaincode method routing allows to consistently define rules how an chaincode responds to a client requests
- Using protocol buffers can help to define data model once and then easily write and read structured data to and from chaincode world state
- Testing tools enhances the development experience with extended version of MockStub for chaincode testing.
Specification for chaincode data model and interface
Next step is to standardize following aspects of blockchain application development using gRPC Interface Definition Language (IDL):
- Chaincode interface definition
- Chaincode SDK and API’s creation with code generation
- Chaincode documentation building with code generation
Proposed methodology leverages power of
gRPC services and messages definitions. A blockchain application developer may express the interface to app in a high level interface definition language, and CCKit
cc-gateway generator will automatically generate:
- chaincode service interface and helper for embedding service into chaincode router
- chaincode gateway for external access (can be used as SDK or exposed as
- chaincode documentation in
- REST API specification in swagger format
Using gRPC ecosystem for chaincode development
Fundamentals of gRPC
With gRPC, a client application can directly call methods on a server application on a remote machine as if it were a local object.
gRPC is based on the foundations of conventional Remote Procedure Call (RPC) technology but implemented on top of the modern technology stacks such as HTTP2, protocol buffers etc. to ensure maximum interoperability.
Like many RPC systems,
gRPC is based around the idea of defining a service, specifying the methods that can be called remotely with their parameters and return types.
gRPC technology stack natively supports a clean and powerful way to specify service contracts using the Interface Definition Language (
- messages defines data structures of the input parameters and return types.
- services definition outlines methods signatures that can be invoked remotely
When the client invokes the service, the client-side
gRPC library uses the protocol buffer and marshals the remote procedure call, which is then sent over HTTP2. On the server side, the request is un-marshaled and the respective procedure invocation is executed using protocol buffers. The response follows a similar execution flow from the server to the client.
The main advantage of developing services and clients with
gRPC is that your service code or client side code doesn't need to worry about parsing JSON or similar text-based message formats. What comes in the wire is a binary format, which is unmarshalled into an object. Also, having first-class support for defining a service interface via an
IDL is a powerful feature when we have to deal with multiple microservices and ensure and maintain interoperability.
gRPC service as RESTful HTTP API
gRPC service can be exposed as
REST service using grpc-gateway plugin of the Google protocol buffers compiler protoc . It reads protobuf service definitions and generates a reverse-proxy server which translates a RESTful HTTP API into
Application, interacting with smart contracts can be defined and implemented as
gRPCservice. But, what if chaincode itself implement with respect to service definition in
Chaincode interacts with the shared ledger and defines business logic for blockchain network: a set of contracts covering common terms, data, rules, concept definitions, and processes (for example, Commercial paper or ERC20 token functionality), lay out the business model that govern all of the interactions between transacting parties.
Chaincode interface is very simple and contains only 2 methods:
getArgs method chaincode implementation can access input parameters as slice (array) of bytes.
At the moment there is no standard way to describe chaincode interface via some definition language. But chaincode itself can be considered as RPC’like service and defined with
gRPC Interface Definition Language (IDL), for example:
As this service definition strongly typed (input:
string ad output:
string) versus relaxed basic chaincode interface (input:
byte and output:
byte) we need mechanisms for converting input
byte to target parameter type, depending on service definition.
Example: Commercial paper chaincode
1. Define data model
2. Create service definition
Chaincode interface can be described with gRPC service notation. Using
grpc-gateway option we can also define mapping for chaincode REST-API.
grpc-gateway is a plugin of the Google protocol buffers compiler
protoc. It reads protobuf service definitions and generates a reverse-proxy server which translates a RESTful HTTP API into gRPC. This server is generated according to the
google.api.http annotations in your service definitions.
3. Code generation
Chaincode-as-service gateway generator allows to generate auxiliary components from
gRPC service definition.
Install the generator:
GO111MODULE=on go install github.com/s7techlab/cckit/gateway/protoc-gen-cc-gateway
For documentation generation install protoc-gen-doc:
go get -u github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc
For generating validation code install ProtoBuf Validator Compiler:
go get github.com/mwitkow/go-proto-validators/protoc-gen-govalidators
Command for generating chaincode auxiliary code can be found in Makefile
-Iflag defines source for data mode source (.schema) or service definition
go_outflag sets output path for
gRPCservice client and server
govalidators_outflag sets output path for
grpc-gateway_outflag sets output path for REST-API proxy for
swagger_outflag sets output for REST API swagger specification
doc_outflag sets output for documentation in markdown format
cc-gateway_out flag sets output path for auxiliary code for building on-chain (chaincode) and off-chain (external applications) blockchain network components:
- Chaincode service to ChaincodeStubInterface mapper
- Chaincode gateway —
gRPCservice implementation for chaincode external access
Chaincode service implementation must conform to interface, generated from service definition CPaperChaincode :
For simple case, such as
Commercial Paper chaincode, service acts as
Create-Read-Update-Delete (CRUD) application:
- creates commercial paper entry in the chaincode state (
- reads from the chaincode state (
- updates commercial paper entry (
- deletes commercial paper entry (
Chaincode implementation also must contain state and event mappings:
Then, chaincode service implementation can be embedded into chaincode method router with generated RegisterCPaperChaincode function:
Components for building blockchain network layers
Chaincode service to ChaincodeStubInterface mapper
Generated on top of
gRPC service definition chaincode service mapper allows to embed chaincode service implementation into CCKit router, leveraging middleware capabilities for converting input and output data.
For example, Commercial Paper as service generated code contains
RegisterCPaperChaincode method which maps chaincode
Issue method to chaincode service implementation:
Chaincode invocation service
Chaincode invocation service defines gRPC service for interacting with smart contract from external application with 3 methods:
ChaincodeInput) returns (
ChaincodeInput) returns (
ChaincodeLocator) returns (
This service used by
Chaincode gateway or can be exposed separately as
gRPC service or
CCKit contains chaincode service implementation based on hlf-sdk-go, unofficial sofware development kit (SDK) for building off-chain Hyperledger Fabric applications, and version for testing, based on Mockstub.
Chaincode gateway use chaincode service to interact with deployed chaincode. It knows about channel and chaincode name, but don’t know about chaincode method signatures.
Chaincode gateway supports options for providing transient data during chaincode invocation, and encrypting/ decrypting data.
gRPC service definition we can generate gateway for particular chaincode, for example for
Commercial Paper. This gateway can be used as:
- Chaincode SDK for using in other services (oracle, API’s etc)
RESTservice via grpc-gateway
Using generated chaincode gateway you can easily build external to chaincode application. For example, to create API application you need to create entry point for the HTTP reverse-proxy server and use generated gateway in
Provided API example use mocked chaincode invocation service, but for interacting with real Hyperledger Fabric network peer you just need to change chaincode invocation service to implementation using SDK, for example hlf-sdk-go.
You can run provided example using command
# cd examples/cpaper_asservice/bin/api/mock
# go run main.go
Then you can use API usage examples and sample payloads:
grpc-gateway will automatically converts http request to
gRPC call, input JSON payloads to protobuf, invokes chaincode service and then converts returned value from protobuf to JSON. You can also use this service as pure gRPC service. Chaincode methods can be called with generated
gRPC client . Service and schema documentation also auto-generated.
Provided tools allows to specify chaincode data model and interface and then generate code for building
on-chain (chaincode) and
off-chain (API, Oracles, SDK etc) application in consistent manner.