github.com/Hnampk/my-fabric@v0.0.0-20201028083322-75069da399c0/integration/gossip/gossip_test.go (about) 1 /* 2 * 3 * Copyright IBM Corp. All Rights Reserved. 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 * / 7 * 8 */ 9 10 package gossip 11 12 import ( 13 "fmt" 14 "io/ioutil" 15 "os" 16 "syscall" 17 18 docker "github.com/fsouza/go-dockerclient" 19 "github.com/hyperledger/fabric/integration/nwo" 20 "github.com/hyperledger/fabric/integration/nwo/commands" 21 . "github.com/onsi/ginkgo" 22 . "github.com/onsi/gomega" 23 "github.com/onsi/gomega/gbytes" 24 "github.com/onsi/gomega/gexec" 25 "github.com/tedsuo/ifrit" 26 "github.com/tedsuo/ifrit/ginkgomon" 27 ) 28 29 var _ = Describe("Gossip Test", func() { 30 var ( 31 testDir string 32 client *docker.Client 33 network *nwo.Network 34 chaincode nwo.Chaincode 35 ) 36 37 BeforeEach(func() { 38 var err error 39 testDir, err = ioutil.TempDir("", "e2e") 40 Expect(err).NotTo(HaveOccurred()) 41 42 client, err = docker.NewClientFromEnv() 43 Expect(err).NotTo(HaveOccurred()) 44 45 chaincode = nwo.Chaincode{ 46 Name: "mycc", 47 Version: "0.0", 48 Path: "github.com/hyperledger/fabric/integration/chaincode/simple/cmd", 49 Ctor: `{"Args":["init","a","100","b","200"]}`, 50 Policy: `OR ('Org1MSP.member','Org2MSP.member')`, 51 } 52 }) 53 54 AfterEach(func() { 55 if network != nil { 56 network.Cleanup() 57 } 58 os.RemoveAll(testDir) 59 }) 60 61 Describe("Gossip state transfer test", func() { 62 var ( 63 ordererProcess ifrit.Process 64 peerProcesses = map[string]ifrit.Process{} 65 peerRunners = map[string]*ginkgomon.Runner{} 66 ) 67 68 BeforeEach(func() { 69 network = nwo.New(nwo.FullSolo(), testDir, client, StartPort(), components) 70 71 network.GenerateConfigTree() 72 // modify peer config 73 // Org1: leader election 74 // Org2: no leader election 75 // peer0: follower 76 // peer1: leader 77 for _, peer := range network.Peers { 78 if peer.Organization == "Org1" { 79 core := network.ReadPeerConfig(peer) 80 if peer.Name == "peer1" { 81 core.Peer.Gossip.Bootstrap = "127.0.0.1:21004" 82 network.WritePeerConfig(peer, core) 83 } 84 85 } 86 if peer.Organization == "Org2" { 87 core := network.ReadPeerConfig(peer) 88 core.Peer.Gossip.UseLeaderElection = false 89 if peer.Name == "peer1" { 90 core.Peer.Gossip.OrgLeader = true 91 } else { 92 core.Peer.Gossip.OrgLeader = false 93 } 94 95 network.WritePeerConfig(peer, core) 96 } 97 } 98 network.Bootstrap() 99 }) 100 101 AfterEach(func() { 102 if ordererProcess != nil { 103 ordererProcess.Signal(syscall.SIGTERM) 104 Eventually(ordererProcess.Wait(), network.EventuallyTimeout).Should(Receive()) 105 } 106 107 for _, process := range peerProcesses { 108 process.Signal(syscall.SIGTERM) 109 Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive()) 110 } 111 }) 112 113 It("syncs blocks from the peer if no orderer is available, using solo network with 2 orgs, 2 peers each", func() { 114 orderer := network.Orderer("orderer") 115 ordererRunner := network.OrdererRunner(orderer) 116 ordererProcess = ifrit.Invoke(ordererRunner) 117 Eventually(ordererProcess.Ready(), network.EventuallyTimeout).Should(BeClosed()) 118 119 peer0Org1, peer1Org1 := network.Peer("Org1", "peer0"), network.Peer("Org1", "peer1") 120 peer0Org2, peer1Org2 := network.Peer("Org2", "peer0"), network.Peer("Org2", "peer1") 121 122 By("bring up all four peers") 123 peersToBringUp := []*nwo.Peer{peer0Org1, peer1Org1, peer0Org2, peer1Org2} 124 startPeers(network, peersToBringUp, peerProcesses, peerRunners, false) 125 126 channelName := "testchannel" 127 network.CreateChannel(channelName, orderer, peer0Org1) 128 By("join all peers to channel") 129 network.JoinChannel(channelName, orderer, peer0Org1, peer1Org1, peer0Org2, peer1Org2) 130 131 network.UpdateChannelAnchors(orderer, channelName) 132 133 // base peer will be used for chaincode interactions 134 basePeerForTransactions := peer0Org1 135 nwo.DeployChaincodeLegacy(network, channelName, orderer, chaincode, basePeerForTransactions) 136 137 By("verifying peer0Org1 discovers all the peers and the legacy chaincode before starting the tests") 138 Eventually(nwo.DiscoverPeers(network, peer0Org1, "User1", "testchannel"), network.EventuallyTimeout).Should(ConsistOf( 139 network.DiscoveredPeer(peer0Org1, "_lifecycle", "mycc"), 140 network.DiscoveredPeer(peer1Org1, "_lifecycle"), 141 network.DiscoveredPeer(peer0Org2, "_lifecycle"), 142 network.DiscoveredPeer(peer1Org2, "_lifecycle"), 143 )) 144 145 By("STATE TRANSFER TEST 1: newly joined peers should receive blocks from the peers that are already up") 146 147 // Note, a better test would be to bring orderer down before joining the two peers. 148 // However, network.JoinChannel() requires orderer to be up so that genesis block can be fetched from orderer before joining peers. 149 // Therefore, for now we've joined all four peers and stop the two peers that should be synced up. 150 peersToStop := []*nwo.Peer{peer1Org1, peer1Org2} 151 stopPeers(network, peersToStop, peerProcesses) 152 153 By("confirm peer0Org1 elected to be a leader") 154 expectedMsg := "Elected as a leader, starting delivery service for channel testchannel" 155 Eventually(peerRunners[peer0Org1.ID()].Err(), network.EventuallyTimeout).Should(gbytes.Say(expectedMsg)) 156 157 peersToSyncUp := []*nwo.Peer{peer1Org1, peer1Org2} 158 sendTransactionsAndSyncUpPeers(network, orderer, basePeerForTransactions, peersToSyncUp, channelName, &ordererProcess, ordererRunner, peerProcesses, peerRunners) 159 160 By("STATE TRANSFER TEST 2: restarted peers should receive blocks from the peers that are already up") 161 basePeerForTransactions = peer1Org1 162 nwo.InstallChaincodeLegacy(network, chaincode, basePeerForTransactions) 163 164 By("verifying peer0Org1 discovers all the peers and the additional legacy chaincode installed on peer1Org1") 165 Eventually(nwo.DiscoverPeers(network, peer0Org1, "User1", "testchannel"), network.EventuallyTimeout).Should(ConsistOf( 166 network.DiscoveredPeer(peer0Org1, "_lifecycle", "mycc"), 167 network.DiscoveredPeer(peer1Org1, "_lifecycle", "mycc"), 168 network.DiscoveredPeer(peer0Org2, "_lifecycle"), 169 network.DiscoveredPeer(peer1Org2, "_lifecycle"), 170 )) 171 172 By("stop peer0Org1 (currently elected leader in Org1) and peer1Org2 (static leader in Org2)") 173 peersToStop = []*nwo.Peer{peer0Org1, peer1Org2} 174 stopPeers(network, peersToStop, peerProcesses) 175 176 By("confirm peer1Org1 elected to be a leader") 177 Eventually(peerRunners[peer1Org1.ID()].Err(), network.EventuallyTimeout).Should(gbytes.Say(expectedMsg)) 178 179 peersToSyncUp = []*nwo.Peer{peer0Org1, peer1Org2} 180 // Note that with the static leader in Org2 down, the static follower peer0Org2 will also get blocks via state transfer 181 // This effectively tests leader election as well, since the newly elected leader in Org1 (peer1Org1) will be the only peer 182 // that receives blocks from orderer and will therefore serve as the provider of blocks to all other peers. 183 sendTransactionsAndSyncUpPeers(network, orderer, basePeerForTransactions, peersToSyncUp, channelName, &ordererProcess, ordererRunner, peerProcesses, peerRunners) 184 185 By("verifying peer0Org1 can still discover all the peers and the legacy chaincode after it has been restarted") 186 Eventually(nwo.DiscoverPeers(network, peer0Org1, "User1", "testchannel"), network.EventuallyTimeout).Should(ConsistOf( 187 network.DiscoveredPeer(peer0Org1, "_lifecycle", "mycc"), 188 network.DiscoveredPeer(peer1Org1, "_lifecycle", "mycc"), 189 network.DiscoveredPeer(peer0Org2, "_lifecycle"), 190 network.DiscoveredPeer(peer1Org2, "_lifecycle"), 191 )) 192 }) 193 194 }) 195 }) 196 197 func runTransactions(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, chaincodeName string, channelID string) { 198 for i := 0; i < 5; i++ { 199 sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{ 200 ChannelID: channelID, 201 Orderer: n.OrdererAddress(orderer, nwo.ListenPort), 202 Name: chaincodeName, 203 Ctor: `{"Args":["invoke","a","b","10"]}`, 204 PeerAddresses: []string{ 205 n.PeerAddress(peer, nwo.ListenPort), 206 }, 207 WaitForEvent: true, 208 }) 209 Expect(err).NotTo(HaveOccurred()) 210 Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0)) 211 Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:200")) 212 } 213 } 214 215 func startPeers(network *nwo.Network, peersToStart []*nwo.Peer, peerProc map[string]ifrit.Process, peerRun map[string]*ginkgomon.Runner, forceStateTransfer bool) { 216 217 env := []string{fmt.Sprint("FABRIC_LOGGING_SPEC=info:gossip.state=debug")} 218 219 // Setting CORE_PEER_GOSSIP_STATE_CHECKINTERVAL to 200ms (from default of 10s) will ensure that state transfer happens quickly, 220 // before blocks are gossipped through normal mechanisms 221 if forceStateTransfer { 222 env = append(env, fmt.Sprint("CORE_PEER_GOSSIP_STATE_CHECKINTERVAL=200ms")) 223 } 224 225 for _, peer := range peersToStart { 226 runner := network.PeerRunner(peer, env...) 227 process := ifrit.Invoke(runner) 228 Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed()) 229 230 peerProc[peer.ID()] = process 231 peerRun[peer.ID()] = runner 232 } 233 } 234 235 func stopPeers(network *nwo.Network, peersToStop []*nwo.Peer, peerProcesses map[string]ifrit.Process) { 236 for _, peer := range peersToStop { 237 id := peer.ID() 238 proc := peerProcesses[id] 239 proc.Signal(syscall.SIGTERM) 240 Eventually(proc.Wait(), network.EventuallyTimeout).Should(Receive()) 241 delete(peerProcesses, id) 242 } 243 } 244 245 func assertPeersLedgerHeight(n *nwo.Network, orderer *nwo.Orderer, peersToSyncUp []*nwo.Peer, expectedVal int, channelID string) { 246 for _, peer := range peersToSyncUp { 247 Eventually(func() int { 248 return nwo.GetLedgerHeight(n, peer, channelID) 249 }, n.EventuallyTimeout).Should(Equal(expectedVal)) 250 } 251 } 252 253 // send transactions, stop orderering server, then start peers to ensure they received blcoks via state transfer 254 func sendTransactionsAndSyncUpPeers(network *nwo.Network, orderer *nwo.Orderer, basePeer *nwo.Peer, peersToSyncUp []*nwo.Peer, channelName string, 255 ordererProcess *ifrit.Process, ordererRunner *ginkgomon.Runner, 256 peerProcesses map[string]ifrit.Process, peerRunners map[string]*ginkgomon.Runner) { 257 258 By("create transactions") 259 runTransactions(network, orderer, basePeer, "mycc", channelName) 260 basePeerLedgerHeight := nwo.GetLedgerHeight(network, basePeer, channelName) 261 262 By("stop orderer") 263 (*ordererProcess).Signal(syscall.SIGTERM) 264 Eventually((*ordererProcess).Wait(), network.EventuallyTimeout).Should(Receive()) 265 *ordererProcess = nil 266 267 By("start the peers contained in the peersToSyncUp list") 268 startPeers(network, peersToSyncUp, peerProcesses, peerRunners, true) 269 270 By("ensure the peers are synced up") 271 assertPeersLedgerHeight(network, orderer, peersToSyncUp, basePeerLedgerHeight, channelName) 272 273 By("restart orderer") 274 orderer = network.Orderer("orderer") 275 ordererRunner = network.OrdererRunner(orderer) 276 *ordererProcess = ifrit.Invoke(ordererRunner) 277 Eventually((*ordererProcess).Ready(), network.EventuallyTimeout).Should(BeClosed()) 278 }