##Chaincode
Chaincode is a piece of code that is written in one of the supported languages such "GO" or "Java" and deployed through SDK or CLI into a network of Hyperledger fabric peer nodes that enables interaction with that network's shared ledger.
There are 3 aspects to chaincode development :
-
The interfaces that the chaincode shoud implement
-
APIs chaincode can use to interact with the fabric
-
The response from the chaincode
A chaincode implement the Chaincode Interface that supports two methods :
-
Init
-
Invoke
Init()
Init is called when you first deploy your chaincode. As the name implies, this function should be used to do any initialization your chaincode needs.
Invoke()
Invoke is called when you want to call chaincode functions to do real work. Invocations will be captured as a transactions, which get grouped into blocks on the chain. When you need to update or query the ledger, you will do so by invoking your chaincode.
The import statement lists a few dependencies that you will need for your chaincode to build successfully.
-
fmt – contains Println for debugging/logging.
-
errors – standard go error format.
-
shim – contains the definition for the chaincode interface and the chaincode stub, which you will need to interact with the ledger.
##Chaincode APIs
When the Init or Invoke function of a chaincode is called, the fabric passes the stub shim.ChaincodeStubInterface parameter and the chaincode returns a pb.Response. This stub can be used to call APIs to access to the ledger services, transaction context, or to invoke other chaincodes.
The current APIs are defined in the shim package, generated by godoc github.com/hyperledger/fabric/core/chaincode/shim command. You can refer to shim here. However, it also includes functions from chaincode.pb.go with an “_” included in its name such as func (*Column) XXX_OneofFuncs that are not intended as public API. The best is to look at the function definitions in chaincode.go and chaincode example for usage.
##Response
The response from the chaincode is in the form of protobuffer.
message Response {
// A status code that should follow the HTTP status codes.
int32 status = 1;
// A message associated with the response code.
string message = 2;
// A payload that can be used to include metadata with this response.
bytes payload = 3;
}
The chaincode also returns events :
messageEvent {
oneof Event {
//Register consumer sent event
Register register = 1;
//producer events common.
Block block = 2;
ChaincodeEvent chaincodeEvent = 3;
Rejection rejection = 4;
//Unregister consumer sent events
Unregister unregister = 5;
}
}
messageChaincodeEvent {
string chaincodeID = 1;
string txID = 2;
string eventName = 3;
bytes payload = 4;
}
Once developed and deployed, there are two ways to interact with the chaincode - through SDK or CLI. The steps for CLI are as described below. For SDK interaction, refer the examples here.
To view the currently available CLI commands, execute the following:
cd /opt/gopath/src/github.com/hyperledger/fabric
build /bin/peer
You will see output similar to the example below (NOTE: rootcommand below is hardcoded in main.go. Currently, the build will create a peer executable file).
Usage:
peer [flags]
peer [command]
Available Commands:
version Print fabric peer version.
node node specific commands.
channel channel specific commands.
chaincode chaincode specific commands.
logging logging specific commands
Flags:
--logging-level string: Default logging level and overrides, see core.yaml for full syntax
--test.coverprofile string: Done (default “coverage.cov)
-v, --version: Display current version of fabric peer server
Use "peer [command] --help" for more information about a command.
The peer
command supports several subcommands and flags, as shown above. To facilitate its use in scripted applications, the peer
command always produces a non-zero return code in the event of command failure. Upon success, many of the subcommands produce a result on stdout as shown in the table below:
Command |
stdout result in the event of success |
---|---|
version |
String form of peer.version defined in core.yaml (https://github.com/hyperledger/fabric/blob/master/peer/core.yaml) |
node start |
N/A |
node status |
String form of StatusCode (https://github.com/hyperledger/fabric/blob/master/protos/server_admin.proto#L36) |
node stop |
String form of StatusCode (https://github.com/hyperledger/fabric/blob/master/protos/server_admin.proto#L36) |
chaincode deploy |
The chaincode container name (hash) required for subsequent chaincode invoke and chaincode query commands |
chaincode invoke |
The transaction ID (UUID) |
chaincode query |
By default, the query result is formatted as a printable |
channel create |
Create a chain |
channel join |
Adds a peer to the chain |
--peer-defaultchain=true
|
Allows users to continue to work with the default TEST_CHAINID string. Command line options support writing this value as raw bytes (-r, –raw) or formatted as the hexadecimal representation of the raw bytes (-x, –hex). If the query response is empty then nothing is output. |
##Deploy a Chaincode
Before we deploy the chaincode, we need to create channels and direct the peers to join the channels. Click and follow the instructions to create
and join
a channel.
#### Start the orderer
ORDERER_GENERAL_LOGLEVEL=debug ./orderer
####Create a chain
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/msp/sampleconfig peer channel create -c myc1
####Start peer in chainless mode
peer node start --peer-defaultchain=false
####Direct peer to join the channel
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/msp/sampleconfig peer channel join -b myc1.block
Deploy creates the docker image for the chaincode and subsequently deploys the package to the validating peer. An example is below.
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/msp/sampleconfig peer chaincode deploy -n mycc -C myc1 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a","100","b","200"]}'
The response to the chaincode deploy command will contain the chaincode identifier (hash) which will be required on subsequent chaincode invoke
and chaincode query
commands in order to uniquely identify the deployed chaincode.
Send an invoke request
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/msp/sampleconfig peer chaincode invoke -n mycc -C myc1 -c '{"Args":["invoke","a","b","10"]}'
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/msp/sampleconfig peer chaincode query -n mycc -C myc1 -c '{"Args":["query","a"]}'
Note: If your GOPATH environment variable contains more than one element, the chaincode must be found in the first one or deployment will fail.