Hyperledger — Chapter 8 | What is Hyperledger Fabric Chaincode ?

Moses Sam Paul
May 4, 2018 · 8 min read

So in the previous chapter we had installed Hyperledger Fabric and we started and stopped a test network on which peers and chain codes run. Now let’s dive deep into the chaincode portion of Hyperledger Fabric as that’s where business logic lies.

Image for post
Image for post

In this post,

We will go through a Sample chaincode and understand the following

  • Dependencies
  • Struct
  • Init Method
  • Invoke Method (Get & Set)
  • Main Function

Recap — Chaincode

Right now, it can be written in Go / Node.JS.

In Hyperledger Fabric, chaincode is the ‘smart contract’ that runs on the peers and creates transactions. More broadly, it enables users to create transactions in the Hyperledger Fabric network’s shared ledger and update the world state of the assets.

Chaincode is programmable code, written in Go, and instantiated on a channel. Developers use chaincode to develop business contracts, asset definitions, and collectively-manage decentralized applications. The chaincode manages the ledger state through transactions invoked by applications. Assets are created and updated by a specific chaincode, and cannot be accessed by another chaincode.

Applications interact with the blockchain ledger through the chaincode. Therefore, the chaincode needs to be installed on every peer that will endorse a transaction and instantiated on the channel.

Remember the Transaction Flow?

Image for post
Image for post
Quick High Level Overview:Peer can be part of one or more channelEvery channel has a separate ledgerEvery Channel has one or more chain codesEvery Chain code has a different endorsement policyChaincode must be part of a channel. As the ledger is part of a channel. One channel can have as many chaincodes as possible.Chaincode must be installed in each peer that is part of the channel and instantiated.When a Chaincode gets instantiated a policy (endorsing) has to be defined. [consensus: before a transaction can be recorded in the ledger only if a rule is met]

There are two ways to develop smart contracts with Hyperledger Fabric:

  • Code individual contracts into standalone instances of chaincode
  • Use chaincode to create decentralized applications that manage the lifecycle of one or multiple types of business contracts, and let the end users instantiate instances of contracts within these applications. [More Efficient]

Chaincode Key APIs

The ChaincodeStub provides functions that allow you to interact with the underlying ledger to query, update, and delete assets.

The key APIs for chaincode include:

  • func (stub *ChaincodeStub) GetState(key string) ([]byte, error)
    Returns the value of the specified key from the ledger. Note that GetState doesn’t read data from the Write set, which has not been committed to the ledger. In other words, GetState doesn’t consider data modified by PutState that has not been committed. If the key does not exist in the state database, (nil, nil) is returned.
  • func (stub *ChaincodeStub) PutState(key string, value []byte) error
    Puts the specified key and value into the transaction’s Write set as a data-write proposal. PutState doesn’t affect the ledger until the transaction is validated and successfully committed.
  • func (stub *ChaincodeStub) DelState(key string) error
    Records the specified key to be deleted in the Write set of the transaction proposal. The key and its value will be deleted from the ledger when the transaction is validated and successfully committed.

Overview of a Chaincode Program

  • Init
    Called when a chaincode receives an instantiate or upgrade transaction. This is where you will initialize any application state.
  • Invoke
    Called when the invoke transaction is received to process any transaction proposals.

As a developer, one must create both an Init and an Invoke method within your chaincode. The chaincode must be installed using the peer chaincode install command, and instantiated using the peer chaincode instantiate command before the chaincode can be invoked. Then, transactions can be created using the peer chaincode invoke or peer chaincode query commands.

Sample Chaincode Decomposed — Dependencies

package main
import (
“fmt”
“github.com/hyperledger/fabric/core/chaincode/shim”
“github.com/hyperledger/fabric/protos/peer”
)

The import statement lists a few dependencies that you will need for your chaincode to build successfully.

  • fmt — contains Println for debugging/logging
  • github.com/hyperledger/fabric/core/chaincode/shim — contains the definition for the chaincode interface and the chaincode stub, which you will need to interact with the ledger, as we described in the Chaincode Key APIs section
  • github.com/hyperledger/fabric/protos/peer — contains the peer protobuf package.

Sample Chaincode Decomposed — Struct

type SampleChaincode struct {}

This might not look like much, but this is the statement that begins the definition of an object/class in Go.

SampleChaincode implements a simple chaincode to manage an asset.

Sample Chaincode Decomposed — Init Method

