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  }