@@ -1179,6 +1179,73 @@ func TestReplicaCrash3(t *testing.T) {
1179
1179
}
1180
1180
}
1181
1181
1182
+ // TestReplicaCrash4 simulates the restart with no checkpoints
1183
+ // in the store because they have been garbage collected
1184
+ // the bug occurs because the low watermark is incorrectly set to
1185
+ // be zero
1186
+ func TestReplicaCrash4 (t * testing.T ) {
1187
+ validatorCount := 4
1188
+ config := loadConfig ()
1189
+ config .Set ("general.K" , 2 )
1190
+ config .Set ("general.logmultiplier" , 2 )
1191
+ net := makePBFTNetwork (validatorCount , config )
1192
+ defer net .stop ()
1193
+
1194
+ twoOffline := false
1195
+ threeOffline := true
1196
+ net .filterFn = func (src int , dst int , msg []byte ) []byte {
1197
+ if twoOffline && dst == 2 { // 2 is 'offline'
1198
+ return nil
1199
+ }
1200
+ if threeOffline && dst == 3 { // 3 is 'offline'
1201
+ return nil
1202
+ }
1203
+ return msg
1204
+ }
1205
+
1206
+ for i := int64 (1 ); i <= 8 ; i ++ {
1207
+ net .pbftEndpoints [0 ].manager .Queue () <- createPbftReqBatch (i , uint64 (generateBroadcaster (validatorCount )))
1208
+ }
1209
+ net .process () // vp0,1,2 should have a stable checkpoint for seqNo 8
1210
+ net .process () // this second time is necessary for garbage collection it seams
1211
+
1212
+ // Now vp0,1,2 should be in sync with 8 executions in view 0, and vp4 should be offline
1213
+ for i , pep := range net .pbftEndpoints {
1214
+
1215
+ if i == 3 {
1216
+ // 3 is offline for this test
1217
+ continue
1218
+ }
1219
+
1220
+ if pep .pbft .view != 0 {
1221
+ t .Errorf ("Expected replica %d to be in view 1, got %d" , pep .id , pep .pbft .view )
1222
+ }
1223
+
1224
+ expectedExecutions := uint64 (8 )
1225
+ if pep .sc .executions != expectedExecutions {
1226
+ t .Errorf ("Expected %d executions on replica %d, got %d" , expectedExecutions , pep .id , pep .sc .executions )
1227
+ }
1228
+ }
1229
+
1230
+ // Create new pbft instances to restore from persistence
1231
+ for id := 0 ; id < 3 ; id ++ {
1232
+ pe := net .pbftEndpoints [id ]
1233
+ config := loadConfig ()
1234
+ config .Set ("general.K" , "2" )
1235
+ pe .pbft .close ()
1236
+ pe .pbft = newPbftCore (uint64 (id ), config , pe .sc , events .NewTimerFactoryImpl (pe .manager ))
1237
+ pe .manager .SetReceiver (pe .pbft )
1238
+ pe .pbft .N = 4
1239
+ pe .pbft .f = (4 - 1 ) / 3
1240
+ pe .pbft .requestTimeout = 200 * time .Millisecond
1241
+
1242
+ expected := uint64 (8 )
1243
+ if pe .pbft .h != expected {
1244
+ t .Errorf ("Low watermark should have been %d, got %d" , expected , pe .pbft .h )
1245
+ }
1246
+ }
1247
+
1248
+ }
1182
1249
func TestReplicaPersistQSet (t * testing.T ) {
1183
1250
persist := make (map [string ][]byte )
1184
1251
0 commit comments