github.com/hyperledger-labs/bdls@v2.1.1+incompatible/integration/pvtdata/implicit_coll_test.go (about)

     1  /*
     2  Copyright IBM Corp All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package pvtdata
     8  
     9  import (
    10  	"encoding/base64"
    11  	"encoding/json"
    12  	"fmt"
    13  	"path/filepath"
    14  	"time"
    15  
    16  	"github.com/hyperledger/fabric/integration/chaincode/kvexecutor"
    17  	"github.com/hyperledger/fabric/integration/nwo"
    18  	"github.com/hyperledger/fabric/integration/nwo/commands"
    19  	. "github.com/onsi/ginkgo"
    20  	. "github.com/onsi/gomega"
    21  
    22  	"github.com/tedsuo/ifrit"
    23  )
    24  
    25  var _ bool = Describe("Pvtdata dissemination for implicit collection", func() {
    26  	var (
    27  		network       *nwo.Network
    28  		process       ifrit.Process
    29  		orderer       *nwo.Orderer
    30  		testChaincode chaincode
    31  	)
    32  
    33  	BeforeEach(func() {
    34  		By("setting up the network")
    35  		network = initThreeOrgsSetup(false)
    36  
    37  		By("disabling pvtdata pull/dissemination/reconciliation on all peers except for enabling dissemination on org1 peers")
    38  		for _, p := range network.Peers {
    39  			core := network.ReadPeerConfig(p)
    40  			core.Peer.Gossip.PvtData.PullRetryThreshold = 0
    41  			core.Peer.Gossip.PvtData.ReconciliationEnabled = false
    42  			// set timeout and reconnect interval to prevent test flake
    43  			core.Peer.Gossip.DialTimeout = 5 * time.Second
    44  			core.Peer.Gossip.ConnTimeout = 5 * time.Second
    45  			core.Peer.Gossip.ReconnectInterval = 7 * time.Second
    46  			if p.Organization == "Org1" {
    47  				// enable dissemination on org1 peers
    48  				core.Peer.Gossip.PvtData.ImplicitCollDisseminationPolicy.RequiredPeerCount = 1
    49  				core.Peer.Gossip.PvtData.ImplicitCollDisseminationPolicy.MaxPeerCount = 3
    50  				core.Peer.Gossip.PvtData.PushAckTimeout = 10 * time.Second
    51  			} else {
    52  				// disable dissemination on non-org1 peers
    53  				core.Peer.Gossip.PvtData.ImplicitCollDisseminationPolicy.RequiredPeerCount = 0
    54  				core.Peer.Gossip.PvtData.ImplicitCollDisseminationPolicy.MaxPeerCount = 0
    55  			}
    56  			network.WritePeerConfig(p, core)
    57  		}
    58  
    59  		By("starting the network")
    60  		process, orderer = startNetwork(network)
    61  
    62  		By("deploying new lifecycle chaincode")
    63  		testChaincode = chaincode{
    64  			Chaincode: nwo.Chaincode{
    65  				Name:        "kvexecutor",
    66  				Version:     "1.0",
    67  				Path:        components.Build("github.com/hyperledger/fabric/integration/chaincode/kvexecutor/cmd"),
    68  				Lang:        "binary",
    69  				PackageFile: filepath.Join(network.RootDir, "kvexcutor.tar.gz"),
    70  				Label:       "kvexcutor",
    71  				Sequence:    "1",
    72  			},
    73  			isLegacy: false,
    74  		}
    75  		nwo.EnableCapabilities(network, channelID, "Application", "V2_0", orderer, network.Peers...)
    76  
    77  		By("verifying org1.peer0 discovers all peers to ensure that gossip has been initialized")
    78  		discoverAllPeers(network, network.Peer("Org1", "peer0"), channelID, 3, 5*time.Second)
    79  
    80  		By("verifying org1.peer1 discovers all peers to ensure that gossip has been initialized")
    81  		discoverAllPeers(network, network.Peer("Org1", "peer1"), channelID, 3, 5*time.Second)
    82  
    83  		By("deploying chaincode to all peers")
    84  		deployChaincode(network, orderer, testChaincode)
    85  	})
    86  
    87  	AfterEach(func() {
    88  		testCleanup(network, process)
    89  	})
    90  
    91  	It("disseminates pvtdata of implicit collection for the peer's own org but not implicit collection for another org", func() {
    92  		org1peer0 := network.Peer("Org1", "peer0")
    93  		org1peer1 := network.Peer("Org1", "peer1")
    94  		org2peer0 := network.Peer("Org2", "peer0")
    95  		org2peer1 := network.Peer("Org2", "peer1")
    96  
    97  		By("writing private data to org1's and org2's implicit collections")
    98  		writeInput := []kvexecutor.KVData{
    99  			{Collection: "_implicit_org_Org1MSP", Key: "org1_key1", Value: "org1_value1"},
   100  			{Collection: "_implicit_org_Org2MSP", Key: "org2_key1", Value: "org2_value1"},
   101  		}
   102  		writeImplicitCollection(network, orderer, testChaincode.Name, writeInput, org1peer0, org2peer0)
   103  
   104  		By("querying org1.peer0 for _implicit_org_Org1MSP collection data, expecting pvtdata")
   105  		readInput1 := []kvexecutor.KVData{{Collection: "_implicit_org_Org1MSP", Key: "org1_key1"}}
   106  		expectedMsg1, err := json.Marshal(writeInput[:1])
   107  		Expect(err).NotTo(HaveOccurred())
   108  		readImplicitCollection(network, org1peer0, testChaincode.Name, readInput1, string(expectedMsg1), true)
   109  
   110  		// org1.peer1 should have _implicit_org_Org1MSP pvtdata because dissemination is enabled on org1 peers
   111  		By("querying org1.peer1 for _implicit_org_Org1MSP collection data, expecting pvtdata")
   112  		readImplicitCollection(network, org1peer1, testChaincode.Name, readInput1, string(expectedMsg1), true)
   113  
   114  		By("querying org2.peer0 for _implicit_org_Org1MSP collection data, expecting error")
   115  		readImplicitCollection(network, org2peer0, testChaincode.Name, readInput1,
   116  			"private data matching public hash version is not available", false)
   117  
   118  		By("querying org2.peer1 for _implicit_org_Org1MSP collection data, expecting error")
   119  		readImplicitCollection(network, org2peer1, testChaincode.Name, readInput1,
   120  			"private data matching public hash version is not available", false)
   121  
   122  		By("querying org2.peer0 for _implicit_org_Org2MSP collection data, expecting pvtdata")
   123  		readInput2 := []kvexecutor.KVData{{Collection: "_implicit_org_Org2MSP", Key: "org2_key1"}}
   124  		expectedMsg2, err := json.Marshal(writeInput[1:])
   125  		Expect(err).NotTo(HaveOccurred())
   126  		readImplicitCollection(network, org2peer0, testChaincode.Name, readInput2, string(expectedMsg2), true)
   127  
   128  		// org2.peer1 should have no _implicit_org_Org2MSP pvtdata because pull/dissemination/reconciliation are disabled on org2 peers
   129  		By("querying org2.peer1 for _implicit_org_Org2MSP collection data, expecting error")
   130  		readImplicitCollection(network, org2peer1, testChaincode.Name, readInput2,
   131  			"private data matching public hash version is not available", false)
   132  
   133  		By("querying org1.peer0 for _implicit_org_Org2MSP collection data, expecting error")
   134  		readImplicitCollection(network, org1peer0, testChaincode.Name, readInput2,
   135  			"private data matching public hash version is not available", false)
   136  
   137  		By("querying org1.peer1 for _implicit_org_Org2MSP collection data, expecting error")
   138  		readImplicitCollection(network, org1peer1, testChaincode.Name, readInput2,
   139  			"private data matching public hash version is not available", false)
   140  	})
   141  })
   142  
   143  func writeImplicitCollection(n *nwo.Network, orderer *nwo.Orderer, chaincodeName string, writeInput []kvexecutor.KVData, peers ...*nwo.Peer) {
   144  	writeInputBytes, err := json.Marshal(writeInput)
   145  	Expect(err).NotTo(HaveOccurred())
   146  	writeInputBase64 := base64.StdEncoding.EncodeToString(writeInputBytes)
   147  
   148  	peerAddresses := make([]string, 0)
   149  	for _, peer := range peers {
   150  		peerAddresses = append(peerAddresses, n.PeerAddress(peer, nwo.ListenPort))
   151  	}
   152  	command := commands.ChaincodeInvoke{
   153  		ChannelID:     channelID,
   154  		Orderer:       n.OrdererAddress(orderer, nwo.ListenPort),
   155  		Name:          chaincodeName,
   156  		Ctor:          fmt.Sprintf(`{"Args":["readWriteKVs","%s","%s"]}`, "", writeInputBase64),
   157  		PeerAddresses: peerAddresses,
   158  		WaitForEvent:  true,
   159  	}
   160  	invokeChaincode(n, peers[0], command)
   161  	nwo.WaitUntilEqualLedgerHeight(n, channelID, nwo.GetLedgerHeight(n, peers[0], channelID), n.Peers...)
   162  }
   163  
   164  func readImplicitCollection(n *nwo.Network, peer *nwo.Peer, chaincodeName string, readInput []kvexecutor.KVData, expectedMsg string, expectSuccess bool) {
   165  	readInputBytes, err := json.Marshal(readInput)
   166  	Expect(err).NotTo(HaveOccurred())
   167  	readInputBase64 := base64.StdEncoding.EncodeToString(readInputBytes)
   168  
   169  	command := commands.ChaincodeQuery{
   170  		ChannelID: channelID,
   171  		Name:      chaincodeName,
   172  		Ctor:      fmt.Sprintf(`{"Args":["readWriteKVs","%s","%s"]}`, readInputBase64, ""),
   173  	}
   174  	queryChaincode(n, peer, command, expectedMsg, expectSuccess)
   175  }
   176  
   177  func discoverAllPeers(n *nwo.Network, peer *nwo.Peer, channelID string, retries int, retryInterval time.Duration) {
   178  	var discoveredPeers []nwo.DiscoveredPeer
   179  	numPeers := len(n.Peers)
   180  	for i := 0; i < retries; i++ {
   181  		discoveredPeers = nwo.DiscoverPeers(n, peer, "User1", channelID)()
   182  		if len(discoveredPeers) == numPeers || i == retries-1 {
   183  			break
   184  		}
   185  		time.Sleep(retryInterval)
   186  	}
   187  	Expect(discoveredPeers).To(HaveLen(numPeers))
   188  }