Skip to content

Instantly share code, notes, and snippets.

@vitiko

vitiko/blog.md Secret

Created July 23, 2019 07:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vitiko/fe3ce6a19f184271fca644274e417d60 to your computer and use it in GitHub Desktop.
Save vitiko/fe3ce6a19f184271fca644274e417d60 to your computer and use it in GitHub Desktop.

Service oriented Hyperledger Fabric application development with CCKit

Hyperledger Fabric application development evolution

Early Hyperledger Fabric application implementations leveraged JSON data model, simple chaincode method routing and REST API architecture as the de-facto technology stack.

CCKit, library for Hyperledger Fabric 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.

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 chaincode app developer may express the interface to their application 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 gRPC or REST service)
  • chaincode documentation in markdown format

code generation

After generating all this components blockchain developer only need to implement chaincode business logic, using CCKit features for working with state, access control or data encryption.

Blockchain network services

Blockchain network consists of multiple services, on-chain (chaincodes) and off-chain (API's and other external to blockchain applications, interacts with smart contracts).

blockchain app

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.

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 (IDL):

  • 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 gRPC.

Chaincode as service

Application, interacting with smart contracts can be defined and implemented as gRPC service. But, what if chaincode itself implement with respect to service definition in gRPC format ?

Chaincode interface

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:

https://gist.github.com/4f36407a35696a7889229d1ed44e60dc

Using ChaincodeStubInterface 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:

https://gist.github.com/d1447dabdc43a5c4791f8c320b95ba39

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

Let's implement Commercial paper chaincode as service using gRPC service definition and code generation.

1. Define data model

At the first step we create .proto description of the data structure you wish to store and input/output payload. You can read details about chaincode state modelling here.

https://gist.github.com/149ad9104f11d15e364a745522caa662

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.

The 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.

https://gist.github.com/baa045f49ac4cc74e2b7b9918ac0e1e7

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

Command for generating chaincode auxiliary code can be found in Makefile

https://gist.github.com/4f260dc1600c96765c4e6f8c88f72507

  • -I flag defines source for data mode source (.schema) or service definition
  • go_out flag sets output path for protobuf structures and gRPC service client and server
  • govalidators_out flag sets output path for protobuf parameter validators
  • grpc-gateway_out flag sets output path for REST-API proxy for gRPC service
  • swagger_out flag sets output for REST API swagger specification

and finally:

  • 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 - gRPC service implementation for chaincode external access

Chaincode implementation

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 (Issue method)
  • reads from the chaincode state (List, Get, GetByExternalId methods)
  • updates commercial paper entry (Buy, Redeem methods)
  • deletes commercial paper entry (Delete method)

Using CCKit state wrapper with entity mapping, implementation should be pretty straightforward:

https://gist.github.com/2db8e9086f94fe7b5f860149eb461ee8

Chaincode implementation also must contain state and event mappings

https://gist.github.com/c139c746505573c43be7244bb1036cc7

Then, chaincode service implementation can be embedded into chaincode method router with generated RegisterCPaperChaincode function:

https://gist.github.com/b67f3b0731c5e971d9ba559ba1f5e90e

CCKit components for 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:

https://gist.github.com/a0c8882b6b48e33cdc51bf72209243f5

Chaincode invocation service

Chaincode invocation service defines gRPC service for interacting with smart contract from external application with 3 methods:

  • Query ( ChaincodeInput ) returns ( ProposalResponse )
  • Invoke ( ChaincodeInput ) returns ( ProposalResponse )
  • Events (ChaincodeLocator ) returns ( ChaincodeEvent )

This service used by Chaincode gateway or can be exposed separately as gRPC or REST API. CCKit contains chaincode service implementation based on https://github.com/s7techlab/hlf-sdk-go and version for testing, based on Mockstub

https://gist.github.com/ef1b4280f6d37ec67764527780a287d7

Chaincode gateway

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.

Using gRPC service definition we can generate gateway for particular chaincode, for example for Commercial Paper. This gateway can be used as:

  • gRPC service
  • Chaincode SDK for using in other services
  • REST service with grpc-gateway

For example, generated chaincode gateway for Commercial Paper example looks like this:

https://gist.github.com/e577a203e3e5d8d24fbfd9c24236240f

API

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 gRPC server:

https://gist.github.com/74be967cb4f9f2ca83d5b2b8a47f7ddb

Provided example use mocked chaincode invocation service, but for interacting with real Hyperledger Fabric network you just need to change chaincode invocation service to implementation using SDK, from example hlf-sdk-go

You can run provide example using command https://gist.github.com/3175e750249fa519d57375815ccd3e45

mocked gateway start

Then you can use API usage examples and sample payloads:

mocked gateway usage

Conclusion

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment