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

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package keylevelep
     8  
     9  import (
    10  	"encoding/json"
    11  	"fmt"
    12  
    13  	"github.com/hyperledger/fabric-chaincode-go/pkg/statebased"
    14  	"github.com/hyperledger/fabric-chaincode-go/shim"
    15  	pb "github.com/hyperledger/fabric-protos-go/peer"
    16  )
    17  
    18  /*
    19  EndorsementCC is an example chaincode that uses state-based endorsement.
    20  In the init function, it creates two KVS states, one public, one private, that
    21  can then be modified through chaincode functions that use the state-based
    22  endorsement chaincode convenience layer. The following chaincode functions
    23  are provided:
    24  -) "addorgs": supply a list of MSP IDs that will be added to the
    25     state's endorsement policy
    26  -) "delorgs": supply a list of MSP IDs that will be removed from
    27     the state's endorsement policy
    28  -) "delep": delete the key-level endorsement policy for the state altogether
    29  -) "listorgs": list the orgs included in the state's endorsement policy
    30  */
    31  type EndorsementCC struct {
    32  }
    33  
    34  // Init callback
    35  func (cc *EndorsementCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
    36  	err := stub.PutState("pub", []byte("foo"))
    37  	if err != nil {
    38  		return shim.Error(err.Error())
    39  	}
    40  	return shim.Success(nil)
    41  }
    42  
    43  // Invoke dispatcher
    44  func (cc *EndorsementCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
    45  	funcName, _ := stub.GetFunctionAndParameters()
    46  	if function, ok := functions[funcName]; ok {
    47  		return function(stub)
    48  	}
    49  	return shim.Error(fmt.Sprintf("Unknown function %s", funcName))
    50  }
    51  
    52  // function dispatch map used by Invoke()
    53  var functions = map[string]func(stub shim.ChaincodeStubInterface) pb.Response{
    54  	"addorgs":  addOrgs,
    55  	"delorgs":  delOrgs,
    56  	"listorgs": listOrgs,
    57  	"delep":    delEP,
    58  	"setval":   setVal,
    59  	"getval":   getVal,
    60  	"cc2cc":    invokeCC,
    61  }
    62  
    63  // addOrgs adds the list of MSP IDs from the invocation parameters
    64  // to the state's endorsement policy
    65  func addOrgs(stub shim.ChaincodeStubInterface) pb.Response {
    66  	_, parameters := stub.GetFunctionAndParameters()
    67  	if len(parameters) < 2 {
    68  		return shim.Error("No orgs to add specified")
    69  	}
    70  
    71  	// get the endorsement policy for the key
    72  	var epBytes []byte
    73  	var err error
    74  	if parameters[0] == "pub" {
    75  		epBytes, err = stub.GetStateValidationParameter("pub")
    76  	} else if parameters[0] == "priv" {
    77  		epBytes, err = stub.GetPrivateDataValidationParameter("col", "priv")
    78  	} else {
    79  		return shim.Error("Unknown key specified")
    80  	}
    81  	if err != nil {
    82  		return shim.Error(err.Error())
    83  	}
    84  	ep, err := statebased.NewStateEP(epBytes)
    85  	if err != nil {
    86  		return shim.Error(err.Error())
    87  	}
    88  
    89  	// add organizations to endorsement policy
    90  	err = ep.AddOrgs(statebased.RoleTypePeer, parameters[1:]...)
    91  	if err != nil {
    92  		return shim.Error(err.Error())
    93  	}
    94  	epBytes, err = ep.Policy()
    95  	if err != nil {
    96  		return shim.Error(err.Error())
    97  	}
    98  
    99  	// set the modified endorsement policy for the key
   100  	if parameters[0] == "pub" {
   101  		err = stub.SetStateValidationParameter("pub", epBytes)
   102  	} else if parameters[0] == "priv" {
   103  		err = stub.SetPrivateDataValidationParameter("col", "priv", epBytes)
   104  	}
   105  	if err != nil {
   106  		return shim.Error(err.Error())
   107  	}
   108  
   109  	return shim.Success([]byte{})
   110  }
   111  
   112  // delOrgs removes the list of MSP IDs from the invocation parameters
   113  // from the state's endorsement policy
   114  func delOrgs(stub shim.ChaincodeStubInterface) pb.Response {
   115  	_, parameters := stub.GetFunctionAndParameters()
   116  	if len(parameters) < 2 {
   117  		return shim.Error("No orgs to delete specified")
   118  	}
   119  
   120  	// get the endorsement policy for the key
   121  	var epBytes []byte
   122  	var err error
   123  	switch parameters[0] {
   124  	case "pub":
   125  		epBytes, err = stub.GetStateValidationParameter("pub")
   126  	case "priv":
   127  		epBytes, err = stub.GetPrivateDataValidationParameter("col", "priv")
   128  	default:
   129  		return shim.Error("Unknown key specified")
   130  	}
   131  	if err != nil {
   132  		return shim.Error(err.Error())
   133  	}
   134  
   135  	ep, err := statebased.NewStateEP(epBytes)
   136  	if err != nil {
   137  		return shim.Error(err.Error())
   138  	}
   139  
   140  	// delete organizations from the endorsement policy of that key
   141  	ep.DelOrgs(parameters...)
   142  	epBytes, err = ep.Policy()
   143  	if err != nil {
   144  		return shim.Error(err.Error())
   145  	}
   146  
   147  	// set the modified endorsement policy for the key
   148  	if parameters[0] == "pub" {
   149  		err = stub.SetStateValidationParameter("pub", epBytes)
   150  	} else if parameters[0] == "priv" {
   151  		err = stub.SetPrivateDataValidationParameter("col", "priv", epBytes)
   152  	}
   153  	if err != nil {
   154  		return shim.Error(err.Error())
   155  	}
   156  
   157  	return shim.Success([]byte{})
   158  }
   159  
   160  // listOrgs returns the list of organizations currently part of
   161  // the state's endorsement policy
   162  func listOrgs(stub shim.ChaincodeStubInterface) pb.Response {
   163  	_, parameters := stub.GetFunctionAndParameters()
   164  	if len(parameters) < 1 {
   165  		return shim.Error("No key specified")
   166  	}
   167  
   168  	// get the endorsement policy for the key
   169  	var epBytes []byte
   170  	var err error
   171  	switch parameters[0] {
   172  	case "pub":
   173  		epBytes, err = stub.GetStateValidationParameter("pub")
   174  	case "priv":
   175  		epBytes, err = stub.GetPrivateDataValidationParameter("col", "priv")
   176  	default:
   177  		return shim.Error("Unknown key specified")
   178  	}
   179  	if err != nil {
   180  		return shim.Error(err.Error())
   181  	}
   182  
   183  	ep, err := statebased.NewStateEP(epBytes)
   184  	if err != nil {
   185  		return shim.Error(err.Error())
   186  	}
   187  
   188  	// get the list of organizations in the endorsement policy
   189  	orgs := ep.ListOrgs()
   190  	orgsList, err := json.Marshal(orgs)
   191  	if err != nil {
   192  		return shim.Error(err.Error())
   193  	}
   194  
   195  	return shim.Success(orgsList)
   196  }
   197  
   198  // delEP deletes the state-based endorsement policy for the key altogether
   199  func delEP(stub shim.ChaincodeStubInterface) pb.Response {
   200  	_, parameters := stub.GetFunctionAndParameters()
   201  	if len(parameters) < 1 {
   202  		return shim.Error("No key specified")
   203  	}
   204  
   205  	// set the modified endorsement policy for the key to nil
   206  	var err error
   207  	if parameters[0] == "pub" {
   208  		err = stub.SetStateValidationParameter("pub", nil)
   209  	} else if parameters[0] == "priv" {
   210  		err = stub.SetPrivateDataValidationParameter("col", "priv", nil)
   211  	} else {
   212  		return shim.Error("Unknown key specified")
   213  	}
   214  	if err != nil {
   215  		return shim.Error(err.Error())
   216  	}
   217  
   218  	return shim.Success([]byte{})
   219  }
   220  
   221  // setVal sets the value of the KVS key
   222  func setVal(stub shim.ChaincodeStubInterface) pb.Response {
   223  	args := stub.GetArgs()
   224  	if len(args) != 3 {
   225  		return shim.Error("setval expects two arguments")
   226  	}
   227  	var err error
   228  	if string(args[1]) == "pub" {
   229  		err = stub.PutState("pub", args[2])
   230  	} else if string(args[1]) == "priv" {
   231  		err = stub.PutPrivateData("col", "priv", args[2])
   232  	} else {
   233  		return shim.Error("Unknown key specified")
   234  	}
   235  	if err != nil {
   236  		return shim.Error(err.Error())
   237  	}
   238  	return shim.Success([]byte{})
   239  }
   240  
   241  // getVal retrieves the value of the KVS key
   242  func getVal(stub shim.ChaincodeStubInterface) pb.Response {
   243  	args := stub.GetArgs()
   244  	if len(args) != 2 {
   245  		return shim.Error("No key specified")
   246  	}
   247  	var err error
   248  	var val []byte
   249  	if string(args[1]) == "pub" {
   250  		val, err = stub.GetState("pub")
   251  	} else if string(args[1]) == "priv" {
   252  		val, err = stub.GetPrivateData("col", "priv")
   253  	} else {
   254  		return shim.Error("Unknown key specified")
   255  	}
   256  	if err != nil {
   257  		return shim.Error(err.Error())
   258  	}
   259  
   260  	return shim.Success(val)
   261  }
   262  
   263  // invokeCC is used for chaincode to chaincode invocation of a given cc on another channel
   264  func invokeCC(stub shim.ChaincodeStubInterface) pb.Response {
   265  	args := stub.GetArgs()
   266  	if len(args) < 3 {
   267  		return shim.Error("cc2cc expects at least two arguments (channel and chaincode)")
   268  	}
   269  	channel := string(args[1])
   270  	cc := string(args[2])
   271  	nargs := args[3:]
   272  	resp := stub.InvokeChaincode(cc, nargs, channel)
   273  	return resp
   274  }