github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/integration/gateway/gateway_discovery_test.go (about)

     1  /*
     2  Copyright hechain All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package gateway
     8  
     9  import (
    10  	"context"
    11  	"io/ioutil"
    12  	"os"
    13  	"path/filepath"
    14  	"syscall"
    15  
    16  	docker "github.com/fsouza/go-dockerclient"
    17  	"github.com/golang/protobuf/proto"
    18  	"github.com/hechain20/hechain/integration/nwo"
    19  	"github.com/hechain20/hechain/protoutil"
    20  	"github.com/hyperledger/fabric-protos-go/gateway"
    21  	"github.com/hyperledger/fabric-protos-go/peer"
    22  	. "github.com/onsi/ginkgo"
    23  	. "github.com/onsi/gomega"
    24  	"github.com/tedsuo/ifrit"
    25  )
    26  
    27  var _ = Describe("GatewayService with endorser discovery", func() {
    28  	var (
    29  		testDir   string
    30  		network   *nwo.Network
    31  		orderer   *nwo.Orderer
    32  		org1Peer0 *nwo.Peer
    33  		org2Peer0 *nwo.Peer
    34  		org3Peer0 *nwo.Peer
    35  		process   ifrit.Process
    36  		peerCerts map[string]string
    37  	)
    38  
    39  	loadPeerCert := func(peer *nwo.Peer) string {
    40  		peerCert, err := ioutil.ReadFile(network.PeerCert(peer))
    41  		Expect(err).NotTo(HaveOccurred())
    42  		return string(peerCert)
    43  	}
    44  
    45  	BeforeEach(func() {
    46  		var err error
    47  		testDir, err = ioutil.TempDir("", "gateway")
    48  		Expect(err).NotTo(HaveOccurred())
    49  
    50  		client, err := docker.NewClientFromEnv()
    51  		Expect(err).NotTo(HaveOccurred())
    52  
    53  		config := nwo.ThreeOrgRaft()
    54  		network = nwo.New(config, testDir, client, StartPort(), components)
    55  
    56  		network.GenerateConfigTree()
    57  		network.Bootstrap()
    58  
    59  		networkRunner := network.NetworkGroupRunner()
    60  		process = ifrit.Invoke(networkRunner)
    61  		Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
    62  
    63  		orderer = network.Orderer("orderer")
    64  		network.CreateAndJoinChannel(orderer, "testchannel")
    65  		network.UpdateChannelAnchors(orderer, "testchannel")
    66  		network.VerifyMembership(
    67  			network.PeersWithChannel("testchannel"),
    68  			"testchannel",
    69  		)
    70  		nwo.EnableCapabilities(
    71  			network,
    72  			"testchannel",
    73  			"Application", "V2_0",
    74  			orderer,
    75  			network.PeersWithChannel("testchannel")...,
    76  		)
    77  
    78  		org1Peer0 = network.Peer("Org1", "peer0")
    79  		org2Peer0 = network.Peer("Org2", "peer0")
    80  		org3Peer0 = network.Peer("Org3", "peer0")
    81  
    82  		peerCerts = map[string]string{
    83  			loadPeerCert(org1Peer0): org1Peer0.ID(),
    84  			loadPeerCert(org2Peer0): org2Peer0.ID(),
    85  			loadPeerCert(org3Peer0): org3Peer0.ID(),
    86  		}
    87  
    88  		chaincode := nwo.Chaincode{
    89  			Name:            "gatewaycc",
    90  			Version:         "0.0",
    91  			Path:            components.Build("github.com/hechain20/hechain/integration/chaincode/simple/cmd"),
    92  			Lang:            "binary",
    93  			PackageFile:     filepath.Join(testDir, "gatewaycc.tar.gz"),
    94  			Ctor:            `{"Args":["init","a","100","b","200"]}`,
    95  			SignaturePolicy: `AND ('Org1MSP.peer')`,
    96  			Sequence:        "1",
    97  			InitRequired:    true,
    98  			Label:           "gatewaycc_label",
    99  		}
   100  		nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
   101  
   102  		chaincode = nwo.Chaincode{
   103  			Name:              "sbecc",
   104  			Version:           "0.0",
   105  			Path:              components.Build("github.com/hechain20/hechain/integration/chaincode/keylevelep/cmd"),
   106  			Ctor:              `{"Args":["init"]}`,
   107  			Lang:              "binary",
   108  			PackageFile:       filepath.Join(testDir, "sbecc.tar.gz"),
   109  			SignaturePolicy:   `OR ('Org3MSP.member')`,
   110  			Sequence:          "1",
   111  			InitRequired:      true,
   112  			Label:             "sbecc_label",
   113  			CollectionsConfig: filepath.Join("testdata", "collections_config_sbe.json"),
   114  		}
   115  		nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
   116  
   117  		chaincode = nwo.Chaincode{
   118  			Name:              "readpvtcc",
   119  			Version:           "0.0",
   120  			Path:              components.Build("github.com/hechain20/hechain/integration/chaincode/keylevelep/cmd"),
   121  			Ctor:              `{"Args":["init"]}`,
   122  			Lang:              "binary",
   123  			PackageFile:       filepath.Join(testDir, "readpvtcc.tar.gz"),
   124  			SignaturePolicy:   `OR ('Org1MSP.member', 'Org3MSP.member')`,
   125  			Sequence:          "1",
   126  			InitRequired:      true,
   127  			Label:             "readpvtcc_label",
   128  			CollectionsConfig: filepath.Join("testdata", "collections_config_read.json"),
   129  		}
   130  		nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
   131  	})
   132  
   133  	AfterEach(func() {
   134  		if process != nil {
   135  			process.Signal(syscall.SIGTERM)
   136  			Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive())
   137  		}
   138  		if network != nil {
   139  			network.Cleanup()
   140  		}
   141  		os.RemoveAll(testDir)
   142  	})
   143  
   144  	verifyEndorsers := func(endorseResponse *gateway.EndorseResponse, expectedEndorsers []string) {
   145  		preparedTransaction := endorseResponse.GetPreparedTransaction()
   146  		payload, err := protoutil.UnmarshalPayload(preparedTransaction.GetPayload())
   147  		Expect(err).NotTo(HaveOccurred())
   148  		transaction, err := protoutil.UnmarshalTransaction(payload.GetData())
   149  		Expect(err).NotTo(HaveOccurred())
   150  		Expect(transaction.GetActions()).To(HaveLen(1))
   151  		action, err := protoutil.UnmarshalChaincodeActionPayload(transaction.Actions[0].GetPayload())
   152  		Expect(err).NotTo(HaveOccurred())
   153  		endorsements := action.GetAction().GetEndorsements()
   154  
   155  		actualEndorsers := []string{}
   156  		for _, endorsement := range endorsements {
   157  			id, err := protoutil.UnmarshalSerializedIdentity(endorsement.GetEndorser())
   158  			Expect(err).NotTo(HaveOccurred())
   159  			actualEndorsers = append(actualEndorsers, peerCerts[string(id.IdBytes)])
   160  		}
   161  
   162  		Expect(actualEndorsers).To(ConsistOf(expectedEndorsers))
   163  	}
   164  
   165  	submitTransaction := func(
   166  		gatewayClient gateway.GatewayClient,
   167  		signer *nwo.SigningIdentity,
   168  		channel string,
   169  		chaincode string,
   170  		transactionName string,
   171  		arguments []string,
   172  		transientData map[string][]byte,
   173  		expectedEndorsers []string,
   174  	) *peer.Response {
   175  		args := [][]byte{}
   176  		for _, arg := range arguments {
   177  			args = append(args, []byte(arg))
   178  		}
   179  		proposedTransaction, transactionID := NewProposedTransaction(
   180  			signer,
   181  			channel,
   182  			chaincode,
   183  			transactionName,
   184  			transientData,
   185  			args...,
   186  		)
   187  
   188  		endorseRequest := &gateway.EndorseRequest{
   189  			TransactionId:       transactionID,
   190  			ChannelId:           channel,
   191  			ProposedTransaction: proposedTransaction,
   192  		}
   193  
   194  		ctx, cancel := context.WithTimeout(context.Background(), network.EventuallyTimeout)
   195  		defer cancel()
   196  
   197  		endorseResponse, err := gatewayClient.Endorse(ctx, endorseRequest)
   198  		Expect(err).NotTo(HaveOccurred())
   199  
   200  		preparedTransaction := endorseResponse.GetPreparedTransaction()
   201  		preparedTransaction.Signature, err = signer.Sign(preparedTransaction.Payload)
   202  		Expect(err).NotTo(HaveOccurred())
   203  
   204  		if expectedEndorsers != nil {
   205  			verifyEndorsers(endorseResponse, expectedEndorsers)
   206  		}
   207  
   208  		submitRequest := &gateway.SubmitRequest{
   209  			TransactionId:       transactionID,
   210  			ChannelId:           channel,
   211  			PreparedTransaction: preparedTransaction,
   212  		}
   213  		_, err = gatewayClient.Submit(ctx, submitRequest)
   214  		Expect(err).NotTo(HaveOccurred())
   215  
   216  		idBytes, err := signer.Serialize()
   217  		Expect(err).NotTo(HaveOccurred())
   218  
   219  		statusRequest := &gateway.CommitStatusRequest{
   220  			ChannelId:     "testchannel",
   221  			Identity:      idBytes,
   222  			TransactionId: transactionID,
   223  		}
   224  		statusRequestBytes, err := proto.Marshal(statusRequest)
   225  		Expect(err).NotTo(HaveOccurred())
   226  
   227  		signature, err := signer.Sign(statusRequestBytes)
   228  		Expect(err).NotTo(HaveOccurred())
   229  
   230  		signedStatusRequest := &gateway.SignedCommitStatusRequest{
   231  			Request:   statusRequestBytes,
   232  			Signature: signature,
   233  		}
   234  
   235  		statusResponse, err := gatewayClient.CommitStatus(ctx, signedStatusRequest)
   236  		Expect(err).NotTo(HaveOccurred())
   237  		Expect(statusResponse.Result).To(Equal(peer.TxValidationCode_VALID))
   238  
   239  		chaincodeAction, err := protoutil.GetActionFromEnvelopeMsg(endorseResponse.GetPreparedTransaction())
   240  		Expect(err).NotTo(HaveOccurred())
   241  
   242  		return chaincodeAction.GetResponse()
   243  	}
   244  
   245  	evaluateTransaction := func(
   246  		gatewayClient gateway.GatewayClient,
   247  		signer *nwo.SigningIdentity,
   248  		channel string,
   249  		chaincode string,
   250  		transactionName string,
   251  		arguments []string,
   252  		transientData map[string][]byte,
   253  	) *peer.Response {
   254  		args := [][]byte{}
   255  		for _, arg := range arguments {
   256  			args = append(args, []byte(arg))
   257  		}
   258  		proposedTransaction, transactionID := NewProposedTransaction(
   259  			signer,
   260  			channel,
   261  			chaincode,
   262  			transactionName,
   263  			transientData,
   264  			args...,
   265  		)
   266  
   267  		evaluateRequest := &gateway.EvaluateRequest{
   268  			TransactionId:       transactionID,
   269  			ChannelId:           channel,
   270  			ProposedTransaction: proposedTransaction,
   271  		}
   272  
   273  		ctx, cancel := context.WithTimeout(context.Background(), network.EventuallyTimeout)
   274  		defer cancel()
   275  
   276  		evaluateResponse, err := gatewayClient.Evaluate(ctx, evaluateRequest)
   277  		Expect(err).NotTo(HaveOccurred())
   278  
   279  		return evaluateResponse.GetResult()
   280  	}
   281  
   282  	It("setting SBE policy should override chaincode policy", func() {
   283  		conn := network.PeerClientConn(org1Peer0)
   284  		defer conn.Close()
   285  		gatewayClient := gateway.NewGatewayClient(conn)
   286  		signingIdentity := network.PeerUserSigner(org1Peer0, "User1")
   287  
   288  		// add org2 to SBE policy - requires endorsement from org3 peer (chaincode policy)
   289  		submitTransaction(
   290  			gatewayClient,
   291  			signingIdentity,
   292  			"testchannel",
   293  			"sbecc",
   294  			"addorgs",
   295  			[]string{"pub", "Org2MSP"},
   296  			nil,
   297  			[]string{org3Peer0.ID()},
   298  		)
   299  
   300  		// add org1 to SBE policy - requires endorsement from org2 peer (SBE policy)
   301  		submitTransaction(
   302  			gatewayClient,
   303  			signingIdentity,
   304  			"testchannel",
   305  			"sbecc",
   306  			"addorgs",
   307  			[]string{"pub", "Org1MSP"},
   308  			nil,
   309  			[]string{org2Peer0.ID()},
   310  		)
   311  
   312  		// remove org2 to SBE policy - requires endorsement from org1, org2 peers (SBE policy)
   313  		submitTransaction(
   314  			gatewayClient,
   315  			signingIdentity,
   316  			"testchannel",
   317  			"sbecc",
   318  			"delorgs",
   319  			[]string{"pub", "Org2MSP"},
   320  			nil,
   321  			[]string{org1Peer0.ID(), org2Peer0.ID()},
   322  		)
   323  	})
   324  
   325  	It("setting SBE policy on private key then writing to should override the collection & chaincode policies", func() {
   326  		conn := network.PeerClientConn(org1Peer0)
   327  		defer conn.Close()
   328  		gatewayClient := gateway.NewGatewayClient(conn)
   329  		signingIdentity := network.PeerUserSigner(org1Peer0, "User1")
   330  
   331  		// write to private collection - requires endorsement from org2 peer (collection policy)
   332  		submitTransaction(
   333  			gatewayClient,
   334  			signingIdentity,
   335  			"testchannel",
   336  			"sbecc",
   337  			"setval",
   338  			[]string{"priv", "initial private value"},
   339  			nil,
   340  			[]string{org2Peer0.ID()},
   341  		)
   342  
   343  		// check the value was set
   344  		result := evaluateTransaction(
   345  			gatewayClient,
   346  			signingIdentity,
   347  			"testchannel",
   348  			"sbecc",
   349  			"getval",
   350  			[]string{"priv"},
   351  			nil,
   352  		)
   353  		Expect(result.Payload).To(Equal([]byte("initial private value")))
   354  
   355  		// add org1 to SBE policy - requires endorsement from org2 peer (collection policy)
   356  		submitTransaction(
   357  			gatewayClient,
   358  			signingIdentity,
   359  			"testchannel",
   360  			"sbecc",
   361  			"addorgs",
   362  			[]string{"priv", "Org1MSP"},
   363  			nil,
   364  			[]string{org2Peer0.ID()},
   365  		)
   366  
   367  		// write to private collection - requires endorsement from org1 peer (SBE policy)
   368  		submitTransaction(
   369  			gatewayClient,
   370  			signingIdentity,
   371  			"testchannel",
   372  			"sbecc",
   373  			"setval",
   374  			[]string{"priv", "updated private value"},
   375  			nil,
   376  			[]string{org1Peer0.ID()},
   377  		)
   378  
   379  		// check the value was set
   380  		result = evaluateTransaction(
   381  			gatewayClient,
   382  			signingIdentity,
   383  			"testchannel",
   384  			"sbecc",
   385  			"getval",
   386  			[]string{"priv"},
   387  			nil,
   388  		)
   389  
   390  		Expect(result.Payload).To(Equal([]byte("updated private value")))
   391  	})
   392  
   393  	It("writing to public and private keys should combine the collection & chaincode policies", func() {
   394  		conn := network.PeerClientConn(org1Peer0)
   395  		defer conn.Close()
   396  		gatewayClient := gateway.NewGatewayClient(conn)
   397  		signingIdentity := network.PeerUserSigner(org1Peer0, "User1")
   398  
   399  		// write to both pub&priv - requires endorsement from org2 (collection policy) and org3 (chaincode policy)
   400  		submitTransaction(
   401  			gatewayClient,
   402  			signingIdentity,
   403  			"testchannel",
   404  			"sbecc",
   405  			"setval",
   406  			[]string{"both", "initial value"},
   407  			nil,
   408  			[]string{org2Peer0.ID(), org3Peer0.ID()},
   409  		)
   410  
   411  		// check the private value was set
   412  		result := evaluateTransaction(
   413  			gatewayClient,
   414  			signingIdentity,
   415  			"testchannel",
   416  			"sbecc",
   417  			"getval",
   418  			[]string{"priv"},
   419  			nil,
   420  		)
   421  		Expect(result.Payload).To(Equal([]byte("initial value")))
   422  
   423  		// check the public value was set
   424  		result = evaluateTransaction(
   425  			gatewayClient,
   426  			signingIdentity,
   427  			"testchannel",
   428  			"sbecc",
   429  			"getval",
   430  			[]string{"pub"},
   431  			nil,
   432  		)
   433  		Expect(result.Payload).To(Equal([]byte("initial value")))
   434  	})
   435  
   436  	It("should combine chaincode and private SBE policies", func() {
   437  		conn := network.PeerClientConn(org1Peer0)
   438  		defer conn.Close()
   439  		gatewayClient := gateway.NewGatewayClient(conn)
   440  		signingIdentity := network.PeerUserSigner(org1Peer0, "User1")
   441  
   442  		// write to both public & private states - requires endorsement from org2 peer (collection policy) and org3 peer (chaincode) policy
   443  		submitTransaction(
   444  			gatewayClient,
   445  			signingIdentity,
   446  			"testchannel",
   447  			"sbecc",
   448  			"setval",
   449  			[]string{"both", "initial private & public value"},
   450  			nil,
   451  			[]string{org2Peer0.ID(), org3Peer0.ID()},
   452  		)
   453  
   454  		// add org1 to SBE policy for private state - requires endorsement from org2 peer (collection policy)
   455  		submitTransaction(
   456  			gatewayClient,
   457  			signingIdentity,
   458  			"testchannel",
   459  			"sbecc",
   460  			"addorgs",
   461  			[]string{"priv", "Org1MSP"},
   462  			nil,
   463  			[]string{org2Peer0.ID()},
   464  		)
   465  
   466  		// write to both pub&priv - requires endorsement from org1 (SBE policy) and org3 (chaincode policy)
   467  		submitTransaction(
   468  			gatewayClient,
   469  			signingIdentity,
   470  			"testchannel",
   471  			"sbecc",
   472  			"setval",
   473  			[]string{"both", "chaincode and SBE policies"},
   474  			nil,
   475  			[]string{org1Peer0.ID(), org3Peer0.ID()},
   476  		)
   477  
   478  		// check the private value was set
   479  		result := evaluateTransaction(
   480  			gatewayClient,
   481  			signingIdentity,
   482  			"testchannel",
   483  			"sbecc",
   484  			"getval",
   485  			[]string{"priv"},
   486  			nil,
   487  		)
   488  		Expect(result.Payload).To(Equal([]byte("chaincode and SBE policies")))
   489  	})
   490  
   491  	It("should combine collection and public SBE policies", func() {
   492  		conn := network.PeerClientConn(org3Peer0)
   493  		defer conn.Close()
   494  		gatewayClient := gateway.NewGatewayClient(conn)
   495  		signingIdentity := network.PeerUserSigner(org3Peer0, "User1")
   496  
   497  		// add org1 to SBE policy - requires endorsement from org3 peer (chaincode policy)
   498  		submitTransaction(
   499  			gatewayClient,
   500  			signingIdentity,
   501  			"testchannel",
   502  			"sbecc",
   503  			"addorgs",
   504  			[]string{"pub", "Org1MSP"},
   505  			nil,
   506  			[]string{org3Peer0.ID()},
   507  		)
   508  
   509  		// write to both pub&priv - requires endorsement from org1 (SBE policy) and org2 (collection policy)
   510  		submitTransaction(
   511  			gatewayClient,
   512  			signingIdentity,
   513  			"testchannel",
   514  			"sbecc",
   515  			"setval",
   516  			[]string{"both", "collection and SBE policies"},
   517  			nil,
   518  			[]string{org1Peer0.ID(), org2Peer0.ID()},
   519  		)
   520  
   521  		// check the private value was set
   522  		result := evaluateTransaction(
   523  			gatewayClient,
   524  			signingIdentity,
   525  			"testchannel",
   526  			"sbecc",
   527  			"getval",
   528  			[]string{"pub"},
   529  			nil,
   530  		)
   531  		Expect(result.Payload).To(Equal([]byte("collection and SBE policies")))
   532  	})
   533  
   534  	It("should endorse chaincode on org3 and also seek endorsement from another org for cc2cc call", func() {
   535  		conn := network.PeerClientConn(org3Peer0)
   536  		defer conn.Close()
   537  		gatewayClient := gateway.NewGatewayClient(conn)
   538  		signingIdentity := network.PeerUserSigner(org3Peer0, "User1")
   539  
   540  		submitTransaction(
   541  			gatewayClient,
   542  			signingIdentity,
   543  			"testchannel",
   544  			"sbecc",
   545  			"cc2cc",
   546  			[]string{"testchannel", "gatewaycc", "invoke", "a", "b", "10"},
   547  			nil,
   548  			[]string{org1Peer0.ID(), org3Peer0.ID()},
   549  		)
   550  
   551  		// check the transaction really worked - query via cc2cc call
   552  		result := evaluateTransaction(
   553  			gatewayClient,
   554  			signingIdentity,
   555  			"testchannel",
   556  			"sbecc",
   557  			"cc2cc",
   558  			[]string{"testchannel", "gatewaycc", "query", "a"},
   559  			nil,
   560  		)
   561  
   562  		Expect(result.Payload).To(Equal([]byte("90")))
   563  	})
   564  
   565  	It("reading private data should use the collection ownership policy, not signature policy", func() {
   566  		conn := network.PeerClientConn(org1Peer0)
   567  		defer conn.Close()
   568  		gatewayClient := gateway.NewGatewayClient(conn)
   569  		signingIdentity := network.PeerUserSigner(org1Peer0, "User1")
   570  
   571  		submitTransaction(
   572  			gatewayClient,
   573  			signingIdentity,
   574  			"testchannel",
   575  			"readpvtcc",
   576  			"setval",
   577  			[]string{"priv", "abcd"},
   578  			nil,
   579  			nil, // don't care - not testing this part
   580  		)
   581  
   582  		result := submitTransaction(
   583  			gatewayClient,
   584  			signingIdentity,
   585  			"testchannel",
   586  			"readpvtcc",
   587  			"getval",
   588  			[]string{"priv"},
   589  			nil,
   590  			[]string{org1Peer0.ID()},
   591  		)
   592  
   593  		Expect(result.GetPayload()).To(Equal([]byte("abcd")))
   594  	})
   595  })