github.com/lzy4123/fabric@v2.1.1+incompatible/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("STATE TRANSFER TEST 1: newly joined peers should receive blocks from the peers that are already up") 138 139 // Note, a better test would be to bring orderer down before joining the two peers. 140 // However, network.JoinChannel() requires orderer to be up so that genesis block can be fetched from orderer before joining peers. 141 // Therefore, for now we've joined all four peers and stop the two peers that should be synced up. 142 peersToStop := []*nwo.Peer{peer1Org1, peer1Org2} 143 stopPeers(network, peersToStop, peerProcesses) 144 145 By("confirm peer0Org1 elected to be a leader") 146 expectedMsg := "Elected as a leader, starting delivery service for channel testchannel" 147 Eventually(peerRunners[peer0Org1.ID()].Err(), network.EventuallyTimeout).Should(gbytes.Say(expectedMsg)) 148 149 peersToSyncUp := []*nwo.Peer{peer1Org1, peer1Org2} 150 sendTransactionsAndSyncUpPeers(network, orderer, basePeerForTransactions, peersToSyncUp, channelName, &ordererProcess, ordererRunner, peerProcesses, peerRunners) 151 152 By("STATE TRANSFER TEST 2: restarted peers should receive blocks from the peers that are already up") 153 basePeerForTransactions = peer1Org1 154 nwo.InstallChaincodeLegacy(network, chaincode, basePeerForTransactions) 155 156 By("stop peer0Org1 (currently elected leader in Org1) and peer1Org2 (static leader in Org2)") 157 peersToStop = []*nwo.Peer{peer0Org1, peer1Org2} 158 stopPeers(network, peersToStop, peerProcesses) 159 160 By("confirm peer1Org1 elected to be a leader") 161 Eventually(peerRunners[peer1Org1.ID()].Err(), network.EventuallyTimeout).Should(gbytes.Say(expectedMsg)) 162 163 peersToSyncUp = []*nwo.Peer{peer0Org1, peer1Org2} 164 // Note that with the static leader in Org2 down, the static follower peer0Org2 will also get blocks via state transfer 165 // This effectively tests leader election as well, since the newly elected leader in Org1 (peer1Org1) will be the only peer 166 // that receives blocks from orderer and will therefore serve as the provider of blocks to all other peers. 167 sendTransactionsAndSyncUpPeers(network, orderer, basePeerForTransactions, peersToSyncUp, channelName, &ordererProcess, ordererRunner, peerProcesses, peerRunners) 168 169 }) 170 171 }) 172 }) 173 174 func runTransactions(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, chaincodeName string, channelID string) { 175 for i := 0; i < 5; i++ { 176 sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{ 177 ChannelID: channelID, 178 Orderer: n.OrdererAddress(orderer, nwo.ListenPort), 179 Name: chaincodeName, 180 Ctor: `{"Args":["invoke","a","b","10"]}`, 181 PeerAddresses: []string{ 182 n.PeerAddress(peer, nwo.ListenPort), 183 }, 184 WaitForEvent: true, 185 }) 186 Expect(err).NotTo(HaveOccurred()) 187 Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0)) 188 Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:200")) 189 } 190 } 191 192 func startPeers(network *nwo.Network, peersToStart []*nwo.Peer, peerProc map[string]ifrit.Process, peerRun map[string]*ginkgomon.Runner, forceStateTransfer bool) { 193 194 env := []string{fmt.Sprint("FABRIC_LOGGING_SPEC=info:gossip.state=debug")} 195 196 // Setting CORE_PEER_GOSSIP_STATE_CHECKINTERVAL to 200ms (from default of 10s) will ensure that state transfer happens quickly, 197 // before blocks are gossipped through normal mechanisms 198 if forceStateTransfer { 199 env = append(env, fmt.Sprint("CORE_PEER_GOSSIP_STATE_CHECKINTERVAL=200ms")) 200 } 201 202 for _, peer := range peersToStart { 203 runner := network.PeerRunner(peer, env...) 204 process := ifrit.Invoke(runner) 205 Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed()) 206 207 peerProc[peer.ID()] = process 208 peerRun[peer.ID()] = runner 209 } 210 } 211 212 func stopPeers(network *nwo.Network, peersToStop []*nwo.Peer, peerProcesses map[string]ifrit.Process) { 213 for _, peer := range peersToStop { 214 id := peer.ID() 215 proc := peerProcesses[id] 216 proc.Signal(syscall.SIGTERM) 217 Eventually(proc.Wait(), network.EventuallyTimeout).Should(Receive()) 218 delete(peerProcesses, id) 219 } 220 } 221 222 func assertPeersLedgerHeight(n *nwo.Network, orderer *nwo.Orderer, peersToSyncUp []*nwo.Peer, expectedVal int, channelID string) { 223 for _, peer := range peersToSyncUp { 224 Eventually(func() int { 225 return nwo.GetLedgerHeight(n, peer, channelID) 226 }, n.EventuallyTimeout).Should(Equal(expectedVal)) 227 } 228 } 229 230 // send transactions, stop orderering server, then start peers to ensure they received blcoks via state transfer 231 func sendTransactionsAndSyncUpPeers(network *nwo.Network, orderer *nwo.Orderer, basePeer *nwo.Peer, peersToSyncUp []*nwo.Peer, channelName string, 232 ordererProcess *ifrit.Process, ordererRunner *ginkgomon.Runner, 233 peerProcesses map[string]ifrit.Process, peerRunners map[string]*ginkgomon.Runner) { 234 235 By("create transactions") 236 runTransactions(network, orderer, basePeer, "mycc", channelName) 237 basePeerLedgerHeight := nwo.GetLedgerHeight(network, basePeer, channelName) 238 239 By("stop orderer") 240 (*ordererProcess).Signal(syscall.SIGTERM) 241 Eventually((*ordererProcess).Wait(), network.EventuallyTimeout).Should(Receive()) 242 *ordererProcess = nil 243 244 By("start the peers contained in the peersToSyncUp list") 245 startPeers(network, peersToSyncUp, peerProcesses, peerRunners, true) 246 247 By("ensure the peers are synced up") 248 assertPeersLedgerHeight(network, orderer, peersToSyncUp, basePeerLedgerHeight, channelName) 249 250 By("restart orderer") 251 orderer = network.Orderer("orderer") 252 ordererRunner = network.OrdererRunner(orderer) 253 *ordererProcess = ifrit.Invoke(ordererRunner) 254 Eventually((*ordererProcess).Ready(), network.EventuallyTimeout).Should(BeClosed()) 255 }