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