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

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package nwo
     8  
     9  import (
    10  	"bytes"
    11  	"context"
    12  	"fmt"
    13  	"io"
    14  	"io/ioutil"
    15  	"net"
    16  	"os"
    17  	"os/exec"
    18  	"path/filepath"
    19  	"runtime"
    20  	"sort"
    21  	"strconv"
    22  	"strings"
    23  	"sync"
    24  	"syscall"
    25  	"text/template"
    26  	"time"
    27  
    28  	docker "github.com/fsouza/go-dockerclient"
    29  	"github.com/hechain20/hechain/integration/nwo/commands"
    30  	"github.com/hechain20/hechain/integration/nwo/fabricconfig"
    31  	"github.com/hechain20/hechain/integration/nwo/runner"
    32  	"github.com/onsi/ginkgo"
    33  	. "github.com/onsi/gomega"
    34  	"github.com/onsi/gomega/gexec"
    35  	"github.com/onsi/gomega/gstruct"
    36  	"github.com/onsi/gomega/types"
    37  	"github.com/tedsuo/ifrit"
    38  	"github.com/tedsuo/ifrit/ginkgomon"
    39  	"github.com/tedsuo/ifrit/grouper"
    40  	"google.golang.org/grpc"
    41  	"google.golang.org/grpc/credentials"
    42  	"gopkg.in/yaml.v2"
    43  )
    44  
    45  // Organization models information about an Organization. It includes
    46  // the information needed to populate an MSP with cryptogen.
    47  type Organization struct {
    48  	MSPID         string `yaml:"msp_id,omitempty"`
    49  	MSPType       string `yaml:"msp_type,omitempty"`
    50  	Name          string `yaml:"name,omitempty"`
    51  	Domain        string `yaml:"domain,omitempty"`
    52  	EnableNodeOUs bool   `yaml:"enable_node_organizational_units"`
    53  	Users         int    `yaml:"users,omitempty"`
    54  	CA            *CA    `yaml:"ca,omitempty"`
    55  }
    56  
    57  type CA struct {
    58  	Hostname string `yaml:"hostname,omitempty"`
    59  }
    60  
    61  // A Consortium is a named collection of Organizations. It is used to populate
    62  // the Orderer geneesis block profile.
    63  type Consortium struct {
    64  	Name          string   `yaml:"name,omitempty"`
    65  	Organizations []string `yaml:"organizations,omitempty"`
    66  }
    67  
    68  // Consensus indicates the orderer types and how many broker and zookeeper
    69  // instances.
    70  type Consensus struct {
    71  	Type                        string `yaml:"type,omitempty"`
    72  	BootstrapMethod             string `yaml:"bootstrap_method,omitempty"`
    73  	Brokers                     int    `yaml:"brokers,omitempty"`
    74  	ZooKeepers                  int    `yaml:"zookeepers,omitempty"`
    75  	ChannelParticipationEnabled bool   `yaml:"channel_participation_enabled,omitempty"`
    76  }
    77  
    78  // The SystemChannel declares the name of the network system channel and its
    79  // associated configtxgen profile name.
    80  type SystemChannel struct {
    81  	Name    string `yaml:"name,omitempty"`
    82  	Profile string `yaml:"profile,omitempty"`
    83  }
    84  
    85  // Channel associates a channel name with a configtxgen profile name.
    86  type Channel struct {
    87  	Name        string `yaml:"name,omitempty"`
    88  	Profile     string `yaml:"profile,omitempty"`
    89  	BaseProfile string `yaml:"baseprofile,omitempty"`
    90  }
    91  
    92  // Orderer defines an orderer instance and its owning organization.
    93  type Orderer struct {
    94  	Name         string `yaml:"name,omitempty"`
    95  	Organization string `yaml:"organization,omitempty"`
    96  }
    97  
    98  // ID provides a unique identifier for an orderer instance.
    99  func (o Orderer) ID() string {
   100  	return fmt.Sprintf("%s.%s", o.Organization, o.Name)
   101  }
   102  
   103  // Peer defines a peer instance, it's owning organization, and the list of
   104  // channels that the peer should be joined to.
   105  type Peer struct {
   106  	Name         string         `yaml:"name,omitempty"`
   107  	DevMode      bool           `yaml:"devmode,omitempty"`
   108  	Organization string         `yaml:"organization,omitempty"`
   109  	Channels     []*PeerChannel `yaml:"channels,omitempty"`
   110  }
   111  
   112  // PeerChannel names of the channel a peer should be joined to and whether or
   113  // not the peer should be an anchor for the channel.
   114  type PeerChannel struct {
   115  	Name   string `yaml:"name,omitempty"`
   116  	Anchor bool   `yaml:"anchor"`
   117  }
   118  
   119  // ID provides a unique identifier for a peer instance.
   120  func (p *Peer) ID() string {
   121  	return fmt.Sprintf("%s.%s", p.Organization, p.Name)
   122  }
   123  
   124  // Anchor returns true if this peer is an anchor for any channel it has joined.
   125  func (p *Peer) Anchor() bool {
   126  	for _, c := range p.Channels {
   127  		if c.Anchor {
   128  			return true
   129  		}
   130  	}
   131  	return false
   132  }
   133  
   134  // A profile encapsulates basic information for a configtxgen profile.
   135  type Profile struct {
   136  	Name                string   `yaml:"name,omitempty"`
   137  	Orderers            []string `yaml:"orderers,omitempty"`
   138  	Consortium          string   `yaml:"consortium,omitempty"`
   139  	Organizations       []string `yaml:"organizations,omitempty"`
   140  	AppCapabilities     []string `yaml:"app_capabilities,omitempty"`
   141  	ChannelCapabilities []string `yaml:"channel_capabilities,omitempty"`
   142  }
   143  
   144  // Network holds information about a fabric network.
   145  type Network struct {
   146  	RootDir               string
   147  	StartPort             uint16
   148  	Components            *Components
   149  	DockerClient          *docker.Client
   150  	ExternalBuilders      []fabricconfig.ExternalBuilder
   151  	NetworkID             string
   152  	EventuallyTimeout     time.Duration
   153  	SessionCreateInterval time.Duration
   154  	MetricsProvider       string
   155  	StatsdEndpoint        string
   156  	ClientAuthRequired    bool
   157  	TLSEnabled            bool
   158  	GatewayEnabled        bool
   159  
   160  	PortsByBrokerID  map[string]Ports
   161  	PortsByOrdererID map[string]Ports
   162  	PortsByPeerID    map[string]Ports
   163  	Organizations    []*Organization
   164  	SystemChannel    *SystemChannel
   165  	Channels         []*Channel
   166  	Consensus        *Consensus
   167  	Orderers         []*Orderer
   168  	Peers            []*Peer
   169  	Profiles         []*Profile
   170  	Consortiums      []*Consortium
   171  	Templates        *Templates
   172  
   173  	mutex        sync.Locker
   174  	colorIndex   uint
   175  	lastExecuted map[string]time.Time
   176  }
   177  
   178  // New creates a Network from a simple configuration. All generated or managed
   179  // artifacts for the network will be located under rootDir. Ports will be
   180  // allocated sequentially from the specified startPort.
   181  func New(c *Config, rootDir string, dockerClient *docker.Client, startPort int, components *Components) *Network {
   182  	network := &Network{
   183  		StartPort:    uint16(startPort),
   184  		RootDir:      rootDir,
   185  		Components:   components,
   186  		DockerClient: dockerClient,
   187  
   188  		NetworkID:         runner.UniqueName(),
   189  		EventuallyTimeout: time.Minute,
   190  		MetricsProvider:   "prometheus",
   191  		PortsByBrokerID:   map[string]Ports{},
   192  		PortsByOrdererID:  map[string]Ports{},
   193  		PortsByPeerID:     map[string]Ports{},
   194  
   195  		Organizations:  c.Organizations,
   196  		Consensus:      c.Consensus,
   197  		Orderers:       c.Orderers,
   198  		Peers:          c.Peers,
   199  		SystemChannel:  c.SystemChannel,
   200  		Channels:       c.Channels,
   201  		Profiles:       c.Profiles,
   202  		Consortiums:    c.Consortiums,
   203  		Templates:      c.Templates,
   204  		TLSEnabled:     true, // Set TLS enabled as true for default
   205  		GatewayEnabled: true, // Set Gateway enabled as true for default
   206  
   207  		mutex:        &sync.Mutex{},
   208  		lastExecuted: make(map[string]time.Time),
   209  	}
   210  
   211  	// add the ccaas builder as well; that is built into the release directory
   212  	// so work that out based on current runtime.
   213  	// make integration-preqreqs have been updated to ensure this is built
   214  	cwd, err := os.Getwd()
   215  	Expect(err).NotTo(HaveOccurred())
   216  	network.ExternalBuilders = []fabricconfig.ExternalBuilder{{
   217  		Path:                 filepath.Join(cwd, "..", "externalbuilders", "binary"),
   218  		Name:                 "binary",
   219  		PropagateEnvironment: []string{"GOPROXY"},
   220  	}, {
   221  		Path:                 filepath.Join(cwd, "..", "..", "release", fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH), "bin", "ccaas_builder"),
   222  		Name:                 "ccaas",
   223  		PropagateEnvironment: []string{"CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG"},
   224  	}}
   225  
   226  	if network.Templates == nil {
   227  		network.Templates = &Templates{}
   228  	}
   229  	if network.SessionCreateInterval == 0 {
   230  		network.SessionCreateInterval = time.Second
   231  	}
   232  
   233  	for i := 0; i < network.Consensus.Brokers; i++ {
   234  		ports := Ports{}
   235  		for _, portName := range BrokerPortNames() {
   236  			ports[portName] = network.ReservePort()
   237  		}
   238  		network.PortsByBrokerID[strconv.Itoa(i)] = ports
   239  	}
   240  
   241  	for _, o := range c.Orderers {
   242  		ports := Ports{}
   243  		for _, portName := range OrdererPortNames() {
   244  			ports[portName] = network.ReservePort()
   245  		}
   246  		network.PortsByOrdererID[o.ID()] = ports
   247  	}
   248  
   249  	for _, p := range c.Peers {
   250  		ports := Ports{}
   251  		for _, portName := range PeerPortNames() {
   252  			ports[portName] = network.ReservePort()
   253  		}
   254  		network.PortsByPeerID[p.ID()] = ports
   255  	}
   256  
   257  	if dockerClient != nil {
   258  		assertImagesExist(dockerClient, RequiredImages...)
   259  	}
   260  
   261  	return network
   262  }
   263  
   264  func assertImagesExist(dockerClient *docker.Client, images ...string) {
   265  	for _, imageName := range images {
   266  		images, err := dockerClient.ListImages(docker.ListImagesOptions{
   267  			Filters: map[string][]string{"reference": {imageName}},
   268  		})
   269  		Expect(err).NotTo(HaveOccurred())
   270  
   271  		if len(images) != 1 {
   272  			ginkgo.Fail(fmt.Sprintf("missing required image: %s", imageName), 1)
   273  		}
   274  	}
   275  }
   276  
   277  // AddOrg adds an organization to a network.
   278  func (n *Network) AddOrg(o *Organization, peers ...*Peer) {
   279  	for _, p := range peers {
   280  		ports := Ports{}
   281  		for _, portName := range PeerPortNames() {
   282  			ports[portName] = n.ReservePort()
   283  		}
   284  		n.PortsByPeerID[p.ID()] = ports
   285  		n.Peers = append(n.Peers, p)
   286  	}
   287  
   288  	n.Organizations = append(n.Organizations, o)
   289  	n.Consortiums[0].Organizations = append(n.Consortiums[0].Organizations, o.Name)
   290  }
   291  
   292  // ConfigTxPath returns the path to the generated configtxgen configuration
   293  // file.
   294  func (n *Network) ConfigTxConfigPath() string {
   295  	return filepath.Join(n.RootDir, "configtx.yaml")
   296  }
   297  
   298  // CryptoPath returns the path to the directory where cryptogen will place its
   299  // generated artifacts.
   300  func (n *Network) CryptoPath() string {
   301  	return filepath.Join(n.RootDir, "crypto")
   302  }
   303  
   304  // CryptoConfigPath returns the path to the generated cryptogen configuration
   305  // file.
   306  func (n *Network) CryptoConfigPath() string {
   307  	return filepath.Join(n.RootDir, "crypto-config.yaml")
   308  }
   309  
   310  // OutputBlockPath returns the path to the genesis block for the named system
   311  // channel.
   312  func (n *Network) OutputBlockPath(channelName string) string {
   313  	return filepath.Join(n.RootDir, fmt.Sprintf("%s_block.pb", channelName))
   314  }
   315  
   316  // CreateChannelTxPath returns the path to the create channel transaction for
   317  // the named channel.
   318  func (n *Network) CreateChannelTxPath(channelName string) string {
   319  	return filepath.Join(n.RootDir, fmt.Sprintf("%s_tx.pb", channelName))
   320  }
   321  
   322  // OrdererDir returns the path to the configuration directory for the specified
   323  // Orderer.
   324  func (n *Network) OrdererDir(o *Orderer) string {
   325  	return filepath.Join(n.RootDir, "orderers", o.ID())
   326  }
   327  
   328  // OrdererConfigPath returns the path to the orderer configuration document for
   329  // the specified Orderer.
   330  func (n *Network) OrdererConfigPath(o *Orderer) string {
   331  	return filepath.Join(n.OrdererDir(o), "orderer.yaml")
   332  }
   333  
   334  // ReadOrdererConfig  unmarshals an orderer's orderer.yaml and returns an
   335  // object approximating its contents.
   336  func (n *Network) ReadOrdererConfig(o *Orderer) *fabricconfig.Orderer {
   337  	var orderer fabricconfig.Orderer
   338  	ordererBytes, err := ioutil.ReadFile(n.OrdererConfigPath(o))
   339  	Expect(err).NotTo(HaveOccurred())
   340  
   341  	err = yaml.Unmarshal(ordererBytes, &orderer)
   342  	Expect(err).NotTo(HaveOccurred())
   343  
   344  	return &orderer
   345  }
   346  
   347  // WriteOrdererConfig serializes the provided configuration as the specified
   348  // orderer's orderer.yaml document.
   349  func (n *Network) WriteOrdererConfig(o *Orderer, config *fabricconfig.Orderer) {
   350  	ordererBytes, err := yaml.Marshal(config)
   351  	Expect(err).NotTo(HaveOccurred())
   352  
   353  	err = ioutil.WriteFile(n.OrdererConfigPath(o), ordererBytes, 0o644)
   354  	Expect(err).NotTo(HaveOccurred())
   355  
   356  	pw := gexec.NewPrefixedWriter(fmt.Sprintf("[updated-%s#orderer.yaml] ", o.ID()), ginkgo.GinkgoWriter)
   357  	_, err = pw.Write(ordererBytes)
   358  	Expect(err).NotTo(HaveOccurred())
   359  }
   360  
   361  // ReadConfigTxConfig  unmarshals the configtx.yaml and returns an
   362  // object approximating its contents.
   363  func (n *Network) ReadConfigTxConfig() *fabricconfig.ConfigTx {
   364  	var configtx fabricconfig.ConfigTx
   365  	configtxBytes, err := ioutil.ReadFile(n.ConfigTxConfigPath())
   366  	Expect(err).NotTo(HaveOccurred())
   367  
   368  	err = yaml.Unmarshal(configtxBytes, &configtx)
   369  	Expect(err).NotTo(HaveOccurred())
   370  
   371  	return &configtx
   372  }
   373  
   374  // WriteConfigTxConfig serializes the provided configuration to configtx.yaml.
   375  func (n *Network) WriteConfigTxConfig(config *fabricconfig.ConfigTx) {
   376  	configtxBytes, err := yaml.Marshal(config)
   377  	Expect(err).NotTo(HaveOccurred())
   378  
   379  	err = ioutil.WriteFile(n.ConfigTxConfigPath(), configtxBytes, 0o644)
   380  	Expect(err).NotTo(HaveOccurred())
   381  }
   382  
   383  // PeerDir returns the path to the configuration directory for the specified
   384  // Peer.
   385  func (n *Network) PeerDir(p *Peer) string {
   386  	return filepath.Join(n.RootDir, "peers", p.ID())
   387  }
   388  
   389  // PeerConfigPath returns the path to the peer configuration document for the
   390  // specified peer.
   391  func (n *Network) PeerConfigPath(p *Peer) string {
   392  	return filepath.Join(n.PeerDir(p), "core.yaml")
   393  }
   394  
   395  // PeerLedgerDir returns the ledger root directory for the specified peer.
   396  func (n *Network) PeerLedgerDir(p *Peer) string {
   397  	return filepath.Join(n.PeerDir(p), "filesystem/ledgersData")
   398  }
   399  
   400  // ReadPeerConfig unmarshals a peer's core.yaml and returns an object
   401  // approximating its contents.
   402  func (n *Network) ReadPeerConfig(p *Peer) *fabricconfig.Core {
   403  	var core fabricconfig.Core
   404  	coreBytes, err := ioutil.ReadFile(n.PeerConfigPath(p))
   405  	Expect(err).NotTo(HaveOccurred())
   406  
   407  	err = yaml.Unmarshal(coreBytes, &core)
   408  	Expect(err).NotTo(HaveOccurred())
   409  
   410  	return &core
   411  }
   412  
   413  // WritePeerConfig serializes the provided configuration as the specified
   414  // peer's core.yaml document.
   415  func (n *Network) WritePeerConfig(p *Peer, config *fabricconfig.Core) {
   416  	coreBytes, err := yaml.Marshal(config)
   417  	Expect(err).NotTo(HaveOccurred())
   418  
   419  	err = ioutil.WriteFile(n.PeerConfigPath(p), coreBytes, 0o644)
   420  	Expect(err).NotTo(HaveOccurred())
   421  
   422  	pw := gexec.NewPrefixedWriter(fmt.Sprintf("[updated-%s#core.yaml] ", p.ID()), ginkgo.GinkgoWriter)
   423  	_, err = pw.Write(coreBytes)
   424  	Expect(err).NotTo(HaveOccurred())
   425  }
   426  
   427  // peerUserCryptoDir returns the path to the directory containing the
   428  // certificates and keys for the specified user of the peer.
   429  func (n *Network) peerUserCryptoDir(p *Peer, user, cryptoMaterialType string) string {
   430  	org := n.Organization(p.Organization)
   431  	Expect(org).NotTo(BeNil())
   432  
   433  	return n.userCryptoDir(org, "peerOrganizations", user, cryptoMaterialType)
   434  }
   435  
   436  // ordererUserCryptoDir returns the path to the directory containing the
   437  // certificates and keys for the specified user of the orderer.
   438  func (n *Network) ordererUserCryptoDir(o *Orderer, user, cryptoMaterialType string) string {
   439  	org := n.Organization(o.Organization)
   440  	Expect(org).NotTo(BeNil())
   441  
   442  	return n.userCryptoDir(org, "ordererOrganizations", user, cryptoMaterialType)
   443  }
   444  
   445  // userCryptoDir returns the path to the folder with crypto materials for either peers or orderer organizations
   446  // specific user
   447  func (n *Network) userCryptoDir(org *Organization, nodeOrganizationType, user, cryptoMaterialType string) string {
   448  	return filepath.Join(
   449  		n.RootDir,
   450  		"crypto",
   451  		nodeOrganizationType,
   452  		org.Domain,
   453  		"users",
   454  		fmt.Sprintf("%s@%s", user, org.Domain),
   455  		cryptoMaterialType,
   456  	)
   457  }
   458  
   459  // PeerOrgCADir returns the path to the folder containing the CA certificate(s) and/or
   460  // keys for the specified peer organization.
   461  func (n *Network) PeerOrgCADir(o *Organization) string {
   462  	return filepath.Join(
   463  		n.CryptoPath(),
   464  		"peerOrganizations",
   465  		o.Domain,
   466  		"ca",
   467  	)
   468  }
   469  
   470  // OrdererOrgCADir returns the path to the folder containing the CA certificate(s) and/or
   471  // keys for the specified orderer organization.
   472  func (n *Network) OrdererOrgCADir(o *Organization) string {
   473  	return filepath.Join(
   474  		n.CryptoPath(),
   475  		"ordererOrganizations",
   476  		o.Domain,
   477  		"ca",
   478  	)
   479  }
   480  
   481  // PeerUserMSPDir returns the path to the MSP directory containing the
   482  // certificates and keys for the specified user of the peer.
   483  func (n *Network) PeerUserMSPDir(p *Peer, user string) string {
   484  	return n.peerUserCryptoDir(p, user, "msp")
   485  }
   486  
   487  // IdemixUserMSPDir returns the path to the MSP directory containing the
   488  // idemix-related crypto material for the specified user of the organization.
   489  func (n *Network) IdemixUserMSPDir(o *Organization, user string) string {
   490  	return n.userCryptoDir(o, "peerOrganizations", user, "")
   491  }
   492  
   493  // OrdererUserMSPDir returns the path to the MSP directory containing the
   494  // certificates and keys for the specified user of the peer.
   495  func (n *Network) OrdererUserMSPDir(o *Orderer, user string) string {
   496  	return n.ordererUserCryptoDir(o, user, "msp")
   497  }
   498  
   499  // PeerUserTLSDir returns the path to the TLS directory containing the
   500  // certificates and keys for the specified user of the peer.
   501  func (n *Network) PeerUserTLSDir(p *Peer, user string) string {
   502  	return n.peerUserCryptoDir(p, user, "tls")
   503  }
   504  
   505  // PeerUserCert returns the path to the certificate for the specified user in
   506  // the peer organization.
   507  func (n *Network) PeerUserCert(p *Peer, user string) string {
   508  	org := n.Organization(p.Organization)
   509  	Expect(org).NotTo(BeNil())
   510  
   511  	return filepath.Join(
   512  		n.PeerUserMSPDir(p, user),
   513  		"signcerts",
   514  		fmt.Sprintf("%s@%s-cert.pem", user, org.Domain),
   515  	)
   516  }
   517  
   518  // PeerCACert returns the path to the CA certificate for the peer
   519  // organization.
   520  func (n *Network) PeerCACert(p *Peer) string {
   521  	org := n.Organization(p.Organization)
   522  	Expect(org).NotTo(BeNil())
   523  
   524  	return filepath.Join(
   525  		n.PeerOrgMSPDir(org),
   526  		"cacerts",
   527  		fmt.Sprintf("ca.%s-cert.pem", org.Domain),
   528  	)
   529  }
   530  
   531  // OrdererUserCert returns the path to the certificate for the specified user in
   532  // the orderer organization.
   533  func (n *Network) OrdererUserCert(o *Orderer, user string) string {
   534  	org := n.Organization(o.Organization)
   535  	Expect(org).NotTo(BeNil())
   536  
   537  	return filepath.Join(
   538  		n.OrdererUserMSPDir(o, user),
   539  		"signcerts",
   540  		fmt.Sprintf("%s@%s-cert.pem", user, org.Domain),
   541  	)
   542  }
   543  
   544  // OrdererCACert returns the path to the CA certificate for the orderer
   545  // organization.
   546  func (n *Network) OrdererCACert(o *Orderer) string {
   547  	org := n.Organization(o.Organization)
   548  	Expect(org).NotTo(BeNil())
   549  
   550  	return filepath.Join(
   551  		n.OrdererOrgMSPDir(org),
   552  		"cacerts",
   553  		fmt.Sprintf("ca.%s-cert.pem", org.Domain),
   554  	)
   555  }
   556  
   557  // PeerUserKey returns the path to the private key for the specified user in
   558  // the peer organization.
   559  func (n *Network) PeerUserKey(p *Peer, user string) string {
   560  	org := n.Organization(p.Organization)
   561  	Expect(org).NotTo(BeNil())
   562  
   563  	keystore := filepath.Join(
   564  		n.PeerUserMSPDir(p, user),
   565  		"keystore",
   566  	)
   567  
   568  	// file names are the SKI and non-deterministic
   569  	keys, err := ioutil.ReadDir(keystore)
   570  	Expect(err).NotTo(HaveOccurred())
   571  	Expect(keys).To(HaveLen(1))
   572  
   573  	return filepath.Join(keystore, keys[0].Name())
   574  }
   575  
   576  // OrdererUserKey returns the path to the private key for the specified user in
   577  // the orderer organization.
   578  func (n *Network) OrdererUserKey(o *Orderer, user string) string {
   579  	org := n.Organization(o.Organization)
   580  	Expect(org).NotTo(BeNil())
   581  
   582  	keystore := filepath.Join(
   583  		n.OrdererUserMSPDir(o, user),
   584  		"keystore",
   585  	)
   586  
   587  	// file names are the SKI and non-deterministic
   588  	keys, err := ioutil.ReadDir(keystore)
   589  	Expect(err).NotTo(HaveOccurred())
   590  	Expect(keys).To(HaveLen(1))
   591  
   592  	return filepath.Join(keystore, keys[0].Name())
   593  }
   594  
   595  // PeerUserSigner returns a SigningIdentity representing the specified user in
   596  // the peer organization.
   597  func (n *Network) PeerUserSigner(p *Peer, user string) *SigningIdentity {
   598  	return &SigningIdentity{
   599  		CertPath: n.PeerUserCert(p, user),
   600  		KeyPath:  n.PeerUserKey(p, user),
   601  		MSPID:    n.Organization(p.Organization).MSPID,
   602  	}
   603  }
   604  
   605  // OrdererUserSigner returns a SigningIdentity representing the specified user in
   606  // the orderer organization.
   607  func (n *Network) OrdererUserSigner(o *Orderer, user string) *SigningIdentity {
   608  	return &SigningIdentity{
   609  		CertPath: n.OrdererUserCert(o, user),
   610  		KeyPath:  n.OrdererUserKey(o, user),
   611  		MSPID:    n.Organization(o.Organization).MSPID,
   612  	}
   613  }
   614  
   615  // peerLocalCryptoDir returns the path to the local crypto directory for the peer.
   616  func (n *Network) peerLocalCryptoDir(p *Peer, cryptoType string) string {
   617  	org := n.Organization(p.Organization)
   618  	Expect(org).NotTo(BeNil())
   619  
   620  	return filepath.Join(
   621  		n.RootDir,
   622  		"crypto",
   623  		"peerOrganizations",
   624  		org.Domain,
   625  		"peers",
   626  		fmt.Sprintf("%s.%s", p.Name, org.Domain),
   627  		cryptoType,
   628  	)
   629  }
   630  
   631  // PeerLocalMSPDir returns the path to the local MSP directory for the peer.
   632  func (n *Network) PeerLocalMSPDir(p *Peer) string {
   633  	return n.peerLocalCryptoDir(p, "msp")
   634  }
   635  
   636  // PeerLocalTLSDir returns the path to the local TLS directory for the peer.
   637  func (n *Network) PeerLocalTLSDir(p *Peer) string {
   638  	return n.peerLocalCryptoDir(p, "tls")
   639  }
   640  
   641  // PeerCert returns the path to the peer's certificate.
   642  func (n *Network) PeerCert(p *Peer) string {
   643  	org := n.Organization(p.Organization)
   644  	Expect(org).NotTo(BeNil())
   645  
   646  	return filepath.Join(
   647  		n.PeerLocalMSPDir(p),
   648  		"signcerts",
   649  		fmt.Sprintf("%s.%s-cert.pem", p.Name, org.Domain),
   650  	)
   651  }
   652  
   653  // PeerOrgMSPDir returns the path to the MSP directory of the Peer organization.
   654  func (n *Network) PeerOrgMSPDir(org *Organization) string {
   655  	return filepath.Join(
   656  		n.RootDir,
   657  		"crypto",
   658  		"peerOrganizations",
   659  		org.Domain,
   660  		"msp",
   661  	)
   662  }
   663  
   664  func (n *Network) IdemixOrgMSPDir(org *Organization) string {
   665  	return filepath.Join(
   666  		n.RootDir,
   667  		"crypto",
   668  		"peerOrganizations",
   669  		org.Domain,
   670  	)
   671  }
   672  
   673  // OrdererOrgMSPDir returns the path to the MSP directory of the Orderer
   674  // organization.
   675  func (n *Network) OrdererOrgMSPDir(o *Organization) string {
   676  	return filepath.Join(
   677  		n.RootDir,
   678  		"crypto",
   679  		"ordererOrganizations",
   680  		o.Domain,
   681  		"msp",
   682  	)
   683  }
   684  
   685  // OrdererLocalCryptoDir returns the path to the local crypto directory for the
   686  // Orderer.
   687  func (n *Network) OrdererLocalCryptoDir(o *Orderer, cryptoType string) string {
   688  	org := n.Organization(o.Organization)
   689  	Expect(org).NotTo(BeNil())
   690  
   691  	return filepath.Join(
   692  		n.RootDir,
   693  		"crypto",
   694  		"ordererOrganizations",
   695  		org.Domain,
   696  		"orderers",
   697  		fmt.Sprintf("%s.%s", o.Name, org.Domain),
   698  		cryptoType,
   699  	)
   700  }
   701  
   702  // OrdererLocalMSPDir returns the path to the local MSP directory for the
   703  // Orderer.
   704  func (n *Network) OrdererLocalMSPDir(o *Orderer) string {
   705  	return n.OrdererLocalCryptoDir(o, "msp")
   706  }
   707  
   708  // OrdererLocalTLSDir returns the path to the local TLS directory for the
   709  // Orderer.
   710  func (n *Network) OrdererLocalTLSDir(o *Orderer) string {
   711  	return n.OrdererLocalCryptoDir(o, "tls")
   712  }
   713  
   714  // ProfileForChannel gets the configtxgen profile name associated with the
   715  // specified channel.
   716  func (n *Network) ProfileForChannel(channelName string) string {
   717  	for _, ch := range n.Channels {
   718  		if ch.Name == channelName {
   719  			return ch.Profile
   720  		}
   721  	}
   722  	return ""
   723  }
   724  
   725  // CACertsBundlePath returns the path to the bundle of CA certificates for the
   726  // network. This bundle is used when connecting to peers.
   727  func (n *Network) CACertsBundlePath() string {
   728  	return filepath.Join(
   729  		n.RootDir,
   730  		"crypto",
   731  		"ca-certs.pem",
   732  	)
   733  }
   734  
   735  // GenerateConfigTree generates the configuration documents required to
   736  // bootstrap a fabric network. A configuration file will be generated for
   737  // cryptogen, configtxgen, and for each peer and orderer. The contents of the
   738  // documents will be based on the Config used to create the Network.
   739  //
   740  // When this method completes, the resulting tree will look something like
   741  // this:
   742  //
   743  //    ${rootDir}/configtx.yaml
   744  //    ${rootDir}/crypto-config.yaml
   745  //    ${rootDir}/orderers/orderer0.orderer-org/orderer.yaml
   746  //    ${rootDir}/peers/peer0.org1/core.yaml
   747  //    ${rootDir}/peers/peer0.org2/core.yaml
   748  //    ${rootDir}/peers/peer1.org1/core.yaml
   749  //    ${rootDir}/peers/peer1.org2/core.yaml
   750  //
   751  func (n *Network) GenerateConfigTree() {
   752  	n.GenerateCryptoConfig()
   753  	n.GenerateConfigTxConfig()
   754  	for _, o := range n.Orderers {
   755  		n.GenerateOrdererConfig(o)
   756  	}
   757  	for _, p := range n.Peers {
   758  		n.GenerateCoreConfig(p)
   759  	}
   760  }
   761  
   762  // Bootstrap generates the cryptographic material, orderer system channel
   763  // genesis block, and create channel transactions needed to run a fabric
   764  // network.
   765  //
   766  // The cryptogen tool is used to create crypto material from the contents of
   767  // ${rootDir}/crypto-config.yaml. The generated artifacts will be placed in
   768  // ${rootDir}/crypto/...
   769  //
   770  // The gensis block is generated from the profile referenced by the
   771  // SystemChannel.Profile attribute. The block is written to
   772  // ${rootDir}/${SystemChannel.Name}_block.pb.
   773  //
   774  // The create channel transactions are generated for each Channel referenced by
   775  // the Network using the channel's Profile attribute. The transactions are
   776  // written to ${rootDir}/${Channel.Name}_tx.pb.
   777  func (n *Network) Bootstrap() {
   778  	if n.DockerClient != nil {
   779  		n.CreateDockerNetwork()
   780  	}
   781  
   782  	sess, err := n.Cryptogen(commands.Generate{
   783  		Config: n.CryptoConfigPath(),
   784  		Output: n.CryptoPath(),
   785  	})
   786  	Expect(err).NotTo(HaveOccurred())
   787  	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
   788  
   789  	n.bootstrapIdemix()
   790  
   791  	sess, err = n.ConfigTxGen(commands.OutputBlock{
   792  		ChannelID:   n.SystemChannel.Name,
   793  		Profile:     n.SystemChannel.Profile,
   794  		ConfigPath:  n.RootDir,
   795  		OutputBlock: n.OutputBlockPath(n.SystemChannel.Name),
   796  	})
   797  	Expect(err).NotTo(HaveOccurred())
   798  	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
   799  
   800  	for _, c := range n.Channels {
   801  		sess, err := n.ConfigTxGen(commands.CreateChannelTx{
   802  			ChannelID:             c.Name,
   803  			Profile:               c.Profile,
   804  			BaseProfile:           c.BaseProfile,
   805  			ConfigPath:            n.RootDir,
   806  			OutputCreateChannelTx: n.CreateChannelTxPath(c.Name),
   807  		})
   808  		Expect(err).NotTo(HaveOccurred())
   809  		Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
   810  	}
   811  
   812  	n.ConcatenateTLSCACertificates()
   813  }
   814  
   815  func (n *Network) CreateDockerNetwork() {
   816  	_, err := n.DockerClient.CreateNetwork(
   817  		docker.CreateNetworkOptions{
   818  			Name:   n.NetworkID,
   819  			Driver: "bridge",
   820  		},
   821  	)
   822  	Expect(err).NotTo(HaveOccurred())
   823  
   824  	if runtime.GOOS == "darwin" {
   825  		n.checkDockerNetworks()
   826  	}
   827  }
   828  
   829  // checkDockerNetworks attempts to discover if the docker network configuration
   830  // will prevent a container from accessing the host. This commonly happens when
   831  // using Docker for Mac on home networks because most home routers provide DHCP
   832  // addresses from 192.168.1.0/24 and the default Docker daemon config uses
   833  // 192.168.0.0/20 as one of the default local address pools.
   834  //
   835  // https://github.com/moby/libnetwork/blob/1a17fb36132631a95fe6bb055b91e24a516ad81d/ipamutils/utils.go#L18-L20
   836  //
   837  // Docker can be configured to use different addresses by adding an
   838  // appropriate default-address-pools configuration element to "daemon.json".
   839  //
   840  // For example:
   841  //   "default-address-pools":[
   842  //       {"base":"172.30.0.0/16","size":24},
   843  //       {"base":"172.31.0.0/16","size":24}
   844  //   ]
   845  func (n *Network) checkDockerNetworks() {
   846  	hostAddrs := hostIPv4Addrs()
   847  	for _, nw := range n.dockerIPNets() {
   848  		for _, a := range hostAddrs {
   849  			if nw.Contains(a) {
   850  				fmt.Fprintf(ginkgo.GinkgoWriter, "\x1b[01;37;41mWARNING: docker network %s overlaps with host address %s.\x1b[0m\n", nw, a)
   851  				fmt.Fprintf(ginkgo.GinkgoWriter, "\x1b[01;37;41mDocker containers may not have connectivity causing chaincode registration to fail with 'no route to host'.\x1b[0m\n")
   852  			}
   853  		}
   854  	}
   855  }
   856  
   857  func (n *Network) dockerIPNets() []*net.IPNet {
   858  	dockerNetworks, err := n.DockerClient.ListNetworks()
   859  	Expect(err).NotTo(HaveOccurred())
   860  
   861  	var nets []*net.IPNet
   862  	for _, nw := range dockerNetworks {
   863  		for _, ipconf := range nw.IPAM.Config {
   864  			if ipconf.Subnet != "" {
   865  				_, ipn, err := net.ParseCIDR(ipconf.Subnet)
   866  				Expect(err).NotTo(HaveOccurred())
   867  				nets = append(nets, ipn)
   868  			}
   869  		}
   870  	}
   871  	return nets
   872  }
   873  
   874  func hostIPv4Addrs() []net.IP {
   875  	interfaces, err := net.Interfaces()
   876  	Expect(err).NotTo(HaveOccurred())
   877  
   878  	var addresses []net.IP
   879  	for _, i := range interfaces {
   880  		addrs, err := i.Addrs()
   881  		Expect(err).NotTo(HaveOccurred())
   882  
   883  		for _, a := range addrs {
   884  			a := a
   885  			switch v := a.(type) {
   886  			case *net.IPAddr:
   887  				if v.IP.To4() != nil {
   888  					addresses = append(addresses, v.IP)
   889  				}
   890  			case *net.IPNet:
   891  				if v.IP.To4() != nil {
   892  					addresses = append(addresses, v.IP)
   893  				}
   894  			}
   895  		}
   896  	}
   897  	return addresses
   898  }
   899  
   900  // bootstrapIdemix creates the idemix-related crypto material
   901  func (n *Network) bootstrapIdemix() {
   902  	for j, org := range n.IdemixOrgs() {
   903  		output := n.IdemixOrgMSPDir(org)
   904  		// - ca-keygen
   905  		sess, err := n.Idemixgen(commands.CAKeyGen{
   906  			Output: output,
   907  		})
   908  		Expect(err).NotTo(HaveOccurred())
   909  		Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
   910  
   911  		// - signerconfig
   912  		usersOutput := filepath.Join(n.IdemixOrgMSPDir(org), "users")
   913  		userOutput := filepath.Join(usersOutput, "User1@"+org.Domain)
   914  		sess, err = n.Idemixgen(commands.SignerConfig{
   915  			CAInput:          output,
   916  			Output:           userOutput,
   917  			OrgUnit:          org.Domain,
   918  			EnrollmentID:     "User1",
   919  			RevocationHandle: fmt.Sprintf("11%d", j),
   920  		})
   921  		Expect(err).NotTo(HaveOccurred())
   922  		Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
   923  	}
   924  }
   925  
   926  // ConcatenateTLSCACertificates concatenates all TLS CA certificates into a
   927  // single file to be used by peer CLI.
   928  func (n *Network) ConcatenateTLSCACertificates() {
   929  	bundle := &bytes.Buffer{}
   930  	for _, tlsCertPath := range n.listTLSCACertificates() {
   931  		certBytes, err := ioutil.ReadFile(tlsCertPath)
   932  		Expect(err).NotTo(HaveOccurred())
   933  		bundle.Write(certBytes)
   934  	}
   935  	err := ioutil.WriteFile(n.CACertsBundlePath(), bundle.Bytes(), 0o660)
   936  	Expect(err).NotTo(HaveOccurred())
   937  }
   938  
   939  // listTLSCACertificates returns the paths of all TLS CA certificates in the
   940  // network, across all organizations.
   941  func (n *Network) listTLSCACertificates() []string {
   942  	fileName2Path := make(map[string]string)
   943  	filepath.Walk(filepath.Join(n.RootDir, "crypto"), func(path string, info os.FileInfo, err error) error {
   944  		// File starts with "tlsca" and has "-cert.pem" in it
   945  		if strings.HasPrefix(info.Name(), "tlsca") && strings.Contains(info.Name(), "-cert.pem") {
   946  			fileName2Path[info.Name()] = path
   947  		}
   948  		return nil
   949  	})
   950  
   951  	var tlsCACertificates []string
   952  	for _, path := range fileName2Path {
   953  		tlsCACertificates = append(tlsCACertificates, path)
   954  	}
   955  	return tlsCACertificates
   956  }
   957  
   958  // Cleanup attempts to cleanup docker related artifacts that may
   959  // have been created by the network.
   960  func (n *Network) Cleanup() {
   961  	if n == nil || n.DockerClient == nil {
   962  		return
   963  	}
   964  
   965  	nw, err := n.DockerClient.NetworkInfo(n.NetworkID)
   966  	Expect(err).NotTo(HaveOccurred())
   967  
   968  	err = n.DockerClient.RemoveNetwork(nw.ID)
   969  	Expect(err).NotTo(HaveOccurred())
   970  
   971  	containers, err := n.DockerClient.ListContainers(docker.ListContainersOptions{All: true})
   972  	Expect(err).NotTo(HaveOccurred())
   973  	for _, c := range containers {
   974  		for _, name := range c.Names {
   975  			if strings.HasPrefix(name, "/"+n.NetworkID) {
   976  				err := n.DockerClient.RemoveContainer(docker.RemoveContainerOptions{ID: c.ID, Force: true})
   977  				Expect(err).NotTo(HaveOccurred())
   978  				break
   979  			}
   980  		}
   981  	}
   982  
   983  	images, err := n.DockerClient.ListImages(docker.ListImagesOptions{All: true})
   984  	Expect(err).NotTo(HaveOccurred())
   985  	for _, i := range images {
   986  		for _, tag := range i.RepoTags {
   987  			if strings.HasPrefix(tag, n.NetworkID) {
   988  				err := n.DockerClient.RemoveImage(i.ID)
   989  				Expect(err).NotTo(HaveOccurred())
   990  				break
   991  			}
   992  		}
   993  	}
   994  }
   995  
   996  // CreateAndJoinChannels will create all channels specified in the config that
   997  // are referenced by peers. The referencing peers will then be joined to the
   998  // channel(s).
   999  //
  1000  // The network must be running before this is called.
  1001  func (n *Network) CreateAndJoinChannels(o *Orderer) {
  1002  	for _, c := range n.Channels {
  1003  		n.CreateAndJoinChannel(o, c.Name)
  1004  	}
  1005  }
  1006  
  1007  // CreateAndJoinChannel will create the specified channel. The referencing
  1008  // peers will then be joined to the channel.
  1009  //
  1010  // The network must be running before this is called.
  1011  func (n *Network) CreateAndJoinChannel(o *Orderer, channelName string) {
  1012  	peers := n.PeersWithChannel(channelName)
  1013  	if len(peers) == 0 {
  1014  		return
  1015  	}
  1016  
  1017  	n.CreateChannel(channelName, o, peers[0])
  1018  	n.JoinChannel(channelName, o, peers...)
  1019  }
  1020  
  1021  // UpdateChannelAnchors determines the anchor peers for the specified channel,
  1022  // creates an anchor peer update transaction for each organization, and submits
  1023  // the update transactions to the orderer.
  1024  func (n *Network) UpdateChannelAnchors(o *Orderer, channelName string) {
  1025  	tempFile, err := ioutil.TempFile("", "update-anchors")
  1026  	Expect(err).NotTo(HaveOccurred())
  1027  	tempFile.Close()
  1028  	defer os.Remove(tempFile.Name())
  1029  
  1030  	peersByOrg := map[string]*Peer{}
  1031  	for _, p := range n.AnchorsForChannel(channelName) {
  1032  		peersByOrg[p.Organization] = p
  1033  	}
  1034  
  1035  	for orgName, p := range peersByOrg {
  1036  		anchorUpdate := commands.OutputAnchorPeersUpdate{
  1037  			OutputAnchorPeersUpdate: tempFile.Name(),
  1038  			ChannelID:               channelName,
  1039  			Profile:                 n.ProfileForChannel(channelName),
  1040  			ConfigPath:              n.RootDir,
  1041  			AsOrg:                   orgName,
  1042  		}
  1043  		sess, err := n.ConfigTxGen(anchorUpdate)
  1044  		Expect(err).NotTo(HaveOccurred())
  1045  		Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
  1046  
  1047  		sess, err = n.PeerAdminSession(p, commands.ChannelUpdate{
  1048  			ChannelID:  channelName,
  1049  			Orderer:    n.OrdererAddress(o, ListenPort),
  1050  			File:       tempFile.Name(),
  1051  			ClientAuth: n.ClientAuthRequired,
  1052  		})
  1053  		Expect(err).NotTo(HaveOccurred())
  1054  		Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
  1055  	}
  1056  }
  1057  
  1058  // VerifyMembership checks that each peer has discovered the expected peers in
  1059  // the network.
  1060  func (n *Network) VerifyMembership(expectedPeers []*Peer, channel string, chaincodes ...string) {
  1061  	// all peers currently include _lifecycle as an available chaincode
  1062  	chaincodes = append(chaincodes, "_lifecycle")
  1063  	expectedDiscoveredPeerMatchers := make([]types.GomegaMatcher, len(expectedPeers))
  1064  	for i, peer := range expectedPeers {
  1065  		expectedDiscoveredPeerMatchers[i] = n.discoveredPeerMatcher(peer, chaincodes...)
  1066  	}
  1067  	for _, peer := range expectedPeers {
  1068  		Eventually(DiscoverPeers(n, peer, "User1", channel), n.EventuallyTimeout).Should(ConsistOf(expectedDiscoveredPeerMatchers))
  1069  	}
  1070  }
  1071  
  1072  func (n *Network) discoveredPeerMatcher(p *Peer, chaincodes ...string) types.GomegaMatcher {
  1073  	peerCert, err := ioutil.ReadFile(n.PeerCert(p))
  1074  	Expect(err).NotTo(HaveOccurred())
  1075  
  1076  	var ccs []interface{}
  1077  	for _, cc := range chaincodes {
  1078  		ccs = append(ccs, cc)
  1079  	}
  1080  	return gstruct.MatchAllFields(gstruct.Fields{
  1081  		"MSPID":      Equal(n.Organization(p.Organization).MSPID),
  1082  		"Endpoint":   Equal(fmt.Sprintf("127.0.0.1:%d", n.PeerPort(p, ListenPort))),
  1083  		"Identity":   Equal(string(peerCert)),
  1084  		"Chaincodes": ContainElements(ccs...),
  1085  	})
  1086  }
  1087  
  1088  // CreateChannel will submit an existing create channel transaction to the
  1089  // specified orderer. The channel transaction must exist at the location
  1090  // returned by CreateChannelTxPath. Optionally, additional signers may be
  1091  // included in the case where the channel creation tx modifies other aspects of
  1092  // the channel config for the new channel.
  1093  //
  1094  // The orderer must be running when this is called.
  1095  func (n *Network) CreateChannel(channelName string, o *Orderer, p *Peer, additionalSigners ...interface{}) {
  1096  	channelCreateTxPath := n.CreateChannelTxPath(channelName)
  1097  	n.signConfigTransaction(channelCreateTxPath, p, additionalSigners...)
  1098  
  1099  	createChannel := func() int {
  1100  		sess, err := n.PeerAdminSession(p, commands.ChannelCreate{
  1101  			ChannelID:   channelName,
  1102  			Orderer:     n.OrdererAddress(o, ListenPort),
  1103  			File:        channelCreateTxPath,
  1104  			OutputBlock: "/dev/null",
  1105  			ClientAuth:  n.ClientAuthRequired,
  1106  		})
  1107  		Expect(err).NotTo(HaveOccurred())
  1108  		return sess.Wait(n.EventuallyTimeout).ExitCode()
  1109  	}
  1110  	Eventually(createChannel, n.EventuallyTimeout).Should(Equal(0))
  1111  }
  1112  
  1113  // CreateChannelExitCode will submit an existing create channel transaction to
  1114  // the specified orderer, wait for the operation to complete, and return the
  1115  // exit status of the "peer channel create" command.
  1116  //
  1117  // The channel transaction must exist at the location returned by
  1118  // CreateChannelTxPath and the orderer must be running when this is called.
  1119  func (n *Network) CreateChannelExitCode(channelName string, o *Orderer, p *Peer, additionalSigners ...interface{}) int {
  1120  	channelCreateTxPath := n.CreateChannelTxPath(channelName)
  1121  	n.signConfigTransaction(channelCreateTxPath, p, additionalSigners...)
  1122  
  1123  	sess, err := n.PeerAdminSession(p, commands.ChannelCreate{
  1124  		ChannelID:   channelName,
  1125  		Orderer:     n.OrdererAddress(o, ListenPort),
  1126  		File:        channelCreateTxPath,
  1127  		OutputBlock: "/dev/null",
  1128  		ClientAuth:  n.ClientAuthRequired,
  1129  	})
  1130  	Expect(err).NotTo(HaveOccurred())
  1131  	return sess.Wait(n.EventuallyTimeout).ExitCode()
  1132  }
  1133  
  1134  func (n *Network) signConfigTransaction(channelTxPath string, submittingPeer *Peer, signers ...interface{}) {
  1135  	for _, signer := range signers {
  1136  		switch signer := signer.(type) {
  1137  		case *Peer:
  1138  			sess, err := n.PeerAdminSession(signer, commands.SignConfigTx{
  1139  				File:       channelTxPath,
  1140  				ClientAuth: n.ClientAuthRequired,
  1141  			})
  1142  			Expect(err).NotTo(HaveOccurred())
  1143  			Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
  1144  
  1145  		case *Orderer:
  1146  			sess, err := n.OrdererAdminSession(signer, submittingPeer, commands.SignConfigTx{
  1147  				File:       channelTxPath,
  1148  				ClientAuth: n.ClientAuthRequired,
  1149  			})
  1150  			Expect(err).NotTo(HaveOccurred())
  1151  			Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
  1152  
  1153  		default:
  1154  			panic(fmt.Sprintf("unknown signer type %T, expect Peer or Orderer", signer))
  1155  		}
  1156  	}
  1157  }
  1158  
  1159  // JoinChannel will join peers to the specified channel. The orderer is used to
  1160  // obtain the current configuration block for the channel.
  1161  //
  1162  // The orderer and listed peers must be running before this is called.
  1163  func (n *Network) JoinChannel(name string, o *Orderer, peers ...*Peer) {
  1164  	if len(peers) == 0 {
  1165  		return
  1166  	}
  1167  
  1168  	tempFile, err := ioutil.TempFile("", "genesis-block")
  1169  	Expect(err).NotTo(HaveOccurred())
  1170  	tempFile.Close()
  1171  	defer os.Remove(tempFile.Name())
  1172  
  1173  	sess, err := n.PeerAdminSession(peers[0], commands.ChannelFetch{
  1174  		Block:      "0",
  1175  		ChannelID:  name,
  1176  		Orderer:    n.OrdererAddress(o, ListenPort),
  1177  		OutputFile: tempFile.Name(),
  1178  		ClientAuth: n.ClientAuthRequired,
  1179  	})
  1180  	Expect(err).NotTo(HaveOccurred())
  1181  	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
  1182  
  1183  	for _, p := range peers {
  1184  		sess, err := n.PeerAdminSession(p, commands.ChannelJoin{
  1185  			BlockPath:  tempFile.Name(),
  1186  			ClientAuth: n.ClientAuthRequired,
  1187  		})
  1188  		Expect(err).NotTo(HaveOccurred())
  1189  		Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
  1190  	}
  1191  }
  1192  
  1193  func (n *Network) JoinChannelBySnapshot(snapshotDir string, peers ...*Peer) {
  1194  	if len(peers) == 0 {
  1195  		return
  1196  	}
  1197  
  1198  	for _, p := range peers {
  1199  		sess, err := n.PeerAdminSession(p, commands.ChannelJoinBySnapshot{
  1200  			SnapshotPath: snapshotDir,
  1201  			ClientAuth:   n.ClientAuthRequired,
  1202  		})
  1203  		Expect(err).NotTo(HaveOccurred())
  1204  		Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
  1205  	}
  1206  }
  1207  
  1208  func (n *Network) JoinBySnapshotStatus(p *Peer) string {
  1209  	sess, err := n.PeerAdminSession(p, commands.ChannelJoinBySnapshotStatus{
  1210  		ClientAuth: n.ClientAuthRequired,
  1211  	})
  1212  	Expect(err).NotTo(HaveOccurred())
  1213  	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
  1214  	return string(sess.Out.Contents())
  1215  }
  1216  
  1217  // Cryptogen starts a gexec.Session for the provided cryptogen command.
  1218  func (n *Network) Cryptogen(command Command) (*gexec.Session, error) {
  1219  	cmd := NewCommand(n.Components.Cryptogen(), command)
  1220  	return n.StartSession(cmd, command.SessionName())
  1221  }
  1222  
  1223  // Idemixgen starts a gexec.Session for the provided idemixgen command.
  1224  func (n *Network) Idemixgen(command Command) (*gexec.Session, error) {
  1225  	cmd := NewCommand(n.Components.Idemixgen(), command)
  1226  	return n.StartSession(cmd, command.SessionName())
  1227  }
  1228  
  1229  // ConfigTxGen starts a gexec.Session for the provided configtxgen command.
  1230  func (n *Network) ConfigTxGen(command Command) (*gexec.Session, error) {
  1231  	cmd := NewCommand(n.Components.ConfigTxGen(), command)
  1232  	return n.StartSession(cmd, command.SessionName())
  1233  }
  1234  
  1235  // Discover starts a gexec.Session for the provided discover command.
  1236  func (n *Network) Discover(command Command) (*gexec.Session, error) {
  1237  	cmd := NewCommand(n.Components.Discover(), command)
  1238  	cmd.Args = append(cmd.Args, "--peerTLSCA", n.CACertsBundlePath())
  1239  	return n.StartSession(cmd, command.SessionName())
  1240  }
  1241  
  1242  // Osnadmin starts a gexec.Session for the provided osnadmin command.
  1243  func (n *Network) Osnadmin(command Command) (*gexec.Session, error) {
  1244  	cmd := NewCommand(n.Components.Osnadmin(), command)
  1245  	return n.StartSession(cmd, command.SessionName())
  1246  }
  1247  
  1248  // ZooKeeperRunner returns a runner for a ZooKeeper instance.
  1249  func (n *Network) ZooKeeperRunner(idx int) *runner.ZooKeeper {
  1250  	colorCode := n.nextColor()
  1251  	name := fmt.Sprintf("zookeeper-%d-%s", idx, n.NetworkID)
  1252  
  1253  	return &runner.ZooKeeper{
  1254  		ZooMyID:     idx + 1, //  IDs must be between 1 and 255
  1255  		Client:      n.DockerClient,
  1256  		Name:        name,
  1257  		NetworkName: n.NetworkID,
  1258  		OutputStream: gexec.NewPrefixedWriter(
  1259  			fmt.Sprintf("\x1b[32m[o]\x1b[%s[%s]\x1b[0m ", colorCode, name),
  1260  			ginkgo.GinkgoWriter,
  1261  		),
  1262  		ErrorStream: gexec.NewPrefixedWriter(
  1263  			fmt.Sprintf("\x1b[91m[e]\x1b[%s[%s]\x1b[0m ", colorCode, name),
  1264  			ginkgo.GinkgoWriter,
  1265  		),
  1266  	}
  1267  }
  1268  
  1269  func (n *Network) minBrokersInSync() int {
  1270  	if n.Consensus.Brokers < 2 {
  1271  		return n.Consensus.Brokers
  1272  	}
  1273  	return 2
  1274  }
  1275  
  1276  func (n *Network) defaultBrokerReplication() int {
  1277  	if n.Consensus.Brokers < 3 {
  1278  		return n.Consensus.Brokers
  1279  	}
  1280  	return 3
  1281  }
  1282  
  1283  // BrokerRunner returns a runner for a Kafka broker instance.
  1284  func (n *Network) BrokerRunner(id int, zookeepers []string) *runner.Kafka {
  1285  	colorCode := n.nextColor()
  1286  	name := fmt.Sprintf("kafka-%d-%s", id, n.NetworkID)
  1287  
  1288  	return &runner.Kafka{
  1289  		BrokerID:                 id + 1,
  1290  		Client:                   n.DockerClient,
  1291  		AdvertisedListeners:      "127.0.0.1",
  1292  		HostPort:                 int(n.PortsByBrokerID[strconv.Itoa(id)][HostPort]),
  1293  		Name:                     name,
  1294  		NetworkName:              n.NetworkID,
  1295  		MinInsyncReplicas:        n.minBrokersInSync(),
  1296  		DefaultReplicationFactor: n.defaultBrokerReplication(),
  1297  		ZooKeeperConnect:         strings.Join(zookeepers, ","),
  1298  		OutputStream: gexec.NewPrefixedWriter(
  1299  			fmt.Sprintf("\x1b[32m[o]\x1b[%s[%s]\x1b[0m ", colorCode, name),
  1300  			ginkgo.GinkgoWriter,
  1301  		),
  1302  		ErrorStream: gexec.NewPrefixedWriter(
  1303  			fmt.Sprintf("\x1b[91m[e]\x1b[%s[%s]\x1b[0m ", colorCode, name),
  1304  			ginkgo.GinkgoWriter,
  1305  		),
  1306  	}
  1307  }
  1308  
  1309  // BrokerGroupRunner returns a runner that manages the processes that make up
  1310  // the Kafka broker network for fabric.
  1311  func (n *Network) BrokerGroupRunner() ifrit.Runner {
  1312  	members := grouper.Members{}
  1313  	zookeepers := []string{}
  1314  
  1315  	for i := 0; i < n.Consensus.ZooKeepers; i++ {
  1316  		zk := n.ZooKeeperRunner(i)
  1317  		zookeepers = append(zookeepers, fmt.Sprintf("%s:2181", zk.Name))
  1318  		members = append(members, grouper.Member{Name: zk.Name, Runner: zk})
  1319  	}
  1320  
  1321  	for i := 0; i < n.Consensus.Brokers; i++ {
  1322  		kafka := n.BrokerRunner(i, zookeepers)
  1323  		members = append(members, grouper.Member{Name: kafka.Name, Runner: kafka})
  1324  	}
  1325  
  1326  	return grouper.NewOrdered(syscall.SIGTERM, members)
  1327  }
  1328  
  1329  // OrdererRunner returns an ifrit.Runner for the specified orderer. The runner
  1330  // can be used to start and manage an orderer process.
  1331  func (n *Network) OrdererRunner(o *Orderer, env ...string) *ginkgomon.Runner {
  1332  	cmd := exec.Command(n.Components.Orderer())
  1333  	cmd.Env = os.Environ()
  1334  	cmd.Env = append(cmd.Env, fmt.Sprintf("FABRIC_CFG_PATH=%s", n.OrdererDir(o)))
  1335  	cmd.Env = append(cmd.Env, env...)
  1336  
  1337  	config := ginkgomon.Config{
  1338  		AnsiColorCode:     n.nextColor(),
  1339  		Name:              o.ID(),
  1340  		Command:           cmd,
  1341  		StartCheck:        "Beginning to serve requests",
  1342  		StartCheckTimeout: 15 * time.Second,
  1343  	}
  1344  
  1345  	// After consensus-type migration, the #brokers is >0, but the type is etcdraft
  1346  	if n.Consensus.Type == "kafka" && n.Consensus.Brokers != 0 {
  1347  		config.StartCheck = "Start phase completed successfully"
  1348  		config.StartCheckTimeout = 30 * time.Second
  1349  	}
  1350  
  1351  	return ginkgomon.New(config)
  1352  }
  1353  
  1354  // OrdererGroupRunner returns a runner that can be used to start and stop all
  1355  // orderers in a network.
  1356  func (n *Network) OrdererGroupRunner() ifrit.Runner {
  1357  	members := grouper.Members{}
  1358  	for _, o := range n.Orderers {
  1359  		members = append(members, grouper.Member{Name: o.ID(), Runner: n.OrdererRunner(o)})
  1360  	}
  1361  	return grouper.NewParallel(syscall.SIGTERM, members)
  1362  }
  1363  
  1364  // PeerRunner returns an ifrit.Runner for the specified peer. The runner can be
  1365  // used to start and manage a peer process.
  1366  func (n *Network) PeerRunner(p *Peer, env ...string) *ginkgomon.Runner {
  1367  	cmd := n.peerCommand(
  1368  		commands.NodeStart{PeerID: p.ID(), DevMode: p.DevMode},
  1369  		"",
  1370  		"FABRIC_CFG_PATH="+n.PeerDir(p),
  1371  		"CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=admin",
  1372  		"CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=adminpw",
  1373  	)
  1374  	cmd.Env = append(cmd.Env, env...)
  1375  
  1376  	return ginkgomon.New(ginkgomon.Config{
  1377  		AnsiColorCode:     n.nextColor(),
  1378  		Name:              p.ID(),
  1379  		Command:           cmd,
  1380  		StartCheck:        `Started peer with ID=.*, .*, address=`,
  1381  		StartCheckTimeout: 15 * time.Second,
  1382  	})
  1383  }
  1384  
  1385  // PeerGroupRunner returns a runner that can be used to start and stop all
  1386  // peers in a network.
  1387  func (n *Network) PeerGroupRunner() ifrit.Runner {
  1388  	members := grouper.Members{}
  1389  	for _, p := range n.Peers {
  1390  		members = append(members, grouper.Member{Name: p.ID(), Runner: n.PeerRunner(p)})
  1391  	}
  1392  	return grouper.NewParallel(syscall.SIGTERM, members)
  1393  }
  1394  
  1395  // NetworkGroupRunner returns a runner that can be used to start and stop an
  1396  // entire fabric network.
  1397  func (n *Network) NetworkGroupRunner() ifrit.Runner {
  1398  	members := grouper.Members{
  1399  		{Name: "brokers", Runner: n.BrokerGroupRunner()},
  1400  		{Name: "orderers", Runner: n.OrdererGroupRunner()},
  1401  		{Name: "peers", Runner: n.PeerGroupRunner()},
  1402  	}
  1403  	return grouper.NewOrdered(syscall.SIGTERM, members)
  1404  }
  1405  
  1406  func (n *Network) peerCommand(command Command, tlsDir string, env ...string) *exec.Cmd {
  1407  	cmd := NewCommand(n.Components.Peer(), command)
  1408  	cmd.Env = append(cmd.Env, env...)
  1409  
  1410  	if connectsToOrderer(command) && n.TLSEnabled {
  1411  		cmd.Args = append(cmd.Args, "--tls")
  1412  		cmd.Args = append(cmd.Args, "--cafile", n.CACertsBundlePath())
  1413  	}
  1414  
  1415  	if clientAuthEnabled(command) {
  1416  		certfilePath := filepath.Join(tlsDir, "client.crt")
  1417  		keyfilePath := filepath.Join(tlsDir, "client.key")
  1418  
  1419  		cmd.Args = append(cmd.Args, "--certfile", certfilePath)
  1420  		cmd.Args = append(cmd.Args, "--keyfile", keyfilePath)
  1421  	}
  1422  
  1423  	// In case we have a peer invoke with multiple certificates, we need to mimic
  1424  	// the correct peer CLI usage, so we count the number of --peerAddresses
  1425  	// usages we have, and add the same (concatenated TLS CA certificates file)
  1426  	// the same number of times to bypass the peer CLI sanity checks
  1427  	requiredPeerAddresses := flagCount("--peerAddresses", cmd.Args)
  1428  	for i := 0; i < requiredPeerAddresses; i++ {
  1429  		cmd.Args = append(cmd.Args, "--tlsRootCertFiles")
  1430  		cmd.Args = append(cmd.Args, n.CACertsBundlePath())
  1431  	}
  1432  
  1433  	// If there is --peerAddress, add --tlsRootCertFile parameter
  1434  	requiredPeerAddress := flagCount("--peerAddress", cmd.Args)
  1435  	if requiredPeerAddress > 0 {
  1436  		cmd.Args = append(cmd.Args, "--tlsRootCertFile")
  1437  		cmd.Args = append(cmd.Args, n.CACertsBundlePath())
  1438  	}
  1439  	return cmd
  1440  }
  1441  
  1442  func connectsToOrderer(c Command) bool {
  1443  	for _, arg := range c.Args() {
  1444  		if arg == "--orderer" {
  1445  			return true
  1446  		}
  1447  	}
  1448  	return false
  1449  }
  1450  
  1451  func clientAuthEnabled(c Command) bool {
  1452  	for _, arg := range c.Args() {
  1453  		if arg == "--clientauth" {
  1454  			return true
  1455  		}
  1456  	}
  1457  	return false
  1458  }
  1459  
  1460  func flagCount(flag string, args []string) int {
  1461  	var c int
  1462  	for _, arg := range args {
  1463  		if arg == flag {
  1464  			c++
  1465  		}
  1466  	}
  1467  	return c
  1468  }
  1469  
  1470  // PeerAdminSession starts a gexec.Session as a peer admin for the provided
  1471  // peer command. This is intended to be used by short running peer cli commands
  1472  // that execute in the context of a peer configuration.
  1473  func (n *Network) PeerAdminSession(p *Peer, command Command) (*gexec.Session, error) {
  1474  	return n.PeerUserSession(p, "Admin", command)
  1475  }
  1476  
  1477  // PeerUserSession starts a gexec.Session as a peer user for the provided peer
  1478  // command. This is intended to be used by short running peer cli commands that
  1479  // execute in the context of a peer configuration.
  1480  func (n *Network) PeerUserSession(p *Peer, user string, command Command) (*gexec.Session, error) {
  1481  	cmd := n.peerCommand(
  1482  		command,
  1483  		n.PeerUserTLSDir(p, user),
  1484  		fmt.Sprintf("FABRIC_CFG_PATH=%s", n.PeerDir(p)),
  1485  		fmt.Sprintf("CORE_PEER_MSPCONFIGPATH=%s", n.PeerUserMSPDir(p, user)),
  1486  	)
  1487  	return n.StartSession(cmd, command.SessionName())
  1488  }
  1489  
  1490  // PeerClientConn returns a grpc.ClientConn configured to connect to the
  1491  // provided peer. This connection can be used to create clients for the peer
  1492  // services. The client connection should be closed when the tests are done
  1493  // using it.
  1494  func (n *Network) PeerClientConn(p *Peer) *grpc.ClientConn {
  1495  	return n.newClientConn(
  1496  		n.PeerAddress(p, ListenPort),
  1497  		filepath.Join(n.PeerLocalTLSDir(p), "ca.crt"),
  1498  	)
  1499  }
  1500  
  1501  // OrdererClientConn returns a grpc.ClientConn configured to connect to the
  1502  // provided orderer. This connection can be used to create clients for the
  1503  // orderer services. The client connection should be closed when the tests are
  1504  // done using it.
  1505  func (n *Network) OrdererClientConn(o *Orderer) *grpc.ClientConn {
  1506  	return n.newClientConn(
  1507  		n.OrdererAddress(o, ListenPort),
  1508  		filepath.Join(n.OrdererLocalTLSDir(o), "ca.crt"),
  1509  	)
  1510  }
  1511  
  1512  func (n *Network) newClientConn(address, ca string) *grpc.ClientConn {
  1513  	fingerprint := "grpc::" + address + "::" + ca
  1514  	if d := n.throttleDuration(fingerprint); d > 0 {
  1515  		time.Sleep(d)
  1516  	}
  1517  
  1518  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  1519  	defer cancel()
  1520  
  1521  	creds, err := credentials.NewClientTLSFromFile(ca, "")
  1522  	Expect(err).NotTo(HaveOccurred())
  1523  
  1524  	conn, err := grpc.DialContext(
  1525  		ctx,
  1526  		address,
  1527  		grpc.WithBlock(),
  1528  		grpc.FailOnNonTempDialError(true),
  1529  		grpc.WithTransportCredentials(creds),
  1530  	)
  1531  	Expect(err).NotTo(HaveOccurred())
  1532  
  1533  	return conn
  1534  }
  1535  
  1536  // IdemixUserSession starts a gexec.Session as a idemix user for the provided peer
  1537  // command. This is intended to be used by short running peer cli commands that
  1538  // execute in the context of a peer configuration.
  1539  func (n *Network) IdemixUserSession(p *Peer, idemixOrg *Organization, user string, command Command) (*gexec.Session, error) {
  1540  	cmd := n.peerCommand(
  1541  		command,
  1542  		n.PeerUserTLSDir(p, user),
  1543  		fmt.Sprintf("FABRIC_CFG_PATH=%s", n.PeerDir(p)),
  1544  		fmt.Sprintf("CORE_PEER_MSPCONFIGPATH=%s", n.IdemixUserMSPDir(idemixOrg, user)),
  1545  		fmt.Sprintf("CORE_PEER_LOCALMSPTYPE=%s", "idemix"),
  1546  		fmt.Sprintf("CORE_PEER_LOCALMSPID=%s", idemixOrg.MSPID),
  1547  	)
  1548  	return n.StartSession(cmd, command.SessionName())
  1549  }
  1550  
  1551  // OrdererAdminSession starts a gexec.Session as an orderer admin user. This
  1552  // is used primarily to generate orderer configuration updates.
  1553  func (n *Network) OrdererAdminSession(o *Orderer, p *Peer, command Command) (*gexec.Session, error) {
  1554  	cmd := n.peerCommand(
  1555  		command,
  1556  		n.ordererUserCryptoDir(o, "Admin", "tls"),
  1557  		fmt.Sprintf("CORE_PEER_LOCALMSPID=%s", n.Organization(o.Organization).MSPID),
  1558  		fmt.Sprintf("FABRIC_CFG_PATH=%s", n.PeerDir(p)),
  1559  		fmt.Sprintf("CORE_PEER_MSPCONFIGPATH=%s", n.OrdererUserMSPDir(o, "Admin")),
  1560  	)
  1561  	return n.StartSession(cmd, command.SessionName())
  1562  }
  1563  
  1564  // Peer returns the information about the named Peer in the named organization.
  1565  func (n *Network) Peer(orgName, peerName string) *Peer {
  1566  	for _, p := range n.PeersInOrg(orgName) {
  1567  		if p.Name == peerName {
  1568  			return p
  1569  		}
  1570  	}
  1571  	return nil
  1572  }
  1573  
  1574  // DiscoveredPeer creates a new DiscoveredPeer from the peer and chaincodes
  1575  // passed as arguments.
  1576  func (n *Network) DiscoveredPeer(p *Peer, chaincodes ...string) DiscoveredPeer {
  1577  	peerCert, err := ioutil.ReadFile(n.PeerCert(p))
  1578  	Expect(err).NotTo(HaveOccurred())
  1579  
  1580  	return DiscoveredPeer{
  1581  		MSPID:      n.Organization(p.Organization).MSPID,
  1582  		Endpoint:   fmt.Sprintf("127.0.0.1:%d", n.PeerPort(p, ListenPort)),
  1583  		Identity:   string(peerCert),
  1584  		Chaincodes: chaincodes,
  1585  	}
  1586  }
  1587  
  1588  // Orderer returns the information about the named Orderer.
  1589  func (n *Network) Orderer(name string) *Orderer {
  1590  	for _, o := range n.Orderers {
  1591  		if o.Name == name {
  1592  			return o
  1593  		}
  1594  	}
  1595  	return nil
  1596  }
  1597  
  1598  // Organization returns the information about the named Organization.
  1599  func (n *Network) Organization(orgName string) *Organization {
  1600  	for _, org := range n.Organizations {
  1601  		if org.Name == orgName {
  1602  			return org
  1603  		}
  1604  	}
  1605  	return nil
  1606  }
  1607  
  1608  // Consortium returns information about the named Consortium.
  1609  func (n *Network) Consortium(name string) *Consortium {
  1610  	for _, c := range n.Consortiums {
  1611  		if c.Name == name {
  1612  			return c
  1613  		}
  1614  	}
  1615  	return nil
  1616  }
  1617  
  1618  // PeerOrgs returns all Organizations associated with at least one Peer.
  1619  func (n *Network) PeerOrgs() []*Organization {
  1620  	orgsByName := map[string]*Organization{}
  1621  	for _, p := range n.Peers {
  1622  		if n.Organization(p.Organization).MSPType != "idemix" {
  1623  			orgsByName[p.Organization] = n.Organization(p.Organization)
  1624  		}
  1625  	}
  1626  
  1627  	orgs := []*Organization{}
  1628  	for _, org := range orgsByName {
  1629  		orgs = append(orgs, org)
  1630  	}
  1631  	return orgs
  1632  }
  1633  
  1634  // IdemixOrgs returns all Organizations of type idemix.
  1635  func (n *Network) IdemixOrgs() []*Organization {
  1636  	orgs := []*Organization{}
  1637  	for _, org := range n.Organizations {
  1638  		if org.MSPType == "idemix" {
  1639  			orgs = append(orgs, org)
  1640  		}
  1641  	}
  1642  	return orgs
  1643  }
  1644  
  1645  // PeersWithChannel returns all Peer instances that have joined the named
  1646  // channel.
  1647  func (n *Network) PeersWithChannel(chanName string) []*Peer {
  1648  	peers := []*Peer{}
  1649  	for _, p := range n.Peers {
  1650  		for _, c := range p.Channels {
  1651  			if c.Name == chanName {
  1652  				peers = append(peers, p)
  1653  			}
  1654  		}
  1655  	}
  1656  
  1657  	// This is a bit of a hack to make the output of this function deterministic.
  1658  	// When this function's output is supplied as input to functions such as ApproveChaincodeForMyOrg
  1659  	// it causes a different subset of peers to be picked, which can create flakiness in tests.
  1660  	sort.Slice(peers, func(i, j int) bool {
  1661  		if peers[i].Organization < peers[j].Organization {
  1662  			return true
  1663  		}
  1664  
  1665  		return peers[i].Organization == peers[j].Organization && peers[i].Name < peers[j].Name
  1666  	})
  1667  	return peers
  1668  }
  1669  
  1670  // AnchorsForChannel returns all Peer instances that are anchors for the
  1671  // named channel.
  1672  func (n *Network) AnchorsForChannel(chanName string) []*Peer {
  1673  	anchors := []*Peer{}
  1674  	for _, p := range n.Peers {
  1675  		for _, pc := range p.Channels {
  1676  			if pc.Name == chanName && pc.Anchor {
  1677  				anchors = append(anchors, p)
  1678  			}
  1679  		}
  1680  	}
  1681  	return anchors
  1682  }
  1683  
  1684  // AnchorsInOrg returns all peers that are an anchor for at least one channel
  1685  // in the named organization.
  1686  func (n *Network) AnchorsInOrg(orgName string) []*Peer {
  1687  	anchors := []*Peer{}
  1688  	for _, p := range n.PeersInOrg(orgName) {
  1689  		if p.Anchor() {
  1690  			anchors = append(anchors, p)
  1691  			break
  1692  		}
  1693  	}
  1694  
  1695  	// No explicit anchor means all peers are anchors.
  1696  	if len(anchors) == 0 {
  1697  		anchors = n.PeersInOrg(orgName)
  1698  	}
  1699  
  1700  	return anchors
  1701  }
  1702  
  1703  // OrderersInOrg returns all Orderer instances owned by the named organization.
  1704  func (n *Network) OrderersInOrg(orgName string) []*Orderer {
  1705  	orderers := []*Orderer{}
  1706  	for _, o := range n.Orderers {
  1707  		if o.Organization == orgName {
  1708  			orderers = append(orderers, o)
  1709  		}
  1710  	}
  1711  	return orderers
  1712  }
  1713  
  1714  // OrgsForOrderers returns all Organization instances that own at least one of
  1715  // the named orderers.
  1716  func (n *Network) OrgsForOrderers(ordererNames []string) []*Organization {
  1717  	orgsByName := map[string]*Organization{}
  1718  	for _, name := range ordererNames {
  1719  		orgName := n.Orderer(name).Organization
  1720  		orgsByName[orgName] = n.Organization(orgName)
  1721  	}
  1722  	orgs := []*Organization{}
  1723  	for _, org := range orgsByName {
  1724  		orgs = append(orgs, org)
  1725  	}
  1726  	return orgs
  1727  }
  1728  
  1729  // OrdererOrgs returns all Organization instances that own at least one
  1730  // orderer.
  1731  func (n *Network) OrdererOrgs() []*Organization {
  1732  	orgsByName := map[string]*Organization{}
  1733  	for _, o := range n.Orderers {
  1734  		orgsByName[o.Organization] = n.Organization(o.Organization)
  1735  	}
  1736  
  1737  	orgs := []*Organization{}
  1738  	for _, org := range orgsByName {
  1739  		orgs = append(orgs, org)
  1740  	}
  1741  	return orgs
  1742  }
  1743  
  1744  // PeersInOrg returns all Peer instances that are owned by the named
  1745  // organization.
  1746  func (n *Network) PeersInOrg(orgName string) []*Peer {
  1747  	peers := []*Peer{}
  1748  	for _, o := range n.Peers {
  1749  		if o.Organization == orgName {
  1750  			peers = append(peers, o)
  1751  		}
  1752  	}
  1753  	return peers
  1754  }
  1755  
  1756  // ReservePort allocates the next available port.
  1757  func (n *Network) ReservePort() uint16 {
  1758  	n.StartPort++
  1759  	return n.StartPort - 1
  1760  }
  1761  
  1762  type (
  1763  	PortName string
  1764  	Ports    map[PortName]uint16
  1765  )
  1766  
  1767  const (
  1768  	ChaincodePort  PortName = "Chaincode"
  1769  	EventsPort     PortName = "Events"
  1770  	HostPort       PortName = "HostPort"
  1771  	ListenPort     PortName = "Listen"
  1772  	ProfilePort    PortName = "Profile"
  1773  	OperationsPort PortName = "Operations"
  1774  	ClusterPort    PortName = "Cluster"
  1775  	AdminPort      PortName = "Admin"
  1776  )
  1777  
  1778  // PeerPortNames returns the list of ports that need to be reserved for a Peer.
  1779  func PeerPortNames() []PortName {
  1780  	return []PortName{ListenPort, ChaincodePort, EventsPort, ProfilePort, OperationsPort}
  1781  }
  1782  
  1783  // OrdererPortNames  returns the list of ports that need to be reserved for an
  1784  // Orderer.
  1785  func OrdererPortNames() []PortName {
  1786  	return []PortName{ListenPort, ProfilePort, OperationsPort, ClusterPort, AdminPort}
  1787  }
  1788  
  1789  // BrokerPortNames returns the list of ports that need to be reserved for a
  1790  // Kafka broker.
  1791  func BrokerPortNames() []PortName {
  1792  	return []PortName{HostPort}
  1793  }
  1794  
  1795  // BrokerAddresses returns the list of broker addresses for the network.
  1796  func (n *Network) BrokerAddresses(portName PortName) []string {
  1797  	addresses := []string{}
  1798  	for _, ports := range n.PortsByBrokerID {
  1799  		addresses = append(addresses, fmt.Sprintf("127.0.0.1:%d", ports[portName]))
  1800  	}
  1801  	return addresses
  1802  }
  1803  
  1804  // OrdererAddress returns the address (host and port) exposed by the Orderer
  1805  // for the named port. Command line tools should use the returned address when
  1806  // connecting to the orderer.
  1807  //
  1808  // This assumes that the orderer is listening on 0.0.0.0 or 127.0.0.1 and is
  1809  // available on the loopback address.
  1810  func (n *Network) OrdererAddress(o *Orderer, portName PortName) string {
  1811  	return fmt.Sprintf("127.0.0.1:%d", n.OrdererPort(o, portName))
  1812  }
  1813  
  1814  // OrdererPort returns the named port reserved for the Orderer instance.
  1815  func (n *Network) OrdererPort(o *Orderer, portName PortName) uint16 {
  1816  	ordererPorts := n.PortsByOrdererID[o.ID()]
  1817  	Expect(ordererPorts).NotTo(BeNil())
  1818  	return ordererPorts[portName]
  1819  }
  1820  
  1821  // PeerAddress returns the address (host and port) exposed by the Peer for the
  1822  // named port. Command line tools should use the returned address when
  1823  // connecting to a peer.
  1824  //
  1825  // This assumes that the peer is listening on 0.0.0.0 and is available on the
  1826  // loopback address.
  1827  func (n *Network) PeerAddress(p *Peer, portName PortName) string {
  1828  	return fmt.Sprintf("127.0.0.1:%d", n.PeerPort(p, portName))
  1829  }
  1830  
  1831  // PeerPort returns the named port reserved for the Peer instance.
  1832  func (n *Network) PeerPort(p *Peer, portName PortName) uint16 {
  1833  	peerPorts := n.PortsByPeerID[p.ID()]
  1834  	Expect(peerPorts).NotTo(BeNil())
  1835  	return peerPorts[portName]
  1836  }
  1837  
  1838  func (n *Network) nextColor() string {
  1839  	n.mutex.Lock()
  1840  	defer n.mutex.Unlock()
  1841  	color := n.colorIndex%14 + 31
  1842  	if color > 37 {
  1843  		color = color + 90 - 37
  1844  	}
  1845  
  1846  	n.colorIndex++
  1847  	return fmt.Sprintf("%dm", color)
  1848  }
  1849  
  1850  // StartSession executes a command session. This should be used to launch
  1851  // command line tools that are expected to run to completion.
  1852  func (n *Network) StartSession(cmd *exec.Cmd, name string) (*gexec.Session, error) {
  1853  	if d := n.throttleDuration(commandFingerprint(cmd)); d > 0 {
  1854  		time.Sleep(d)
  1855  	}
  1856  
  1857  	ansiColorCode := n.nextColor()
  1858  	fmt.Fprintf(
  1859  		ginkgo.GinkgoWriter,
  1860  		"\x1b[33m[d]\x1b[%s[%s]\x1b[0m starting %s %s\n",
  1861  		ansiColorCode,
  1862  		name,
  1863  		filepath.Base(cmd.Args[0]),
  1864  		strings.Join(cmd.Args[1:], " "),
  1865  	)
  1866  	return gexec.Start(
  1867  		cmd,
  1868  		gexec.NewPrefixedWriter(
  1869  			fmt.Sprintf("\x1b[32m[o]\x1b[%s[%s]\x1b[0m ", ansiColorCode, name),
  1870  			ginkgo.GinkgoWriter,
  1871  		),
  1872  		gexec.NewPrefixedWriter(
  1873  			fmt.Sprintf("\x1b[91m[e]\x1b[%s[%s]\x1b[0m ", ansiColorCode, name),
  1874  			ginkgo.GinkgoWriter,
  1875  		),
  1876  	)
  1877  }
  1878  
  1879  // commandFingerprint creates a string containing the program, args, and environment
  1880  // of an exec.Cmd. This fingerprint is used to identify repeated calls to the
  1881  // same command for throttling.
  1882  func commandFingerprint(cmd *exec.Cmd) string {
  1883  	buf := bytes.NewBuffer(nil)
  1884  	_, err := buf.WriteString(cmd.Dir)
  1885  	Expect(err).NotTo(HaveOccurred())
  1886  	_, err = buf.WriteString(cmd.Path)
  1887  	Expect(err).NotTo(HaveOccurred())
  1888  
  1889  	// sort the environment since it's not positional
  1890  	env := append([]string(nil), cmd.Env...)
  1891  	sort.Strings(env)
  1892  	for _, e := range env {
  1893  		_, err := buf.WriteString(e)
  1894  		Expect(err).NotTo(HaveOccurred())
  1895  	}
  1896  
  1897  	// grab the args but ignore references to temporary files
  1898  	for _, arg := range cmd.Args {
  1899  		if strings.HasPrefix(arg, os.TempDir()) {
  1900  			continue
  1901  		}
  1902  		_, err := buf.WriteString(arg)
  1903  		Expect(err).NotTo(HaveOccurred())
  1904  	}
  1905  
  1906  	return buf.String()
  1907  }
  1908  
  1909  // throttleDuration returns the time to wait before performing some operation
  1910  // representted by the fingerprint.
  1911  //
  1912  // The duration is determined by looking at when the fingerprinted operation
  1913  // was last executed by the network. If the time between now and the last
  1914  // execution was less than SessionCreateInterval, the difference between now
  1915  // and (execution + SessionCreateInterval) is returned. If more than
  1916  // SessionCreateInterval has elapsed since the last command execution, a
  1917  // duration of 0 is returned.
  1918  func (n *Network) throttleDuration(fingerprint string) time.Duration {
  1919  	now := time.Now()
  1920  	n.mutex.Lock()
  1921  	last := n.lastExecuted[fingerprint]
  1922  	n.lastExecuted[fingerprint] = now
  1923  	n.mutex.Unlock()
  1924  
  1925  	if diff := last.Add(n.SessionCreateInterval).Sub(now); diff > 0 {
  1926  		return diff
  1927  	}
  1928  
  1929  	return 0
  1930  }
  1931  
  1932  // GenerateCryptoConfig creates the `crypto-config.yaml` configuration file
  1933  // provided to `cryptogen` when running Bootstrap. The path to the generated
  1934  // file can be obtained from CryptoConfigPath.
  1935  func (n *Network) GenerateCryptoConfig() {
  1936  	crypto, err := os.Create(n.CryptoConfigPath())
  1937  	Expect(err).NotTo(HaveOccurred())
  1938  	defer crypto.Close()
  1939  
  1940  	t, err := template.New("crypto").Parse(n.Templates.CryptoTemplate())
  1941  	Expect(err).NotTo(HaveOccurred())
  1942  
  1943  	pw := gexec.NewPrefixedWriter("[crypto-config.yaml] ", ginkgo.GinkgoWriter)
  1944  	err = t.Execute(io.MultiWriter(crypto, pw), n)
  1945  	Expect(err).NotTo(HaveOccurred())
  1946  }
  1947  
  1948  // GenerateConfigTxConfig creates the `configtx.yaml` configuration file
  1949  // provided to `configtxgen` when running Bootstrap. The path to the generated
  1950  // file can be obtained from ConfigTxConfigPath.
  1951  func (n *Network) GenerateConfigTxConfig() {
  1952  	config, err := os.Create(n.ConfigTxConfigPath())
  1953  	Expect(err).NotTo(HaveOccurred())
  1954  	defer config.Close()
  1955  
  1956  	t, err := template.New("configtx").Parse(n.Templates.ConfigTxTemplate())
  1957  	Expect(err).NotTo(HaveOccurred())
  1958  
  1959  	pw := gexec.NewPrefixedWriter("[configtx.yaml] ", ginkgo.GinkgoWriter)
  1960  	err = t.Execute(io.MultiWriter(config, pw), n)
  1961  	Expect(err).NotTo(HaveOccurred())
  1962  }
  1963  
  1964  // GenerateOrdererConfig creates the `orderer.yaml` configuration file for the
  1965  // specified orderer. The path to the generated file can be obtained from
  1966  // OrdererConfigPath.
  1967  func (n *Network) GenerateOrdererConfig(o *Orderer) {
  1968  	err := os.MkdirAll(n.OrdererDir(o), 0o755)
  1969  	Expect(err).NotTo(HaveOccurred())
  1970  
  1971  	orderer, err := os.Create(n.OrdererConfigPath(o))
  1972  	Expect(err).NotTo(HaveOccurred())
  1973  	defer orderer.Close()
  1974  
  1975  	t, err := template.New("orderer").Funcs(template.FuncMap{
  1976  		"Orderer":    func() *Orderer { return o },
  1977  		"ToLower":    func(s string) string { return strings.ToLower(s) },
  1978  		"ReplaceAll": func(s, old, new string) string { return strings.Replace(s, old, new, -1) },
  1979  	}).Parse(n.Templates.OrdererTemplate())
  1980  	Expect(err).NotTo(HaveOccurred())
  1981  
  1982  	pw := gexec.NewPrefixedWriter(fmt.Sprintf("[%s#orderer.yaml] ", o.ID()), ginkgo.GinkgoWriter)
  1983  	err = t.Execute(io.MultiWriter(orderer, pw), n)
  1984  	Expect(err).NotTo(HaveOccurred())
  1985  }
  1986  
  1987  // GenerateCoreConfig creates the `core.yaml` configuration file for the
  1988  // specified peer. The path to the generated file can be obtained from
  1989  // PeerConfigPath.
  1990  func (n *Network) GenerateCoreConfig(p *Peer) {
  1991  	err := os.MkdirAll(n.PeerDir(p), 0o755)
  1992  	Expect(err).NotTo(HaveOccurred())
  1993  
  1994  	core, err := os.Create(n.PeerConfigPath(p))
  1995  	Expect(err).NotTo(HaveOccurred())
  1996  	defer core.Close()
  1997  
  1998  	t, err := template.New("peer").Funcs(template.FuncMap{
  1999  		"Peer":       func() *Peer { return p },
  2000  		"ToLower":    func(s string) string { return strings.ToLower(s) },
  2001  		"ReplaceAll": func(s, old, new string) string { return strings.Replace(s, old, new, -1) },
  2002  	}).Parse(n.Templates.CoreTemplate())
  2003  	Expect(err).NotTo(HaveOccurred())
  2004  
  2005  	pw := gexec.NewPrefixedWriter(fmt.Sprintf("[%s#core.yaml] ", p.ID()), ginkgo.GinkgoWriter)
  2006  	err = t.Execute(io.MultiWriter(core, pw), n)
  2007  	Expect(err).NotTo(HaveOccurred())
  2008  }