462 lines
16 KiB
Go
462 lines
16 KiB
Go
/*
|
|
Copyright IBM Corp All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package sbe
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"syscall"
|
|
|
|
docker "github.com/fsouza/go-dockerclient"
|
|
"github.com/hyperledger/fabric-protos-go/common"
|
|
"github.com/hyperledger/fabric/integration/channelparticipation"
|
|
"github.com/hyperledger/fabric/integration/nwo"
|
|
"github.com/hyperledger/fabric/integration/nwo/commands"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"github.com/onsi/gomega/gbytes"
|
|
"github.com/onsi/gomega/gexec"
|
|
"github.com/tedsuo/ifrit"
|
|
ginkgomon "github.com/tedsuo/ifrit/ginkgomon_v2"
|
|
)
|
|
|
|
var _ = Describe("SBE_E2E", func() {
|
|
var (
|
|
testDir string
|
|
client *docker.Client
|
|
network *nwo.Network
|
|
chaincode nwo.Chaincode
|
|
ordererRunner *ginkgomon.Runner
|
|
ordererProcess, peerProcess ifrit.Process
|
|
tempDir string
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
var err error
|
|
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"]}`,
|
|
CollectionsConfig: "testdata/collection_config.json",
|
|
}
|
|
|
|
tempDir, err = ioutil.TempDir("", "sbe")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
AfterEach(func() {
|
|
if ordererProcess != nil {
|
|
ordererProcess.Signal(syscall.SIGTERM)
|
|
Eventually(ordererProcess.Wait(), network.EventuallyTimeout).Should(Receive())
|
|
}
|
|
|
|
if peerProcess != nil {
|
|
peerProcess.Signal(syscall.SIGTERM)
|
|
Eventually(peerProcess.Wait(), network.EventuallyTimeout).Should(Receive())
|
|
}
|
|
|
|
if network != nil {
|
|
network.Cleanup()
|
|
}
|
|
os.RemoveAll(tempDir)
|
|
os.RemoveAll(testDir)
|
|
})
|
|
|
|
Describe("basic etcdraft network with 2 orgs", func() {
|
|
BeforeEach(func() {
|
|
network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components)
|
|
network.GenerateConfigTree()
|
|
network.Bootstrap()
|
|
|
|
ordererRunner, ordererProcess, peerProcess = network.StartSingleOrdererNetwork("orderer")
|
|
})
|
|
|
|
It("executes a basic etcdraft network with 2 orgs and SBE checks", func() {
|
|
By("getting the orderer by name")
|
|
orderer := network.Orderer("orderer")
|
|
|
|
By("setting up the channel")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", orderer, ordererRunner)
|
|
|
|
By("deploying the chaincode")
|
|
nwo.DeployChaincodeLegacy(network, "testchannel", orderer, chaincode)
|
|
|
|
By("deploying a second instance of the chaincode")
|
|
chaincode.Name = "mycc2"
|
|
nwo.DeployChaincodeLegacy(network, "testchannel", orderer, chaincode)
|
|
|
|
RunSBE(network, orderer, "pub")
|
|
RunSBE(network, orderer, "priv")
|
|
})
|
|
|
|
It("executes a basic etcdraft network with 2 orgs and SBE checks with _lifecycle", func() {
|
|
chaincode = nwo.Chaincode{
|
|
Name: "mycc",
|
|
Version: "0.0",
|
|
Path: "github.com/hyperledger/fabric/integration/chaincode/keylevelep/cmd",
|
|
Lang: "golang",
|
|
PackageFile: filepath.Join(tempDir, "simplecc.tar.gz"),
|
|
Ctor: `{"Args":["init"]}`,
|
|
SignaturePolicy: `OR('Org1MSP.member','Org2MSP.member')`,
|
|
Sequence: "1",
|
|
InitRequired: true,
|
|
Label: "my_simple_chaincode",
|
|
CollectionsConfig: "testdata/collection_config.json",
|
|
}
|
|
|
|
By("getting the orderer by name")
|
|
orderer := network.Orderer("orderer")
|
|
|
|
By("setting up the channel")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", orderer, ordererRunner)
|
|
network.VerifyMembership(network.PeersWithChannel("testchannel"), "testchannel")
|
|
|
|
By("enabling 2.0 application capabilities")
|
|
nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
|
|
|
|
By("deploying the chaincode")
|
|
nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
|
|
|
|
By("deploying a second instance of the chaincode")
|
|
chaincode.Name = "mycc2"
|
|
chaincode.PackageFile = filepath.Join(tempDir, "simplecc2.tar.gz")
|
|
chaincode.Label = "my_other_simple_chaincode"
|
|
nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
|
|
|
|
RunSBE(network, orderer, "pub")
|
|
RunSBE(network, orderer, "priv")
|
|
})
|
|
})
|
|
})
|
|
|
|
func RunSBE(n *nwo.Network, orderer *nwo.Orderer, mode string) {
|
|
peerOrg1 := n.Peer("Org1", "peer0")
|
|
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":["setval", "` + mode + `", "foo"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(peerOrg1, nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
|
|
syncLedgerHeights(n, peerOrg1, peerOrg2)
|
|
|
|
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, n.EventuallyTimeout).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),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
|
|
By("checking that the modification succeeded through listing the orgs in the ep")
|
|
sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeQuery{
|
|
ChannelID: "testchannel",
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["listorgs", "` + mode + `"]}`,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say("Org1MSP"))
|
|
|
|
By("org1 sets the value of the key")
|
|
sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: "testchannel",
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["setval", "` + mode + `", "val1"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(peerOrg1, nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
|
|
syncLedgerHeights(n, peerOrg1, peerOrg2)
|
|
|
|
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, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say("val1"))
|
|
|
|
By("org2 sets the value of the key")
|
|
sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: "testchannel",
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["setval", "` + mode + `", "val2"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(peerOrg2, nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(1))
|
|
Expect(sess.Err).To(gbytes.Say(`\Qcommitted with status (ENDORSEMENT_POLICY_FAILURE)\E`))
|
|
|
|
By("org2 checks that setting the value was not 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, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say("val1"))
|
|
|
|
syncLedgerHeights(n, peerOrg2, peerOrg1)
|
|
|
|
By("org1 adds org2 to the ep of the key")
|
|
sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: "testchannel",
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["addorgs", "` + mode + `", "Org2MSP"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(peerOrg1, nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
|
|
By("org1 lists the orgs of the ep to check that both org1 and org2 are there")
|
|
sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeQuery{
|
|
ChannelID: "testchannel",
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["listorgs", "` + mode + `"]}`,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
orgs := [2]string{"Org1MSP", "Org2MSP"}
|
|
orgsList, err := json.Marshal(orgs)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(sess).To(gbytes.Say(string(orgsList)))
|
|
|
|
syncLedgerHeights(n, peerOrg1, peerOrg2)
|
|
|
|
By("org2 sets the value of the key")
|
|
sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: "testchannel",
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["setval", "` + mode + `", "val3"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(peerOrg2, nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(1))
|
|
Expect(sess.Err).To(gbytes.Say(`\Qcommitted with status (ENDORSEMENT_POLICY_FAILURE)\E`))
|
|
|
|
By("org2 checks that seting the value was not 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, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say("val1"))
|
|
|
|
syncLedgerHeights(n, peerOrg2, peerOrg1)
|
|
|
|
By("org1 and org2 set the value of the key")
|
|
sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: "testchannel",
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["setval", "` + mode + `", "val4"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(peerOrg1, nwo.ListenPort),
|
|
n.PeerAddress(peerOrg2, nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
|
|
By("org1 checks that setting the value was successful by reading it")
|
|
sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeQuery{
|
|
ChannelID: "testchannel",
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["getval", "` + mode + `"]}`,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say("val4"))
|
|
|
|
syncLedgerHeights(n, peerOrg1, peerOrg2)
|
|
|
|
By("org2 deletes org1 from the ep of the key")
|
|
sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: "testchannel",
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["delorgs", "` + mode + `", "Org1MSP"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(peerOrg2, nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(1))
|
|
Expect(sess.Err).To(gbytes.Say(`\Qcommitted with status (ENDORSEMENT_POLICY_FAILURE)\E`))
|
|
|
|
By("org2 lists the orgs of the key to check that deleting org1 did not succeed")
|
|
sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeQuery{
|
|
ChannelID: "testchannel",
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["listorgs", "` + mode + `"]}`,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say(string(orgsList)))
|
|
|
|
syncLedgerHeights(n, peerOrg2, peerOrg1)
|
|
|
|
By("org1 and org2 delete org1 from the ep of the key")
|
|
sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: "testchannel",
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["delorgs", "` + mode + `", "Org1MSP"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(peerOrg1, nwo.ListenPort),
|
|
n.PeerAddress(peerOrg2, nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
|
|
By("org2 lists the orgs of the key's ep to check that removing org1 from the ep was successful")
|
|
sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeQuery{
|
|
ChannelID: "testchannel",
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["listorgs", "` + mode + `"]}`,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say("Org2MSP"))
|
|
|
|
By("org2 uses cc2cc invocation to set the value of the key")
|
|
sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: "testchannel",
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc2",
|
|
Ctor: `{"Args":["cc2cc", "testchannel", "mycc", "setval", "` + mode + `", "cc2cc_org2"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(peerOrg2, nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
|
|
By("org2 reads the value of the key to check that setting it was successful")
|
|
sess, err = n.PeerUserSession(peerOrg2, "User1", commands.ChaincodeQuery{
|
|
ChannelID: "testchannel",
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["getval", "` + mode + `"]}`,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say("cc2cc_org2"))
|
|
|
|
syncLedgerHeights(n, peerOrg2, peerOrg1)
|
|
|
|
By("org1 uses cc2cc to set the value of the key")
|
|
sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: "testchannel",
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc2",
|
|
Ctor: `{"Args":["cc2cc", "testchannel", "mycc", "setval", "` + mode + `", "cc2cc_org1"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(peerOrg1, nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(1))
|
|
Expect(sess.Err).To(gbytes.Say(`\Qcommitted with status (ENDORSEMENT_POLICY_FAILURE)\E`))
|
|
|
|
By("org1 reads the value of the key to check that setting it was not successful")
|
|
sess, err = n.PeerUserSession(peerOrg1, "User1", commands.ChaincodeQuery{
|
|
ChannelID: "testchannel",
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["getval", "` + mode + `"]}`,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say("cc2cc_org2"))
|
|
}
|
|
|
|
func getLedgerHeight(n *nwo.Network, peer *nwo.Peer, channelName string) int {
|
|
sess, err := n.PeerUserSession(peer, "User1", commands.ChannelInfo{
|
|
ChannelID: channelName,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
|
|
channelInfoStr := strings.TrimPrefix(string(sess.Buffer().Contents()[:]), "Blockchain info:")
|
|
channelInfo := common.BlockchainInfo{}
|
|
err = json.Unmarshal([]byte(channelInfoStr), &channelInfo)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
return int(channelInfo.Height)
|
|
}
|
|
|
|
func syncLedgerHeights(n *nwo.Network, peer1 *nwo.Peer, peer2 *nwo.Peer) {
|
|
// get height from peer1
|
|
height := getLedgerHeight(n, peer1, "testchannel")
|
|
// wait for same height on peer2
|
|
Eventually(func() int {
|
|
return getLedgerHeight(n, peer2, "testchannel")
|
|
}, n.EventuallyTimeout).Should(Equal(height))
|
|
}
|