-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FAB-8824] CC sample for state-based endorsement
This example chaincode demonstrates state-based endorsement, leveraging the chaincode convenience layer. Change-Id: I1cb34e2617a1068d5631b9d1b7040d938eab70e4 Signed-off-by: Matthias Neugschwandtner <[email protected]> Signed-off-by: Alessandro Sorniotti <[email protected]>
- Loading branch information
Matthias Neugschwandtner
committed
Sep 5, 2018
1 parent
63c34a6
commit 7c4311f
Showing
1 changed file
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/hyperledger/fabric/core/chaincode/shim" | ||
"github.com/hyperledger/fabric/core/chaincode/shim/ext/statebased" | ||
pb "github.com/hyperledger/fabric/protos/peer" | ||
) | ||
|
||
/* | ||
EndorsementCC is an example chaincode that uses state-based endorsement. | ||
In the init function, it creates a single KVS state "endorsed_state" 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 json-encoded MSP IDs that will be added to the | ||
state's endorsement policy | ||
-) "delorgs": supply a list of json-encoded 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("endorsed_state", []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, | ||
} | ||
|
||
// addOrgs adds the list of json-encoded 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) == 0 { | ||
return shim.Error("No orgs to add specified") | ||
} | ||
|
||
// get the endorsement policy for the key | ||
epBytes, err := stub.GetStateValidationParameter("endorsed_state") | ||
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...) | ||
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 | ||
err = stub.SetStateValidationParameter("endorsed_state", epBytes) | ||
if err != nil { | ||
return shim.Error(err.Error()) | ||
} | ||
|
||
return shim.Success([]byte{}) | ||
} | ||
|
||
// delOrgs adds the list of json-encoded 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) == 0 { | ||
return shim.Error("No orgs to delete specified") | ||
} | ||
|
||
// get the endorsement policy for the key | ||
epBytes, err := stub.GetStateValidationParameter("endorsed_state") | ||
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 | ||
err = stub.SetStateValidationParameter("endorsed_state", 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 { | ||
// get the endorsement policy for the key | ||
epBytes, err := stub.GetStateValidationParameter("endorsed_state") | ||
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 { | ||
// set the modified endorsement policy for the key to nil | ||
err := stub.SetStateValidationParameter("endorsed_state", nil) | ||
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) != 2 { | ||
return shim.Error("setval expects one argument") | ||
} | ||
err := stub.PutState("endorsed_state", args[1]) | ||
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 { | ||
val, err := stub.GetState("endorsed_state") | ||
if err != nil { | ||
return shim.Error(err.Error()) | ||
} | ||
return shim.Success(val) | ||
} | ||
|
||
func main() { | ||
err := shim.Start(new(EndorsementCC)) | ||
if err != nil { | ||
fmt.Printf("Error starting chaincode: %s", err) | ||
} | ||
} |