github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/examples/chaincode/go/map/map.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"strconv"
    23  	"time"
    24  
    25  	"github.com/hyperledger/fabric/core/chaincode/shim"
    26  	pb "github.com/hyperledger/fabric/protos/peer"
    27  )
    28  
    29  // This chaincode implements a simple map that is stored in the state.
    30  // The following operations are available.
    31  
    32  // Invoke operations
    33  // put - requires two arguments, a key and value
    34  // remove - requires a key
    35  // get - requires one argument, a key, and returns a value
    36  // keys - requires no arguments, returns all keys
    37  
    38  // SimpleChaincode example simple Chaincode implementation
    39  type SimpleChaincode struct {
    40  }
    41  
    42  // Init is a no-op
    43  func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
    44  	return shim.Success(nil)
    45  }
    46  
    47  // Invoke has two functions
    48  // put - takes two arguments, a key and value, and stores them in the state
    49  // remove - takes one argument, a key, and removes if from the state
    50  func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
    51  	function, args := stub.GetFunctionAndParameters()
    52  	switch function {
    53  	case "put":
    54  		if len(args) < 2 {
    55  			return shim.Error("put operation must include two arguments, a key and value")
    56  		}
    57  		key := args[0]
    58  		value := args[1]
    59  
    60  		if err := stub.PutState(key, []byte(value)); err != nil {
    61  			fmt.Printf("Error putting state %s", err)
    62  			return shim.Error(fmt.Sprintf("put operation failed. Error updating state: %s", err))
    63  		}
    64  
    65  		indexName := "compositeKeyTest"
    66  		compositeKeyTestIndex, err := stub.CreateCompositeKey(indexName, []string{key})
    67  		if err != nil {
    68  			return shim.Error(err.Error())
    69  		}
    70  
    71  		valueByte := []byte{0x00}
    72  		if err := stub.PutState(compositeKeyTestIndex, valueByte); err != nil {
    73  			fmt.Printf("Error putting state with compositeKey %s", err)
    74  			return shim.Error(fmt.Sprintf("put operation failed. Error updating state with compositeKey: %s", err))
    75  		}
    76  
    77  		return shim.Success(nil)
    78  
    79  	case "remove":
    80  		if len(args) < 1 {
    81  			return shim.Error("remove operation must include one argument, a key")
    82  		}
    83  		key := args[0]
    84  
    85  		err := stub.DelState(key)
    86  		if err != nil {
    87  			return shim.Error(fmt.Sprintf("remove operation failed. Error updating state: %s", err))
    88  		}
    89  		return shim.Success(nil)
    90  
    91  	case "get":
    92  		if len(args) < 1 {
    93  			return shim.Error("get operation must include one argument, a key")
    94  		}
    95  		key := args[0]
    96  		value, err := stub.GetState(key)
    97  		if err != nil {
    98  			return shim.Error(fmt.Sprintf("get operation failed. Error accessing state: %s", err))
    99  		}
   100  		return shim.Success(value)
   101  
   102  	case "keys":
   103  		if len(args) < 2 {
   104  			return shim.Error("put operation must include two arguments, a key and value")
   105  		}
   106  		startKey := args[0]
   107  		endKey := args[1]
   108  
   109  		//sleep needed to test peer's timeout behavior when using iterators
   110  		stime := 0
   111  		if len(args) > 2 {
   112  			stime, _ = strconv.Atoi(args[2])
   113  		}
   114  
   115  		keysIter, err := stub.GetStateByRange(startKey, endKey)
   116  		if err != nil {
   117  			return shim.Error(fmt.Sprintf("keys operation failed. Error accessing state: %s", err))
   118  		}
   119  		defer keysIter.Close()
   120  
   121  		var keys []string
   122  		for keysIter.HasNext() {
   123  			//if sleeptime is specied, take a nap
   124  			if stime > 0 {
   125  				time.Sleep(time.Duration(stime) * time.Millisecond)
   126  			}
   127  
   128  			response, iterErr := keysIter.Next()
   129  			if iterErr != nil {
   130  				return shim.Error(fmt.Sprintf("keys operation failed. Error accessing state: %s", err))
   131  			}
   132  			keys = append(keys, response.Key)
   133  		}
   134  
   135  		for key, value := range keys {
   136  			fmt.Printf("key %d contains %s\n", key, value)
   137  		}
   138  
   139  		jsonKeys, err := json.Marshal(keys)
   140  		if err != nil {
   141  			return shim.Error(fmt.Sprintf("keys operation failed. Error marshaling JSON: %s", err))
   142  		}
   143  
   144  		return shim.Success(jsonKeys)
   145  	case "query":
   146  		query := args[0]
   147  		keysIter, err := stub.GetQueryResult(query)
   148  		if err != nil {
   149  			return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
   150  		}
   151  		defer keysIter.Close()
   152  
   153  		var keys []string
   154  		for keysIter.HasNext() {
   155  			response, iterErr := keysIter.Next()
   156  			if iterErr != nil {
   157  				return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
   158  			}
   159  			keys = append(keys, response.Key)
   160  		}
   161  
   162  		jsonKeys, err := json.Marshal(keys)
   163  		if err != nil {
   164  			return shim.Error(fmt.Sprintf("query operation failed. Error marshaling JSON: %s", err))
   165  		}
   166  
   167  		return shim.Success(jsonKeys)
   168  	case "history":
   169  		key := args[0]
   170  		keysIter, err := stub.GetHistoryForKey(key)
   171  		if err != nil {
   172  			return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
   173  		}
   174  		defer keysIter.Close()
   175  
   176  		var keys []string
   177  		for keysIter.HasNext() {
   178  			response, iterErr := keysIter.Next()
   179  			if iterErr != nil {
   180  				return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
   181  			}
   182  			keys = append(keys, response.TxId)
   183  		}
   184  
   185  		for key, txID := range keys {
   186  			fmt.Printf("key %d contains %s\n", key, txID)
   187  		}
   188  
   189  		jsonKeys, err := json.Marshal(keys)
   190  		if err != nil {
   191  			return shim.Error(fmt.Sprintf("query operation failed. Error marshaling JSON: %s", err))
   192  		}
   193  
   194  		return shim.Success(jsonKeys)
   195  
   196  	default:
   197  		return shim.Success([]byte("Unsupported operation"))
   198  	}
   199  }
   200  
   201  func main() {
   202  	err := shim.Start(new(SimpleChaincode))
   203  	if err != nil {
   204  		fmt.Printf("Error starting chaincode: %s", err)
   205  	}
   206  }