284 lines
7.5 KiB
Go
284 lines
7.5 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package keylevelep
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/hyperledger/fabric-chaincode-go/pkg/statebased"
|
|
"github.com/hyperledger/fabric-chaincode-go/shim"
|
|
pb "github.com/hyperledger/fabric-protos-go/peer"
|
|
)
|
|
|
|
/*
|
|
EndorsementCC is an example chaincode that uses state-based endorsement.
|
|
In the init function, it creates two KVS states, one public, one private, that
|
|
can then be modified through chaincode functions that use the state-based
|
|
endorsement chaincode convenience layer. The following chaincode functions
|
|
are provided:
|
|
-) "addorgs": supply a list of MSP IDs that will be added to the
|
|
|
|
state's endorsement policy
|
|
|
|
-) "delorgs": supply a list of MSP IDs that will be removed from
|
|
|
|
the state's endorsement policy
|
|
|
|
-) "delep": delete the key-level endorsement policy for the state altogether
|
|
-) "listorgs": list the orgs included in the state's endorsement policy
|
|
*/
|
|
type EndorsementCC struct{}
|
|
|
|
// Init callback
|
|
func (cc *EndorsementCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
|
|
err := stub.PutState("pub", []byte("foo"))
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
return shim.Success(nil)
|
|
}
|
|
|
|
// Invoke dispatcher
|
|
func (cc *EndorsementCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
|
|
funcName, _ := stub.GetFunctionAndParameters()
|
|
if function, ok := functions[funcName]; ok {
|
|
return function(stub)
|
|
}
|
|
return shim.Error(fmt.Sprintf("Unknown function %s", funcName))
|
|
}
|
|
|
|
// function dispatch map used by Invoke()
|
|
var functions = map[string]func(stub shim.ChaincodeStubInterface) pb.Response{
|
|
"addorgs": addOrgs,
|
|
"delorgs": delOrgs,
|
|
"listorgs": listOrgs,
|
|
"delep": delEP,
|
|
"setval": setVal,
|
|
"getval": getVal,
|
|
"cc2cc": invokeCC,
|
|
}
|
|
|
|
// addOrgs adds the list of MSP IDs from the invocation parameters
|
|
// to the state's endorsement policy
|
|
func addOrgs(stub shim.ChaincodeStubInterface) pb.Response {
|
|
_, parameters := stub.GetFunctionAndParameters()
|
|
if len(parameters) < 2 {
|
|
return shim.Error("No orgs to add specified")
|
|
}
|
|
|
|
// get the endorsement policy for the key
|
|
var epBytes []byte
|
|
var err error
|
|
if parameters[0] == "pub" {
|
|
epBytes, err = stub.GetStateValidationParameter("pub")
|
|
} else if parameters[0] == "priv" {
|
|
epBytes, err = stub.GetPrivateDataValidationParameter("col", "priv")
|
|
} else {
|
|
return shim.Error("Unknown key specified")
|
|
}
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
ep, err := statebased.NewStateEP(epBytes)
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
// add organizations to endorsement policy
|
|
err = ep.AddOrgs(statebased.RoleTypePeer, parameters[1:]...)
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
epBytes, err = ep.Policy()
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
// set the modified endorsement policy for the key
|
|
if parameters[0] == "pub" {
|
|
err = stub.SetStateValidationParameter("pub", epBytes)
|
|
} else if parameters[0] == "priv" {
|
|
err = stub.SetPrivateDataValidationParameter("col", "priv", epBytes)
|
|
}
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
return shim.Success([]byte{})
|
|
}
|
|
|
|
// delOrgs removes the list of MSP IDs from the invocation parameters
|
|
// from the state's endorsement policy
|
|
func delOrgs(stub shim.ChaincodeStubInterface) pb.Response {
|
|
_, parameters := stub.GetFunctionAndParameters()
|
|
if len(parameters) < 2 {
|
|
return shim.Error("No orgs to delete specified")
|
|
}
|
|
|
|
// get the endorsement policy for the key
|
|
var epBytes []byte
|
|
var err error
|
|
switch parameters[0] {
|
|
case "pub":
|
|
epBytes, err = stub.GetStateValidationParameter("pub")
|
|
case "priv":
|
|
epBytes, err = stub.GetPrivateDataValidationParameter("col", "priv")
|
|
default:
|
|
return shim.Error("Unknown key specified")
|
|
}
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
ep, err := statebased.NewStateEP(epBytes)
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
// delete organizations from the endorsement policy of that key
|
|
ep.DelOrgs(parameters...)
|
|
epBytes, err = ep.Policy()
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
// set the modified endorsement policy for the key
|
|
if parameters[0] == "pub" {
|
|
err = stub.SetStateValidationParameter("pub", epBytes)
|
|
} else if parameters[0] == "priv" {
|
|
err = stub.SetPrivateDataValidationParameter("col", "priv", epBytes)
|
|
}
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
return shim.Success([]byte{})
|
|
}
|
|
|
|
// listOrgs returns the list of organizations currently part of
|
|
// the state's endorsement policy
|
|
func listOrgs(stub shim.ChaincodeStubInterface) pb.Response {
|
|
_, parameters := stub.GetFunctionAndParameters()
|
|
if len(parameters) < 1 {
|
|
return shim.Error("No key specified")
|
|
}
|
|
|
|
// get the endorsement policy for the key
|
|
var epBytes []byte
|
|
var err error
|
|
switch parameters[0] {
|
|
case "pub":
|
|
epBytes, err = stub.GetStateValidationParameter("pub")
|
|
case "priv":
|
|
epBytes, err = stub.GetPrivateDataValidationParameter("col", "priv")
|
|
default:
|
|
return shim.Error("Unknown key specified")
|
|
}
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
ep, err := statebased.NewStateEP(epBytes)
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
// get the list of organizations in the endorsement policy
|
|
orgs := ep.ListOrgs()
|
|
orgsList, err := json.Marshal(orgs)
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
return shim.Success(orgsList)
|
|
}
|
|
|
|
// delEP deletes the state-based endorsement policy for the key altogether
|
|
func delEP(stub shim.ChaincodeStubInterface) pb.Response {
|
|
_, parameters := stub.GetFunctionAndParameters()
|
|
if len(parameters) < 1 {
|
|
return shim.Error("No key specified")
|
|
}
|
|
|
|
// set the modified endorsement policy for the key to nil
|
|
var err error
|
|
if parameters[0] == "pub" {
|
|
err = stub.SetStateValidationParameter("pub", nil)
|
|
} else if parameters[0] == "priv" {
|
|
err = stub.SetPrivateDataValidationParameter("col", "priv", nil)
|
|
} else {
|
|
return shim.Error("Unknown key specified")
|
|
}
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
return shim.Success([]byte{})
|
|
}
|
|
|
|
// setVal sets the value of the KVS key
|
|
func setVal(stub shim.ChaincodeStubInterface) pb.Response {
|
|
args := stub.GetArgs()
|
|
if len(args) != 3 {
|
|
return shim.Error("setval expects two arguments")
|
|
}
|
|
var err error
|
|
if string(args[1]) == "pub" {
|
|
err = stub.PutState("pub", args[2])
|
|
} else if string(args[1]) == "priv" {
|
|
err = stub.PutPrivateData("col", "priv", args[2])
|
|
} else if string(args[1]) == "both" {
|
|
err = stub.PutState("pub", args[2])
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
err = stub.PutPrivateData("col", "priv", args[2])
|
|
} else {
|
|
return shim.Error("Unknown key specified")
|
|
}
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
return shim.Success([]byte{})
|
|
}
|
|
|
|
// getVal retrieves the value of the KVS key
|
|
func getVal(stub shim.ChaincodeStubInterface) pb.Response {
|
|
args := stub.GetArgs()
|
|
if len(args) != 2 {
|
|
return shim.Error("No key specified")
|
|
}
|
|
var err error
|
|
var val []byte
|
|
if string(args[1]) == "pub" {
|
|
val, err = stub.GetState("pub")
|
|
} else if string(args[1]) == "priv" {
|
|
val, err = stub.GetPrivateData("col", "priv")
|
|
} else {
|
|
return shim.Error("Unknown key specified")
|
|
}
|
|
if err != nil {
|
|
return shim.Error(err.Error())
|
|
}
|
|
|
|
return shim.Success(val)
|
|
}
|
|
|
|
// invokeCC is used for chaincode to chaincode invocation of a given cc on another channel
|
|
func invokeCC(stub shim.ChaincodeStubInterface) pb.Response {
|
|
args := stub.GetArgs()
|
|
if len(args) < 3 {
|
|
return shim.Error("cc2cc expects at least two arguments (channel and chaincode)")
|
|
}
|
|
channel := string(args[1])
|
|
cc := string(args[2])
|
|
nargs := args[3:]
|
|
resp := stub.InvokeChaincode(cc, nargs, channel)
|
|
return resp
|
|
}
|