func (t *SampleChaincode) Init(stub shim.ChainCodeStubInterface) peer.Response {// Get the args from the transaction proposalargs := stub.GetStringArgs()if len(args) != 2 {return shim.Error("Incorrect arguments. Expecting a key and a value")}// We store the key and the value on the ledgererr := stub.PutState(args[0], []byte(args[1]))if err != nil {return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))}return shim.Success(nil)}

The Init implementation accepts two parameters as inputs, and proposes to write a key/value pair to the ledger by using the stub.PutState function.

stub.GetStringArgs retrieves and checks the validity of arguments which we expect to be a key/value pair. Therefore, we check to ensure that there are two arguments specified. If not, we return an error from the Init method, to indicate that something went wrong.

stub.PutState function is used to store the initial state in the ledger. In order to accomplish this, we call the function, specifying the first argument as the key, and the second argument as the value for that key. If no errors are returned, we will return success from the Init method.

Sample Chaincode Decomposed — Invoke Method

func (t *SampleChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {// Extract the function and args from the transaction proposalfn, args := stub.GetFunctionAndParameters()var result stringvar err errorif fn == "set" {result, err = set(stub, args)} else { // assume 'get' even if fn is nilresult, err = get(stub, args)}if err != nil { //Failed to get function and/or arguments from transaction proposalreturn shim.Error(err.Error())}// Return the result as success payloadreturn shim.Success([]byte(result))}

There are two basic actions a client can invoke: get and set.

  • The get method will be used to query and return the value of an existing asset.
  • The set method will be used to create a new asset or update the value of an existing asset.

To start, we’ll call GetFunctionandParameters to isolate the function name and parameter variables. Each transaction is either a set or a get. Let’s first look at how the set method is implemented:

func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {if len(args) != 2 {return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value")}err := stub.PutState(args[0], []byte(args[1]))if err != nil {return "", fmt.Errorf("Failed to set asset: %s", args[0])}return args[1], nil}

The set method will create or modify an asset identified by a key with the specified value. The set method will modify the world state to include the key/value pair specified. If the key exists, it will override the value with the new one, using the PutState method; otherwise, a new asset will be created with the specified value.

Next, let’s look at how the get method is implemented:

func get(stub shim.ChaincodeStubInterface, args []string) (string, error) {if len(args) != 1 {return "", fmt.Errorf("Incorrect arguments. Expecting a key")}value, err := stub.GetState(args[0])if err != nil {return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err)}if value == nil {return "", fmt.Errorf("Asset not found: %s", args[0])}return string(value), nil}

The get method will attempt to retrieve the value for the specified key. If the application does not pass in a single key, an error will be returned; otherwise, the GetState method will be used to query the world state for the specified key. If the key has not yet been added to the ledger (and world state), then an error will be returned; otherwise, the value that was set for the specified key is returned from the method.

Sample Chaincode Decomposed — Main Function

func main() {err := shim.Start(new(SampleChaincode))if err != nil {fmt.Println(“Could not start SampleChaincode”)} else {fmt.Println(“SampleChaincode successfully started”)}}
Image for post
Image for post
Recap:Peer can be part of one or more channelEvery channel has a separate ledgerEvery Channel has one or more chain codes getting & setting values in the ledgerEvery Chain code has a different endorsement policyChaincode must be installed in each peer that is part of the channel and instantiated.When a Chaincode gets instantiated a policy (endorsing) has to be defined. [consensus: before a transaction can be recorded in the ledger only if a rule is met]

I know, it’s a lot to take in but we’ll use the Tuna Fish Application’s chain code in the next chapter and then it should be easy to digest.

This is a 10 part series.Please tap or click “♥︎” to help recommend this article to others and stay updated!You can reach me on Twitter, Medium or LinkedIn.Source: Linux Foundation, Whitepapers of Bitcoin, Ethereum

Nandri,

Moses Sam Paul

Image for post
Image for post
Chapter 9: Chaincode in Tunafish Scenario
Image for post
Image for post
Chapter 8: Understading Hyperledger Fabric Chain code
Image for post
Image for post
Chapter 7: Installing Hyperledger Fabric
Image for post
Image for post

This story is published in The Startup, Medium’s largest entrepreneurship publication followed by 321,672+ people.

Subscribe to receive our top stories here.

Image for post
Image for post

The Startup

Medium's largest active publication, followed by +719K people. Follow to join our community.

Moses Sam Paul

Written by

Bachelor: Information Technology; Master: Public Policy; Now: Growing www.heptagon.in; Building #SkillsChain; Curating @OpenHouse332

The Startup

Medium's largest active publication, followed by +719K people. Follow to join our community.

Moses Sam Paul

Written by

Bachelor: Information Technology; Master: Public Policy; Now: Growing www.heptagon.in; Building #SkillsChain; Curating @OpenHouse332

The Startup

Medium's largest active publication, followed by +719K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store