github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/integration/chaincode/simple/chaincode.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package simple
     8  
     9  import (
    10  	"fmt"
    11  	"os"
    12  	"strconv"
    13  
    14  	"github.com/hyperledger/fabric-chaincode-go/shim"
    15  	pb "github.com/hyperledger/fabric-protos-go/peer"
    16  )
    17  
    18  // SimpleChaincode example simple Chaincode implementation
    19  type SimpleChaincode struct {
    20  }
    21  
    22  func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
    23  	fmt.Println("Init invoked")
    24  	_, args := stub.GetFunctionAndParameters()
    25  	var A, B string    // Entities
    26  	var Aval, Bval int // Asset holdings
    27  	var err error
    28  
    29  	if len(args) != 4 {
    30  		return shim.Error("Incorrect number of arguments. Expecting 4")
    31  	}
    32  
    33  	// Initialize the chaincode
    34  	A = args[0]
    35  	Aval, err = strconv.Atoi(args[1])
    36  	if err != nil {
    37  		return shim.Error("Expecting integer value for asset holding")
    38  	}
    39  	B = args[2]
    40  	Bval, err = strconv.Atoi(args[3])
    41  	if err != nil {
    42  		return shim.Error("Expecting integer value for asset holding")
    43  	}
    44  	fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
    45  
    46  	// Write the state to the ledger
    47  	err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
    48  	if err != nil {
    49  		return shim.Error(err.Error())
    50  	}
    51  
    52  	err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
    53  	if err != nil {
    54  		return shim.Error(err.Error())
    55  	}
    56  
    57  	fmt.Println("Init returning with success")
    58  	return shim.Success(nil)
    59  }
    60  
    61  func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
    62  	fmt.Println("ex02 Invoke")
    63  	if os.Getenv("DEVMODE_ENABLED") != "" {
    64  		fmt.Println("invoking in devmode")
    65  	}
    66  	function, args := stub.GetFunctionAndParameters()
    67  	switch function {
    68  	case "invoke":
    69  		// Make payment of X units from A to B
    70  		return t.invoke(stub, args)
    71  	case "delete":
    72  		// Deletes an entity from its state
    73  		return t.delete(stub, args)
    74  	case "query":
    75  		// the old "Query" is now implemtned in invoke
    76  		return t.query(stub, args)
    77  	case "respond":
    78  		// return with an error
    79  		return t.respond(stub, args)
    80  	case "mspid":
    81  		// Checks the shim's GetMSPID() API
    82  		return t.mspid(args)
    83  	default:
    84  		return shim.Error(`Invalid invoke function name. Expecting "invoke", "delete", "query", "respond", or "mspid"`)
    85  	}
    86  }
    87  
    88  // Transaction makes payment of X units from A to B
    89  func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    90  	var A, B string    // Entities
    91  	var Aval, Bval int // Asset holdings
    92  	var X int          // Transaction value
    93  	var err error
    94  
    95  	if len(args) != 3 {
    96  		return shim.Error("Incorrect number of arguments. Expecting 3")
    97  	}
    98  
    99  	A = args[0]
   100  	B = args[1]
   101  
   102  	// Get the state from the ledger
   103  	// TODO: will be nice to have a GetAllState call to ledger
   104  	Avalbytes, err := stub.GetState(A)
   105  	if err != nil {
   106  		return shim.Error("Failed to get state")
   107  	}
   108  	if Avalbytes == nil {
   109  		return shim.Error("Entity not found")
   110  	}
   111  	Aval, _ = strconv.Atoi(string(Avalbytes))
   112  
   113  	Bvalbytes, err := stub.GetState(B)
   114  	if err != nil {
   115  		return shim.Error("Failed to get state")
   116  	}
   117  	if Bvalbytes == nil {
   118  		return shim.Error("Entity not found")
   119  	}
   120  	Bval, _ = strconv.Atoi(string(Bvalbytes))
   121  
   122  	// Perform the execution
   123  	X, err = strconv.Atoi(args[2])
   124  	if err != nil {
   125  		return shim.Error("Invalid transaction amount, expecting a integer value")
   126  	}
   127  	Aval = Aval - X
   128  	Bval = Bval + X
   129  	fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
   130  
   131  	// Write the state back to the ledger
   132  	err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
   133  	if err != nil {
   134  		return shim.Error(err.Error())
   135  	}
   136  
   137  	err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
   138  	if err != nil {
   139  		return shim.Error(err.Error())
   140  	}
   141  
   142  	return shim.Success(nil)
   143  }
   144  
   145  // Deletes an entity from state
   146  func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
   147  	if len(args) != 1 {
   148  		return shim.Error("Incorrect number of arguments. Expecting 1")
   149  	}
   150  
   151  	A := args[0]
   152  
   153  	// Delete the key from the state in ledger
   154  	err := stub.DelState(A)
   155  	if err != nil {
   156  		return shim.Error("Failed to delete state")
   157  	}
   158  
   159  	return shim.Success(nil)
   160  }
   161  
   162  // query callback representing the query of a chaincode
   163  func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
   164  	var A string // Entities
   165  	var err error
   166  
   167  	if len(args) != 1 {
   168  		return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
   169  	}
   170  
   171  	A = args[0]
   172  
   173  	// Get the state from the ledger
   174  	Avalbytes, err := stub.GetState(A)
   175  	if err != nil {
   176  		jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
   177  		return shim.Error(jsonResp)
   178  	}
   179  
   180  	if Avalbytes == nil {
   181  		jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
   182  		return shim.Error(jsonResp)
   183  	}
   184  
   185  	jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
   186  	fmt.Printf("Query Response:%s\n", jsonResp)
   187  	return shim.Success(Avalbytes)
   188  }
   189  
   190  // respond simply generates a response payload from the args
   191  func (t *SimpleChaincode) respond(stub shim.ChaincodeStubInterface, args []string) pb.Response {
   192  	if len(args) != 3 {
   193  		return shim.Error("expected three arguments")
   194  	}
   195  
   196  	status, err := strconv.ParseInt(args[0], 10, 32)
   197  	if err != nil {
   198  		return shim.Error(err.Error())
   199  	}
   200  	message := args[1]
   201  	payload := []byte(args[2])
   202  
   203  	return pb.Response{
   204  		Status:  int32(status),
   205  		Message: message,
   206  		Payload: payload,
   207  	}
   208  }
   209  
   210  // mspid simply calls shim.GetMSPID() to verify the mspid was properly passed from the peer
   211  // via the CORE_PEER_LOCALMSPID env var
   212  func (t *SimpleChaincode) mspid(args []string) pb.Response {
   213  	if len(args) != 0 {
   214  		return shim.Error("expected no arguments")
   215  	}
   216  
   217  	// Get the mspid from the env var
   218  	mspid, err := shim.GetMSPID()
   219  	if err != nil {
   220  		jsonResp := "{\"Error\":\"Failed to get mspid\"}"
   221  		return shim.Error(jsonResp)
   222  	}
   223  
   224  	if mspid == "" {
   225  		jsonResp := "{\"Error\":\"Empty mspid\"}"
   226  		return shim.Error(jsonResp)
   227  	}
   228  
   229  	fmt.Printf("MSPID:%s\n", mspid)
   230  	return shim.Success([]byte(mspid))
   231  }