Chaincode Application Development¶
Like many modern build tools, chaintool is opinionated. It expects a specific structure to your project as follows:
- chaincode.yaml in the top-level directory of your project
- a chaincode entry-point in ./src/chaincode (example)
- interface files in ./src/interfaces (example)
- every project must define an appinit interface ./src/interfaces/appinit.cci (example)
chaincode.yaml is the central configuration file for a given chaintool-managed chaincode project. An example looks like this:
# ---------------------------------- # chaincode example02 # ---------------------------------- # # Copyright (C) 2016 - Hyperledger # All rights reserved # Schema: 1 Name: org.hyperledger.chaincode.example02 Version: 0.1-SNAPSHOT Platform: Name: org.hyperledger.chaincode.golang Version: 1 Provides: [self] # 'self' is a keyword that means there should be $name.cci (e.g. org.hyperledger.chaincode.example02.cci)
All chaincode.yaml should minimally contain:
- project name/version
- interface declarations (provides/consumes)
This helps to relay compatibility with the structures used in the chaincode.yaml itself. At the time of writing, it should be “1”.
This is something that should uniquely identify your chaincode project for human/UX consumption. It is generally advised that a DNS name of some kind be incorporated to promote global uniqueness. Note that the Hyperledger subsystem in general does not interpret these names in any meaningful way other than for display purposes.
It is here that a chaincode may declare the compatibility/conformity to a specific platform. The idea is to promote extensibility (e.g. other platforms may be added in the future) and also compatility (e.g. platform X, version Y may mean something very specifically about the type of chaincode language supported, the ABI for any peripheral libraries, etc). It is analogous to the notion that java 1.7 is a different ABI than java 1.8, etc. At the time of writing, the only supported platform are:
- org.hyperledger.chaincode.golang - The canonical platform for chaincode development, expressed as a chaintool managed superset.
- org.hyperledger.chaincode.system - A special variant of org.hyperledger.chaincode.golang designed for system-chaincode development as an extension of the hyperledger fabric. This platform is implicitly golang based and notably not compiled as system chaincode is compiled as part of the fabric build.
More platforms may be added in the future.
The only core requirement is that both chaintool and the chosen Hyperledger network are in agreement to support said platform. The details of implementing this are “coming soon”.
Interfaces (as included in ./src/interfaces) may be in one or two categories: Provided or Consumed. Provided means that the chaincode implements the interface and supports having clients or other chaincode invoke methods as declared. Likewise, consumed indicates that the chaincode expects to perform inter-chaincode invoke operations to a disparate chaincode instance that provides the interface. It is perfectly fine (though perhaps uncommon) for a chaincode to both provide and consume a given interface (such as for proxy contracts which may accept operations in a polymorphic manner before passing operations on to a concrete instance).
Both Provides and Consumes are expressed as an array of 1 or more entries. For example:
Provides: [org.hyperledger.chaincode.example02, org.hyperledger.chaincode.example03] Consumes: [org.hyperledger.chaincode.example02]
If there aren’t any interfaces in a particular category, the entry may be omitted. Note that a chaincode that doesn’t provide any interfaces doesn’t sound particularly useful, however. Therefore, it is expected that every project will include at least a Provides clause.
The keyword self may be used as shorthand for an interface that shares the same name as the project (for instance, the org.hyperledger.chaincode.example02 project surfacing the org.hyperledger.chaincode.example02.cci interface), as a convenience. It is idiomatic for a project to name its primary interfaces after itself, and therefore this shortcut is expected to be commonly used. Example:
The opinionated portion of chaincode path solely applies to the entry-point for your application. Other paths for non-entry point code are generally fine if you are using a language that supports namespaces, etc. For instance, the org.hyperledger.chaincode.golang platform assumes a $GOPATH of ./src and tries to build “chaincode” (via $GOPATH/src/chaincode). However, if your chaincode uses go imports such as:
import ( "foo" "bar/baz" )
placed in ./src/foo and ./src/bar/baz respectively, they will be discovered perfectly fine.
This work is licensed under a Creative Commons Attribution 4.0 International License. s