github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/integration/gossip/gossip_test.go (about) 1 /* 2 * Copyright hechain. All Rights Reserved. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package gossip 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "os" 13 "syscall" 14 "time" 15 16 docker "github.com/fsouza/go-dockerclient" 17 "github.com/hechain20/hechain/integration/nwo" 18 "github.com/hechain20/hechain/integration/nwo/commands" 19 . "github.com/onsi/ginkgo" 20 . "github.com/onsi/gomega" 21 "github.com/onsi/gomega/gbytes" 22 "github.com/onsi/gomega/gexec" 23 "github.com/tedsuo/ifrit" 24 "github.com/tedsuo/ifrit/ginkgomon" 25 ) 26 27 var _ = Describe("Gossip State Transfer and Membership", func() { 28 var ( 29 testDir string 30 network *nwo.Network 31 nwprocs *networkProcesses 32 chaincode nwo.Chaincode 33 channelName string 34 ) 35 36 BeforeEach(func() { 37 var err error 38 testDir, err = ioutil.TempDir("", "gossip-statexfer") 39 Expect(err).NotTo(HaveOccurred()) 40 41 dockerClient, err := docker.NewClientFromEnv() 42 Expect(err).NotTo(HaveOccurred()) 43 44 channelName = "testchannel" 45 network = nwo.New(nwo.FullSolo(), testDir, dockerClient, StartPort(), components) 46 network.GenerateConfigTree() 47 48 nwprocs = &networkProcesses{ 49 network: network, 50 peerRunners: map[string]*ginkgomon.Runner{}, 51 peerProcesses: map[string]ifrit.Process{}, 52 } 53 54 chaincode = nwo.Chaincode{ 55 Name: "mycc", 56 Version: "0.0", 57 Path: "github.com/hechain20/hechain/integration/chaincode/simple/cmd", 58 Ctor: `{"Args":["init","a","100","b","200"]}`, 59 Policy: `OR ('Org1MSP.member','Org2MSP.member')`, 60 } 61 }) 62 63 AfterEach(func() { 64 if nwprocs != nil { 65 nwprocs.terminateAll() 66 } 67 if network != nil { 68 network.Cleanup() 69 } 70 os.RemoveAll(testDir) 71 }) 72 73 It("syncs blocks from the peer via state transfer when no orderer is available", func() { 74 // modify peer config to enable state transfer on all peers, and configure leaders as follows: 75 // Org1: leader election 76 // Org2: no leader election 77 // peer0: follower 78 // peer1: leader 79 for _, peer := range network.Peers { 80 if peer.Organization == "Org1" { 81 if peer.Name == "peer0" { 82 core := network.ReadPeerConfig(peer) 83 core.Peer.Gossip.State.Enabled = true 84 core.Peer.Gossip.UseLeaderElection = true 85 core.Peer.Gossip.OrgLeader = false 86 network.WritePeerConfig(peer, core) 87 } 88 if peer.Name == "peer1" { 89 core := network.ReadPeerConfig(peer) 90 core.Peer.Gossip.State.Enabled = true 91 core.Peer.Gossip.UseLeaderElection = true 92 core.Peer.Gossip.OrgLeader = false 93 core.Peer.Gossip.Bootstrap = fmt.Sprintf("127.0.0.1:%d", network.ReservePort()) 94 network.WritePeerConfig(peer, core) 95 } 96 } 97 if peer.Organization == "Org2" { 98 core := network.ReadPeerConfig(peer) 99 core.Peer.Gossip.State.Enabled = true 100 core.Peer.Gossip.UseLeaderElection = false 101 core.Peer.Gossip.OrgLeader = peer.Name == "peer1" 102 network.WritePeerConfig(peer, core) 103 } 104 } 105 106 network.Bootstrap() 107 orderer := network.Orderer("orderer") 108 nwprocs.ordererRunner = network.OrdererRunner(orderer) 109 nwprocs.ordererProcess = ifrit.Invoke(nwprocs.ordererRunner) 110 Eventually(nwprocs.ordererProcess.Ready(), network.EventuallyTimeout).Should(BeClosed()) 111 112 peer0Org1, peer1Org1 := network.Peer("Org1", "peer0"), network.Peer("Org1", "peer1") 113 peer0Org2, peer1Org2 := network.Peer("Org2", "peer0"), network.Peer("Org2", "peer1") 114 115 By("bringing up all four peers") 116 startPeers(nwprocs, false, peer0Org1, peer1Org1, peer0Org2, peer1Org2) 117 118 network.CreateChannel(channelName, orderer, peer0Org1) 119 By("joining all peers to channel") 120 network.JoinChannel(channelName, orderer, peer0Org1, peer1Org1, peer0Org2, peer1Org2) 121 122 network.UpdateChannelAnchors(orderer, channelName) 123 124 // base peer will be used for chaincode interactions 125 basePeerForTransactions := peer0Org1 126 nwo.DeployChaincodeLegacy(network, channelName, orderer, chaincode, basePeerForTransactions) 127 128 By("verifying peer0Org1 discovers all the peers and the legacy chaincode before starting the tests") 129 Eventually(nwo.DiscoverPeers(network, peer0Org1, "User1", "testchannel"), network.EventuallyTimeout).Should(ConsistOf( 130 network.DiscoveredPeer(peer0Org1, "_lifecycle", "mycc"), 131 network.DiscoveredPeer(peer1Org1, "_lifecycle"), 132 network.DiscoveredPeer(peer0Org2, "_lifecycle"), 133 network.DiscoveredPeer(peer1Org2, "_lifecycle"), 134 )) 135 136 By("STATE TRANSFER TEST 1: newly joined peers should receive blocks from the peers that are already up") 137 138 // Note, a better test would be to bring orderer down before joining the two peers. 139 // However, network.JoinChannel() requires orderer to be up so that genesis block can be fetched from orderer before joining peers. 140 // Therefore, for now we've joined all four peers and stop the two peers that should be synced up. 141 stopPeers(nwprocs, peer1Org1, peer1Org2) 142 143 By("confirming peer0Org1 was elected to be a leader") 144 expectedMsg := "Elected as a leader, starting delivery service for channel testchannel" 145 Eventually(nwprocs.peerRunners[peer0Org1.ID()].Err(), network.EventuallyTimeout).Should(gbytes.Say(expectedMsg)) 146 147 sendTransactionsAndSyncUpPeers(nwprocs, orderer, basePeerForTransactions, channelName, peer1Org1, peer1Org2) 148 149 By("STATE TRANSFER TEST 2: restarted peers should receive blocks from the peers that are already up") 150 basePeerForTransactions = peer1Org1 151 nwo.InstallChaincodeLegacy(network, chaincode, basePeerForTransactions) 152 153 By("verifying peer0Org1 discovers all the peers and the additional legacy chaincode installed on peer1Org1") 154 Eventually(nwo.DiscoverPeers(network, peer0Org1, "User1", "testchannel"), network.EventuallyTimeout).Should(ConsistOf( 155 network.DiscoveredPeer(peer0Org1, "_lifecycle", "mycc"), 156 network.DiscoveredPeer(peer1Org1, "_lifecycle", "mycc"), 157 network.DiscoveredPeer(peer0Org2, "_lifecycle"), 158 network.DiscoveredPeer(peer1Org2, "_lifecycle"), 159 )) 160 161 By("stopping peer0Org1 (currently elected leader in Org1) and peer1Org2 (static leader in Org2)") 162 stopPeers(nwprocs, peer0Org1, peer1Org2) 163 164 By("confirming peer1Org1 was elected to be a leader") 165 Eventually(nwprocs.peerRunners[peer1Org1.ID()].Err(), network.EventuallyTimeout).Should(gbytes.Say(expectedMsg)) 166 167 // Note that with the static leader in Org2 down, the static follower peer0Org2 will also get blocks via state transfer 168 // This effectively tests leader election as well, since the newly elected leader in Org1 (peer1Org1) will be the only peer 169 // that receives blocks from orderer and will therefore serve as the provider of blocks to all other peers. 170 sendTransactionsAndSyncUpPeers(nwprocs, orderer, basePeerForTransactions, channelName, peer0Org1, peer1Org2) 171 172 By("verifying peer0Org1 can still discover all the peers and the legacy chaincode after it has been restarted") 173 Eventually(nwo.DiscoverPeers(network, peer0Org1, "User1", "testchannel"), network.EventuallyTimeout).Should(ConsistOf( 174 network.DiscoveredPeer(peer0Org1, "_lifecycle", "mycc"), 175 network.DiscoveredPeer(peer1Org1, "_lifecycle", "mycc"), 176 network.DiscoveredPeer(peer0Org2, "_lifecycle"), 177 network.DiscoveredPeer(peer1Org2, "_lifecycle"), 178 )) 179 }) 180 181 When("gossip connection is lost and restored", func() { 182 var ( 183 orderer *nwo.Orderer 184 peerEndpoints map[string]string = map[string]string{} 185 ) 186 187 BeforeEach(func() { 188 // modify peer config 189 for _, peer := range network.Peers { 190 core := network.ReadPeerConfig(peer) 191 core.Peer.Gossip.AliveTimeInterval = 1 * time.Second 192 core.Peer.Gossip.AliveExpirationTimeout = 2 * core.Peer.Gossip.AliveTimeInterval 193 core.Peer.Gossip.ReconnectInterval = 2 * time.Second 194 core.Peer.Gossip.MsgExpirationFactor = 2 195 core.Peer.Gossip.MaxConnectionAttempts = 10 196 network.WritePeerConfig(peer, core) 197 peerEndpoints[peer.ID()] = core.Peer.Address 198 } 199 200 network.Bootstrap() 201 orderer = network.Orderer("orderer") 202 nwprocs.ordererRunner = network.OrdererRunner(orderer) 203 nwprocs.ordererProcess = ifrit.Invoke(nwprocs.ordererRunner) 204 Eventually(nwprocs.ordererProcess.Ready(), network.EventuallyTimeout).Should(BeClosed()) 205 }) 206 207 It("updates membership when peers in the same org are stopped and restarted", func() { 208 peer0Org1 := network.Peer("Org1", "peer0") 209 peer1Org1 := network.Peer("Org1", "peer1") 210 211 By("bringing up all peers") 212 startPeers(nwprocs, false, peer0Org1, peer1Org1) 213 214 By("creating and joining a channel") 215 network.CreateChannel(channelName, orderer, peer0Org1) 216 network.JoinChannel(channelName, orderer, peer0Org1, peer1Org1) 217 network.UpdateChannelAnchors(orderer, channelName) 218 219 By("verifying peer1Org1 discovers all the peers before testing membership change on it") 220 Eventually(nwo.DiscoverPeers(network, peer1Org1, "User1", "testchannel"), network.EventuallyTimeout).Should(ConsistOf( 221 network.DiscoveredPeer(peer0Org1, "_lifecycle"), 222 network.DiscoveredPeer(peer1Org1, "_lifecycle"), 223 )) 224 225 By("verifying membership change on peer1Org1 when an anchor peer in the same org is stopped and restarted") 226 expectedMsgFromExpirationCallback := fmt.Sprintf("Do not remove bootstrap or anchor peer endpoint %s from membership", peerEndpoints[peer0Org1.ID()]) 227 assertPeerMembershipUpdate(network, peer1Org1, []*nwo.Peer{peer0Org1}, nwprocs, expectedMsgFromExpirationCallback) 228 229 By("verifying peer0Org1 discovers all the peers before testing membership change on it") 230 Eventually(nwo.DiscoverPeers(network, peer0Org1, "User1", "testchannel"), network.EventuallyTimeout).Should(ConsistOf( 231 network.DiscoveredPeer(peer0Org1, "_lifecycle"), 232 network.DiscoveredPeer(peer1Org1, "_lifecycle"), 233 )) 234 235 By("verifying membership change on peer0Org1 when a non-anchor peer in the same org is stopped and restarted") 236 expectedMsgFromExpirationCallback = fmt.Sprintf("Removing member: Endpoint: %s", peerEndpoints[peer1Org1.ID()]) 237 assertPeerMembershipUpdate(network, peer0Org1, []*nwo.Peer{peer1Org1}, nwprocs, expectedMsgFromExpirationCallback) 238 }) 239 240 It("updates peer membership when peers in another org are stopped and restarted", func() { 241 peer0Org1, peer1Org1 := network.Peer("Org1", "peer0"), network.Peer("Org1", "peer1") 242 peer0Org2, peer1Org2 := network.Peer("Org2", "peer0"), network.Peer("Org2", "peer1") 243 244 By("bringing up all peers") 245 startPeers(nwprocs, false, peer0Org1, peer1Org1, peer0Org2, peer1Org2) 246 247 By("creating and joining a channel") 248 network.CreateChannel(channelName, orderer, peer0Org1) 249 network.JoinChannel(channelName, orderer, peer0Org1, peer1Org1, peer0Org2, peer1Org2) 250 network.UpdateChannelAnchors(orderer, channelName) 251 252 By("verifying membership on peer1Org1") 253 Eventually(nwo.DiscoverPeers(network, peer1Org1, "User1", "testchannel"), network.EventuallyTimeout).Should(ConsistOf( 254 network.DiscoveredPeer(peer0Org1, "_lifecycle"), 255 network.DiscoveredPeer(peer1Org1, "_lifecycle"), 256 network.DiscoveredPeer(peer0Org2, "_lifecycle"), 257 network.DiscoveredPeer(peer1Org2, "_lifecycle"), 258 )) 259 260 By("stopping anchor peer peer0Org1 to have only one peer in org1") 261 stopPeers(nwprocs, peer0Org1) 262 263 By("verifying peer membership update when peers in another org are stopped and restarted") 264 expectedMsgFromExpirationCallback := fmt.Sprintf("Do not remove bootstrap or anchor peer endpoint %s from membership", peerEndpoints[peer0Org2.ID()]) 265 assertPeerMembershipUpdate(network, peer1Org1, []*nwo.Peer{peer0Org2, peer1Org2}, nwprocs, expectedMsgFromExpirationCallback) 266 }) 267 }) 268 }) 269 270 func runTransactions(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, chaincodeName string, channelID string) { 271 for i := 0; i < 5; i++ { 272 sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{ 273 ChannelID: channelID, 274 Orderer: n.OrdererAddress(orderer, nwo.ListenPort), 275 Name: chaincodeName, 276 Ctor: `{"Args":["invoke","a","b","10"]}`, 277 PeerAddresses: []string{ 278 n.PeerAddress(peer, nwo.ListenPort), 279 }, 280 WaitForEvent: true, 281 }) 282 Expect(err).NotTo(HaveOccurred()) 283 Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0)) 284 Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:200")) 285 } 286 } 287 288 // networkProcesses holds references to the network, its runners, and processes. 289 type networkProcesses struct { 290 network *nwo.Network 291 292 ordererRunner *ginkgomon.Runner 293 ordererProcess ifrit.Process 294 295 peerRunners map[string]*ginkgomon.Runner 296 peerProcesses map[string]ifrit.Process 297 } 298 299 func (n *networkProcesses) terminateAll() { 300 if n.ordererProcess != nil { 301 n.ordererProcess.Signal(syscall.SIGTERM) 302 Eventually(n.ordererProcess.Wait(), n.network.EventuallyTimeout).Should(Receive()) 303 } 304 for _, process := range n.peerProcesses { 305 process.Signal(syscall.SIGTERM) 306 Eventually(process.Wait(), n.network.EventuallyTimeout).Should(Receive()) 307 } 308 } 309 310 func startPeers(n *networkProcesses, forceStateTransfer bool, peersToStart ...*nwo.Peer) { 311 env := []string{"FABRIC_LOGGING_SPEC=info:gossip.state=debug:gossip.discovery=debug"} 312 313 // Setting CORE_PEER_GOSSIP_STATE_CHECKINTERVAL to 200ms (from default of 10s) will ensure that state transfer happens quickly, 314 // before blocks are gossipped through normal mechanisms 315 if forceStateTransfer { 316 env = append(env, "CORE_PEER_GOSSIP_STATE_CHECKINTERVAL=200ms") 317 } 318 319 for _, peer := range peersToStart { 320 runner := n.network.PeerRunner(peer, env...) 321 process := ifrit.Invoke(runner) 322 Eventually(process.Ready(), n.network.EventuallyTimeout).Should(BeClosed()) 323 324 n.peerProcesses[peer.ID()] = process 325 n.peerRunners[peer.ID()] = runner 326 } 327 } 328 329 func stopPeers(n *networkProcesses, peersToStop ...*nwo.Peer) { 330 for _, peer := range peersToStop { 331 id := peer.ID() 332 proc := n.peerProcesses[id] 333 proc.Signal(syscall.SIGTERM) 334 Eventually(proc.Wait(), n.network.EventuallyTimeout).Should(Receive()) 335 delete(n.peerProcesses, id) 336 } 337 } 338 339 func assertPeersLedgerHeight(n *nwo.Network, peersToSyncUp []*nwo.Peer, expectedVal int, channelID string) { 340 for _, peer := range peersToSyncUp { 341 Eventually(func() int { 342 return nwo.GetLedgerHeight(n, peer, channelID) 343 }, n.EventuallyTimeout).Should(Equal(expectedVal)) 344 } 345 } 346 347 // send transactions, stop orderering server, then start peers to ensure they received blcoks via state transfer 348 func sendTransactionsAndSyncUpPeers(n *networkProcesses, orderer *nwo.Orderer, basePeer *nwo.Peer, channelName string, peersToSyncUp ...*nwo.Peer) { 349 By("creating transactions") 350 runTransactions(n.network, orderer, basePeer, "mycc", channelName) 351 basePeerLedgerHeight := nwo.GetLedgerHeight(n.network, basePeer, channelName) 352 353 By("stopping orderer") 354 n.ordererProcess.Signal(syscall.SIGTERM) 355 Eventually(n.ordererProcess.Wait(), n.network.EventuallyTimeout).Should(Receive()) 356 n.ordererProcess = nil 357 358 By("starting the peers contained in the peersToSyncUp list") 359 startPeers(n, true, peersToSyncUp...) 360 361 By("ensuring the peers are synced up") 362 assertPeersLedgerHeight(n.network, peersToSyncUp, basePeerLedgerHeight, channelName) 363 364 By("restarting orderer") 365 n.ordererRunner = n.network.OrdererRunner(orderer) 366 n.ordererProcess = ifrit.Invoke(n.ordererRunner) 367 Eventually(n.ordererProcess.Ready(), n.network.EventuallyTimeout).Should(BeClosed()) 368 } 369 370 // assertPeerMembershipUpdate stops and restart peersToRestart and verify peer membership 371 func assertPeerMembershipUpdate(network *nwo.Network, peer *nwo.Peer, peersToRestart []*nwo.Peer, nwprocs *networkProcesses, expectedMsgFromExpirationCallback string) { 372 stopPeers(nwprocs, peersToRestart...) 373 374 // timeout is the same amount of time as it takes to remove a message from the aliveMsgStore, and add a second as buffer 375 core := network.ReadPeerConfig(peer) 376 timeout := core.Peer.Gossip.AliveExpirationTimeout*time.Duration(core.Peer.Gossip.MsgExpirationFactor) + time.Second 377 By("verifying peer membership after all other peers are stopped") 378 Eventually(nwo.DiscoverPeers(network, peer, "User1", "testchannel"), timeout, 100*time.Millisecond).Should(ConsistOf( 379 network.DiscoveredPeer(peer, "_lifecycle"), 380 )) 381 382 By("verifying expected log message from expiration callback") 383 runner := nwprocs.peerRunners[peer.ID()] 384 Eventually(runner.Err(), network.EventuallyTimeout).Should(gbytes.Say(expectedMsgFromExpirationCallback)) 385 386 By("restarting peers") 387 startPeers(nwprocs, false, peersToRestart...) 388 389 By("verifying peer membership, expected to discover restarted peers") 390 expectedPeers := make([]nwo.DiscoveredPeer, len(peersToRestart)+1) 391 expectedPeers[0] = network.DiscoveredPeer(peer, "_lifecycle") 392 for i, p := range peersToRestart { 393 expectedPeers[i+1] = network.DiscoveredPeer(p, "_lifecycle") 394 } 395 timeout = 3 * core.Peer.Gossip.ReconnectInterval 396 Eventually(nwo.DiscoverPeers(network, peer, "User1", "testchannel"), timeout, 100*time.Millisecond).Should(ConsistOf(expectedPeers)) 397 }