github.com/kaituanwang/hyperledger@v2.0.1+incompatible/discovery/test/integration_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package test
     8  
     9  import (
    10  	"bytes"
    11  	"context"
    12  	"crypto/ecdsa"
    13  	"crypto/rand"
    14  	"crypto/x509"
    15  	"encoding/hex"
    16  	"encoding/pem"
    17  	"fmt"
    18  	"io/ioutil"
    19  	"os"
    20  	"os/exec"
    21  	"path/filepath"
    22  	"sync/atomic"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/golang/protobuf/proto"
    27  	"github.com/hyperledger/fabric-protos-go/common"
    28  	. "github.com/hyperledger/fabric-protos-go/discovery"
    29  	"github.com/hyperledger/fabric-protos-go/gossip"
    30  	msprotos "github.com/hyperledger/fabric-protos-go/msp"
    31  	"github.com/hyperledger/fabric-protos-go/peer"
    32  	"github.com/hyperledger/fabric/bccsp/sw"
    33  	bccsp "github.com/hyperledger/fabric/bccsp/utils"
    34  	"github.com/hyperledger/fabric/common/cauthdsl"
    35  	"github.com/hyperledger/fabric/common/configtx"
    36  	"github.com/hyperledger/fabric/common/crypto/tlsgen"
    37  	"github.com/hyperledger/fabric/common/policies"
    38  	"github.com/hyperledger/fabric/common/util"
    39  	"github.com/hyperledger/fabric/core/cclifecycle"
    40  	lifecyclemocks "github.com/hyperledger/fabric/core/cclifecycle/mocks"
    41  	"github.com/hyperledger/fabric/core/comm"
    42  	"github.com/hyperledger/fabric/core/common/ccprovider"
    43  	"github.com/hyperledger/fabric/discovery"
    44  	disc "github.com/hyperledger/fabric/discovery/client"
    45  	"github.com/hyperledger/fabric/discovery/endorsement"
    46  	discsupport "github.com/hyperledger/fabric/discovery/support"
    47  	discacl "github.com/hyperledger/fabric/discovery/support/acl"
    48  	ccsupport "github.com/hyperledger/fabric/discovery/support/chaincode"
    49  	"github.com/hyperledger/fabric/discovery/support/config"
    50  	"github.com/hyperledger/fabric/discovery/support/mocks"
    51  	"github.com/hyperledger/fabric/gossip/api"
    52  	gcommon "github.com/hyperledger/fabric/gossip/common"
    53  	gdisc "github.com/hyperledger/fabric/gossip/discovery"
    54  	"github.com/hyperledger/fabric/gossip/protoext"
    55  	"github.com/hyperledger/fabric/internal/configtxgen/encoder"
    56  	"github.com/hyperledger/fabric/internal/configtxgen/genesisconfig"
    57  	"github.com/hyperledger/fabric/msp"
    58  	"github.com/hyperledger/fabric/protoutil"
    59  	"github.com/onsi/gomega/gexec"
    60  	"github.com/pkg/errors"
    61  	"github.com/stretchr/testify/assert"
    62  	"google.golang.org/grpc"
    63  )
    64  
    65  var (
    66  	testPeers testPeerSet
    67  
    68  	cryptogen, idemixgen, testdir string
    69  
    70  	collectionConfigBytes = buildCollectionConfig(map[string][]*msprotos.MSPPrincipal{
    71  		"col1":  {orgPrincipal("Org1MSP")},
    72  		"col12": {orgPrincipal("Org1MSP"), orgPrincipal("Org2MSP")},
    73  	})
    74  
    75  	cc1Bytes = protoutil.MarshalOrPanic(&ccprovider.ChaincodeData{
    76  		Name:    "cc1",
    77  		Version: "1.0",
    78  		Id:      []byte{42},
    79  		Policy:  protoutil.MarshalOrPanic(policyFromString("AND('Org1MSP.member', 'Org1MSP.member')")),
    80  	})
    81  
    82  	cc2Bytes = protoutil.MarshalOrPanic(&ccprovider.ChaincodeData{
    83  		Name:    "cc2",
    84  		Version: "1.0",
    85  		Id:      []byte{43},
    86  		Policy:  protoutil.MarshalOrPanic(policyFromString("AND('Org1MSP.member', 'Org2MSP.member')")),
    87  	})
    88  )
    89  
    90  func TestMain(m *testing.M) {
    91  	if err := buildBinaries(); err != nil {
    92  		fmt.Printf("failed to build binaries: +%v", err)
    93  		gexec.CleanupBuildArtifacts()
    94  		os.Exit(1)
    95  	}
    96  
    97  	var err error
    98  	testdir, err = generateChannelArtifacts()
    99  	if err != nil {
   100  		fmt.Printf("failed to generate channel artifacts: +%v", err)
   101  		os.RemoveAll(testdir)
   102  		gexec.CleanupBuildArtifacts()
   103  		os.Exit(1)
   104  	}
   105  
   106  	peerDirPrefix := filepath.Join(testdir, "crypto-config", "peerOrganizations")
   107  	testPeers = testPeerSet{
   108  		newPeer(peerDirPrefix, "Org1MSP", 1, 0),
   109  		newPeer(peerDirPrefix, "Org1MSP", 1, 1),
   110  		newPeer(peerDirPrefix, "Org2MSP", 2, 0),
   111  		newPeer(peerDirPrefix, "Org2MSP", 2, 1),
   112  	}
   113  
   114  	rc := m.Run()
   115  	os.RemoveAll(testdir)
   116  	gexec.CleanupBuildArtifacts()
   117  	os.Exit(rc)
   118  }
   119  
   120  func TestGreenPath(t *testing.T) {
   121  	t.Parallel()
   122  	client, admin, service := createClientAndService(t, testdir)
   123  	defer service.Stop()
   124  	defer client.conn.Close()
   125  
   126  	service.lsccMetadataManager.query.On("GetState", "lscc", "cc1").Return(cc1Bytes, nil)
   127  	service.lsccMetadataManager.query.On("GetState", "lscc", "cc2").Return(cc2Bytes, nil)
   128  	service.lsccMetadataManager.query.On("GetState", "lscc", "cc2~collection").Return(collectionConfigBytes, nil)
   129  
   130  	ccWithCollection := &ChaincodeInterest{
   131  		Chaincodes: []*ChaincodeCall{
   132  			{Name: "cc2", CollectionNames: []string{"col12"}},
   133  		},
   134  	}
   135  	cc2cc := &ChaincodeInterest{
   136  		Chaincodes: []*ChaincodeCall{
   137  			{Name: "cc1"}, {Name: "cc2"},
   138  		},
   139  	}
   140  
   141  	// Send all queries
   142  	req := disc.NewRequest().AddLocalPeersQuery().OfChannel("mychannel")
   143  	col1 := &ChaincodeCall{Name: "cc2", CollectionNames: []string{"col1"}}
   144  	nonExistentCollection := &ChaincodeCall{Name: "cc2", CollectionNames: []string{"col3"}}
   145  	_ = nonExistentCollection
   146  	req, err := req.AddPeersQuery().AddPeersQuery(col1).AddPeersQuery(nonExistentCollection).AddConfigQuery().AddEndorsersQuery(cc2cc, ccWithCollection)
   147  
   148  	t.Run("Local peer query", func(t *testing.T) {
   149  		assert.NoError(t, err)
   150  		res, err := admin.Send(context.Background(), req, admin.AuthInfo)
   151  		assert.NoError(t, err)
   152  		returnedPeers, err := res.ForLocal().Peers()
   153  		assert.NoError(t, err)
   154  		assert.True(t, peersToTestPeers(returnedPeers).Equal(testPeers.withoutStateInfo()))
   155  	})
   156  
   157  	t.Run("Channel peer queries", func(t *testing.T) {
   158  		assert.NoError(t, err)
   159  		res, err := client.Send(context.Background(), req, client.AuthInfo)
   160  		assert.NoError(t, err)
   161  		returnedPeers, err := res.ForChannel("mychannel").Peers()
   162  		assert.NoError(t, err)
   163  		assert.True(t, peersToTestPeers(returnedPeers).Equal(testPeers))
   164  
   165  		returnedPeers, err = res.ForChannel("mychannel").Peers(col1)
   166  		assert.NoError(t, err)
   167  		// Ensure only peers from Org1 are returned
   168  		for _, p := range returnedPeers {
   169  			assert.Equal(t, "Org1MSP", p.MSPID)
   170  		}
   171  
   172  		// Ensure that the client handles correctly errors returned from the server
   173  		// in case of a bad request
   174  		returnedPeers, err = res.ForChannel("mychannel").Peers(nonExistentCollection)
   175  		assert.Equal(t, "collection col3 doesn't exist in collection config for chaincode cc2", err.Error())
   176  	})
   177  
   178  	t.Run("Endorser chaincode to chaincode", func(t *testing.T) {
   179  		assert.NoError(t, err)
   180  		res, err := client.Send(context.Background(), req, client.AuthInfo)
   181  		assert.NoError(t, err)
   182  		endorsers, err := res.ForChannel("mychannel").Endorsers(cc2cc.Chaincodes, disc.NoFilter)
   183  		assert.NoError(t, err)
   184  		endorsersByMSP := map[string][]string{}
   185  
   186  		for _, endorser := range endorsers {
   187  			endorsersByMSP[endorser.MSPID] = append(endorsersByMSP[endorser.MSPID], string(endorser.Identity))
   188  		}
   189  		// For cc2cc we expect 2 peers from Org1MSP and 1 from Org2MSP
   190  		assert.Equal(t, 2, len(endorsersByMSP["Org1MSP"]))
   191  		assert.Equal(t, 1, len(endorsersByMSP["Org2MSP"]))
   192  	})
   193  
   194  	t.Run("Endorser chaincode with collection", func(t *testing.T) {
   195  		assert.NoError(t, err)
   196  		res, err := client.Send(context.Background(), req, client.AuthInfo)
   197  		assert.NoError(t, err)
   198  		endorsers, err := res.ForChannel("mychannel").Endorsers(ccWithCollection.Chaincodes, disc.NoFilter)
   199  		assert.NoError(t, err)
   200  
   201  		endorsersByMSP := map[string][]string{}
   202  		for _, endorser := range endorsers {
   203  			endorsersByMSP[endorser.MSPID] = append(endorsersByMSP[endorser.MSPID], string(endorser.Identity))
   204  		}
   205  		assert.Equal(t, 1, len(endorsersByMSP["Org1MSP"]))
   206  		assert.Equal(t, 1, len(endorsersByMSP["Org2MSP"]))
   207  	})
   208  
   209  	t.Run("Config query", func(t *testing.T) {
   210  		assert.NoError(t, err)
   211  		res, err := client.Send(context.Background(), req, client.AuthInfo)
   212  		assert.NoError(t, err)
   213  		conf, err := res.ForChannel("mychannel").Config()
   214  		assert.NoError(t, err)
   215  		// Ensure MSP Configs are exactly as they appear in the config block
   216  		for mspID, mspConfig := range conf.Msps {
   217  			expectedConfig := service.sup.mspConfigs[mspID]
   218  			assert.Equal(t, expectedConfig, mspConfig)
   219  		}
   220  		// Ensure orderer endpoints are as they appear in the config block
   221  		for mspID, endpoints := range conf.Orderers {
   222  			assert.Equal(t, "OrdererMSP", mspID)
   223  			endpoints := endpoints.Endpoint
   224  			assert.Len(t, endpoints, 1)
   225  			assert.Equal(t, "orderer.example.com", endpoints[0].Host)
   226  			assert.Equal(t, uint32(7050), endpoints[0].Port)
   227  		}
   228  	})
   229  }
   230  
   231  func TestEndorsementComputationFailure(t *testing.T) {
   232  	t.Parallel()
   233  	client, _, service := createClientAndService(t, testdir)
   234  	defer service.Stop()
   235  	defer client.conn.Close()
   236  
   237  	service.lsccMetadataManager.query.On("GetState", "lscc", "cc1").Return(cc1Bytes, nil)
   238  	service.lsccMetadataManager.query.On("GetState", "lscc", "cc2").Return(cc2Bytes, nil)
   239  	service.lsccMetadataManager.query.On("GetState", "lscc", "cc2~collection").Return(collectionConfigBytes, nil)
   240  
   241  	// Now test a collection query that should fail because cc2's endorsement policy is Org1MSP AND org2MSP
   242  	// but the collection is configured only to have peers from Org1MSP
   243  	ccWithCollection := &ChaincodeInterest{
   244  		Chaincodes: []*ChaincodeCall{
   245  			{Name: "cc2", CollectionNames: []string{"col1"}},
   246  		},
   247  	}
   248  	req, err := disc.NewRequest().OfChannel("mychannel").AddEndorsersQuery(ccWithCollection)
   249  	assert.NoError(t, err)
   250  	res, err := client.Send(context.Background(), req, client.AuthInfo)
   251  	assert.NoError(t, err)
   252  
   253  	endorsers, err := res.ForChannel("mychannel").Endorsers(ccWithCollection.Chaincodes, disc.NoFilter)
   254  	assert.Empty(t, endorsers)
   255  	assert.Contains(t, err.Error(), "failed constructing descriptor")
   256  }
   257  
   258  func TestLedgerFailure(t *testing.T) {
   259  	t.Parallel()
   260  	client, _, service := createClientAndService(t, testdir)
   261  	defer service.Stop()
   262  	defer client.conn.Close()
   263  
   264  	service.lsccMetadataManager.query.On("GetState", "lscc", "cc1").Return(cc1Bytes, nil)
   265  	service.lsccMetadataManager.query.On("GetState", "lscc", "cc2").Return(nil, errors.New("IO error"))
   266  	service.lsccMetadataManager.query.On("GetState", "lscc", "cc12~collection").Return(collectionConfigBytes, nil)
   267  
   268  	ccWithCollection := &ChaincodeInterest{
   269  		Chaincodes: []*ChaincodeCall{
   270  			{Name: "cc1"},
   271  			{Name: "cc2", CollectionNames: []string{"col1"}},
   272  		},
   273  	}
   274  	req, err := disc.NewRequest().OfChannel("mychannel").AddEndorsersQuery(ccWithCollection)
   275  	assert.NoError(t, err)
   276  	res, err := client.Send(context.Background(), req, client.AuthInfo)
   277  	assert.NoError(t, err)
   278  
   279  	endorsers, err := res.ForChannel("mychannel").Endorsers(ccWithCollection.Chaincodes, disc.NoFilter)
   280  	assert.Empty(t, endorsers)
   281  	assert.Contains(t, err.Error(), "failed constructing descriptor")
   282  }
   283  
   284  func TestRevocation(t *testing.T) {
   285  	t.Parallel()
   286  	client, _, service := createClientAndService(t, testdir)
   287  	defer service.Stop()
   288  	defer client.conn.Close()
   289  
   290  	req := disc.NewRequest().OfChannel("mychannel").AddPeersQuery()
   291  	res, err := client.Send(context.Background(), req, client.AuthInfo)
   292  	assert.NoError(t, err)
   293  	// Record number of times we deserialized the identity
   294  	firstCount := atomic.LoadUint32(&service.sup.deserializeIdentityCount)
   295  
   296  	// Do the same query again
   297  	peers, err := res.ForChannel("mychannel").Peers()
   298  	assert.NotEmpty(t, peers)
   299  	assert.NoError(t, err)
   300  
   301  	res, err = client.Send(context.Background(), req, client.AuthInfo)
   302  	assert.NoError(t, err)
   303  	// The amount of times deserializeIdentity was called should not have changed
   304  	// because requests should have hit the cache
   305  	secondCount := atomic.LoadUint32(&service.sup.deserializeIdentityCount)
   306  	assert.Equal(t, firstCount, secondCount)
   307  
   308  	// Now, increment the config sequence
   309  	oldSeq := service.sup.sequenceWrapper.Sequence()
   310  	v := &mocks.ConfigtxValidator{}
   311  	v.SequenceReturns(oldSeq + 1)
   312  	service.sup.sequenceWrapper.instance.Store(v)
   313  
   314  	// Revoke all identities inside the MSP manager
   315  	atomic.AddUint32(&service.sup.mspWrapper.blocks, uint32(1))
   316  
   317  	// Send the query for the third time
   318  	res, err = client.Send(context.Background(), req, client.AuthInfo)
   319  	assert.NoError(t, err)
   320  	// The cache should have been purged, thus deserializeIdentity should have been
   321  	// called an additional time
   322  	thirdCount := atomic.LoadUint32(&service.sup.deserializeIdentityCount)
   323  	assert.NotEqual(t, thirdCount, secondCount)
   324  
   325  	// We should be denied access
   326  	peers, err = res.ForChannel("mychannel").Peers()
   327  	assert.Empty(t, peers)
   328  	assert.Contains(t, err.Error(), "access denied")
   329  }
   330  
   331  type client struct {
   332  	*disc.Client
   333  	*AuthInfo
   334  	conn *grpc.ClientConn
   335  }
   336  
   337  func (c *client) newConnection() (*grpc.ClientConn, error) {
   338  	return c.conn, nil
   339  }
   340  
   341  type mspWrapper struct {
   342  	deserializeIdentityCount uint32
   343  	msp.MSPManager
   344  	mspConfigs map[string]*msprotos.FabricMSPConfig
   345  	blocks     uint32
   346  }
   347  
   348  func (w *mspWrapper) DeserializeIdentity(serializedIdentity []byte) (msp.Identity, error) {
   349  	atomic.AddUint32(&w.deserializeIdentityCount, 1)
   350  	if atomic.LoadUint32(&w.blocks) == uint32(1) {
   351  		return nil, errors.New("failed deserializing identity")
   352  	}
   353  	return w.MSPManager.DeserializeIdentity(serializedIdentity)
   354  }
   355  
   356  type lsccMetadataManager struct {
   357  	*cclifecycle.MetadataManager
   358  	query *lifecyclemocks.Query
   359  }
   360  
   361  func newLSCCMetadataManager() *lsccMetadataManager {
   362  	enumerator := &lifecyclemocks.Enumerator{}
   363  	enumerator.On("Enumerate").Return(nil, nil)
   364  	m, err := cclifecycle.NewMetadataManager(enumerator)
   365  	if err != nil {
   366  		panic(err)
   367  	}
   368  	qc := &lifecyclemocks.QueryCreator{}
   369  	query := &lifecyclemocks.Query{}
   370  	query.On("Done").Return()
   371  	qc.On("NewQuery").Return(query, nil)
   372  	_, err = m.NewChannelSubscription("mychannel", qc)
   373  	if err != nil {
   374  		panic(err)
   375  	}
   376  	return &lsccMetadataManager{
   377  		MetadataManager: m,
   378  		query:           query,
   379  	}
   380  }
   381  
   382  type principalEvaluator struct {
   383  	*discacl.DiscoverySupport
   384  	msp.MSPManager
   385  }
   386  
   387  type service struct {
   388  	*grpc.Server
   389  	lsccMetadataManager *lsccMetadataManager
   390  	sup                 *support
   391  }
   392  
   393  type support struct {
   394  	discovery.Support
   395  	*mspWrapper
   396  	*sequenceWrapper
   397  }
   398  
   399  type sequenceWrapper struct {
   400  	configtx.Validator
   401  	instance atomic.Value
   402  }
   403  
   404  func (s *sequenceWrapper) Sequence() uint64 {
   405  	return s.instance.Load().(*mocks.ConfigtxValidator).Sequence()
   406  }
   407  
   408  func createSupport(t *testing.T, dir string, lsccMetadataManager *lsccMetadataManager) *support {
   409  	configs := make(map[string]*msprotos.FabricMSPConfig)
   410  	mspMgr := createMSPManager(t, dir, configs)
   411  	mspManagerWrapper := &mspWrapper{
   412  		MSPManager: mspMgr,
   413  		mspConfigs: configs,
   414  	}
   415  	mspMgr = mspManagerWrapper
   416  	msps, _ := mspMgr.GetMSPs()
   417  	org1MSP := msps["Org1MSP"]
   418  	s := &sequenceWrapper{}
   419  	v := &mocks.ConfigtxValidator{}
   420  	v.SequenceReturns(1)
   421  	s.instance.Store(v)
   422  	chConfig := createChannelConfigGetter(s, mspMgr)
   423  	polMgr := createPolicyManagerGetter(t, mspMgr)
   424  
   425  	channelVerifier := discacl.NewChannelVerifier(policies.ChannelApplicationWriters, polMgr)
   426  
   427  	org1Admin, err := cauthdsl.FromString("OR('Org1MSP.admin')")
   428  	assert.NoError(t, err)
   429  	org1AdminPolicy, _, err := cauthdsl.NewPolicyProvider(org1MSP).NewPolicy(protoutil.MarshalOrPanic(org1Admin))
   430  	assert.NoError(t, err)
   431  	acl := discacl.NewDiscoverySupport(channelVerifier, org1AdminPolicy, chConfig)
   432  
   433  	gSup := &mocks.GossipSupport{}
   434  	gSup.On("ChannelExists", "mychannel").Return(true)
   435  	gSup.On("PeersOfChannel", gcommon.ChannelID("mychannel")).Return(testPeers.toStateInfoSet())
   436  	gSup.On("Peers").Return(testPeers.toMembershipSet())
   437  	gSup.On("IdentityInfo").Return(testPeers.toIdentitySet())
   438  
   439  	pe := &principalEvaluator{
   440  		MSPManager: mspMgr,
   441  		DiscoverySupport: &discacl.DiscoverySupport{
   442  			ChannelConfigGetter: createChannelConfigGetter(s, mspMgr),
   443  		},
   444  	}
   445  
   446  	ccSup := ccsupport.NewDiscoverySupport(lsccMetadataManager)
   447  	ea := endorsement.NewEndorsementAnalyzer(gSup, ccSup, pe, lsccMetadataManager)
   448  
   449  	fakeBlockGetter := &mocks.ConfigBlockGetter{}
   450  	fakeBlockGetter.GetCurrConfigBlockReturns(createGenesisBlock(filepath.Join(dir, "crypto-config")))
   451  	confSup := config.NewDiscoverySupport(fakeBlockGetter)
   452  	return &support{
   453  		Support:         discsupport.NewDiscoverySupport(acl, gSup, ea, confSup, acl),
   454  		mspWrapper:      mspManagerWrapper,
   455  		sequenceWrapper: s,
   456  	}
   457  }
   458  
   459  func createClientAndService(t *testing.T, testdir string) (*client, *client, *service) {
   460  	ca, err := tlsgen.NewCA()
   461  	assert.NoError(t, err)
   462  
   463  	serverKeyPair, err := ca.NewServerCertKeyPair("127.0.0.1")
   464  	assert.NoError(t, err)
   465  
   466  	// Create a server on an ephemeral port
   467  	gRPCServer, err := comm.NewGRPCServer("127.0.0.1:", comm.ServerConfig{
   468  		SecOpts: comm.SecureOptions{
   469  			Key:         serverKeyPair.Key,
   470  			Certificate: serverKeyPair.Cert,
   471  			UseTLS:      true,
   472  		},
   473  	})
   474  
   475  	l := newLSCCMetadataManager()
   476  	sup := createSupport(t, testdir, l)
   477  	svc := discovery.NewService(discovery.Config{
   478  		TLS:                          gRPCServer.TLSEnabled(),
   479  		AuthCacheEnabled:             true,
   480  		AuthCacheMaxSize:             10,
   481  		AuthCachePurgeRetentionRatio: 0.5,
   482  	}, sup)
   483  
   484  	RegisterDiscoveryServer(gRPCServer.Server(), svc)
   485  
   486  	assert.NoError(t, err)
   487  	go gRPCServer.Start()
   488  
   489  	clientKeyPair, err := ca.NewClientCertKeyPair()
   490  	assert.NoError(t, err)
   491  
   492  	dialer, err := comm.NewGRPCClient(comm.ClientConfig{
   493  		Timeout: time.Second * 3,
   494  		SecOpts: comm.SecureOptions{
   495  			UseTLS:        true,
   496  			Certificate:   clientKeyPair.Cert,
   497  			Key:           clientKeyPair.Key,
   498  			ServerRootCAs: [][]byte{ca.CertBytes()},
   499  		},
   500  	})
   501  	assert.NoError(t, err)
   502  
   503  	conn, err := dialer.NewConnection(gRPCServer.Address())
   504  	assert.NoError(t, err)
   505  
   506  	userSigner := createUserSigner(t)
   507  	wrapperUserClient := &client{AuthInfo: &AuthInfo{
   508  		ClientIdentity:    userSigner.Creator,
   509  		ClientTlsCertHash: util.ComputeSHA256(clientKeyPair.TLSCert.Raw),
   510  	}, conn: conn}
   511  	var signerCacheSize uint = 10
   512  	wrapperUserClient.Client = disc.NewClient(wrapperUserClient.newConnection, userSigner.Sign, signerCacheSize)
   513  
   514  	adminSigner := createAdminSigner(t)
   515  	wrapperAdminClient := &client{AuthInfo: &AuthInfo{
   516  		ClientIdentity:    adminSigner.Creator,
   517  		ClientTlsCertHash: util.ComputeSHA256(clientKeyPair.TLSCert.Raw),
   518  	}, conn: conn}
   519  	wrapperAdminClient.Client = disc.NewClient(wrapperAdminClient.newConnection, adminSigner.Sign, signerCacheSize)
   520  
   521  	service := &service{Server: gRPCServer.Server(), lsccMetadataManager: l, sup: sup}
   522  	return wrapperUserClient, wrapperAdminClient, service
   523  }
   524  
   525  func createUserSigner(t *testing.T) *signer {
   526  	identityDir := filepath.Join(testdir, "crypto-config", "peerOrganizations", "org1.example.com", "users", "User1@org1.example.com", "msp")
   527  	certPath := filepath.Join(identityDir, "signcerts", "User1@org1.example.com-cert.pem")
   528  	keyPath := filepath.Join(identityDir, "keystore")
   529  	keys, err := ioutil.ReadDir(keyPath)
   530  	assert.NoError(t, err)
   531  	assert.Len(t, keys, 1)
   532  	keyPath = filepath.Join(keyPath, keys[0].Name())
   533  	signer, err := newSigner("Org1MSP", certPath, keyPath)
   534  	assert.NoError(t, err)
   535  	return signer
   536  }
   537  
   538  func createAdminSigner(t *testing.T) *signer {
   539  	identityDir := filepath.Join(testdir, "crypto-config", "peerOrganizations", "org1.example.com", "users", "Admin@org1.example.com", "msp")
   540  	certPath := filepath.Join(identityDir, "signcerts", "Admin@org1.example.com-cert.pem")
   541  	keyPath := filepath.Join(identityDir, "keystore")
   542  	keys, err := ioutil.ReadDir(keyPath)
   543  	assert.NoError(t, err)
   544  	assert.Len(t, keys, 1)
   545  	keyPath = filepath.Join(keyPath, keys[0].Name())
   546  	signer, err := newSigner("Org1MSP", certPath, keyPath)
   547  	assert.NoError(t, err)
   548  	return signer
   549  }
   550  
   551  func createMSP(t *testing.T, dir, mspID string) (msp.MSP, *msprotos.FabricMSPConfig) {
   552  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   553  	assert.NoError(t, err)
   554  	channelMSP, err := msp.New(
   555  		&msp.BCCSPNewOpts{NewBaseOpts: msp.NewBaseOpts{Version: msp.MSPv1_4_3}},
   556  		cryptoProvider,
   557  	)
   558  	assert.NoError(t, err)
   559  
   560  	mspConf, err := msp.GetVerifyingMspConfig(dir, mspID, "bccsp")
   561  	assert.NoError(t, err)
   562  
   563  	fabConf := &msprotos.FabricMSPConfig{}
   564  	proto.Unmarshal(mspConf.Config, fabConf)
   565  
   566  	channelMSP.Setup(mspConf)
   567  	return channelMSP, fabConf
   568  }
   569  
   570  func createMSPManager(t *testing.T, dir string, configs map[string]*msprotos.FabricMSPConfig) msp.MSPManager {
   571  	var mspsOfChannel []msp.MSP
   572  	for _, mspConf := range []struct {
   573  		mspID  string
   574  		mspDir string
   575  	}{
   576  		{
   577  			mspID:  "Org1MSP",
   578  			mspDir: filepath.Join(dir, "crypto-config", "peerOrganizations", "org1.example.com", "msp"),
   579  		},
   580  		{
   581  			mspID:  "Org2MSP",
   582  			mspDir: filepath.Join(dir, "crypto-config", "peerOrganizations", "org2.example.com", "msp"),
   583  		},
   584  		{
   585  			mspID:  "OrdererMSP",
   586  			mspDir: filepath.Join(dir, "crypto-config", "ordererOrganizations", "example.com", "msp"),
   587  		},
   588  	} {
   589  		mspInstance, conf := createMSP(t, mspConf.mspDir, mspConf.mspID)
   590  		configs[mspConf.mspID] = conf
   591  		mspsOfChannel = append(mspsOfChannel, mspInstance)
   592  	}
   593  
   594  	mspMgr := msp.NewMSPManager()
   595  	mspMgr.Setup(mspsOfChannel)
   596  	return mspMgr
   597  }
   598  
   599  func createChannelConfigGetter(s *sequenceWrapper, mspMgr msp.MSPManager) discacl.ChannelConfigGetter {
   600  	resources := &mocks.Resources{}
   601  	resources.ConfigtxValidatorReturns(s)
   602  	resources.MSPManagerReturns(mspMgr)
   603  	chConfig := &mocks.ChannelConfigGetter{}
   604  	chConfig.GetChannelConfigReturns(resources)
   605  	return chConfig
   606  }
   607  
   608  func createPolicyManagerGetter(t *testing.T, mspMgr msp.MSPManager) *mocks.ChannelPolicyManagerGetter {
   609  	org1Org2Members, err := cauthdsl.FromString("OR('Org1MSP.client', 'Org2MSP.client')")
   610  	assert.NoError(t, err)
   611  	org1Org2MembersPolicy, _, err := cauthdsl.NewPolicyProvider(mspMgr).NewPolicy(protoutil.MarshalOrPanic(org1Org2Members))
   612  	assert.NoError(t, err)
   613  
   614  	polMgr := &mocks.ChannelPolicyManagerGetter{}
   615  	policyMgr := &mocks.PolicyManager{}
   616  	policyMgr.On("GetPolicy", policies.ChannelApplicationWriters).Return(org1Org2MembersPolicy, true)
   617  	polMgr.On("Manager", "mychannel").Return(policyMgr, false)
   618  	return polMgr
   619  }
   620  
   621  func buildBinaries() error {
   622  	var err error
   623  	cryptogen, err = gexec.Build("github.com/hyperledger/fabric/cmd/cryptogen")
   624  	if err != nil {
   625  		return errors.WithStack(err)
   626  	}
   627  
   628  	idemixgen, err = gexec.Build("github.com/hyperledger/fabric/cmd/idemixgen")
   629  	if err != nil {
   630  		return errors.WithStack(err)
   631  	}
   632  	return nil
   633  }
   634  
   635  func generateChannelArtifacts() (string, error) {
   636  	dir, err := ioutil.TempDir("", "TestMSPIDMapping")
   637  	if err != nil {
   638  		return "", errors.WithStack(err)
   639  	}
   640  	cryptoConfigDir := filepath.Join(dir, "crypto-config")
   641  	args := []string{
   642  		"generate",
   643  		fmt.Sprintf("--output=%s", cryptoConfigDir),
   644  		fmt.Sprintf("--config=%s", filepath.Join("testdata", "crypto-config.yaml")),
   645  	}
   646  	b, err := exec.Command(cryptogen, args...).CombinedOutput()
   647  	if err != nil {
   648  		return "", errors.Wrap(err, string(b))
   649  	}
   650  
   651  	idemixConfigDir := filepath.Join(dir, "crypto-config", "idemix")
   652  	b, err = exec.Command(idemixgen, "ca-keygen", fmt.Sprintf("--output=%s", idemixConfigDir)).CombinedOutput()
   653  	if err != nil {
   654  		return "", errors.Wrap(err, string(b))
   655  	}
   656  	return dir, nil
   657  }
   658  
   659  func createGenesisBlock(cryptoConfigDir string) *common.Block {
   660  	appConfig := genesisconfig.Load("TwoOrgsChannel", "testdata")
   661  	ordererConfig := genesisconfig.Load("TwoOrgsOrdererGenesis", "testdata")
   662  	// Glue the two parts together, without loss of generality - to the application parts
   663  	appConfig.Orderer = ordererConfig.Orderer
   664  	channelConfig := appConfig
   665  
   666  	idemixConfigDir := filepath.Join(cryptoConfigDir, "idemix")
   667  	// Override the MSP directories
   668  	for _, org := range channelConfig.Orderer.Organizations {
   669  		org.MSPDir = filepath.Join(cryptoConfigDir, "ordererOrganizations", "example.com", "msp")
   670  	}
   671  	for i, org := range channelConfig.Application.Organizations {
   672  		if org.MSPType != "bccsp" {
   673  			org.MSPDir = filepath.Join(idemixConfigDir)
   674  			continue
   675  		}
   676  		org.MSPDir = filepath.Join(cryptoConfigDir, "peerOrganizations", fmt.Sprintf("org%d.example.com", i+1), "msp")
   677  	}
   678  
   679  	channelGenerator := encoder.New(channelConfig)
   680  	return channelGenerator.GenesisBlockForChannel("mychannel")
   681  }
   682  
   683  type testPeer struct {
   684  	mspID        string
   685  	identity     []byte
   686  	stateInfoMsg gdisc.NetworkMember
   687  	aliveMsg     gdisc.NetworkMember
   688  }
   689  
   690  func (tp testPeer) Equal(other testPeer) bool {
   691  	if tp.mspID != other.mspID || !bytes.Equal(tp.identity, other.identity) {
   692  		return false
   693  	}
   694  	if tp.aliveMsg.Endpoint != other.aliveMsg.Endpoint || !bytes.Equal(tp.aliveMsg.PKIid, other.aliveMsg.PKIid) {
   695  		return false
   696  	}
   697  	if !proto.Equal(tp.aliveMsg.Envelope, other.aliveMsg.Envelope) {
   698  		return false
   699  	}
   700  	if !bytes.Equal(tp.stateInfoMsg.PKIid, other.stateInfoMsg.PKIid) {
   701  		return false
   702  	}
   703  	if !proto.Equal(tp.stateInfoMsg.Envelope, other.stateInfoMsg.Envelope) {
   704  		return false
   705  	}
   706  	if !proto.Equal(tp.stateInfoMsg.Properties, other.stateInfoMsg.Properties) {
   707  		return false
   708  	}
   709  	return true
   710  }
   711  
   712  type testPeerSet []*testPeer
   713  
   714  func (ps testPeerSet) withoutStateInfo() testPeerSet {
   715  	var res testPeerSet
   716  	for _, p := range ps {
   717  		peer := *p
   718  		peer.stateInfoMsg = gdisc.NetworkMember{}
   719  		res = append(res, &peer)
   720  	}
   721  	return res
   722  }
   723  
   724  func (ps testPeerSet) toStateInfoSet() gdisc.Members {
   725  	var members gdisc.Members
   726  	for _, p := range ps {
   727  		members = append(members, p.stateInfoMsg)
   728  	}
   729  	return members
   730  }
   731  
   732  func (ps testPeerSet) toMembershipSet() gdisc.Members {
   733  	var members gdisc.Members
   734  	for _, p := range ps {
   735  		members = append(members, p.aliveMsg)
   736  	}
   737  	return members
   738  }
   739  
   740  func (ps testPeerSet) toIdentitySet() api.PeerIdentitySet {
   741  	var idSet api.PeerIdentitySet
   742  	for _, p := range ps {
   743  		idSet = append(idSet, api.PeerIdentityInfo{
   744  			Identity:     p.identity,
   745  			PKIId:        p.aliveMsg.PKIid,
   746  			Organization: api.OrgIdentityType(p.mspID),
   747  		})
   748  	}
   749  	return idSet
   750  }
   751  
   752  func (ps testPeerSet) Equal(that testPeerSet) bool {
   753  	this := ps
   754  	return this.SubsetEqual(that) && that.SubsetEqual(this)
   755  }
   756  
   757  func (ps testPeerSet) SubsetEqual(that testPeerSet) bool {
   758  	this := ps
   759  	for _, p := range this {
   760  		if !that.Contains(p) {
   761  			return false
   762  		}
   763  	}
   764  	return true
   765  }
   766  
   767  func (ps testPeerSet) Contains(peer *testPeer) bool {
   768  	for _, p := range ps {
   769  		if peer.Equal(*p) {
   770  			return true
   771  		}
   772  	}
   773  	return false
   774  }
   775  
   776  func peersToTestPeers(peers []*disc.Peer) testPeerSet {
   777  	var res testPeerSet
   778  	for _, p := range peers {
   779  		pkiID := gcommon.PKIidType(hex.EncodeToString(util.ComputeSHA256(p.Identity)))
   780  		var stateInfoMember gdisc.NetworkMember
   781  		if p.StateInfoMessage != nil {
   782  			stateInfo, _ := protoext.EnvelopeToGossipMessage(p.StateInfoMessage.Envelope)
   783  			stateInfoMember = gdisc.NetworkMember{
   784  				PKIid:      pkiID,
   785  				Envelope:   p.StateInfoMessage.Envelope,
   786  				Properties: stateInfo.GetStateInfo().Properties,
   787  			}
   788  		}
   789  
   790  		tp := &testPeer{
   791  			mspID:    p.MSPID,
   792  			identity: p.Identity,
   793  			aliveMsg: gdisc.NetworkMember{
   794  				PKIid:    pkiID,
   795  				Endpoint: string(pkiID),
   796  				Envelope: p.AliveMessage.Envelope,
   797  			},
   798  			stateInfoMsg: stateInfoMember,
   799  		}
   800  		res = append(res, tp)
   801  	}
   802  	return res
   803  }
   804  
   805  func newPeer(dir, mspID string, org, id int) *testPeer {
   806  	peerStr := fmt.Sprintf("peer%d.org%d.example.com", id, org)
   807  	certFile := filepath.Join(dir, fmt.Sprintf("org%d.example.com", org),
   808  		"peers", peerStr, "msp", "signcerts", fmt.Sprintf("%s-cert.pem", peerStr))
   809  	certBytes, err := ioutil.ReadFile(certFile)
   810  	if err != nil {
   811  		panic(fmt.Sprintf("failed reading file %s: %v", certFile, err))
   812  	}
   813  	sID := &msprotos.SerializedIdentity{
   814  		Mspid:   mspID,
   815  		IdBytes: certBytes,
   816  	}
   817  	identityBytes := protoutil.MarshalOrPanic(sID)
   818  	pkiID := gcommon.PKIidType(hex.EncodeToString(util.ComputeSHA256(identityBytes)))
   819  	return &testPeer{
   820  		mspID:        mspID,
   821  		identity:     identityBytes,
   822  		aliveMsg:     aliveMsg(pkiID),
   823  		stateInfoMsg: stateInfoMsg(pkiID),
   824  	}
   825  }
   826  
   827  func stateInfoMsg(pkiID gcommon.PKIidType) gdisc.NetworkMember {
   828  	si := &gossip.StateInfo{
   829  		Properties: &gossip.Properties{
   830  			LedgerHeight: 100,
   831  			Chaincodes: []*gossip.Chaincode{
   832  				{
   833  					Name:     "cc1",
   834  					Version:  "1.0",
   835  					Metadata: []byte{42},
   836  				},
   837  				{
   838  					Name:     "cc2",
   839  					Version:  "1.0",
   840  					Metadata: []byte{43},
   841  				},
   842  			},
   843  		},
   844  		PkiId:     pkiID,
   845  		Timestamp: &gossip.PeerTime{},
   846  	}
   847  	gm := &gossip.GossipMessage{
   848  		Content: &gossip.GossipMessage_StateInfo{
   849  			StateInfo: si,
   850  		},
   851  	}
   852  	sm, _ := protoext.NoopSign(gm)
   853  	return gdisc.NetworkMember{
   854  		Properties: si.Properties,
   855  		PKIid:      pkiID,
   856  		Envelope:   sm.Envelope,
   857  	}
   858  }
   859  
   860  func aliveMsg(pkiID gcommon.PKIidType) gdisc.NetworkMember {
   861  	am := &gossip.AliveMessage{
   862  		Membership: &gossip.Member{
   863  			PkiId:    pkiID,
   864  			Endpoint: string(pkiID),
   865  		},
   866  		Timestamp: &gossip.PeerTime{},
   867  	}
   868  	gm := &gossip.GossipMessage{
   869  		Content: &gossip.GossipMessage_AliveMsg{
   870  			AliveMsg: am,
   871  		},
   872  	}
   873  	sm, _ := protoext.NoopSign(gm)
   874  	return gdisc.NetworkMember{
   875  		PKIid:    pkiID,
   876  		Endpoint: string(pkiID),
   877  		Envelope: sm.Envelope,
   878  	}
   879  }
   880  
   881  func buildCollectionConfig(col2principals map[string][]*msprotos.MSPPrincipal) []byte {
   882  	collections := &peer.CollectionConfigPackage{}
   883  	for col, principals := range col2principals {
   884  		collections.Config = append(collections.Config, &peer.CollectionConfig{
   885  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   886  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   887  					Name: col,
   888  					MemberOrgsPolicy: &peer.CollectionPolicyConfig{
   889  						Payload: &peer.CollectionPolicyConfig_SignaturePolicy{
   890  							SignaturePolicy: &common.SignaturePolicyEnvelope{
   891  								Identities: principals,
   892  							},
   893  						},
   894  					},
   895  				},
   896  			},
   897  		})
   898  	}
   899  	return protoutil.MarshalOrPanic(collections)
   900  }
   901  
   902  func orgPrincipal(mspID string) *msprotos.MSPPrincipal {
   903  	return &msprotos.MSPPrincipal{
   904  		PrincipalClassification: msprotos.MSPPrincipal_ROLE,
   905  		Principal: protoutil.MarshalOrPanic(&msprotos.MSPRole{
   906  			MspIdentifier: mspID,
   907  			Role:          msprotos.MSPRole_MEMBER,
   908  		}),
   909  	}
   910  }
   911  
   912  func policyFromString(s string) *common.SignaturePolicyEnvelope {
   913  	p, err := cauthdsl.FromString(s)
   914  	if err != nil {
   915  		panic(err)
   916  	}
   917  	return p
   918  }
   919  
   920  type signer struct {
   921  	key     *ecdsa.PrivateKey
   922  	Creator []byte
   923  }
   924  
   925  func newSigner(msp, certPath, keyPath string) (*signer, error) {
   926  	sId, err := serializeIdentity(certPath, msp)
   927  	if err != nil {
   928  		return nil, errors.WithStack(err)
   929  	}
   930  	key, err := loadPrivateKey(keyPath)
   931  	if err != nil {
   932  		return nil, errors.WithStack(err)
   933  	}
   934  	return &signer{
   935  		Creator: sId,
   936  		key:     key,
   937  	}, nil
   938  }
   939  
   940  func serializeIdentity(clientCert string, mspID string) ([]byte, error) {
   941  	b, err := ioutil.ReadFile(clientCert)
   942  	if err != nil {
   943  		return nil, errors.WithStack(err)
   944  	}
   945  	sId := &msprotos.SerializedIdentity{
   946  		Mspid:   mspID,
   947  		IdBytes: b,
   948  	}
   949  	return protoutil.MarshalOrPanic(sId), nil
   950  }
   951  
   952  func (si *signer) Sign(msg []byte) ([]byte, error) {
   953  	digest := util.ComputeSHA256(msg)
   954  	return signECDSA(si.key, digest)
   955  }
   956  
   957  func loadPrivateKey(file string) (*ecdsa.PrivateKey, error) {
   958  	b, err := ioutil.ReadFile(file)
   959  	if err != nil {
   960  		return nil, errors.WithStack(err)
   961  	}
   962  	bl, _ := pem.Decode(b)
   963  	key, err := x509.ParsePKCS8PrivateKey(bl.Bytes)
   964  	if err != nil {
   965  		return nil, errors.WithStack(err)
   966  	}
   967  	return key.(*ecdsa.PrivateKey), nil
   968  }
   969  
   970  func signECDSA(k *ecdsa.PrivateKey, digest []byte) (signature []byte, err error) {
   971  	r, s, err := ecdsa.Sign(rand.Reader, k, digest)
   972  	if err != nil {
   973  		return nil, err
   974  	}
   975  
   976  	s, _, err = bccsp.ToLowS(&k.PublicKey, s)
   977  	if err != nil {
   978  		return nil, err
   979  	}
   980  	return bccsp.MarshalECDSASignature(r, s)
   981  }