diff --git a/integration/chaincode/keylevelep/chaincode.go b/integration/chaincode/keylevelep/chaincode.go index 8bdadf83fc8..10a2195120e 100644 --- a/integration/chaincode/keylevelep/chaincode.go +++ b/integration/chaincode/keylevelep/chaincode.go @@ -17,7 +17,7 @@ import ( /* EndorsementCC is an example chaincode that uses state-based endorsement. -In the init function, it creates a single KVS state "endorsed_state" that +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: @@ -33,7 +33,7 @@ type EndorsementCC struct { // Init callback func (cc *EndorsementCC) Init(stub shim.ChaincodeStubInterface) pb.Response { - err := stub.PutState("endorsed_state", []byte("foo")) + err := stub.PutState("pub", []byte("foo")) if err != nil { return shim.Error(err.Error()) } @@ -64,12 +64,20 @@ var functions = map[string]func(stub shim.ChaincodeStubInterface) pb.Response{ // to the state's endorsement policy func addOrgs(stub shim.ChaincodeStubInterface) pb.Response { _, parameters := stub.GetFunctionAndParameters() - if len(parameters) == 0 { + if len(parameters) < 2 { return shim.Error("No orgs to add specified") } // get the endorsement policy for the key - epBytes, err := stub.GetStateValidationParameter("endorsed_state") + 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()) } @@ -79,7 +87,7 @@ func addOrgs(stub shim.ChaincodeStubInterface) pb.Response { } // add organizations to endorsement policy - err = ep.AddOrgs(statebased.RoleTypePeer, parameters...) + err = ep.AddOrgs(statebased.RoleTypePeer, parameters[1:]...) if err != nil { return shim.Error(err.Error()) } @@ -89,7 +97,11 @@ func addOrgs(stub shim.ChaincodeStubInterface) pb.Response { } // set the modified endorsement policy for the key - err = stub.SetStateValidationParameter("endorsed_state", epBytes) + 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()) } @@ -101,14 +113,19 @@ func addOrgs(stub shim.ChaincodeStubInterface) pb.Response { // from the state's endorsement policy func delOrgs(stub shim.ChaincodeStubInterface) pb.Response { _, parameters := stub.GetFunctionAndParameters() - if len(parameters) == 0 { + if len(parameters) < 2 { 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()) + 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") } ep, err := statebased.NewStateEP(epBytes) if err != nil { @@ -123,7 +140,11 @@ func delOrgs(stub shim.ChaincodeStubInterface) pb.Response { } // set the modified endorsement policy for the key - err = stub.SetStateValidationParameter("endorsed_state", epBytes) + 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()) } @@ -134,10 +155,20 @@ func delOrgs(stub shim.ChaincodeStubInterface) pb.Response { // 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 - epBytes, err := stub.GetStateValidationParameter("endorsed_state") - if err != nil { - return shim.Error(err.Error()) + 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") } ep, err := statebased.NewStateEP(epBytes) if err != nil { @@ -156,8 +187,20 @@ func listOrgs(stub shim.ChaincodeStubInterface) pb.Response { // 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 - err := stub.SetStateValidationParameter("endorsed_state", 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()) } @@ -168,10 +211,17 @@ func delEP(stub shim.ChaincodeStubInterface) pb.Response { // 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") + 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 { + return shim.Error("Unknown key specified") } - err := stub.PutState("endorsed_state", args[1]) if err != nil { return shim.Error(err.Error()) } @@ -180,10 +230,23 @@ func setVal(stub shim.ChaincodeStubInterface) pb.Response { // getVal retrieves the value of the KVS key func getVal(stub shim.ChaincodeStubInterface) pb.Response { - val, err := stub.GetState("endorsed_state") + 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) } diff --git a/integration/sbe/sbe_suite_test.go b/integration/sbe/sbe_suite_test.go index 798ee7ed309..a8f794ecc51 100644 --- a/integration/sbe/sbe_suite_test.go +++ b/integration/sbe/sbe_suite_test.go @@ -8,6 +8,8 @@ package e2e import ( "encoding/json" + "fmt" + "runtime" "github.com/hyperledger/fabric/integration/nwo" . "github.com/onsi/ginkgo" @@ -24,6 +26,9 @@ func TestEndToEnd(t *testing.T) { var components *nwo.Components var _ = SynchronizedBeforeSuite(func() []byte { + nwo.RequiredImages = []string{ + fmt.Sprintf("hyperledger/fabric-ccenv:%s-latest", runtime.GOARCH), + } components = &nwo.Components{} components.Build() diff --git a/integration/sbe/sbe_test.go b/integration/sbe/sbe_test.go index 208403e1eb7..dccfbc5b1c4 100644 --- a/integration/sbe/sbe_test.go +++ b/integration/sbe/sbe_test.go @@ -35,17 +35,18 @@ var _ = Describe("SBE_E2E", func() { BeforeEach(func() { var err error - testDir, err = ioutil.TempDir("", "e2e") + testDir, err = ioutil.TempDir("", "e2e_sbe") Expect(err).NotTo(HaveOccurred()) client, err = docker.NewClientFromEnv() Expect(err).NotTo(HaveOccurred()) chaincode = nwo.Chaincode{ - Name: "mycc", - Version: "0.0", - Path: "github.com/hyperledger/fabric/integration/chaincode/keylevelep/cmd", - Ctor: `{"Args":["init"]}`, + Name: "mycc", + Version: "0.0", + Path: "github.com/hyperledger/fabric/integration/chaincode/keylevelep/cmd", + Ctor: `{"Args":["init"]}`, + CollectionsConfig: "testdata/collection_config.json", } }) @@ -78,32 +79,58 @@ var _ = Describe("SBE_E2E", func() { By("setting up the channel") network.CreateAndJoinChannel(orderer, "testchannel") - By("deploy first chaincode") + By("updating the anchor peers") + network.UpdateChannelAnchors(orderer, "testchannel") + + By("deploying the chaincode") nwo.DeployChaincode(network, "testchannel", orderer, chaincode) - By("deploy second chaincode") + By("deploying a second instance of the chaincode") chaincode.Name = "mycc2" nwo.DeployChaincode(network, "testchannel", orderer, chaincode) - By("getting the client peer by name") - - RunSBE(network, orderer) + RunSBE(network, orderer, "pub") + RunSBE(network, orderer, "priv") }) }) }) -func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { +func RunSBE(n *nwo.Network, orderer *nwo.Orderer, mode string) { peerOrg1 := n.Peer("Org1", "peer0") - peerOrg2 := n.Peer("Org2", "peer1") - By("org1 adds org1 to the state-based ep of a key") + peerOrg2 := n.Peer("Org2", "peer0") + + By("org1 initializes the key") sess, err := n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeInvoke{ ChannelID: "testchannel", Orderer: n.OrdererAddress(orderer, nwo.ListenPort), Name: "mycc", - Ctor: `{"Args":["addorgs", "Org1MSP"]}`, + Ctor: `{"Args":["setval", "` + mode + `", "foo"]}`, + PeerAddresses: []string{ + n.PeerAddress(peerOrg1, nwo.ListenPort), + }, + WaitForEvent: true, + }) + Expect(err).NotTo(HaveOccurred()) + Eventually(sess, time.Minute).Should(gexec.Exit(0)) + + By("org2 checks that setting the value was successful by reading it") + sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeQuery{ + ChannelID: "testchannel", + Name: "mycc", + Ctor: `{"Args":["getval", "` + mode + `"]}`, + }) + Expect(err).NotTo(HaveOccurred()) + Eventually(sess, time.Minute).Should(gexec.Exit(0)) + Expect(sess).To(gbytes.Say("foo")) + + By("org1 adds org1 to the state-based ep of a key") + sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeInvoke{ + ChannelID: "testchannel", + Orderer: n.OrdererAddress(orderer, nwo.ListenPort), + Name: "mycc", + Ctor: `{"Args":["addorgs", "` + mode + `", "Org1MSP"]}`, PeerAddresses: []string{ n.PeerAddress(peerOrg1, nwo.ListenPort), - n.PeerAddress(peerOrg2, nwo.ListenPort), }, WaitForEvent: true, }) @@ -114,7 +141,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeQuery{ ChannelID: "testchannel", Name: "mycc", - Ctor: `{"Args":["listorgs"]}`, + Ctor: `{"Args":["listorgs", "` + mode + `"]}`, }) Expect(err).NotTo(HaveOccurred()) Eventually(sess, time.Minute).Should(gexec.Exit(0)) @@ -125,7 +152,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { ChannelID: "testchannel", Orderer: n.OrdererAddress(orderer, nwo.ListenPort), Name: "mycc", - Ctor: `{"Args":["setval", "val1"]}`, + Ctor: `{"Args":["setval", "` + mode + `", "val1"]}`, PeerAddresses: []string{ n.PeerAddress(peerOrg1, nwo.ListenPort), }, @@ -134,11 +161,11 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { Expect(err).NotTo(HaveOccurred()) Eventually(sess, time.Minute).Should(gexec.Exit(0)) - By("org1 checks that setting the value was successful by reading it") - sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeQuery{ + By("org2 checks that setting the value was successful by reading it") + sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeQuery{ ChannelID: "testchannel", Name: "mycc", - Ctor: `{"Args":["getval"]}`, + Ctor: `{"Args":["getval", "` + mode + `"]}`, }) Expect(err).NotTo(HaveOccurred()) Eventually(sess, time.Minute).Should(gexec.Exit(0)) @@ -149,7 +176,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { ChannelID: "testchannel", Orderer: n.OrdererAddress(orderer, nwo.ListenPort), Name: "mycc", - Ctor: `{"Args":["setval", "val2"]}`, + Ctor: `{"Args":["setval", "` + mode + `", "val2"]}`, PeerAddresses: []string{ n.PeerAddress(peerOrg2, nwo.ListenPort), }, @@ -162,7 +189,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeQuery{ ChannelID: "testchannel", Name: "mycc", - Ctor: `{"Args":["getval"]}`, + Ctor: `{"Args":["getval", "` + mode + `"]}`, }) Expect(err).NotTo(HaveOccurred()) Eventually(sess, time.Minute).Should(gexec.Exit(0)) @@ -173,7 +200,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { ChannelID: "testchannel", Orderer: n.OrdererAddress(orderer, nwo.ListenPort), Name: "mycc", - Ctor: `{"Args":["addorgs", "Org2MSP"]}`, + Ctor: `{"Args":["addorgs", "` + mode + `", "Org2MSP"]}`, PeerAddresses: []string{ n.PeerAddress(peerOrg1, nwo.ListenPort), }, @@ -186,7 +213,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeQuery{ ChannelID: "testchannel", Name: "mycc", - Ctor: `{"Args":["listorgs"]}`, + Ctor: `{"Args":["listorgs", "` + mode + `"]}`, }) Expect(err).NotTo(HaveOccurred()) Eventually(sess, time.Minute).Should(gexec.Exit(0)) @@ -200,7 +227,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { ChannelID: "testchannel", Orderer: n.OrdererAddress(orderer, nwo.ListenPort), Name: "mycc", - Ctor: `{"Args":["setval", "val3"]}`, + Ctor: `{"Args":["setval", "` + mode + `", "val3"]}`, PeerAddresses: []string{ n.PeerAddress(peerOrg2, nwo.ListenPort), }, @@ -213,7 +240,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeQuery{ ChannelID: "testchannel", Name: "mycc", - Ctor: `{"Args":["getval"]}`, + Ctor: `{"Args":["getval", "` + mode + `"]}`, }) Expect(err).NotTo(HaveOccurred()) Eventually(sess, time.Minute).Should(gexec.Exit(0)) @@ -224,10 +251,10 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { ChannelID: "testchannel", Orderer: n.OrdererAddress(orderer, nwo.ListenPort), Name: "mycc", - Ctor: `{"Args":["setval", "val4"]}`, + Ctor: `{"Args":["setval", "` + mode + `", "val4"]}`, PeerAddresses: []string{ - n.PeerAddress(n.Peer("Org1", "peer0"), nwo.ListenPort), - n.PeerAddress(n.Peer("Org2", "peer1"), nwo.ListenPort), + n.PeerAddress(peerOrg1, nwo.ListenPort), + n.PeerAddress(peerOrg2, nwo.ListenPort), }, WaitForEvent: true, }) @@ -238,7 +265,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeQuery{ ChannelID: "testchannel", Name: "mycc", - Ctor: `{"Args":["getval"]}`, + Ctor: `{"Args":["getval", "` + mode + `"]}`, }) Expect(err).NotTo(HaveOccurred()) Eventually(sess, time.Minute).Should(gexec.Exit(0)) @@ -249,7 +276,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { ChannelID: "testchannel", Orderer: n.OrdererAddress(orderer, nwo.ListenPort), Name: "mycc", - Ctor: `{"Args":["delorgs", "Org1MSP"]}`, + Ctor: `{"Args":["delorgs", "` + mode + `", "Org1MSP"]}`, PeerAddresses: []string{ n.PeerAddress(peerOrg2, nwo.ListenPort), }, @@ -262,7 +289,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeQuery{ ChannelID: "testchannel", Name: "mycc", - Ctor: `{"Args":["listorgs"]}`, + Ctor: `{"Args":["listorgs", "` + mode + `"]}`, }) Expect(err).NotTo(HaveOccurred()) Eventually(sess, time.Minute).Should(gexec.Exit(0)) @@ -273,10 +300,10 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { ChannelID: "testchannel", Orderer: n.OrdererAddress(orderer, nwo.ListenPort), Name: "mycc", - Ctor: `{"Args":["delorgs", "Org1MSP"]}`, + Ctor: `{"Args":["delorgs", "` + mode + `", "Org1MSP"]}`, PeerAddresses: []string{ - n.PeerAddress(n.Peer("Org1", "peer0"), nwo.ListenPort), - n.PeerAddress(n.Peer("Org2", "peer1"), nwo.ListenPort), + n.PeerAddress(peerOrg1, nwo.ListenPort), + n.PeerAddress(peerOrg2, nwo.ListenPort), }, WaitForEvent: true, }) @@ -287,7 +314,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeQuery{ ChannelID: "testchannel", Name: "mycc", - Ctor: `{"Args":["listorgs"]}`, + Ctor: `{"Args":["listorgs", "` + mode + `"]}`, }) Expect(err).NotTo(HaveOccurred()) Eventually(sess, time.Minute).Should(gexec.Exit(0)) @@ -298,9 +325,9 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { ChannelID: "testchannel", Orderer: n.OrdererAddress(orderer, nwo.ListenPort), Name: "mycc2", - Ctor: `{"Args":["cc2cc", "testchannel", "mycc", "setval", "cc2cc_org2"]}`, + Ctor: `{"Args":["cc2cc", "testchannel", "mycc", "setval", "` + mode + `", "cc2cc_org2"]}`, PeerAddresses: []string{ - n.PeerAddress(n.Peer("Org2", "peer1"), nwo.ListenPort), + n.PeerAddress(peerOrg2, nwo.ListenPort), }, WaitForEvent: true, }) @@ -311,7 +338,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeQuery{ ChannelID: "testchannel", Name: "mycc", - Ctor: `{"Args":["getval"]}`, + Ctor: `{"Args":["getval", "` + mode + `"]}`, }) Expect(err).NotTo(HaveOccurred()) Eventually(sess, time.Minute).Should(gexec.Exit(0)) @@ -322,7 +349,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { ChannelID: "testchannel", Orderer: n.OrdererAddress(orderer, nwo.ListenPort), Name: "mycc2", - Ctor: `{"Args":["cc2cc", "testchannel", "mycc", "setval", "cc2cc_org1"]}`, + Ctor: `{"Args":["cc2cc", "testchannel", "mycc", "setval", "` + mode + `", "cc2cc_org1"]}`, PeerAddresses: []string{ n.PeerAddress(peerOrg1, nwo.ListenPort), }, @@ -335,7 +362,7 @@ func RunSBE(n *nwo.Network, orderer *nwo.Orderer) { sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeQuery{ ChannelID: "testchannel", Name: "mycc", - Ctor: `{"Args":["getval"]}`, + Ctor: `{"Args":["getval", "` + mode + `"]}`, }) Expect(err).NotTo(HaveOccurred()) Eventually(sess, time.Minute).Should(gexec.Exit(0)) diff --git a/integration/sbe/testdata/collection_config.json b/integration/sbe/testdata/collection_config.json new file mode 100644 index 00000000000..f2214a84f08 --- /dev/null +++ b/integration/sbe/testdata/collection_config.json @@ -0,0 +1,9 @@ +[ + { + "name": "col", + "policy": "OR('Org1MSP.peer', 'Org2MSP.peer')", + "requiredPeerCount": 2, + "maxPeerCount": 2, + "blockToLive":1000000 + } +]