@@ -63,7 +63,7 @@ var _ = Describe("Gossip Test", func() {
63
63
os .RemoveAll (testDir )
64
64
})
65
65
66
- PDescribe ("State transfer test" , func () {
66
+ PDescribe ("Gossip state transfer test" , func () {
67
67
var (
68
68
ordererProcess ifrit.Process
69
69
peerProcesses = map [string ]ifrit.Process {}
@@ -74,6 +74,32 @@ var _ = Describe("Gossip Test", func() {
74
74
network = nwo .New (nwo .BasicSolo (), testDir , client , StartPort (), components )
75
75
76
76
network .GenerateConfigTree ()
77
+ // modify peer config
78
+ // Org1: leader election
79
+ // Org2: no leader election
80
+ // peer0: follower
81
+ // peer1: leader
82
+ for _ , peer := range network .Peers {
83
+ if peer .Organization == "Org1" {
84
+ core := network .ReadPeerConfig (peer )
85
+ if peer .Name == "peer1" {
86
+ core .Peer .Gossip .Bootstrap = "127.0.0.1:21004"
87
+ network .WritePeerConfig (peer , core )
88
+ }
89
+
90
+ }
91
+ if peer .Organization == "Org2" {
92
+ core := network .ReadPeerConfig (peer )
93
+ core .Peer .Gossip .UseLeaderElection = false
94
+ if peer .Name == "peer1" {
95
+ core .Peer .Gossip .OrgLeader = true
96
+ } else {
97
+ core .Peer .Gossip .OrgLeader = false
98
+ }
99
+
100
+ network .WritePeerConfig (peer , core )
101
+ }
102
+ }
77
103
network .Bootstrap ()
78
104
})
79
105
@@ -89,101 +115,61 @@ var _ = Describe("Gossip Test", func() {
89
115
}
90
116
})
91
117
92
- It ("solo network with 2 orgs, 2 peers each, should sync from the peer if no orderer available " , func () {
118
+ It ("syncs blocks from the peer if no orderer is available, using solo network with 2 orgs, 2 peers each " , func () {
93
119
orderer := network .Orderer ("orderer" )
94
120
ordererRunner := network .OrdererRunner (orderer )
95
121
ordererProcess = ifrit .Invoke (ordererRunner )
96
122
97
123
peer0Org1 , peer1Org1 := network .Peer ("Org1" , "peer0" ), network .Peer ("Org1" , "peer1" )
98
124
peer0Org2 , peer1Org2 := network .Peer ("Org2" , "peer0" ), network .Peer ("Org2" , "peer1" )
99
125
100
- for _ , peer := range []* nwo.Peer {peer0Org1 , peer1Org1 , peer0Org2 , peer1Org2 } {
101
- runner := network .PeerRunner (peer )
102
- peerProcesses [peer .ID ()] = ifrit .Invoke (runner )
103
- peerRunners [peer .ID ()] = runner
104
- }
126
+ By ("bring up all four peers" )
127
+ peersToBringUp := []* nwo.Peer {peer0Org1 , peer1Org1 , peer0Org2 , peer1Org2 }
128
+ startPeers (network , peersToBringUp , peerProcesses , peerRunners , false )
105
129
106
130
channelName := "testchannel"
107
131
network .CreateChannel (channelName , orderer , peer0Org1 )
132
+ By ("join all peers to channel" )
108
133
network .JoinChannel (channelName , orderer , peer0Org1 , peer1Org1 , peer0Org2 , peer1Org2 )
109
134
110
- nwo .DeployChaincodeLegacy (network , channelName , orderer , chaincode , peer0Org1 )
111
135
network .UpdateChannelAnchors (orderer , channelName )
112
136
113
- for _ , peer := range []* nwo.Peer {peer0Org1 , peer1Org1 , peer0Org2 , peer1Org2 } {
114
- Eventually (func () int {
115
- return nwo .GetLedgerHeight (network , peer , channelName )
116
- }, network .EventuallyTimeout ).Should (BeNumerically (">=" , 2 ))
117
- }
118
-
119
- By ("stop peers except peer0Org1 to make sure they cannot get blocks from orderer" )
120
- for id , proc := range peerProcesses {
121
- if id == peer0Org1 .ID () {
122
- continue
123
- }
124
- proc .Signal (syscall .SIGTERM )
125
- Eventually (proc .Wait (), network .EventuallyTimeout ).Should (Receive ())
126
- delete (peerProcesses , id )
127
- }
128
-
129
- By ("create transactions" )
130
- runTransactions (network , orderer , peer0Org1 , "mycc" , channelName )
131
-
132
- peer0LedgerHeight := nwo .GetLedgerHeight (network , peer0Org1 , channelName )
133
-
134
- By ("turning down ordering service" )
135
- ordererProcess .Signal (syscall .SIGTERM )
136
- Eventually (ordererProcess .Wait (), network .EventuallyTimeout ).Should (Receive ())
137
- ordererProcess = nil
138
-
139
- By ("restart the three peers that were stopped" )
140
- peerList := []* nwo.Peer {peer1Org1 , peer0Org2 , peer1Org2 }
141
- peersRestart (network , orderer , peerList , peerProcesses , peerRunners )
142
-
143
- By ("Make sure peers are synced up" )
144
- assertPeersLedgerHeight (network , orderer , peerList , peer0LedgerHeight , channelName )
145
-
146
- By ("start the orderer" )
147
- orderer = network .Orderer ("orderer" )
148
- ordererRunner = network .OrdererRunner (orderer )
149
- ordererProcess = ifrit .Invoke (ordererRunner )
150
-
151
- By ("install chaincode" )
152
- nwo .InstallChaincodeLegacy (network , chaincode , peer1Org1 )
153
-
154
- By ("stop leader, peer0Org1, to make sure it cannot get blocks from orderer" )
155
- id := peer0Org1 .ID ()
156
- proc := peerProcesses [id ]
157
- proc .Signal (syscall .SIGTERM )
158
- Eventually (proc .Wait (), network .EventuallyTimeout ).Should (Receive ())
137
+ // base peer will be used for chaincode interactions
138
+ basePeerForTransactions := peer0Org1
139
+ nwo .DeployChaincodeLegacy (network , channelName , orderer , chaincode , basePeerForTransactions )
159
140
160
- expectedMsg := "Stopped being a leader"
161
- Eventually (peerRunners [id ].Err (), network .EventuallyTimeout ).Should (gbytes .Say (expectedMsg ))
141
+ By ("STATE TRANSFER TEST 1: newly joined peers should receive blocks from the peers that are already up" )
162
142
163
- delete (peerProcesses , id )
143
+ // Note, a better test would be to bring orderer down before joining the two peers.
144
+ // However, network.JoinChannel() requires orderer to be up so that genesis block can be fetched from orderer before joining peers.
145
+ // Therefore, for now we've joined all four peers and stop the two peers that should be synced up.
146
+ peersToStop := []* nwo.Peer {peer1Org1 , peer1Org2 }
147
+ stopPeers (network , peersToStop , peerProcesses )
164
148
165
- By ( "create transactions" )
166
- runTransactions (network , orderer , peer1Org1 , "mycc" , channelName )
149
+ peersToSyncUp := [] * nwo. Peer { peer1Org1 , peer1Org2 }
150
+ sendTransactionsAndSyncUpPeers (network , orderer , basePeerForTransactions , peersToSyncUp , channelName , & ordererProcess , ordererRunner , peerProcesses , peerRunners )
167
151
168
- peer1LedgerHeight := nwo .GetLedgerHeight (network , peer1Org1 , channelName )
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 )
169
155
170
- By ("turning down ordering service" )
171
- ordererProcess .Signal (syscall .SIGTERM )
172
- Eventually (ordererProcess .Wait (), network .EventuallyTimeout ).Should (Receive ())
173
- ordererProcess = nil
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 )
174
159
175
- By ("restart peer0Org1" )
176
- peerList = []* nwo.Peer {peer0Org1 }
177
- peersRestart (network , orderer , peerList , peerProcesses , peerRunners )
160
+ peersToSyncUp = []* nwo.Peer {peer0Org1 , peer1Org2 }
161
+ // Note that with the static leader in Org2 down, the static follower peer0Org2 will also get blocks via state transfer
162
+ // This effectively tests leader election as well, since the newly elected leader in Org1 (peer1Org1) will be the only peer
163
+ // that receives blocks from orderer and will therefore serve as the provider of blocks to all other peers.
164
+ sendTransactionsAndSyncUpPeers (network , orderer , basePeerForTransactions , peersToSyncUp , channelName , & ordererProcess , ordererRunner , peerProcesses , peerRunners )
178
165
179
- By ("Make sure peer0Org1 is synced up" )
180
- assertPeersLedgerHeight (network , orderer , peerList , peer1LedgerHeight , channelName )
181
166
})
167
+
182
168
})
183
169
})
184
170
185
171
func runTransactions (n * nwo.Network , orderer * nwo.Orderer , peer * nwo.Peer , chaincodeName string , channelID string ) {
186
- for i := 0 ; i < 10 ; i ++ {
172
+ for i := 0 ; i < 5 ; i ++ {
187
173
sess , err := n .PeerUserSession (peer , "User1" , commands.ChaincodeInvoke {
188
174
ChannelID : channelID ,
189
175
Orderer : n .OrdererAddress (orderer , nwo .ListenPort ),
@@ -200,20 +186,64 @@ func runTransactions(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, chain
200
186
}
201
187
}
202
188
203
- func peersRestart (n * nwo.Network , orderer * nwo.Orderer , peerList []* nwo.Peer , peerProc map [string ]ifrit.Process , peerRun map [string ]* ginkgomon.Runner ) {
204
- for _ , peer := range peerList {
205
- runner := n .PeerRunner (peer , fmt .Sprint ("CORE_PEER_GOSSIP_STATE_CHECKINTERVAL=200ms" ),
206
- fmt .Sprint ("FABRIC_LOGGING_SPEC=info:gossip.state=debug" ),
207
- )
189
+ func startPeers (network * nwo.Network , peersToStart []* nwo.Peer , peerProc map [string ]ifrit.Process , peerRun map [string ]* ginkgomon.Runner , forceStateTransfer bool ) {
190
+
191
+ env := []string {fmt .Sprint ("FABRIC_LOGGING_SPEC=info:gossip.state=debug" )}
192
+
193
+ // Setting CORE_PEER_GOSSIP_STATE_CHECKINTERVAL to 200ms (from default of 10s) will ensure that state transfer happens quickly,
194
+ // before blocks are gossipped through normal mechanisms
195
+ if forceStateTransfer {
196
+ env = append (env , fmt .Sprint ("CORE_PEER_GOSSIP_STATE_CHECKINTERVAL=200ms" ))
197
+ }
198
+
199
+ for _ , peer := range peersToStart {
200
+ runner := network .PeerRunner (peer , env ... )
208
201
peerProc [peer .ID ()] = ifrit .Invoke (runner )
209
202
peerRun [peer .ID ()] = runner
210
203
}
211
204
}
212
205
213
- func assertPeersLedgerHeight (n * nwo.Network , orderer * nwo.Orderer , peerList []* nwo.Peer , expectedVal int , channelID string ) {
214
- for _ , peer := range peerList {
206
+ func stopPeers (network * nwo.Network , peersToStop []* nwo.Peer , peerProcesses map [string ]ifrit.Process ) {
207
+ for _ , peer := range peersToStop {
208
+ id := peer .ID ()
209
+ proc := peerProcesses [id ]
210
+ proc .Signal (syscall .SIGTERM )
211
+ Eventually (proc .Wait (), network .EventuallyTimeout ).Should (Receive ())
212
+ delete (peerProcesses , id )
213
+ }
214
+ }
215
+
216
+ func assertPeersLedgerHeight (n * nwo.Network , orderer * nwo.Orderer , peersToSyncUp []* nwo.Peer , expectedVal int , channelID string ) {
217
+ for _ , peer := range peersToSyncUp {
215
218
Eventually (func () int {
216
219
return nwo .GetLedgerHeight (n , peer , channelID )
217
220
}, n .EventuallyTimeout ).Should (Equal (expectedVal ))
218
221
}
219
222
}
223
+
224
+ // send transactions, stop orderering server, then start peers to ensure they received blcoks via state transfer
225
+ func sendTransactionsAndSyncUpPeers (network * nwo.Network , orderer * nwo.Orderer , basePeer * nwo.Peer , peersToSyncUp []* nwo.Peer , channelName string ,
226
+ ordererProcess * ifrit.Process , ordererRunner * ginkgomon.Runner ,
227
+ peerProcesses map [string ]ifrit.Process , peerRunners map [string ]* ginkgomon.Runner ) {
228
+
229
+ By ("create transactions" )
230
+ runTransactions (network , orderer , basePeer , "mycc" , channelName )
231
+ basePeerLedgerHeight := nwo .GetLedgerHeight (network , basePeer , channelName )
232
+
233
+ By ("stop orderer" )
234
+ (* ordererProcess ).Signal (syscall .SIGTERM )
235
+ Eventually ((* ordererProcess ).Wait (), network .EventuallyTimeout ).Should (Receive ())
236
+ * ordererProcess = nil
237
+
238
+ By ("start the peers contained in the peersToSyncUp list" )
239
+ startPeers (network , peersToSyncUp , peerProcesses , peerRunners , true )
240
+
241
+ By ("ensure the peers are synced up" )
242
+ assertPeersLedgerHeight (network , orderer , peersToSyncUp , basePeerLedgerHeight , channelName )
243
+
244
+ By ("restart orderer" )
245
+ orderer = network .Orderer ("orderer" )
246
+ ordererRunner = network .OrdererRunner (orderer )
247
+ * ordererProcess = ifrit .Invoke (ordererRunner )
248
+
249
+ }
0 commit comments