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