BYFN Chaincode - chaincode_example02.go

Q

What is the chaincode in Golang used in BYFN (Build Your First Network)?

✍: FYIcenter.com

A

The chaincode in Golang used in BYFN (Build Your First Network) is located in the chaincode_example02.go file and localed in hyperledger-binaries/fabric-samples/chaincode/chaincode_example02/go/ directory:

$ cd hyperledger-binaries/fabric-samples
$ more chaincode/chaincode_example02/go/chaincode_example02.go

/* Copyright IBM Corp. 2016 All Rights Reserved.
*/

package main

//WARNING - this chaincode's ID is hard-coded in chaincode_example04 to illustrate one way of
//calling chaincode from a chaincode. If this example is modified, chaincode_example04.go has
//to be modified as well with the new ID of chaincode_example02.

//chaincode_example05 show's how chaincode ID can be passed in as a parameter instead of
//hard-coding.

import (
   "fmt"
   "strconv"
   "github.com/hyperledger/fabric/core/chaincode/shim"
   pb "github.com/hyperledger/fabric/protos/peer"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
   fmt.Println("ex02 Init")
   _, args := stub.GetFunctionAndParameters()
   var A, B string    // Entities
   var Aval, Bval int // Asset holdings
   var err error
   if len(args) != 4 {
      return shim.Error("Incorrect number of arguments. Expecting 4")
   }

   // Initialize the chaincode
   A = args[0]
   Aval, err = strconv.Atoi(args[1])
   if err != nil {
      return shim.Error("Expecting integer value for asset holding")
   }
   B = args[2]
   Bval, err = strconv.Atoi(args[3])
   if err != nil {
      return shim.Error("Expecting integer value for asset holding")
   }
   fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)

   // Write the state to the ledger
   err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
   if err != nil {
      return shim.Error(err.Error())
   }

   err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
   if err != nil {
      return shim.Error(err.Error())
   }

   return shim.Success(nil)
}

func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
   fmt.Println("ex02 Invoke")
   function, args := stub.GetFunctionAndParameters()
   if function == "invoke" {
      // Make payment of X units from A to B
      return t.invoke(stub, args)
   } else if function == "delete" {
      // Deletes an entity from its state
      return t.delete(stub, args)
   } else if function == "query" {
      // the old "Query" is now implemtned in invoke
      return t.query(stub, args)
   }

   return shim.Error
   ("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")
}

// Transaction makes payment of X units from A to B
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string
) pb.Response {
   var A, B string    // Entities
   var Aval, Bval int // Asset holdings
   var X int     // Transaction value
   var err error

   if len(args) != 3 {
      return shim.Error("Incorrect number of arguments. Expecting 3")
   }
   A = args[0]
   B = args[1]

   // Get the state from the ledger
   // TODO: will be nice to have a GetAllState call to ledger
   Avalbytes, err := stub.GetState(A)
   if err != nil {
      return shim.Error("Failed to get state")
   }
   if Avalbytes == nil {
      return shim.Error("Entity not found")
   }
   Aval, _ = strconv.Atoi(string(Avalbytes))

   Bvalbytes, err := stub.GetState(B)
   if err != nil {
      return shim.Error("Failed to get state")
   }
   if Bvalbytes == nil {
      return shim.Error("Entity not found")
   }
   Bval, _ = strconv.Atoi(string(Bvalbytes))

   // Perform the execution
   X, err = strconv.Atoi(args[2])
   if err != nil {
      return shim.Error("Invalid transaction amount, expecting a integer value")
   }
   Aval = Aval - X
   Bval = Bval + X
   fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)

   // Write the state back to the ledger
   err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
   if err != nil {
      return shim.Error(err.Error())
   }

   err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
   if err != nil {
      return shim.Error(err.Error())
   }

   return shim.Success(nil)
}

// Deletes an entity from state
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string
) pb.Response {
   if len(args) != 1 {
      return shim.Error("Incorrect number of arguments. Expecting 1")
   }
   A := args[0]

   // Delete the key from the state in ledger
   err := stub.DelState(A)
   if err != nil {
      return shim.Error("Failed to delete state")
   }

   return shim.Success(nil)
}

// query callback representing the query of a chaincode
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string)
 pb.Response {
   var A string // Entities
   var err error

   if len(args) != 1 {
      return shim.Error
      ("Incorrect number of arguments. Expecting name of the person to query")
   }

   A = args[0]

   // Get the state from the ledger
   Avalbytes, err := stub.GetState(A)
   if err != nil {
      jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
      return shim.Error(jsonResp)
   }

   if Avalbytes == nil {
      jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
      return shim.Error(jsonResp)
   }

   jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes)+ "\"}"
   fmt.Printf("Query Response:%s\n", jsonResp)
   return shim.Success(Avalbytes)
}

func main() {
   err := shim.Start(new(SimpleChaincode))
   if err != nil {
      fmt.Printf("Error starting Simple chaincode: %s", err)
   }
}

The same chaincode file is also deployed on the BYFN CLI conainer:

$ docker exec -it cli bash

bash-4.4# echo $GOPATH
/opt/gopath

bash-4.4# ls -l $GOPATH/src/github.com/chaincode/chaincode_example02/go\
   /chaincode_example02.go

-rw-rw-r--  1 1000  1000  5436 Feb 21 23:01 /opt/gopath/src/github.com/chaincode\
   /chaincode_example02/go/chaincode_example02.go

 

Install Chaincode on BYFN Peers

Update Anchor Peer of Each BYFN Organization

Hyperledger Fabric Sample Networks

⇑⇑ Hyperledger Tutorials

2019-04-13, 242👍, 0💬