github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/integration/raft/config_test.go (about)

     1  /*
     2  Copyright IBM Corp All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package raft
     8  
     9  import (
    10  	"bytes"
    11  	"crypto/x509"
    12  	"encoding/pem"
    13  	"fmt"
    14  	"io/ioutil"
    15  	"os"
    16  	"path"
    17  	"path/filepath"
    18  	"strings"
    19  	"syscall"
    20  	"time"
    21  
    22  	docker "github.com/fsouza/go-dockerclient"
    23  	"github.com/golang/protobuf/proto"
    24  	"github.com/hyperledger/fabric-protos-go/common"
    25  	"github.com/hyperledger/fabric-protos-go/msp"
    26  	protosorderer "github.com/hyperledger/fabric-protos-go/orderer"
    27  	"github.com/hyperledger/fabric-protos-go/orderer/etcdraft"
    28  	"github.com/osdi23p228/fabric/common/crypto/tlsgen"
    29  	"github.com/osdi23p228/fabric/integration/nwo"
    30  	"github.com/osdi23p228/fabric/integration/nwo/commands"
    31  	"github.com/osdi23p228/fabric/internal/configtxgen/encoder"
    32  	"github.com/osdi23p228/fabric/internal/configtxgen/genesisconfig"
    33  	"github.com/osdi23p228/fabric/protoutil"
    34  	. "github.com/onsi/ginkgo"
    35  	. "github.com/onsi/gomega"
    36  	"github.com/onsi/gomega/gbytes"
    37  	"github.com/onsi/gomega/gexec"
    38  	"github.com/tedsuo/ifrit"
    39  	"github.com/tedsuo/ifrit/ginkgomon"
    40  )
    41  
    42  var _ = Describe("EndToEnd reconfiguration and onboarding", func() {
    43  	var (
    44  		testDir string
    45  		client  *docker.Client
    46  		network *nwo.Network
    47  		peer    *nwo.Peer
    48  
    49  		networkProcess   ifrit.Process
    50  		ordererProcesses []ifrit.Process
    51  		ordererRunners   []*ginkgomon.Runner
    52  	)
    53  
    54  	BeforeEach(func() {
    55  		ordererRunners = nil
    56  		ordererProcesses = nil
    57  
    58  		var err error
    59  		testDir, err = ioutil.TempDir("", "e2e-etcdraft_reconfig")
    60  		Expect(err).NotTo(HaveOccurred())
    61  
    62  		client, err = docker.NewClientFromEnv()
    63  		Expect(err).NotTo(HaveOccurred())
    64  	})
    65  
    66  	AfterEach(func() {
    67  		if networkProcess != nil {
    68  			networkProcess.Signal(syscall.SIGTERM)
    69  			Eventually(networkProcess.Wait(), network.EventuallyTimeout).Should(Receive())
    70  		}
    71  		if network != nil {
    72  			network.Cleanup()
    73  		}
    74  		for _, ordererInstance := range ordererProcesses {
    75  			ordererInstance.Signal(syscall.SIGTERM)
    76  			Eventually(ordererInstance.Wait(), network.EventuallyTimeout).Should(Receive())
    77  		}
    78  		os.RemoveAll(testDir)
    79  	})
    80  
    81  	Describe("three node etcdraft network with 2 orgs", func() {
    82  		BeforeEach(func() {
    83  			network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components)
    84  			network.GenerateConfigTree()
    85  			network.Bootstrap()
    86  
    87  			networkRunner := network.NetworkGroupRunner()
    88  			networkProcess = ifrit.Invoke(networkRunner)
    89  			Eventually(networkProcess.Ready(), network.EventuallyTimeout).Should(BeClosed())
    90  		})
    91  
    92  		// This tests:
    93  		//
    94  		// 1. channel creation with raft orderer,
    95  		// 2. all the nodes on three-node raft cluster are in sync wrt blocks,
    96  		// 3. raft orderer processes type A config updates and delivers the
    97  		//    config blocks to the peers.
    98  		It("executes an etcdraft network with 2 orgs and three orderer nodes", func() {
    99  			orderer1 := network.Orderer("orderer1")
   100  			orderer2 := network.Orderer("orderer2")
   101  			orderer3 := network.Orderer("orderer3")
   102  			peer := network.Peer("Org1", "peer0")
   103  			blockFile1 := filepath.Join(testDir, "newest_orderer1_block.pb")
   104  			blockFile2 := filepath.Join(testDir, "newest_orderer2_block.pb")
   105  			blockFile3 := filepath.Join(testDir, "newest_orderer3_block.pb")
   106  
   107  			By("Ordering service system channel is ready")
   108  			assertBlockReception(map[string]int{
   109  				"systemchannel": 0,
   110  			}, []*nwo.Orderer{orderer1, orderer2, orderer3}, peer, network)
   111  
   112  			fetchLatestBlock := func(targetOrderer *nwo.Orderer, blockFile string) {
   113  				c := commands.ChannelFetch{
   114  					ChannelID:  "testchannel",
   115  					Block:      "newest",
   116  					OutputFile: blockFile,
   117  				}
   118  				if targetOrderer != nil {
   119  					c.Orderer = network.OrdererAddress(targetOrderer, nwo.ListenPort)
   120  				}
   121  				sess, err := network.PeerAdminSession(peer, c)
   122  				Expect(err).NotTo(HaveOccurred())
   123  				Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   124  			}
   125  
   126  			By("Creating a new channel")
   127  			network.CreateChannel("testchannel", orderer1, peer)
   128  
   129  			// the above can work even if the orderer nodes are not in the same Raft
   130  			// cluster; we need to verify all the three orderer nodes are in sync wrt
   131  			// blocks.
   132  			By("Fetching the latest blocks from all the orderer nodes and testing them for equality")
   133  			fetchLatestBlock(orderer1, blockFile1)
   134  			fetchLatestBlock(orderer2, blockFile2)
   135  			fetchLatestBlock(orderer3, blockFile3)
   136  			b1 := nwo.UnmarshalBlockFromFile(blockFile1)
   137  			b2 := nwo.UnmarshalBlockFromFile(blockFile2)
   138  			b3 := nwo.UnmarshalBlockFromFile(blockFile3)
   139  			Expect(protoutil.BlockHeaderBytes(b1.Header)).To(Equal(protoutil.BlockHeaderBytes(b2.Header)))
   140  			Expect(protoutil.BlockHeaderBytes(b2.Header)).To(Equal(protoutil.BlockHeaderBytes(b3.Header)))
   141  		})
   142  	})
   143  
   144  	Describe("Invalid Raft config metadata", func() {
   145  		It("refuses to start orderer or rejects config update", func() {
   146  			By("Creating malformed genesis block")
   147  			network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components)
   148  			network.GenerateConfigTree()
   149  			network.Bootstrap()
   150  
   151  			sysProfile := genesisconfig.Load(network.SystemChannel.Profile, network.RootDir)
   152  			Expect(sysProfile.Orderer).NotTo(BeNil())
   153  			sysProfile.Orderer.EtcdRaft.Options.ElectionTick = sysProfile.Orderer.EtcdRaft.Options.HeartbeatTick
   154  			pgen := encoder.New(sysProfile)
   155  			genesisBlock := pgen.GenesisBlockForChannel(network.SystemChannel.Name)
   156  			data, err := proto.Marshal(genesisBlock)
   157  			Expect(err).NotTo(HaveOccurred())
   158  			err = ioutil.WriteFile(network.OutputBlockPath(network.SystemChannel.Name), data, 0644)
   159  			Expect(err).NotTo(HaveOccurred())
   160  
   161  			By("Starting orderer with malformed genesis block")
   162  			ordererRunner := network.OrdererGroupRunner()
   163  			process := ifrit.Invoke(ordererRunner)
   164  			Eventually(process.Wait, network.EventuallyTimeout).Should(Receive()) // orderer process should exit
   165  			network.Cleanup()
   166  			os.RemoveAll(testDir)
   167  
   168  			By("Starting orderer with correct genesis block")
   169  			testDir, err = ioutil.TempDir("", "e2e")
   170  			Expect(err).NotTo(HaveOccurred())
   171  			network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components)
   172  			network.GenerateConfigTree()
   173  			network.Bootstrap()
   174  
   175  			orderer := network.Orderer("orderer")
   176  			runner := network.OrdererRunner(orderer)
   177  			process = ifrit.Invoke(runner)
   178  			Eventually(process.Ready, network.EventuallyTimeout).Should(BeClosed())
   179  			defer func() {
   180  				process.Signal(syscall.SIGTERM)
   181  				Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive())
   182  			}()
   183  
   184  			By("Waiting for system channel to be ready")
   185  			findLeader([]*ginkgomon.Runner{runner})
   186  
   187  			By("Creating malformed channel creation config tx")
   188  			channel := "testchannel"
   189  			sysProfile = genesisconfig.Load(network.SystemChannel.Profile, network.RootDir)
   190  			Expect(sysProfile.Orderer).NotTo(BeNil())
   191  			appProfile := genesisconfig.Load(network.ProfileForChannel(channel), network.RootDir)
   192  			Expect(appProfile).NotTo(BeNil())
   193  			o := *sysProfile.Orderer
   194  			appProfile.Orderer = &o
   195  			appProfile.Orderer.EtcdRaft = proto.Clone(sysProfile.Orderer.EtcdRaft).(*etcdraft.ConfigMetadata)
   196  			appProfile.Orderer.EtcdRaft.Options.HeartbeatTick = appProfile.Orderer.EtcdRaft.Options.ElectionTick
   197  			configtx, err := encoder.MakeChannelCreationTransactionWithSystemChannelContext(channel, nil, appProfile, sysProfile)
   198  			Expect(err).NotTo(HaveOccurred())
   199  			data, err = proto.Marshal(configtx)
   200  			Expect(err).NotTo(HaveOccurred())
   201  			err = ioutil.WriteFile(network.CreateChannelTxPath(channel), data, 0644)
   202  			Expect(err).NotTo(HaveOccurred())
   203  
   204  			By("Submitting malformed channel creation config tx to orderer")
   205  			org1Peer0 := network.Peer("Org1", "peer0")
   206  			org2Peer0 := network.Peer("Org2", "peer0")
   207  
   208  			exitCode := network.CreateChannelExitCode(channel, orderer, org1Peer0, org1Peer0, org2Peer0, orderer)
   209  			Expect(exitCode).NotTo(Equal(0))
   210  			Consistently(process.Wait).ShouldNot(Receive()) // malformed tx should not crash orderer
   211  			Expect(runner.Err()).To(gbytes.Say(`invalid new config metadata: ElectionTick \(10\) must be greater than HeartbeatTick \(10\)`))
   212  
   213  			By("Submitting channel config update with illegal value")
   214  			channel = network.SystemChannel.Name
   215  			config := nwo.GetConfig(network, org1Peer0, orderer, channel)
   216  			updatedConfig := proto.Clone(config).(*common.Config)
   217  
   218  			consensusTypeConfigValue := updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"]
   219  			consensusTypeValue := &protosorderer.ConsensusType{}
   220  			Expect(proto.Unmarshal(consensusTypeConfigValue.Value, consensusTypeValue)).To(Succeed())
   221  
   222  			metadata := &etcdraft.ConfigMetadata{}
   223  			Expect(proto.Unmarshal(consensusTypeValue.Metadata, metadata)).To(Succeed())
   224  
   225  			metadata.Options.HeartbeatTick = 10
   226  			metadata.Options.ElectionTick = 10
   227  
   228  			newMetadata, err := proto.Marshal(metadata)
   229  			Expect(err).NotTo(HaveOccurred())
   230  			consensusTypeValue.Metadata = newMetadata
   231  
   232  			updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"] = &common.ConfigValue{
   233  				ModPolicy: "Admins",
   234  				Value:     protoutil.MarshalOrPanic(consensusTypeValue),
   235  			}
   236  
   237  			sess := nwo.UpdateOrdererConfigSession(network, orderer, channel, config, updatedConfig, org1Peer0, orderer)
   238  			Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   239  			Expect(sess.Err).To(gbytes.Say(`invalid new config metadata: ElectionTick \(10\) must be greater than HeartbeatTick \(10\)`))
   240  		})
   241  	})
   242  
   243  	When("a single node cluster is expanded", func() {
   244  		It("is still possible to onboard the new cluster member and then another one with a different TLS root CA", func() {
   245  			launch := func(o *nwo.Orderer) {
   246  				runner := network.OrdererRunner(o)
   247  				ordererRunners = append(ordererRunners, runner)
   248  
   249  				process := ifrit.Invoke(runner)
   250  				Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
   251  				ordererProcesses = append(ordererProcesses, process)
   252  			}
   253  
   254  			network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components)
   255  			network.GenerateConfigTree()
   256  			network.Bootstrap()
   257  
   258  			orderer := network.Orderer("orderer")
   259  			peer = network.Peer("Org1", "peer0")
   260  
   261  			By("Launching the orderer")
   262  			launch(orderer)
   263  
   264  			By("Checking that it elected itself as a leader")
   265  			findLeader(ordererRunners)
   266  
   267  			By("Extending the network configuration to add a new orderer")
   268  			orderer2 := &nwo.Orderer{
   269  				Name:         "orderer2",
   270  				Organization: "OrdererOrg",
   271  			}
   272  			ports := nwo.Ports{}
   273  			for _, portName := range nwo.OrdererPortNames() {
   274  				ports[portName] = network.ReservePort()
   275  			}
   276  			network.PortsByOrdererID[orderer2.ID()] = ports
   277  			network.Orderers = append(network.Orderers, orderer2)
   278  			network.GenerateOrdererConfig(orderer2)
   279  			extendNetwork(network)
   280  
   281  			secondOrdererCertificatePath := filepath.Join(network.OrdererLocalTLSDir(orderer2), "server.crt")
   282  			secondOrdererCertificate, err := ioutil.ReadFile(secondOrdererCertificatePath)
   283  			Expect(err).NotTo(HaveOccurred())
   284  
   285  			By("Adding the second orderer")
   286  			addConsenter(network, peer, orderer, "systemchannel", etcdraft.Consenter{
   287  				ServerTlsCert: secondOrdererCertificate,
   288  				ClientTlsCert: secondOrdererCertificate,
   289  				Host:          "127.0.0.1",
   290  				Port:          uint32(network.OrdererPort(orderer2, nwo.ClusterPort)),
   291  			})
   292  
   293  			By("Obtaining the last config block from the orderer")
   294  			// Get the last config block of the system channel
   295  			configBlock := nwo.GetConfigBlock(network, peer, orderer, "systemchannel")
   296  			// Plant it in the file system of orderer2, the new node to be onboarded.
   297  			err = ioutil.WriteFile(filepath.Join(testDir, "systemchannel_block.pb"), protoutil.MarshalOrPanic(configBlock), 0644)
   298  			Expect(err).NotTo(HaveOccurred())
   299  
   300  			By("Waiting for the existing orderer to relinquish its leadership")
   301  			Eventually(ordererRunners[0].Err(), network.EventuallyTimeout).Should(gbytes.Say("1 stepped down to follower since quorum is not active"))
   302  			Eventually(ordererRunners[0].Err(), network.EventuallyTimeout).Should(gbytes.Say("No leader is present, cluster size is 2"))
   303  			By("Launching the second orderer")
   304  			launch(orderer2)
   305  			By("Waiting for a leader to be re-elected")
   306  			findLeader(ordererRunners)
   307  
   308  			// In the next part of the test we're going to bring up a third node
   309  			// with a different TLS root CA. We're then going to remove the TLS
   310  			// root CA and restart the orderer, to ensure that we can dynamically
   311  			// update TLS root CAs in Raft while membership stays the same.
   312  
   313  			By("Creating configuration for a third orderer with a different TLS root CA")
   314  			orderer3 := &nwo.Orderer{
   315  				Name:         "orderer3",
   316  				Organization: "OrdererOrg",
   317  			}
   318  			ports = nwo.Ports{}
   319  			for _, portName := range nwo.OrdererPortNames() {
   320  				ports[portName] = network.ReservePort()
   321  			}
   322  			network.PortsByOrdererID[orderer3.ID()] = ports
   323  			network.Orderers = append(network.Orderers, orderer3)
   324  			network.GenerateOrdererConfig(orderer3)
   325  
   326  			tmpDir, err := ioutil.TempDir("", "e2e-etcfraft_reconfig")
   327  			Expect(err).NotTo(HaveOccurred())
   328  			defer os.RemoveAll(tmpDir)
   329  
   330  			sess, err := network.Cryptogen(commands.Generate{
   331  				Config: network.CryptoConfigPath(),
   332  				Output: tmpDir,
   333  			})
   334  			Expect(err).NotTo(HaveOccurred())
   335  			Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   336  
   337  			name := network.Orderers[0].Name
   338  			domain := network.Organization(network.Orderers[0].Organization).Domain
   339  			nameDomain := fmt.Sprintf("%s.%s", name, domain)
   340  			ordererTLSPath := filepath.Join(tmpDir, "ordererOrganizations", domain, "orderers", nameDomain, "tls")
   341  
   342  			caCertPath := filepath.Join(tmpDir, "ordererOrganizations", domain, "tlsca", fmt.Sprintf("tlsca.%s-cert.pem", domain))
   343  
   344  			caCert, err := ioutil.ReadFile(caCertPath)
   345  			Expect(err).NotTo(HaveOccurred())
   346  
   347  			thirdOrdererCertificatePath := filepath.Join(ordererTLSPath, "server.crt")
   348  			thirdOrdererCertificate, err := ioutil.ReadFile(thirdOrdererCertificatePath)
   349  			Expect(err).NotTo(HaveOccurred())
   350  
   351  			By("Updating it on the file system")
   352  			err = ioutil.WriteFile(caCertPath, caCert, 0644)
   353  			Expect(err).NotTo(HaveOccurred())
   354  			err = ioutil.WriteFile(thirdOrdererCertificatePath, thirdOrdererCertificate, 0644)
   355  			Expect(err).NotTo(HaveOccurred())
   356  
   357  			By("Overwriting the TLS directory of the new orderer")
   358  			for _, fileName := range []string{"server.crt", "server.key", "ca.crt"} {
   359  				dst := filepath.Join(network.OrdererLocalTLSDir(orderer3), fileName)
   360  
   361  				data, err := ioutil.ReadFile(filepath.Join(ordererTLSPath, fileName))
   362  				Expect(err).NotTo(HaveOccurred())
   363  
   364  				err = ioutil.WriteFile(dst, data, 0644)
   365  				Expect(err).NotTo(HaveOccurred())
   366  			}
   367  
   368  			By("Obtaining the last config block from the orderer once more to update the bootstrap file")
   369  			configBlock = nwo.GetConfigBlock(network, peer, orderer, "systemchannel")
   370  			err = ioutil.WriteFile(filepath.Join(testDir, "systemchannel_block.pb"), protoutil.MarshalOrPanic(configBlock), 0644)
   371  			Expect(err).NotTo(HaveOccurred())
   372  
   373  			By("Launching orderer3")
   374  			launch(orderer3)
   375  
   376  			By("Expanding the TLS root CA certificates and adding orderer3 to the channel")
   377  			updateOrdererMSPAndConsensusMetadata(network, peer, orderer, "systemchannel", "OrdererOrg", func(config msp.FabricMSPConfig) msp.FabricMSPConfig {
   378  				config.TlsRootCerts = append(config.TlsRootCerts, caCert)
   379  				return config
   380  			},
   381  				func(metadata *etcdraft.ConfigMetadata) {
   382  					metadata.Consenters = append(metadata.Consenters, &etcdraft.Consenter{
   383  						ServerTlsCert: thirdOrdererCertificate,
   384  						ClientTlsCert: thirdOrdererCertificate,
   385  						Host:          "127.0.0.1",
   386  						Port:          uint32(network.OrdererPort(orderer3, nwo.ClusterPort)),
   387  					})
   388  				},
   389  			)
   390  
   391  			By("Waiting for orderer3 to see the leader")
   392  			findLeader([]*ginkgomon.Runner{ordererRunners[2]})
   393  
   394  			By("Attemping to add a consenter with invalid certs")
   395  			// create new certs that are not in the channel config
   396  			ca, err := tlsgen.NewCA()
   397  			Expect(err).NotTo(HaveOccurred())
   398  			client, err := ca.NewClientCertKeyPair()
   399  			Expect(err).NotTo(HaveOccurred())
   400  
   401  			newConsenterCertPem, _ := pem.Decode(client.Cert)
   402  			newConsenterCert, err := x509.ParseCertificate(newConsenterCertPem.Bytes)
   403  			Expect(err).NotTo(HaveOccurred())
   404  
   405  			current, updated := consenterAdder(
   406  				network,
   407  				peer,
   408  				orderer,
   409  				"systemchannel",
   410  				etcdraft.Consenter{
   411  					ServerTlsCert: client.Cert,
   412  					ClientTlsCert: client.Cert,
   413  					Host:          "127.0.0.1",
   414  					Port:          uint32(network.OrdererPort(orderer3, nwo.ListenPort)),
   415  				},
   416  			)
   417  			sess = nwo.UpdateOrdererConfigSession(network, orderer, network.SystemChannel.Name, current, updated, peer, orderer)
   418  			Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   419  			Expect(sess.Err).To(gbytes.Say(fmt.Sprintf("BAD_REQUEST -- error applying config update to existing channel 'systemchannel': consensus metadata update for channel config update is invalid: invalid new config metadata: verifying tls client cert with serial number %d: x509: certificate signed by unknown authority", newConsenterCert.SerialNumber)))
   420  		})
   421  	})
   422  
   423  	When("a single node cluster has the tick interval overridden", func() {
   424  		It("reflects this in its startup logs", func() {
   425  			network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components)
   426  			network.GenerateConfigTree()
   427  			network.Bootstrap()
   428  
   429  			orderer := network.Orderer("orderer")
   430  			ordererConfig := network.ReadOrdererConfig(orderer)
   431  			ordererConfig.Consensus["TickIntervalOverride"] = "642ms"
   432  			network.WriteOrdererConfig(orderer, ordererConfig)
   433  
   434  			By("Launching the orderer")
   435  			runner := network.OrdererRunner(orderer)
   436  			ordererRunners = append(ordererRunners, runner)
   437  
   438  			process := ifrit.Invoke(runner)
   439  			Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
   440  			ordererProcesses = append(ordererProcesses, process)
   441  
   442  			Eventually(runner.Err()).Should(gbytes.Say("TickIntervalOverride is set, overriding channel configuration tick interval to 642ms"))
   443  
   444  		})
   445  	})
   446  
   447  	When("the orderer certificates are all rotated", func() {
   448  		It("is possible to rotate certificate by adding & removing cert in single config", func() {
   449  			layout := nwo.MultiNodeEtcdRaft()
   450  			network = nwo.New(layout, testDir, client, StartPort(), components)
   451  			network.GenerateConfigTree()
   452  			network.Bootstrap()
   453  
   454  			o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3")
   455  			orderers := []*nwo.Orderer{o1, o2, o3}
   456  			peer = network.Peer("Org1", "peer0")
   457  
   458  			By("Launching the orderers")
   459  			for _, o := range orderers {
   460  				runner := network.OrdererRunner(o)
   461  				ordererRunners = append(ordererRunners, runner)
   462  				process := ifrit.Invoke(runner)
   463  				ordererProcesses = append(ordererProcesses, process)
   464  			}
   465  
   466  			for _, ordererProc := range ordererProcesses {
   467  				Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed())
   468  			}
   469  
   470  			By("Finding leader")
   471  			leader := findLeader(ordererRunners)
   472  			leaderIndex := leader - 1
   473  			blockSeq := 0
   474  
   475  			By("Checking that all orderers are online")
   476  			assertBlockReception(map[string]int{
   477  				"systemchannel": blockSeq,
   478  			}, orderers, peer, network)
   479  
   480  			By("Preparing new certificates for the orderer nodes")
   481  			extendNetwork(network)
   482  			certificateRotations := refreshOrdererPEMs(network)
   483  
   484  			swap := func(o *nwo.Orderer, certificate []byte, c etcdraft.Consenter) {
   485  				updateEtcdRaftMetadata(network, peer, o, network.SystemChannel.Name, func(metadata *etcdraft.ConfigMetadata) {
   486  					var newConsenters []*etcdraft.Consenter
   487  					for _, consenter := range metadata.Consenters {
   488  						if bytes.Equal(consenter.ClientTlsCert, certificate) || bytes.Equal(consenter.ServerTlsCert, certificate) {
   489  							continue
   490  						}
   491  						newConsenters = append(newConsenters, consenter)
   492  					}
   493  					newConsenters = append(newConsenters, &c)
   494  
   495  					metadata.Consenters = newConsenters
   496  				})
   497  				blockSeq++
   498  			}
   499  
   500  			rotate := func(target int) {
   501  				// submit a config tx to rotate the cert of an orderer.
   502  				// The orderer being rotated is going to be unavailable
   503  				// eventually, therefore submitter of tx is different
   504  				// from the target, so the configuration can be reliably
   505  				// checked.
   506  				submitter := (target + 1) % 3
   507  				rotation := certificateRotations[target]
   508  				targetOrderer := network.Orderers[target]
   509  				remainder := func() []*nwo.Orderer {
   510  					var ret []*nwo.Orderer
   511  					for i, o := range network.Orderers {
   512  						if i == target {
   513  							continue
   514  						}
   515  						ret = append(ret, o)
   516  					}
   517  					return ret
   518  				}()
   519  				submitterOrderer := network.Orderers[submitter]
   520  				port := network.OrdererPort(targetOrderer, nwo.ClusterPort)
   521  
   522  				fmt.Fprintf(GinkgoWriter, "Rotating certificate of orderer node %d\n", target+1)
   523  				swap(submitterOrderer, rotation.oldCert, etcdraft.Consenter{
   524  					ServerTlsCert: rotation.newCert,
   525  					ClientTlsCert: rotation.newCert,
   526  					Host:          "127.0.0.1",
   527  					Port:          uint32(port),
   528  				})
   529  
   530  				By("Waiting for all orderers to sync")
   531  				assertBlockReception(map[string]int{
   532  					"systemchannel": blockSeq,
   533  				}, remainder, peer, network)
   534  
   535  				By("Waiting for rotated node to be unavailable")
   536  				c := commands.ChannelFetch{
   537  					ChannelID:  network.SystemChannel.Name,
   538  					Block:      "newest",
   539  					OutputFile: "/dev/null",
   540  					Orderer:    network.OrdererAddress(targetOrderer, nwo.ClusterPort),
   541  				}
   542  				Eventually(func() string {
   543  					sess, err := network.OrdererAdminSession(targetOrderer, peer, c)
   544  					Expect(err).NotTo(HaveOccurred())
   545  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit())
   546  					if sess.ExitCode() != 0 {
   547  						return fmt.Sprintf("exit code is %d: %s", sess.ExitCode(), string(sess.Err.Contents()))
   548  					}
   549  					sessErr := string(sess.Err.Contents())
   550  					expected := fmt.Sprintf("Received block: %d", blockSeq)
   551  					if strings.Contains(sessErr, expected) {
   552  						return ""
   553  					}
   554  					return sessErr
   555  				}, network.EventuallyTimeout, time.Second).ShouldNot(BeEmpty())
   556  
   557  				By("Killing the orderer")
   558  				ordererProcesses[target].Signal(syscall.SIGTERM)
   559  				Eventually(ordererProcesses[target].Wait(), network.EventuallyTimeout).Should(Receive())
   560  
   561  				By("Starting the orderer again")
   562  				ordererRunner := network.OrdererRunner(targetOrderer)
   563  				ordererRunners = append(ordererRunners, ordererRunner)
   564  				ordererProcesses[target] = ifrit.Invoke(ordererRunner)
   565  				Eventually(ordererProcesses[target].Ready(), network.EventuallyTimeout).Should(BeClosed())
   566  
   567  				By("And waiting for it to stabilize")
   568  				assertBlockReception(map[string]int{
   569  					"systemchannel": blockSeq,
   570  				}, orderers, peer, network)
   571  			}
   572  
   573  			By(fmt.Sprintf("Rotating cert on leader %d", leader))
   574  			rotate(leaderIndex)
   575  
   576  			By("Rotating certificates of other orderer nodes")
   577  			for i := range certificateRotations {
   578  				if i != leaderIndex {
   579  					rotate(i)
   580  				}
   581  			}
   582  		})
   583  
   584  		It("is still possible to onboard new orderers", func() {
   585  			// In this test, we have 3 OSNs and we rotate their TLS certificates one by one,
   586  			// by adding the future certificate to the channel, killing the OSN to make it
   587  			// grab the new certificate, and then removing the old certificate from the channel.
   588  
   589  			// After we completely rotate all the certificates, we put the last config block
   590  			// of the system channel into the file system of orderer4, and then launch it,
   591  			// and ensure it onboards and pulls channels testchannel only, and not testchannel2
   592  			// which it is not part of.
   593  
   594  			// Consenter i after its certificate is rotated is denoted as consenter i'
   595  			// The blocks of channels contain the following updates:
   596  			//    | system channel height | testchannel  height  | update description
   597  			// ------------------------------------------------------------------------
   598  			// 0  |            2          |         1            | adding consenter 1'
   599  			// 1  |            3          |         2            | removing consenter 1
   600  			// 2  |            4          |         3            | adding consenter 2'
   601  			// 3  |            5          |         4            | removing consenter 2
   602  			// 4  |            6          |         5            | adding consenter 3'
   603  			// 5  |            7          |         6            | removing consenter 3
   604  			// 6  |            8          |         6            | creating channel testchannel2
   605  			// 7  |            9          |         6            | creating channel testchannel3
   606  			// 8  |            10         |         7            | adding consenter 4
   607  
   608  			layout := nwo.MultiNodeEtcdRaft()
   609  			layout.Channels = append(layout.Channels, &nwo.Channel{
   610  				Name:    "testchannel2",
   611  				Profile: "TwoOrgsChannel",
   612  			}, &nwo.Channel{
   613  				Name:    "testchannel3",
   614  				Profile: "TwoOrgsChannel",
   615  			})
   616  
   617  			network = nwo.New(layout, testDir, client, StartPort(), components)
   618  			network.GenerateConfigTree()
   619  			network.Bootstrap()
   620  
   621  			o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3")
   622  			orderers := []*nwo.Orderer{o1, o2, o3}
   623  			peer = network.Peer("Org1", "peer0")
   624  
   625  			By("Launching the orderers")
   626  			for _, o := range orderers {
   627  				runner := network.OrdererRunner(o)
   628  				ordererRunners = append(ordererRunners, runner)
   629  				process := ifrit.Invoke(runner)
   630  				ordererProcesses = append(ordererProcesses, process)
   631  			}
   632  
   633  			for _, ordererProc := range ordererProcesses {
   634  				Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed())
   635  			}
   636  
   637  			By("Checking that all orderers are online")
   638  			assertBlockReception(map[string]int{
   639  				"systemchannel": 0,
   640  			}, orderers, peer, network)
   641  
   642  			By("Creating a channel and checking that all orderers got the channel creation")
   643  			network.CreateChannel("testchannel", network.Orderers[0], peer)
   644  			assertBlockReception(map[string]int{
   645  				"systemchannel": 1,
   646  				"testchannel":   0,
   647  			}, orderers, peer, network)
   648  
   649  			By("Preparing new certificates for the orderer nodes")
   650  			extendNetwork(network)
   651  			certificateRotations := refreshOrdererPEMs(network)
   652  
   653  			expectedBlockHeightsPerChannel := []map[string]int{
   654  				{"systemchannel": 2, "testchannel": 1},
   655  				{"systemchannel": 3, "testchannel": 2},
   656  				{"systemchannel": 4, "testchannel": 3},
   657  				{"systemchannel": 5, "testchannel": 4},
   658  				{"systemchannel": 6, "testchannel": 5},
   659  				{"systemchannel": 7, "testchannel": 6},
   660  			}
   661  
   662  			for i, rotation := range certificateRotations {
   663  				o := network.Orderers[i]
   664  				port := network.OrdererPort(o, nwo.ClusterPort)
   665  
   666  				By(fmt.Sprintf("Adding the future certificate of orderer node %d", i))
   667  				for _, channelName := range []string{"systemchannel", "testchannel"} {
   668  					addConsenter(network, peer, o, channelName, etcdraft.Consenter{
   669  						ServerTlsCert: rotation.newCert,
   670  						ClientTlsCert: rotation.newCert,
   671  						Host:          "127.0.0.1",
   672  						Port:          uint32(port),
   673  					})
   674  				}
   675  
   676  				By("Waiting for all orderers to sync")
   677  				assertBlockReception(expectedBlockHeightsPerChannel[i*2], orderers, peer, network)
   678  
   679  				By("Killing the orderer")
   680  				ordererProcesses[i].Signal(syscall.SIGTERM)
   681  				Eventually(ordererProcesses[i].Wait(), network.EventuallyTimeout).Should(Receive())
   682  
   683  				By("Starting the orderer again")
   684  				ordererRunner := network.OrdererRunner(orderers[i])
   685  				ordererRunners = append(ordererRunners, ordererRunner)
   686  				ordererProcesses[i] = ifrit.Invoke(ordererRunner)
   687  				Eventually(ordererProcesses[i].Ready(), network.EventuallyTimeout).Should(BeClosed())
   688  
   689  				By("And waiting for it to stabilize")
   690  				assertBlockReception(expectedBlockHeightsPerChannel[i*2], orderers, peer, network)
   691  
   692  				By("Removing the previous certificate of the old orderer")
   693  				for _, channelName := range []string{"systemchannel", "testchannel"} {
   694  					removeConsenter(network, peer, network.Orderers[(i+1)%len(network.Orderers)], channelName, rotation.oldCert)
   695  				}
   696  
   697  				By("Waiting for all orderers to sync")
   698  				assertBlockReception(expectedBlockHeightsPerChannel[i*2+1], orderers, peer, network)
   699  			}
   700  
   701  			By("Creating testchannel2")
   702  			network.CreateChannel("testchannel2", network.Orderers[0], peer)
   703  			assertBlockReception(map[string]int{
   704  				"systemchannel": 8,
   705  			}, orderers, peer, network)
   706  
   707  			By("Creating testchannel3")
   708  			network.CreateChannel("testchannel3", network.Orderers[0], peer)
   709  			assertBlockReception(map[string]int{
   710  				"systemchannel": 9,
   711  			}, orderers, peer, network)
   712  
   713  			o4 := &nwo.Orderer{
   714  				Name:         "orderer4",
   715  				Organization: "OrdererOrg",
   716  			}
   717  
   718  			By("Configuring orderer4 in the network")
   719  			ports := nwo.Ports{}
   720  			for _, portName := range nwo.OrdererPortNames() {
   721  				ports[portName] = network.ReservePort()
   722  			}
   723  			network.PortsByOrdererID[o4.ID()] = ports
   724  
   725  			network.Orderers = append(network.Orderers, o4)
   726  			network.GenerateOrdererConfig(network.Orderer("orderer4"))
   727  
   728  			By("Adding orderer4 to the channels")
   729  			orderer4CertificatePath := filepath.Join(network.OrdererLocalTLSDir(o4), "server.crt")
   730  			orderer4Certificate, err := ioutil.ReadFile(orderer4CertificatePath)
   731  			Expect(err).NotTo(HaveOccurred())
   732  			for _, channel := range []string{"systemchannel", "testchannel"} {
   733  				addConsenter(network, peer, o1, channel, etcdraft.Consenter{
   734  					ServerTlsCert: orderer4Certificate,
   735  					ClientTlsCert: orderer4Certificate,
   736  					Host:          "127.0.0.1",
   737  					Port:          uint32(network.OrdererPort(o4, nwo.ClusterPort)),
   738  				})
   739  			}
   740  
   741  			By("Ensuring all orderers know about orderer4's addition")
   742  			assertBlockReception(map[string]int{
   743  				"systemchannel": 10,
   744  				"testchannel":   7,
   745  			}, orderers, peer, network)
   746  
   747  			By("Broadcasting envelope to testchannel")
   748  			env := CreateBroadcastEnvelope(network, peer, "testchannel", []byte("hello"))
   749  			resp, err := nwo.Broadcast(network, o1, env)
   750  			Expect(err).NotTo(HaveOccurred())
   751  			Expect(resp.Status).To(Equal(common.Status_SUCCESS))
   752  
   753  			assertBlockReception(map[string]int{
   754  				"testchannel": 8,
   755  			}, orderers, peer, network)
   756  
   757  			By("Corrupting the readers policy of testchannel3")
   758  			revokeReaderAccess(network, "testchannel3", o3, peer)
   759  
   760  			// Get the last config block of the system channel
   761  			configBlock := nwo.GetConfigBlock(network, peer, o1, "systemchannel")
   762  			// Plant it in the file system of orderer4, the new node to be onboarded.
   763  			err = ioutil.WriteFile(filepath.Join(testDir, "systemchannel_block.pb"), protoutil.MarshalOrPanic(configBlock), 0644)
   764  			Expect(err).NotTo(HaveOccurred())
   765  
   766  			By("Launching orderer4")
   767  			orderers = append(orderers, o4)
   768  			orderer4Runner := network.OrdererRunner(o4)
   769  			ordererRunners = append(ordererRunners, orderer4Runner)
   770  			// Spawn orderer4's process
   771  			o4process := ifrit.Invoke(orderer4Runner)
   772  			Eventually(o4process.Ready(), network.EventuallyTimeout).Should(BeClosed())
   773  			ordererProcesses = append(ordererProcesses, o4process)
   774  
   775  			By("And waiting for it to sync with the rest of the orderers")
   776  			assertBlockReception(map[string]int{
   777  				"systemchannel": 10,
   778  				"testchannel":   8,
   779  			}, orderers, peer, network)
   780  
   781  			By("Ensuring orderer4 doesn't serve testchannel2 and testchannel3")
   782  			env = CreateBroadcastEnvelope(network, peer, "testchannel2", []byte("hello"))
   783  			resp, err = nwo.Broadcast(network, o4, env)
   784  			Expect(err).NotTo(HaveOccurred())
   785  			Expect(resp.Status).To(Equal(common.Status_SERVICE_UNAVAILABLE))
   786  
   787  			env = CreateBroadcastEnvelope(network, peer, "testchannel3", []byte("hello"))
   788  			resp, err = nwo.Broadcast(network, o4, env)
   789  			Expect(err).NotTo(HaveOccurred())
   790  			Expect(resp.Status).To(Equal(common.Status_SERVICE_UNAVAILABLE))
   791  
   792  			belongRegex := `\QI do not belong to channel testchannel2 or am forbidden pulling it (not in the channel), skipping chain retrieval\E`
   793  			forbiddenRegex := `\QI do not belong to channel testchannel3 or am forbidden pulling it (forbidden pulling the channel), skipping chain retrieval\E`
   794  
   795  			Expect(orderer4Runner.Err()).To(gbytes.Say(belongRegex + "|" + forbiddenRegex))
   796  			Expect(orderer4Runner.Err()).To(gbytes.Say(belongRegex + "|" + forbiddenRegex))
   797  
   798  			By("Adding orderer4 to testchannel2")
   799  			addConsenter(network, peer, o1, "testchannel2", etcdraft.Consenter{
   800  				ServerTlsCert: orderer4Certificate,
   801  				ClientTlsCert: orderer4Certificate,
   802  				Host:          "127.0.0.1",
   803  				Port:          uint32(network.OrdererPort(o4, nwo.ClusterPort)),
   804  			})
   805  
   806  			By("Waiting for orderer4 and to replicate testchannel2")
   807  			assertBlockReception(map[string]int{
   808  				"testchannel2": 1,
   809  			}, []*nwo.Orderer{o4}, peer, network)
   810  
   811  			By("Ensuring orderer4 doesn't have any errors in the logs")
   812  			Consistently(orderer4Runner.Err()).ShouldNot(gbytes.Say("ERRO"))
   813  
   814  			By("Submitting a transaction through orderer4")
   815  			env = CreateBroadcastEnvelope(network, peer, "testchannel2", []byte("hello"))
   816  			resp, err = nwo.Broadcast(network, o4, env)
   817  			Expect(err).NotTo(HaveOccurred())
   818  			Expect(resp.Status).To(Equal(common.Status_SUCCESS))
   819  
   820  			By("And ensuring it is propagated amongst all orderers")
   821  			assertBlockReception(map[string]int{
   822  				"testchannel2": 2,
   823  			}, orderers, peer, network)
   824  		})
   825  	})
   826  
   827  	When("an orderer channel is created with a subset of nodes", func() {
   828  		It("is still possible to onboard a new orderer to the channel", func() {
   829  			network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components)
   830  			network.Profiles = append(network.Profiles, &nwo.Profile{
   831  				Name:          "myprofile",
   832  				Consortium:    "SampleConsortium",
   833  				Orderers:      []string{"orderer1"},
   834  				Organizations: []string{"Org1"},
   835  			})
   836  			network.Channels = append(network.Channels, &nwo.Channel{
   837  				Name:        "mychannel",
   838  				Profile:     "myprofile",
   839  				BaseProfile: "SampleDevModeEtcdRaft",
   840  			})
   841  
   842  			network.GenerateConfigTree()
   843  			network.Bootstrap()
   844  
   845  			o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3")
   846  			orderers := []*nwo.Orderer{o1, o2, o3}
   847  			peer = network.Peer("Org1", "peer0")
   848  
   849  			By("Launching the orderers")
   850  			for _, o := range orderers {
   851  				runner := network.OrdererRunner(o)
   852  				ordererRunners = append(ordererRunners, runner)
   853  				process := ifrit.Invoke(runner)
   854  				ordererProcesses = append(ordererProcesses, process)
   855  			}
   856  
   857  			for _, ordererProc := range ordererProcesses {
   858  				Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed())
   859  			}
   860  
   861  			By("Waiting for the system channel to be available")
   862  			assertBlockReception(map[string]int{
   863  				"systemchannel": 0,
   864  			}, orderers, peer, network)
   865  
   866  			By("Creating a channel with a subset of orderers")
   867  			network.CreateChannel("mychannel", o1, peer, peer, o1)
   868  
   869  			By("Waiting for the channel to be available")
   870  			assertBlockReception(map[string]int{
   871  				"mychannel": 0,
   872  			}, []*nwo.Orderer{o1}, peer, network)
   873  
   874  			By("Ensuring only orderer1 services the channel")
   875  			ensureEvicted(o2, peer, network, "mychannel")
   876  			ensureEvicted(o3, peer, network, "mychannel")
   877  
   878  			By("Adding orderer2 to the channel")
   879  			ordererCertificatePath := filepath.Join(network.OrdererLocalTLSDir(o2), "server.crt")
   880  			ordererCertificate, err := ioutil.ReadFile(ordererCertificatePath)
   881  			Expect(err).NotTo(HaveOccurred())
   882  
   883  			addConsenter(network, peer, o1, "mychannel", etcdraft.Consenter{
   884  				ServerTlsCert: ordererCertificate,
   885  				ClientTlsCert: ordererCertificate,
   886  				Host:          "127.0.0.1",
   887  				Port:          uint32(network.OrdererPort(o2, nwo.ClusterPort)),
   888  			})
   889  
   890  			By("Waiting for orderer2 to join the channel")
   891  			assertBlockReception(map[string]int{
   892  				"mychannel": 1,
   893  			}, []*nwo.Orderer{o1, o2}, peer, network)
   894  
   895  			By("Adding orderer3 to the channel")
   896  			ordererCertificatePath = filepath.Join(network.OrdererLocalTLSDir(o3), "server.crt")
   897  			ordererCertificate, err = ioutil.ReadFile(ordererCertificatePath)
   898  			Expect(err).NotTo(HaveOccurred())
   899  			addConsenter(network, peer, o1, "mychannel", etcdraft.Consenter{
   900  				ServerTlsCert: ordererCertificate,
   901  				ClientTlsCert: ordererCertificate,
   902  				Host:          "127.0.0.1",
   903  				Port:          uint32(network.OrdererPort(o3, nwo.ClusterPort)),
   904  			})
   905  
   906  			By("Waiting for orderer3 to join the channel")
   907  			assertBlockReception(map[string]int{
   908  				"mychannel": 2,
   909  			}, orderers, peer, network)
   910  		})
   911  	})
   912  
   913  	When("orderer cluster is not healthy", func() {
   914  		var (
   915  			o1, o2 *nwo.Orderer
   916  		)
   917  
   918  		BeforeEach(func() {
   919  			network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components)
   920  			network.GenerateConfigTree()
   921  			network.Bootstrap()
   922  
   923  			o1, o2 = network.Orderer("orderer1"), network.Orderer("orderer2")
   924  			orderers := []*nwo.Orderer{o1, o2}
   925  			By("Launching the orderers")
   926  			for _, o := range orderers {
   927  				runner := network.OrdererRunner(o)
   928  				ordererRunners = append(ordererRunners, runner)
   929  				process := ifrit.Invoke(runner)
   930  				ordererProcesses = append(ordererProcesses, process)
   931  			}
   932  
   933  			for _, ordererProc := range ordererProcesses {
   934  				Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed())
   935  			}
   936  		})
   937  
   938  		AfterEach(func() {
   939  			for _, ordererInstance := range ordererProcesses {
   940  				ordererInstance.Signal(syscall.SIGTERM)
   941  				Eventually(ordererInstance.Wait(), network.EventuallyTimeout).Should(Receive())
   942  			}
   943  		})
   944  
   945  		It("refuses to reconfig if it results in quorum loss", func() {
   946  			By("Waiting for them to elect a leader")
   947  			findLeader(ordererRunners)
   948  
   949  			extendNetwork(network)
   950  			certificatesOfOrderers := refreshOrdererPEMs(network)
   951  
   952  			By("Removing alive node from 2/3 cluster")
   953  			peer := network.Peer("Org1", "peer0")
   954  			current, updated := consenterRemover(network, peer, o2, network.SystemChannel.Name, certificatesOfOrderers[1].oldCert)
   955  			Eventually(func() []byte {
   956  				sess := nwo.UpdateOrdererConfigSession(network, o2, network.SystemChannel.Name, current, updated, peer, o2)
   957  				Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   958  				return sess.Err.Contents()
   959  			}, network.EventuallyTimeout).Should(ContainSubstring("2 out of 3 nodes are alive, configuration will result in quorum loss"))
   960  
   961  			By("Adding node to 2/3 cluster")
   962  			current, updated = consenterAdder(
   963  				network,
   964  				peer,
   965  				o2,
   966  				network.SystemChannel.Name,
   967  				etcdraft.Consenter{
   968  					ServerTlsCert: certificatesOfOrderers[0].newCert,
   969  					ClientTlsCert: certificatesOfOrderers[0].newCert,
   970  					Host:          "127.0.0.1",
   971  					Port:          uint32(network.OrdererPort(o1, nwo.ListenPort)),
   972  				},
   973  			)
   974  			sess := nwo.UpdateOrdererConfigSession(network, o2, network.SystemChannel.Name, current, updated, peer, o2)
   975  			Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   976  			Expect(string(sess.Err.Contents())).To(ContainSubstring("2 out of 3 nodes are alive, configuration will result in quorum loss"))
   977  		})
   978  	})
   979  
   980  	When("an orderer node is evicted", func() {
   981  		BeforeEach(func() {
   982  			ordererRunners = nil
   983  			ordererProcesses = nil
   984  
   985  			network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components)
   986  			network.GenerateConfigTree()
   987  			network.Bootstrap()
   988  
   989  			o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3")
   990  			orderers := []*nwo.Orderer{o1, o2, o3}
   991  			peer = network.Peer("Org1", "peer0")
   992  
   993  			By("Launching the orderers")
   994  			for _, o := range orderers {
   995  				runner := network.OrdererRunner(o, "FABRIC_LOGGING_SPEC=orderer.consensus.etcdraft=debug:info")
   996  				ordererRunners = append(ordererRunners, runner)
   997  				process := ifrit.Invoke(runner)
   998  				ordererProcesses = append(ordererProcesses, process)
   999  			}
  1000  
  1001  			for _, ordererProc := range ordererProcesses {
  1002  				Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed())
  1003  			}
  1004  		})
  1005  
  1006  		AfterEach(func() {
  1007  			for _, ordererInstance := range ordererProcesses {
  1008  				ordererInstance.Signal(syscall.SIGTERM)
  1009  				Eventually(ordererInstance.Wait(), network.EventuallyTimeout).Should(Receive())
  1010  			}
  1011  		})
  1012  
  1013  		It("doesn't complain and does it obediently", func() {
  1014  			o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3")
  1015  			orderers := []*nwo.Orderer{o1, o2, o3}
  1016  
  1017  			By("Waiting for them to elect a leader")
  1018  			firstEvictedNode := findLeader(ordererRunners) - 1
  1019  
  1020  			By("Removing the leader from 3-node channel")
  1021  			server1CertBytes, err := ioutil.ReadFile(filepath.Join(network.OrdererLocalTLSDir(orderers[firstEvictedNode]), "server.crt"))
  1022  			Expect(err).To(Not(HaveOccurred()))
  1023  
  1024  			removeConsenter(network, peer, network.Orderers[(firstEvictedNode+1)%3], "systemchannel", server1CertBytes)
  1025  
  1026  			var survivedOrdererRunners []*ginkgomon.Runner
  1027  			for i := range orderers {
  1028  				if i == firstEvictedNode {
  1029  					continue
  1030  				}
  1031  
  1032  				survivedOrdererRunners = append(survivedOrdererRunners, ordererRunners[i])
  1033  			}
  1034  
  1035  			secondEvictedNode := findLeader(survivedOrdererRunners) - 1
  1036  
  1037  			var survivor int
  1038  			for i := range orderers {
  1039  				if i != firstEvictedNode && i != secondEvictedNode {
  1040  					survivor = i
  1041  					break
  1042  				}
  1043  			}
  1044  
  1045  			const stopMsg = "Raft node stopped channel=systemchannel"
  1046  			fmt.Fprintln(GinkgoWriter, "Ensuring the evicted orderer stops rafting on channel systemchannel")
  1047  			Eventually(ordererRunners[firstEvictedNode].Err(), network.EventuallyTimeout, time.Second).Should(gbytes.Say(stopMsg))
  1048  
  1049  			By("Ensuring the evicted orderer now doesn't serve clients")
  1050  			ensureEvicted(orderers[firstEvictedNode], peer, network, "systemchannel")
  1051  
  1052  			By("Removing the leader from 2-node channel")
  1053  			server2CertBytes, err := ioutil.ReadFile(filepath.Join(network.OrdererLocalTLSDir(orderers[secondEvictedNode]), "server.crt"))
  1054  			Expect(err).To(Not(HaveOccurred()))
  1055  
  1056  			removeConsenter(network, peer, orderers[survivor], "systemchannel", server2CertBytes)
  1057  			findLeader([]*ginkgomon.Runner{ordererRunners[survivor]})
  1058  
  1059  			fmt.Fprintln(GinkgoWriter, "Ensuring the other orderer detect the eviction of the node on channel systemchannel")
  1060  			Eventually(ordererRunners[secondEvictedNode].Err(), network.EventuallyTimeout, time.Second).Should(gbytes.Say(stopMsg))
  1061  
  1062  			By("Ensuring the evicted orderer now doesn't serve clients")
  1063  			ensureEvicted(orderers[secondEvictedNode], peer, network, "systemchannel")
  1064  
  1065  			By("Re-adding first evicted orderer")
  1066  			addConsenter(network, peer, network.Orderers[survivor], "systemchannel", etcdraft.Consenter{
  1067  				Host:          "127.0.0.1",
  1068  				Port:          uint32(network.OrdererPort(orderers[firstEvictedNode], nwo.ClusterPort)),
  1069  				ClientTlsCert: server1CertBytes,
  1070  				ServerTlsCert: server1CertBytes,
  1071  			})
  1072  
  1073  			By("Ensuring re-added orderer starts serving system channel")
  1074  			assertBlockReception(map[string]int{
  1075  				"systemchannel": 3,
  1076  			}, []*nwo.Orderer{orderers[firstEvictedNode]}, peer, network)
  1077  
  1078  			env := CreateBroadcastEnvelope(network, orderers[secondEvictedNode], network.SystemChannel.Name, []byte("foo"))
  1079  			resp, err := nwo.Broadcast(network, orderers[survivor], env)
  1080  			Expect(err).NotTo(HaveOccurred())
  1081  			Expect(resp.Status).To(Equal(common.Status_SUCCESS))
  1082  		})
  1083  
  1084  		When("an evicted node is added back while it's offline", func() {
  1085  			It("can start with correct new raft id", func() {
  1086  				o1 := network.Orderer("orderer1")
  1087  				o2 := network.Orderer("orderer2")
  1088  				o3 := network.Orderer("orderer3")
  1089  
  1090  				By("Waiting for them to elect a leader")
  1091  				findLeader(ordererRunners)
  1092  
  1093  				By("Creating an application channel testchannel")
  1094  				network.CreateChannel("testchannel", o1, peer)
  1095  
  1096  				assertBlockReception(map[string]int{
  1097  					"testchannel":   0,
  1098  					"systemchannel": 1,
  1099  				}, []*nwo.Orderer{o1, o2, o3}, peer, network)
  1100  
  1101  				By("Killing the first orderer")
  1102  				ordererProcesses[0].Signal(syscall.SIGTERM)
  1103  				Eventually(ordererProcesses[0].Wait(), network.EventuallyTimeout).Should(Receive())
  1104  
  1105  				// We need to wait for stabilization, as we might have killed the leader OSN.
  1106  				By("Waiting for the channel to stabilize after killing the orderer")
  1107  				assertBlockReception(map[string]int{
  1108  					"testchannel":   0,
  1109  					"systemchannel": 1,
  1110  				}, []*nwo.Orderer{o2, o3}, peer, network)
  1111  
  1112  				By("observing active nodes to shrink")
  1113  				o2Runner := ordererRunners[1]
  1114  				Eventually(o2Runner.Err(), network.EventuallyTimeout).Should(gbytes.Say("Current active nodes in cluster are: \\[2 3\\]"))
  1115  
  1116  				By("Removing the first orderer from the application channel")
  1117  				server1CertBytes, err := ioutil.ReadFile(filepath.Join(network.OrdererLocalTLSDir(o1), "server.crt"))
  1118  				Expect(err).To(Not(HaveOccurred()))
  1119  				removeConsenter(network, peer, o2, "testchannel", server1CertBytes)
  1120  
  1121  				By("Adding the evicted orderer back to the application channel")
  1122  				addConsenter(network, peer, o2, "testchannel", etcdraft.Consenter{
  1123  					ServerTlsCert: server1CertBytes,
  1124  					ClientTlsCert: server1CertBytes,
  1125  					Host:          "127.0.0.1",
  1126  					Port:          uint32(network.OrdererPort(o1, nwo.ClusterPort)),
  1127  				})
  1128  
  1129  				By("Removing the first orderer from the application channel again")
  1130  				removeConsenter(network, peer, o2, "testchannel", server1CertBytes)
  1131  
  1132  				By("Adding the evicted orderer back to the application channel again")
  1133  				addConsenter(network, peer, o2, "testchannel", etcdraft.Consenter{
  1134  					ServerTlsCert: server1CertBytes,
  1135  					ClientTlsCert: server1CertBytes,
  1136  					Host:          "127.0.0.1",
  1137  					Port:          uint32(network.OrdererPort(o1, nwo.ClusterPort)),
  1138  				})
  1139  
  1140  				By("Starting the first orderer again")
  1141  				o1Runner := network.OrdererRunner(o1)
  1142  				ordererProcesses[0] = ifrit.Invoke(o1Runner)
  1143  				Eventually(ordererProcesses[0].Ready(), network.EventuallyTimeout).Should(BeClosed())
  1144  
  1145  				By("Submitting tx")
  1146  				env := CreateBroadcastEnvelope(network, o2, "testchannel", []byte("foo"))
  1147  				resp, err := nwo.Broadcast(network, o2, env)
  1148  				Expect(err).NotTo(HaveOccurred())
  1149  				Expect(resp.Status).To(Equal(common.Status_SUCCESS))
  1150  
  1151  				By("Waiting for the channel to stabilize")
  1152  				assertBlockReception(map[string]int{
  1153  					"testchannel": 5,
  1154  				}, []*nwo.Orderer{o1, o2, o3}, peer, network)
  1155  			})
  1156  		})
  1157  
  1158  		It("notices it even if it is down at the time of its eviction", func() {
  1159  			o1 := network.Orderer("orderer1")
  1160  			o2 := network.Orderer("orderer2")
  1161  			o3 := network.Orderer("orderer3")
  1162  
  1163  			orderers := []*nwo.Orderer{o1, o2, o3}
  1164  
  1165  			By("Waiting for them to elect a leader")
  1166  			findLeader(ordererRunners)
  1167  
  1168  			By("Creating a channel")
  1169  			network.CreateChannel("testchannel", o1, peer)
  1170  
  1171  			assertBlockReception(map[string]int{
  1172  				"testchannel":   0,
  1173  				"systemchannel": 1,
  1174  			}, []*nwo.Orderer{o1, o2, o3}, peer, network)
  1175  
  1176  			By("Killing the orderer")
  1177  			ordererProcesses[0].Signal(syscall.SIGTERM)
  1178  			Eventually(ordererProcesses[0].Wait(), network.EventuallyTimeout).Should(Receive())
  1179  
  1180  			// We need to wait for stabilization, as we might have killed the leader OSN.
  1181  			By("Waiting for the channel to stabilize after killing the orderer")
  1182  			assertBlockReception(map[string]int{
  1183  				"testchannel":   0,
  1184  				"systemchannel": 1,
  1185  			}, []*nwo.Orderer{o2, o3}, peer, network)
  1186  
  1187  			By("Removing the first orderer from an application channel")
  1188  			o1cert, err := ioutil.ReadFile(path.Join(network.OrdererLocalTLSDir(o1), "server.crt"))
  1189  			Expect(err).ToNot(HaveOccurred())
  1190  			removeConsenter(network, peer, o2, "testchannel", o1cert)
  1191  
  1192  			By("Starting the orderer again")
  1193  			ordererRunner := network.OrdererRunner(orderers[0])
  1194  			ordererRunners[0] = ordererRunner
  1195  			ordererProcesses[0] = ifrit.Invoke(ordererRunner)
  1196  			Eventually(ordererProcesses[0].Ready(), network.EventuallyTimeout).Should(BeClosed())
  1197  
  1198  			By("Ensuring the remaining OSNs reject authentication")
  1199  			Eventually(ordererRunners[1].Err(), time.Minute, time.Second).Should(gbytes.Say("certificate extracted from TLS connection isn't authorized"))
  1200  			Eventually(ordererRunners[2].Err(), time.Minute, time.Second).Should(gbytes.Say("certificate extracted from TLS connection isn't authorized"))
  1201  
  1202  			By("Ensuring it detects its eviction")
  1203  			evictionDetection := gbytes.Say(`Detected our own eviction from the channel in block \[1\] channel=testchannel`)
  1204  			Eventually(ordererRunner.Err(), time.Minute, time.Second).Should(evictionDetection)
  1205  
  1206  			By("Ensuring all blocks are pulled up to the block that evicts the OSN")
  1207  			Eventually(ordererRunner.Err(), time.Minute, time.Second).Should(gbytes.Say("Periodic check is stopping. channel=testchannel"))
  1208  			Eventually(ordererRunner.Err(), time.Minute, time.Second).Should(gbytes.Say("Pulled all blocks up to eviction block. channel=testchannel"))
  1209  
  1210  			By("Killing the evicted orderer")
  1211  			ordererProcesses[0].Signal(syscall.SIGTERM)
  1212  			Eventually(ordererProcesses[0].Wait(), network.EventuallyTimeout).Should(Receive())
  1213  
  1214  			By("Starting the evicted orderer again")
  1215  			ordererRunner = network.OrdererRunner(orderers[0])
  1216  			ordererRunners[0] = ordererRunner
  1217  			ordererProcesses[0] = ifrit.Invoke(ordererRunner)
  1218  			Eventually(ordererProcesses[0].Ready(), network.EventuallyTimeout).Should(BeClosed())
  1219  
  1220  			By("Ensuring the evicted orderer starts up marked the channel is inactive")
  1221  			Eventually(ordererRunner.Err(), time.Minute, time.Second).Should(gbytes.Say("Found 1 inactive chains"))
  1222  
  1223  			iDoNotBelong := "I do not belong to channel testchannel or am forbidden pulling it"
  1224  			Eventually(ordererRunner.Err(), time.Minute, time.Second).Should(gbytes.Say(iDoNotBelong))
  1225  
  1226  			By("Adding the evicted orderer back to the application channel")
  1227  			addConsenter(network, peer, o2, "testchannel", etcdraft.Consenter{
  1228  				ServerTlsCert: o1cert,
  1229  				ClientTlsCert: o1cert,
  1230  				Host:          "127.0.0.1",
  1231  				Port:          uint32(network.OrdererPort(orderers[0], nwo.ClusterPort)),
  1232  			})
  1233  
  1234  			By("Ensuring the re-added orderer joins the Raft cluster")
  1235  			findLeader([]*ginkgomon.Runner{ordererRunner})
  1236  		})
  1237  	})
  1238  
  1239  	When("an orderer node is joined", func() {
  1240  		It("isn't influenced by outdated orderers", func() {
  1241  			// This test checks that if a lagged is not aware of newly added nodes,
  1242  			// among which leader is present, it eventually pulls config block from
  1243  			// the orderer it knows, gets the certificates from it and participate
  1244  			// in consensus again.
  1245  			//
  1246  			// Steps:
  1247  			// Initial nodes in cluster: <1, 2, 3, 4>
  1248  			// - start <1, 2, 3>
  1249  			// - add <5, 6, 7>, start <5, 6, 7>
  1250  			// - kill <1>
  1251  			// - submit a tx, so that Raft index on <1> is behind <5, 6, 7> and <2, 3>
  1252  			// - kill <2, 3>
  1253  			// - start <1> and <4>. Since <1> is behind <5, 6, 7>, leader is certainly
  1254  			//   going to be elected from <5, 6, 7>
  1255  			// - assert that even <4> is not aware of leader, it can pull config block
  1256  			//   from <1>, and start participating in consensus.
  1257  
  1258  			orderers := make([]*nwo.Orderer, 7)
  1259  			ordererRunners = make([]*ginkgomon.Runner, 7)
  1260  			ordererProcesses = make([]ifrit.Process, 7)
  1261  
  1262  			for i := range orderers {
  1263  				orderers[i] = &nwo.Orderer{
  1264  					Name:         fmt.Sprintf("orderer%d", i+1),
  1265  					Organization: "OrdererOrg",
  1266  				}
  1267  			}
  1268  
  1269  			layout := nwo.MultiNodeEtcdRaft()
  1270  			layout.Orderers = orderers[:4]
  1271  			layout.Profiles[0].Orderers = []string{"orderer1", "orderer2", "orderer3", "orderer4"}
  1272  
  1273  			network = nwo.New(layout, testDir, client, StartPort(), components)
  1274  			network.GenerateConfigTree()
  1275  			network.Bootstrap()
  1276  
  1277  			peer = network.Peer("Org1", "peer0")
  1278  
  1279  			launch := func(i int) {
  1280  				runner := network.OrdererRunner(orderers[i])
  1281  				ordererRunners[i] = runner
  1282  				process := ifrit.Invoke(runner)
  1283  				Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
  1284  				ordererProcesses[i] = process
  1285  			}
  1286  
  1287  			By("Launching 3 out of 4 orderers")
  1288  			for i := range orderers[:3] {
  1289  				launch(i)
  1290  			}
  1291  
  1292  			leader := findLeader(ordererRunners[:3])
  1293  
  1294  			By("Checking that all orderers are online")
  1295  			assertBlockReception(map[string]int{
  1296  				"systemchannel": 0,
  1297  			}, orderers[:3], peer, network)
  1298  
  1299  			By("Configuring orderer[5, 6, 7] in the network")
  1300  			extendNetwork(network)
  1301  
  1302  			for _, o := range orderers[4:7] {
  1303  				ports := nwo.Ports{}
  1304  				for _, portName := range nwo.OrdererPortNames() {
  1305  					ports[portName] = network.ReservePort()
  1306  				}
  1307  				network.PortsByOrdererID[o.ID()] = ports
  1308  
  1309  				network.Orderers = append(network.Orderers, o)
  1310  				network.GenerateOrdererConfig(o)
  1311  			}
  1312  
  1313  			// Backup previous system channel block
  1314  			genesisBootBlock, err := ioutil.ReadFile(filepath.Join(testDir, "systemchannel_block.pb"))
  1315  			Expect(err).NotTo(HaveOccurred())
  1316  			restoreBootBlock := func() {
  1317  				err = ioutil.WriteFile(filepath.Join(testDir, "systemchannel_block.pb"), genesisBootBlock, 0644)
  1318  				Expect(err).NotTo(HaveOccurred())
  1319  			}
  1320  
  1321  			blockSeq := 0 // there's only one block in channel - genesis
  1322  			for _, i := range []int{4, 5, 6} {
  1323  				By(fmt.Sprintf("Adding orderer%d", i+1))
  1324  				ordererCertificatePath := filepath.Join(network.OrdererLocalTLSDir(orderers[i]), "server.crt")
  1325  				ordererCertificate, err := ioutil.ReadFile(ordererCertificatePath)
  1326  				Expect(err).NotTo(HaveOccurred())
  1327  
  1328  				addConsenter(network, peer, orderers[0], "systemchannel", etcdraft.Consenter{
  1329  					ServerTlsCert: ordererCertificate,
  1330  					ClientTlsCert: ordererCertificate,
  1331  					Host:          "127.0.0.1",
  1332  					Port:          uint32(network.OrdererPort(orderers[i], nwo.ClusterPort)),
  1333  				})
  1334  				blockSeq++
  1335  
  1336  				// Get the last config block of the system channel
  1337  				configBlock := nwo.GetConfigBlock(network, peer, orderers[0], "systemchannel")
  1338  				// Plant it in the file system of orderer, the new node to be onboarded.
  1339  				err = ioutil.WriteFile(filepath.Join(testDir, "systemchannel_block.pb"), protoutil.MarshalOrPanic(configBlock), 0644)
  1340  				Expect(err).NotTo(HaveOccurred())
  1341  
  1342  				By(fmt.Sprintf("Launching orderer%d", i+1))
  1343  				launch(i)
  1344  
  1345  				By(fmt.Sprintf("Checking that orderer%d has onboarded the network", i+1))
  1346  				assertBlockReception(map[string]int{
  1347  					"systemchannel": blockSeq,
  1348  				}, []*nwo.Orderer{orderers[i]}, peer, network)
  1349  			}
  1350  
  1351  			Expect(findLeader(ordererRunners[4:])).To(Equal(leader))
  1352  
  1353  			// Later on, when we start [1, 4, 5, 6, 7], we want to make sure that leader
  1354  			// is elected from [5, 6, 7], who are unknown to [4]. So we can assert that
  1355  			// [4] suspects its own eviction, pulls block from [1], and join the cluster.
  1356  			// Otherwise, if [1] is elected, and all other nodes already knew it, [4] may
  1357  			// simply replicate missing blocks with Raft, instead of pulling from others
  1358  			// triggered by eviction suspector.
  1359  
  1360  			By("Killing orderer1")
  1361  			ordererProcesses[0].Signal(syscall.SIGTERM)
  1362  			Eventually(ordererProcesses[0].Wait(), network.EventuallyTimeout).Should(Receive())
  1363  
  1364  			By("Submitting another tx to increment Raft index on alive orderers")
  1365  			if leader == 1 {
  1366  				// if orderer1 was leader, we should expect a new leader being elected before going forward
  1367  				findLeader([]*ginkgomon.Runner{ordererRunners[4]})
  1368  			}
  1369  
  1370  			env := CreateBroadcastEnvelope(network, orderers[4], network.SystemChannel.Name, []byte("hello"))
  1371  			resp, err := nwo.Broadcast(network, orderers[4], env)
  1372  			Expect(err).NotTo(HaveOccurred())
  1373  			Expect(resp.Status).To(Equal(common.Status_SUCCESS))
  1374  			blockSeq++
  1375  
  1376  			assertBlockReception(map[string]int{
  1377  				"systemchannel": blockSeq,
  1378  			}, []*nwo.Orderer{orderers[1], orderers[2], orderers[4], orderers[5], orderers[6]}, peer, network) // alive orderers: 2, 3, 5, 6, 7
  1379  
  1380  			By("Killing orderer[2,3]")
  1381  			for _, i := range []int{1, 2} {
  1382  				ordererProcesses[i].Signal(syscall.SIGTERM)
  1383  				Eventually(ordererProcesses[i].Wait(), network.EventuallyTimeout).Should(Receive())
  1384  			}
  1385  
  1386  			By("Launching the orderer that was never started")
  1387  			restoreBootBlock()
  1388  			launch(3)
  1389  
  1390  			By("Launching orderer1")
  1391  			launch(0)
  1392  
  1393  			By("Waiting until it suspects its eviction from the channel")
  1394  			Eventually(ordererRunners[3].Err(), time.Minute, time.Second).Should(gbytes.Say("Suspecting our own eviction from the channel"))
  1395  
  1396  			By("Making sure 4/7 orderers form quorum and serve request")
  1397  			assertBlockReception(map[string]int{
  1398  				"systemchannel": blockSeq,
  1399  			}, []*nwo.Orderer{orderers[3], orderers[4], orderers[5], orderers[6]}, peer, network) // alive orderers: 4, 5, 6, 7
  1400  		})
  1401  	})
  1402  
  1403  	It("can create a channel that contains a subset of orderers in system channel", func() {
  1404  		config := nwo.BasicEtcdRaft()
  1405  		config.Orderers = []*nwo.Orderer{
  1406  			{Name: "orderer1", Organization: "OrdererOrg"},
  1407  			{Name: "orderer2", Organization: "OrdererOrg"},
  1408  			{Name: "orderer3", Organization: "OrdererOrg"},
  1409  		}
  1410  		config.Profiles = []*nwo.Profile{{
  1411  			Name:     "SampleDevModeEtcdRaft",
  1412  			Orderers: []string{"orderer1", "orderer2", "orderer3"},
  1413  		}, {
  1414  			Name:          "ThreeOrdererChannel",
  1415  			Consortium:    "SampleConsortium",
  1416  			Organizations: []string{"Org1", "Org2"},
  1417  			Orderers:      []string{"orderer1", "orderer2", "orderer3"},
  1418  		}, {
  1419  			Name:          "SingleOrdererChannel",
  1420  			Consortium:    "SampleConsortium",
  1421  			Organizations: []string{"Org1", "Org2"},
  1422  			Orderers:      []string{"orderer1"},
  1423  		}}
  1424  		config.Channels = []*nwo.Channel{
  1425  			{Name: "single-orderer-channel", Profile: "SingleOrdererChannel", BaseProfile: "SampleDevModeEtcdRaft"},
  1426  			{Name: "three-orderer-channel", Profile: "ThreeOrdererChannel"},
  1427  		}
  1428  
  1429  		network = nwo.New(config, testDir, client, StartPort(), components)
  1430  		o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3")
  1431  		orderers := []*nwo.Orderer{o1, o2, o3}
  1432  		peer = network.Peer("Org1", "peer0")
  1433  
  1434  		network.GenerateConfigTree()
  1435  		network.Bootstrap()
  1436  
  1437  		By("Launching the orderers")
  1438  		for _, o := range orderers {
  1439  			runner := network.OrdererRunner(o)
  1440  			ordererRunners = append(ordererRunners, runner)
  1441  			process := ifrit.Invoke(runner)
  1442  			ordererProcesses = append(ordererProcesses, process)
  1443  		}
  1444  
  1445  		for _, ordererProc := range ordererProcesses {
  1446  			Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed())
  1447  		}
  1448  
  1449  		By("Creating an application channel with a subset of orderers in system channel")
  1450  		additionalPeer := network.Peer("Org2", "peer0")
  1451  		network.CreateChannel("single-orderer-channel", network.Orderers[0], peer, additionalPeer, network.Orderers[0])
  1452  
  1453  		By("Creating another channel via the orderer that is in system channel but not app channel")
  1454  		network.CreateChannel("three-orderer-channel", network.Orderers[2], peer)
  1455  	})
  1456  
  1457  	It("can add a new orderer organization", func() {
  1458  		network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components)
  1459  		o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3")
  1460  		orderers := []*nwo.Orderer{o1, o2, o3}
  1461  
  1462  		network.GenerateConfigTree()
  1463  		network.Bootstrap()
  1464  
  1465  		By("Launching the orderers")
  1466  		for _, o := range orderers {
  1467  			runner := network.OrdererRunner(o)
  1468  			ordererRunners = append(ordererRunners, runner)
  1469  			process := ifrit.Invoke(runner)
  1470  			ordererProcesses = append(ordererProcesses, process)
  1471  		}
  1472  
  1473  		for _, ordererProc := range ordererProcesses {
  1474  			Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed())
  1475  		}
  1476  
  1477  		By("Waiting for system channel to be ready")
  1478  		findLeader(ordererRunners)
  1479  
  1480  		peer := network.Peer("Org1", "peer0")
  1481  		channel := "systemchannel"
  1482  
  1483  		config := nwo.GetConfig(network, peer, o1, channel)
  1484  		updatedConfig := proto.Clone(config).(*common.Config)
  1485  
  1486  		ordererOrg := updatedConfig.ChannelGroup.Groups["Orderer"].Groups["OrdererOrg"]
  1487  		mspConfig := &msp.MSPConfig{}
  1488  		err := proto.Unmarshal(ordererOrg.Values["MSP"].Value, mspConfig)
  1489  		Expect(err).NotTo(HaveOccurred())
  1490  
  1491  		fabMSPConfig := &msp.FabricMSPConfig{}
  1492  		err = proto.Unmarshal(mspConfig.Config, fabMSPConfig)
  1493  		Expect(err).NotTo(HaveOccurred())
  1494  
  1495  		fabMSPConfig.Name = "OrdererMSP2"
  1496  
  1497  		mspConfig.Config, _ = proto.Marshal(fabMSPConfig)
  1498  		updatedConfig.ChannelGroup.Groups["Orderer"].Groups["OrdererMSP2"] = &common.ConfigGroup{
  1499  			Values: map[string]*common.ConfigValue{
  1500  				"MSP": {
  1501  					Value:     protoutil.MarshalOrPanic(mspConfig),
  1502  					ModPolicy: "Admins",
  1503  				},
  1504  			},
  1505  			ModPolicy: "Admins",
  1506  		}
  1507  
  1508  		nwo.UpdateOrdererConfig(network, o1, channel, config, updatedConfig, peer, o1)
  1509  	})
  1510  })
  1511  
  1512  func ensureEvicted(evictedOrderer *nwo.Orderer, submitter *nwo.Peer, network *nwo.Network, channel string) {
  1513  	c := commands.ChannelFetch{
  1514  		ChannelID:  channel,
  1515  		Block:      "newest",
  1516  		OutputFile: "/dev/null",
  1517  		Orderer:    network.OrdererAddress(evictedOrderer, nwo.ListenPort),
  1518  	}
  1519  
  1520  	sess, err := network.OrdererAdminSession(evictedOrderer, submitter, c)
  1521  	Expect(err).NotTo(HaveOccurred())
  1522  
  1523  	Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit())
  1524  	Expect(sess.Err).To(gbytes.Say("SERVICE_UNAVAILABLE"))
  1525  }
  1526  
  1527  var extendedCryptoConfig = `---
  1528  OrdererOrgs:
  1529  - Name: OrdererOrg
  1530    Domain: example.com
  1531    EnableNodeOUs: false
  1532    CA:
  1533      Hostname: ca
  1534    Specs:
  1535    - Hostname: orderer1
  1536      SANS:
  1537      - localhost
  1538      - 127.0.0.1
  1539      - ::1
  1540    - Hostname: orderer1new
  1541      SANS:
  1542      - localhost
  1543      - 127.0.0.1
  1544      - ::1
  1545    - Hostname: orderer2
  1546      SANS:
  1547      - localhost
  1548      - 127.0.0.1
  1549      - ::1
  1550    - Hostname: orderer2new
  1551      SANS:
  1552      - localhost
  1553      - 127.0.0.1
  1554      - ::1
  1555    - Hostname: orderer3
  1556      SANS:
  1557      - localhost
  1558      - 127.0.0.1
  1559      - ::1
  1560    - Hostname: orderer3new
  1561      SANS:
  1562      - localhost
  1563      - 127.0.0.1
  1564      - ::1
  1565    - Hostname: orderer4
  1566      SANS:
  1567      - localhost
  1568      - 127.0.0.1
  1569      - ::1
  1570    - Hostname: orderer5
  1571      SANS:
  1572      - localhost
  1573      - 127.0.0.1
  1574      - ::1
  1575    - Hostname: orderer6
  1576      SANS:
  1577      - localhost
  1578      - 127.0.0.1
  1579      - ::1
  1580    - Hostname: orderer7
  1581      SANS:
  1582      - localhost
  1583      - 127.0.0.1
  1584      - ::1
  1585  `
  1586  
  1587  type certificateChange struct {
  1588  	srcFile string
  1589  	dstFile string
  1590  	oldCert []byte
  1591  	oldKey  []byte
  1592  	newCert []byte
  1593  }
  1594  
  1595  // extendNetwork rotates adds an additional orderer
  1596  func extendNetwork(n *nwo.Network) {
  1597  	// Overwrite the current crypto-config with additional orderers
  1598  	cryptoConfigYAML, err := ioutil.TempFile("", "crypto-config.yaml")
  1599  	Expect(err).NotTo(HaveOccurred())
  1600  	defer os.Remove(cryptoConfigYAML.Name())
  1601  
  1602  	err = ioutil.WriteFile(cryptoConfigYAML.Name(), []byte(extendedCryptoConfig), 0644)
  1603  	Expect(err).NotTo(HaveOccurred())
  1604  
  1605  	// Invoke cryptogen extend to add new orderers
  1606  	sess, err := n.Cryptogen(commands.Extend{
  1607  		Config: cryptoConfigYAML.Name(),
  1608  		Input:  n.CryptoPath(),
  1609  	})
  1610  	Expect(err).NotTo(HaveOccurred())
  1611  	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
  1612  }
  1613  
  1614  // refreshOrdererPEMs rotates all TLS certificates of all nodes,
  1615  // and returns the deltas
  1616  func refreshOrdererPEMs(n *nwo.Network) []*certificateChange {
  1617  	var fileChanges []*certificateChange
  1618  	// Populate source to destination files
  1619  	err := filepath.Walk(n.CryptoPath(), func(path string, info os.FileInfo, err error) error {
  1620  		if !strings.Contains(path, "/tls/") {
  1621  			return nil
  1622  		}
  1623  		if strings.Contains(path, "new") {
  1624  			fileChanges = append(fileChanges, &certificateChange{
  1625  				srcFile: path,
  1626  				dstFile: strings.Replace(path, "new", "", -1),
  1627  			})
  1628  		}
  1629  		return nil
  1630  	})
  1631  	Expect(err).NotTo(HaveOccurred())
  1632  
  1633  	var serverCertChanges []*certificateChange
  1634  
  1635  	// Overwrite the destination files with the contents of the source files.
  1636  	for _, certChange := range fileChanges {
  1637  		previousCertBytes, err := ioutil.ReadFile(certChange.dstFile)
  1638  		Expect(err).NotTo(HaveOccurred())
  1639  
  1640  		newCertBytes, err := ioutil.ReadFile(certChange.srcFile)
  1641  		Expect(err).NotTo(HaveOccurred())
  1642  
  1643  		err = ioutil.WriteFile(certChange.dstFile, newCertBytes, 0644)
  1644  		Expect(err).NotTo(HaveOccurred())
  1645  
  1646  		if !strings.Contains(certChange.dstFile, "server.crt") {
  1647  			continue
  1648  		}
  1649  
  1650  		// Read the previous key file
  1651  		previousKeyBytes, err := ioutil.ReadFile(strings.Replace(certChange.dstFile, "server.crt", "server.key", -1))
  1652  		Expect(err).NotTo(HaveOccurred())
  1653  
  1654  		serverCertChanges = append(serverCertChanges, certChange)
  1655  		certChange.newCert = newCertBytes
  1656  		certChange.oldCert = previousCertBytes
  1657  		certChange.oldKey = previousKeyBytes
  1658  	}
  1659  	return serverCertChanges
  1660  }
  1661  
  1662  // assertBlockReception asserts that the given orderers have expected heights for the given channel--> height mapping
  1663  func assertBlockReception(expectedHeightsPerChannel map[string]int, orderers []*nwo.Orderer, p *nwo.Peer, n *nwo.Network) {
  1664  	for channelName, blockSeq := range expectedHeightsPerChannel {
  1665  		for _, orderer := range orderers {
  1666  			waitForBlockReception(orderer, p, n, channelName, blockSeq)
  1667  		}
  1668  	}
  1669  }
  1670  
  1671  func waitForBlockReception(o *nwo.Orderer, submitter *nwo.Peer, network *nwo.Network, channelName string, blockSeq int) {
  1672  	c := commands.ChannelFetch{
  1673  		ChannelID:  channelName,
  1674  		Block:      "newest",
  1675  		OutputFile: "/dev/null",
  1676  		Orderer:    network.OrdererAddress(o, nwo.ListenPort),
  1677  	}
  1678  	Eventually(func() string {
  1679  		sess, err := network.OrdererAdminSession(o, submitter, c)
  1680  		Expect(err).NotTo(HaveOccurred())
  1681  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit())
  1682  		if sess.ExitCode() != 0 {
  1683  			return fmt.Sprintf("exit code is %d: %s", sess.ExitCode(), string(sess.Err.Contents()))
  1684  		}
  1685  		sessErr := string(sess.Err.Contents())
  1686  		expected := fmt.Sprintf("Received block: %d", blockSeq)
  1687  		if strings.Contains(sessErr, expected) {
  1688  			return ""
  1689  		}
  1690  		return sessErr
  1691  	}, network.EventuallyTimeout, time.Second).Should(BeEmpty())
  1692  }
  1693  
  1694  func revokeReaderAccess(network *nwo.Network, channel string, orderer *nwo.Orderer, peer *nwo.Peer) {
  1695  	config := nwo.GetConfig(network, peer, orderer, channel)
  1696  	updatedConfig := proto.Clone(config).(*common.Config)
  1697  
  1698  	// set the policy
  1699  	adminPolicy := protoutil.MarshalOrPanic(&common.ImplicitMetaPolicy{
  1700  		SubPolicy: "Admins",
  1701  		Rule:      common.ImplicitMetaPolicy_MAJORITY,
  1702  	})
  1703  	updatedConfig.ChannelGroup.Groups["Orderer"].Policies["Readers"].Policy.Value = adminPolicy
  1704  	nwo.UpdateOrdererConfig(network, orderer, channel, config, updatedConfig, peer, orderer)
  1705  }
  1706  
  1707  // consenterAdder constructs configs that can be used by `UpdateOrdererConfig`
  1708  // to add a consenter.
  1709  func consenterAdder(n *nwo.Network, peer *nwo.Peer, orderer *nwo.Orderer, channel string, consenter etcdraft.Consenter) (current, updated *common.Config) {
  1710  	config := nwo.GetConfig(n, peer, orderer, channel)
  1711  	updatedConfig := proto.Clone(config).(*common.Config)
  1712  
  1713  	consensusTypeConfigValue := updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"]
  1714  	consensusTypeValue := &protosorderer.ConsensusType{}
  1715  	err := proto.Unmarshal(consensusTypeConfigValue.Value, consensusTypeValue)
  1716  	Expect(err).NotTo(HaveOccurred())
  1717  
  1718  	metadata := &etcdraft.ConfigMetadata{}
  1719  	err = proto.Unmarshal(consensusTypeValue.Metadata, metadata)
  1720  	Expect(err).NotTo(HaveOccurred())
  1721  
  1722  	metadata.Consenters = append(metadata.Consenters, &consenter)
  1723  
  1724  	consensusTypeValue.Metadata, err = proto.Marshal(metadata)
  1725  	Expect(err).NotTo(HaveOccurred())
  1726  
  1727  	updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"] = &common.ConfigValue{
  1728  		ModPolicy: "Admins",
  1729  		Value:     protoutil.MarshalOrPanic(consensusTypeValue),
  1730  	}
  1731  
  1732  	return config, updatedConfig
  1733  }
  1734  
  1735  // consenterRemover constructs configs that can be used by
  1736  // `UpdateOrdererConfig` to remove a consenter.
  1737  func consenterRemover(n *nwo.Network, peer *nwo.Peer, orderer *nwo.Orderer, channel string, certificate []byte) (current, updated *common.Config) {
  1738  	config := nwo.GetConfig(n, peer, orderer, channel)
  1739  	updatedConfig := proto.Clone(config).(*common.Config)
  1740  
  1741  	consensusTypeConfigValue := updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"]
  1742  	consensusTypeValue := &protosorderer.ConsensusType{}
  1743  	err := proto.Unmarshal(consensusTypeConfigValue.Value, consensusTypeValue)
  1744  	Expect(err).NotTo(HaveOccurred())
  1745  
  1746  	metadata := &etcdraft.ConfigMetadata{}
  1747  	err = proto.Unmarshal(consensusTypeValue.Metadata, metadata)
  1748  	Expect(err).NotTo(HaveOccurred())
  1749  
  1750  	var newConsenters []*etcdraft.Consenter
  1751  	for _, consenter := range metadata.Consenters {
  1752  		if bytes.Equal(consenter.ClientTlsCert, certificate) || bytes.Equal(consenter.ServerTlsCert, certificate) {
  1753  			continue
  1754  		}
  1755  		newConsenters = append(newConsenters, consenter)
  1756  	}
  1757  
  1758  	metadata.Consenters = newConsenters
  1759  	consensusTypeValue.Metadata, err = proto.Marshal(metadata)
  1760  	Expect(err).NotTo(HaveOccurred())
  1761  
  1762  	updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"] = &common.ConfigValue{
  1763  		ModPolicy: "Admins",
  1764  		Value:     protoutil.MarshalOrPanic(consensusTypeValue),
  1765  	}
  1766  
  1767  	return config, updatedConfig
  1768  }
  1769  
  1770  // addConsenter adds a new consenter to the given channel.
  1771  func addConsenter(n *nwo.Network, peer *nwo.Peer, orderer *nwo.Orderer, channel string, consenter etcdraft.Consenter) {
  1772  	updateEtcdRaftMetadata(n, peer, orderer, channel, func(metadata *etcdraft.ConfigMetadata) {
  1773  		metadata.Consenters = append(metadata.Consenters, &consenter)
  1774  	})
  1775  }
  1776  
  1777  // removeConsenter removes a consenter with the given certificate in PEM format
  1778  // from the given channel.
  1779  func removeConsenter(n *nwo.Network, peer *nwo.Peer, orderer *nwo.Orderer, channel string, certificate []byte) {
  1780  	updateEtcdRaftMetadata(n, peer, orderer, channel, func(metadata *etcdraft.ConfigMetadata) {
  1781  		var newConsenters []*etcdraft.Consenter
  1782  		for _, consenter := range metadata.Consenters {
  1783  			if bytes.Equal(consenter.ClientTlsCert, certificate) || bytes.Equal(consenter.ServerTlsCert, certificate) {
  1784  				continue
  1785  			}
  1786  			newConsenters = append(newConsenters, consenter)
  1787  		}
  1788  
  1789  		metadata.Consenters = newConsenters
  1790  	})
  1791  }
  1792  
  1793  // updateEtcdRaftMetadata executes a config update that updates the etcdraft
  1794  // metadata according to the given function f.
  1795  func updateEtcdRaftMetadata(network *nwo.Network, peer *nwo.Peer, orderer *nwo.Orderer, channel string, f func(md *etcdraft.ConfigMetadata)) {
  1796  	nwo.UpdateConsensusMetadata(network, peer, orderer, channel, func(originalMetadata []byte) []byte {
  1797  		metadata := &etcdraft.ConfigMetadata{}
  1798  		err := proto.Unmarshal(originalMetadata, metadata)
  1799  		Expect(err).NotTo(HaveOccurred())
  1800  
  1801  		f(metadata)
  1802  
  1803  		newMetadata, err := proto.Marshal(metadata)
  1804  		Expect(err).NotTo(HaveOccurred())
  1805  		return newMetadata
  1806  	})
  1807  }
  1808  
  1809  func mutateConsensusMetadata(originalMetadata []byte, f func(md *etcdraft.ConfigMetadata)) []byte {
  1810  	metadata := &etcdraft.ConfigMetadata{}
  1811  	err := proto.Unmarshal(originalMetadata, metadata)
  1812  	Expect(err).NotTo(HaveOccurred())
  1813  
  1814  	f(metadata)
  1815  
  1816  	newMetadata, err := proto.Marshal(metadata)
  1817  	Expect(err).NotTo(HaveOccurred())
  1818  	return newMetadata
  1819  }
  1820  
  1821  func updateOrdererMSPAndConsensusMetadata(network *nwo.Network, peer *nwo.Peer, orderer *nwo.Orderer, channel, orgID string, mutateMSP nwo.MSPMutator, f func(md *etcdraft.ConfigMetadata)) {
  1822  	config := nwo.GetConfig(network, peer, orderer, channel)
  1823  	updatedConfig := proto.Clone(config).(*common.Config)
  1824  
  1825  	// Unpack the MSP config
  1826  	rawMSPConfig := updatedConfig.ChannelGroup.Groups["Orderer"].Groups[orgID].Values["MSP"]
  1827  	mspConfig := &msp.MSPConfig{}
  1828  	err := proto.Unmarshal(rawMSPConfig.Value, mspConfig)
  1829  	Expect(err).NotTo(HaveOccurred())
  1830  
  1831  	fabricConfig := &msp.FabricMSPConfig{}
  1832  	err = proto.Unmarshal(mspConfig.Config, fabricConfig)
  1833  	Expect(err).NotTo(HaveOccurred())
  1834  
  1835  	// Mutate it as we are asked
  1836  	*fabricConfig = mutateMSP(*fabricConfig)
  1837  
  1838  	// Wrap it back into the config
  1839  	mspConfig.Config = protoutil.MarshalOrPanic(fabricConfig)
  1840  	rawMSPConfig.Value = protoutil.MarshalOrPanic(mspConfig)
  1841  
  1842  	consensusTypeConfigValue := updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"]
  1843  	consensusTypeValue := &protosorderer.ConsensusType{}
  1844  	err = proto.Unmarshal(consensusTypeConfigValue.Value, consensusTypeValue)
  1845  	Expect(err).NotTo(HaveOccurred())
  1846  
  1847  	consensusTypeValue.Metadata = mutateConsensusMetadata(consensusTypeValue.Metadata, f)
  1848  
  1849  	updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"] = &common.ConfigValue{
  1850  		ModPolicy: "Admins",
  1851  		Value:     protoutil.MarshalOrPanic(consensusTypeValue),
  1852  	}
  1853  
  1854  	nwo.UpdateOrdererConfig(network, orderer, channel, config, updatedConfig, peer, orderer)
  1855  }