github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/sbft/simplebft/simplebft_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package simplebft 18 19 import ( 20 "reflect" 21 "testing" 22 "time" 23 24 "math" 25 26 "fmt" 27 "strconv" 28 29 "github.com/golang/protobuf/proto" 30 "github.com/op/go-logging" 31 ) 32 33 const chainId = "id" 34 const lowN uint64 = 4 //keep lowN greater or equal to 4 35 const highN uint64 = 10 //keep highN greater or equal to 10 36 37 var testLog = logging.MustGetLogger("test") 38 39 func init() { 40 // logging.SetLevel(logging.NOTICE, "") 41 // logging.SetLevel(logging.DEBUG, "test") 42 logging.SetLevel(logging.DEBUG, "sbft") 43 } 44 45 func skipInShortMode(t *testing.T) { 46 if testing.Short() { 47 t.Skip("Skipping test in short mode.") 48 } 49 } 50 51 func connectAll(sys *testSystem, chainIds []string) { 52 for _, chainId := range chainIds { 53 connectAllForChainId(sys, chainId) 54 } 55 } 56 57 func connectAllForDefaultChain(sys *testSystem) { 58 connectAllForChainId(sys, chainId) 59 } 60 61 func connectAllForChainId(sys *testSystem, chainId string) { 62 // map iteration is non-deterministic, so use linear iteration instead 63 max := uint64(0) 64 for _, a := range sys.adapters { 65 if a.id > max { 66 max = a.id 67 } 68 } 69 70 for i := uint64(0); i <= max; i++ { 71 a, ok := sys.adapters[i] 72 if !ok { 73 continue 74 } 75 76 for j := uint64(0); j <= max; j++ { 77 b, ok := sys.adapters[j] 78 if !ok { 79 continue 80 } 81 if a.id != b.id { 82 a.receivers[chainId].Connection(b.id) 83 } 84 } 85 } 86 sys.Run() 87 } 88 89 func TestMultiChain(t *testing.T) { 90 skipInShortMode(t) 91 N := lowN 92 M := uint64(5) 93 sys := newTestSystem(N) 94 chainIds := make([]string, 0, M) 95 var repls map[string][]*SBFT = map[string][]*SBFT{} 96 var adapters []*testSystemAdapter 97 for i := uint64(0); i < N; i++ { 98 a := sys.NewAdapter(i) 99 for j := uint64(0); j < M; j++ { 100 chainId := fmt.Sprintf("%d", j) 101 s, err := New(i, chainId, &Config{N: N, F: 0, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 102 if err != nil { 103 t.Fatal(err) 104 } 105 repls[chainId] = append(repls[chainId], s) 106 if uint64(len(chainIds)) < M { 107 chainIds = append(chainIds, chainId) 108 } 109 } 110 adapters = append(adapters, a) 111 } 112 connectAll(sys, chainIds) 113 r1 := []byte{1, 2, 3} 114 for i := uint64(0); i < N; i++ { 115 for j := uint64(0); j < M; j++ { 116 if j%uint64(2) == 0 { 117 chainId := fmt.Sprintf("%d", j) 118 repls[chainId][i].Request(r1) 119 } 120 } 121 } 122 sys.Run() 123 for _, a := range adapters { 124 for chainId := range a.batches { 125 // we check that if this is a chain where we sent a req then the req 126 // was written to the "ledger" 127 j, _ := strconv.ParseInt(chainId, 10, 64) 128 if j%2 == 0 && len(a.batches[chainId]) != 1 { 129 t.Fatalf("expected one batches on chain %s", chainId) 130 } 131 // in other cases, we should have at most an empty ledger 132 if j%2 != 0 && len(a.batches[chainId]) != 0 { 133 t.Fatalf("expected one batches on chain %s", chainId) 134 } 135 } 136 } 137 } 138 139 func TestSBFT(t *testing.T) { 140 skipInShortMode(t) 141 N := lowN 142 sys := newTestSystem(N) 143 var repls []*SBFT 144 var adapters []*testSystemAdapter 145 for i := uint64(0); i < N; i++ { 146 a := sys.NewAdapter(i) 147 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 148 if err != nil { 149 t.Fatal(err) 150 } 151 repls = append(repls, s) 152 adapters = append(adapters, a) 153 } 154 connectAllForDefaultChain(sys) 155 r1 := []byte{1, 2, 3} 156 repls[0].Request(r1) 157 sys.Run() 158 r2 := []byte{3, 1, 2} 159 r3 := []byte{3, 5, 2} 160 repls[1].Request(r2) 161 repls[1].Request(r3) 162 sys.Run() 163 for _, a := range adapters { 164 if len(a.batches[chainId]) != 2 { 165 t.Fatal("expected execution of 2 batches") 166 } 167 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 168 t.Error("wrong request executed (1)") 169 } 170 if !reflect.DeepEqual([][]byte{r2, r3}, a.batches[chainId][1].Payloads) { 171 t.Error("wrong request executed (2)") 172 } 173 } 174 } 175 176 func TestQuorumSizes(t *testing.T) { 177 for N := uint64(1); N < 100; N++ { 178 for f := uint64(0); f <= uint64(math.Floor(float64(N-1)/float64(3))); f++ { 179 sys := newTestSystem(N) 180 a := sys.NewAdapter(0) 181 s, err := New(0, chainId, &Config{N: N, F: f, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 182 if err != nil { 183 t.Fatal(err) 184 } 185 if uint64(2*s.commonCaseQuorum())-N < f+1 { 186 t.Fatal("insufficient intersection of two common case quorums", "N = ", N, " F = ", f) 187 } 188 if uint64(s.commonCaseQuorum()+s.viewChangeQuorum())-N < f+1 { 189 t.Fatal("insufficient intersection of common case and view change quorums", "N = ", N, " F = ", f) 190 } 191 if f < uint64(math.Floor(float64(N-1)/float64(3))) { 192 //end test for unoptimized f 193 continue 194 } 195 //test additionally when f is optimized 196 switch int(math.Mod(float64(N), float64(3))) { 197 case 1: 198 if s.commonCaseQuorum() != int(N-f) || s.viewChangeQuorum() != int(N-f) { 199 t.Fatal("quorum sizes are wrong in default case N mod 3 == 1") 200 } 201 case 2: 202 if s.viewChangeQuorum() >= s.commonCaseQuorum() || s.viewChangeQuorum() >= int(N-f) { 203 t.Fatal("view change quorums size not optimized when N mod 3 == 2") 204 } 205 case 3: 206 if s.commonCaseQuorum() >= int(N-f) || s.viewChangeQuorum() >= int(N-f) { 207 t.Fatal("quorum sizes not optimized when N mod 3 == 3") 208 } 209 } 210 } 211 } 212 } 213 214 func TestSBFTDelayed(t *testing.T) { 215 skipInShortMode(t) 216 N := lowN 217 BS := uint64(1) 218 sys := newTestSystemWithBatchSize(N, BS) 219 var repls []*SBFT 220 var adapters []*testSystemAdapter 221 for i := uint64(0); i < N; i++ { 222 a := sys.NewAdapter(i) 223 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: BS, RequestTimeoutNsec: 20000000000}, a) 224 if err != nil { 225 t.Fatal(err) 226 } 227 repls = append(repls, s) 228 adapters = append(adapters, a) 229 } 230 231 // make replica 3 lag out against 1 and 2 232 for i := uint64(1); i < 3; i++ { 233 adapters[i].arrivals[3] = 200 * time.Millisecond 234 adapters[3].arrivals[i] = 200 * time.Millisecond 235 } 236 237 connectAllForDefaultChain(sys) 238 r1 := []byte{1, 2, 3} 239 r2 := []byte{3, 1, 2} 240 repls[0].Request(r1) 241 repls[1].Request(r2) 242 sys.Run() 243 for i, a := range adapters { 244 if len(a.batches[chainId]) != 2 { 245 t.Errorf("expected execution of 2 batches on %d", i) 246 continue 247 } 248 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 249 t.Error("wrong request executed (1)") 250 } 251 if !reflect.DeepEqual([][]byte{r2}, a.batches[chainId][1].Payloads) { 252 t.Error("wrong request executed (2)") 253 } 254 } 255 } 256 257 func TestN1(t *testing.T) { 258 skipInShortMode(t) 259 N := uint64(1) 260 sys := newTestSystem(N) 261 var repls []*SBFT 262 var adapters []*testSystemAdapter 263 for i := uint64(0); i < N; i++ { 264 a := sys.NewAdapter(i) 265 s, err := New(i, chainId, &Config{N: N, F: 0, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 266 if err != nil { 267 t.Fatal(err) 268 } 269 repls = append(repls, s) 270 adapters = append(adapters, a) 271 } 272 connectAllForDefaultChain(sys) 273 r1 := []byte{1, 2, 3} 274 repls[0].Request(r1) 275 sys.Run() 276 for _, a := range adapters { 277 if len(a.batches[chainId]) != 1 { 278 t.Fatal("expected execution of 1 batches") 279 } 280 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 281 t.Error("wrong request executed (1)") 282 } 283 } 284 } 285 286 func TestMonotonicViews(t *testing.T) { 287 skipInShortMode(t) 288 N := lowN 289 sys := newTestSystem(N) 290 var repls []*SBFT 291 var adapters []*testSystemAdapter 292 for i := uint64(0); i < N; i++ { 293 a := sys.NewAdapter(i) 294 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 295 if err != nil { 296 t.Fatal(err) 297 } 298 repls = append(repls, s) 299 adapters = append(adapters, a) 300 } 301 302 repls[0].sendViewChange() 303 sys.Run() 304 305 view := repls[0].view 306 testLog.Notice("TEST: Replica 0 is in view ", view) 307 testLog.Notice("TEST: restarting replica 0") 308 repls[0], _ = New(0, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, adapters[0]) 309 for _, a := range adapters { 310 if a.id != 0 { 311 a.receivers[chainId].Connection(0) 312 adapters[0].receivers[chainId].Connection(a.id) 313 } 314 } 315 sys.Run() 316 317 if repls[0].view < view { 318 t.Fatalf("Replica 0 must be at least in view %d, but is in view %d", view, repls[0].view) 319 } 320 } 321 322 func TestByzPrimaryN4(t *testing.T) { 323 skipInShortMode(t) 324 N := uint64(4) 325 sys := newTestSystem(N) 326 var repls []*SBFT 327 var adapters []*testSystemAdapter 328 for i := uint64(0); i < N; i++ { 329 a := sys.NewAdapter(i) 330 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 1, RequestTimeoutNsec: 20000000000}, a) 331 if err != nil { 332 t.Fatal(err) 333 } 334 repls = append(repls, s) 335 adapters = append(adapters, a) 336 } 337 338 r1 := []byte{1, 2, 3} 339 r2 := []byte{5, 6, 7} 340 341 // change preprepare to 2, 3 342 sys.filterFn = func(e testElem) (testElem, bool) { 343 if msg, ok := e.ev.(*testMsgEvent); ok { 344 if pp := msg.msg.GetPreprepare(); pp != nil && msg.src == 0 && msg.dst >= 2 { 345 pp := *pp 346 batch := *pp.Batch 347 batch.Payloads = [][]byte{r2} 348 pp.Batch = &batch 349 h := merkleHashData(batch.Payloads) 350 bh := &BatchHeader{} 351 proto.Unmarshal(pp.Batch.Header, bh) 352 bh.DataHash = h 353 bhraw, _ := proto.Marshal(bh) 354 pp.Batch.Header = bhraw 355 msg.msg = &Msg{&Msg_Preprepare{&pp}} 356 } 357 } 358 return e, true 359 } 360 361 connectAllForDefaultChain(sys) 362 repls[0].Request(r1) 363 sys.Run() 364 for _, a := range adapters { 365 if len(a.batches[chainId]) != 2 { 366 t.Fatal("expected execution of 2 batches") 367 } 368 if !reflect.DeepEqual([][]byte{r2}, a.batches[chainId][0].Payloads) { 369 t.Error("wrong request executed first") 370 } 371 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][1].Payloads) { 372 t.Error("wrong request executed second") 373 } 374 } 375 } 376 377 func TestNewPrimaryHandlingViewChange(t *testing.T) { 378 skipInShortMode(t) 379 N := uint64(7) 380 sys := newTestSystem(N) 381 var repls []*SBFT 382 var adapters []*testSystemAdapter 383 for i := uint64(0); i < N; i++ { 384 a := sys.NewAdapter(i) 385 s, err := New(i, chainId, &Config{N: N, F: 2, BatchDurationNsec: 2000000000, BatchSizeBytes: 1, RequestTimeoutNsec: 20000000000}, a) 386 if err != nil { 387 t.Fatal(err) 388 } 389 repls = append(repls, s) 390 adapters = append(adapters, a) 391 } 392 393 r1 := []byte{1, 2, 3} 394 r2 := []byte{5, 6, 7} 395 396 // change preprepare to 2-6 397 sys.filterFn = func(e testElem) (testElem, bool) { 398 if msg, ok := e.ev.(*testMsgEvent); ok { 399 if pp := msg.msg.GetPreprepare(); pp != nil && msg.src == 0 && msg.dst >= 2 { 400 pp := *pp 401 batch := *pp.Batch 402 batch.Payloads = [][]byte{r2} 403 pp.Batch = &batch 404 h := merkleHashData(batch.Payloads) 405 bh := &BatchHeader{} 406 proto.Unmarshal(pp.Batch.Header, bh) 407 bh.DataHash = h 408 bhraw, _ := proto.Marshal(bh) 409 pp.Batch.Header = bhraw 410 msg.msg = &Msg{&Msg_Preprepare{&pp}} 411 } 412 } 413 return e, true 414 } 415 416 connectAllForDefaultChain(sys) 417 repls[0].Request(r1) 418 sys.Run() 419 for _, a := range adapters { 420 if len(a.batches[chainId]) < 1 { 421 t.Fatal("expected execution of at least one batches") 422 } 423 if a.batches[chainId][0].Payloads != nil && !reflect.DeepEqual(adapters[2].batches[chainId][0].Payloads, a.batches[chainId][0].Payloads) { 424 t.Error("consensus violated on first batches at replica", a.id) 425 } 426 } 427 } 428 429 func TestByzPrimaryBullyingSingleReplica(t *testing.T) { 430 skipInShortMode(t) 431 N := highN 432 sys := newTestSystem(N) 433 var repls []*SBFT 434 var adapters []*testSystemAdapter 435 for i := uint64(0); i < N; i++ { 436 a := sys.NewAdapter(i) 437 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 1, RequestTimeoutNsec: 20000000000}, a) 438 if err != nil { 439 t.Fatal(err) 440 } 441 repls = append(repls, s) 442 adapters = append(adapters, a) 443 } 444 445 r1 := []byte{1, 2, 3} 446 r2 := []byte{5, 6, 7} 447 448 // change preprepare to 1 449 sys.filterFn = func(e testElem) (testElem, bool) { 450 if msg, ok := e.ev.(*testMsgEvent); ok { 451 if pp := msg.msg.GetPreprepare(); pp != nil && msg.src == 0 && msg.dst == 1 { 452 pp := *pp 453 batch := *pp.Batch 454 batch.Payloads = [][]byte{r2} 455 pp.Batch = &batch 456 h := merkleHashData(batch.Payloads) 457 bh := &BatchHeader{} 458 proto.Unmarshal(pp.Batch.Header, bh) 459 bh.DataHash = h 460 bhraw, _ := proto.Marshal(bh) 461 pp.Batch.Header = bhraw 462 msg.msg = &Msg{&Msg_Preprepare{&pp}} 463 } 464 } 465 return e, true 466 } 467 468 connectAllForDefaultChain(sys) 469 repls[0].Request(r1) 470 sys.Run() 471 for _, a := range adapters { 472 if a.id != 1 && len(a.batches[chainId]) != 1 { 473 t.Fatal("expected execution of 1 batches at all except replica 1") 474 } 475 } 476 } 477 478 func TestViewChange(t *testing.T) { 479 skipInShortMode(t) 480 N := lowN 481 sys := newTestSystem(N) 482 var repls []*SBFT 483 var adapters []*testSystemAdapter 484 for i := uint64(0); i < N; i++ { 485 a := sys.NewAdapter(i) 486 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 1, RequestTimeoutNsec: 20000000000}, a) 487 if err != nil { 488 t.Fatal(err) 489 } 490 repls = append(repls, s) 491 adapters = append(adapters, a) 492 } 493 494 // network outage after prepares are received 495 sys.filterFn = func(e testElem) (testElem, bool) { 496 if msg, ok := e.ev.(*testMsgEvent); ok { 497 if c := msg.msg.GetCommit(); c != nil && c.Seq.View == 0 { 498 return e, false 499 } 500 } 501 return e, true 502 } 503 504 connectAllForDefaultChain(sys) 505 r1 := []byte{1, 2, 3} 506 repls[0].Request(r1) 507 sys.Run() 508 for _, a := range adapters { 509 if len(a.batches[chainId]) != 1 { 510 t.Fatal("expected execution of 1 batches") 511 } 512 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 513 t.Error("wrong request executed (1)") 514 } 515 } 516 } 517 518 func TestMsgReordering(t *testing.T) { 519 skipInShortMode(t) 520 N := lowN 521 sys := newTestSystem(N) 522 var repls []*SBFT 523 var adapters []*testSystemAdapter 524 for i := uint64(0); i < N; i++ { 525 a := sys.NewAdapter(i) 526 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 1, RequestTimeoutNsec: 20000000000}, a) 527 if err != nil { 528 t.Fatal(err) 529 } 530 repls = append(repls, s) 531 adapters = append(adapters, a) 532 } 533 534 var preprep *testMsgEvent 535 536 // forcing pre-prepare from primary 0 to reach replica 1 after some delay 537 // effectivelly delivering pre-prepare instead of checkpoint 538 sys.filterFn = func(e testElem) (testElem, bool) { 539 if msg, ok := e.ev.(*testMsgEvent); ok { 540 if msg.src == 0 && msg.dst == 1 { 541 c := msg.msg.GetPreprepare() 542 if c != nil && c.Seq.View == 0 { 543 preprep = msg //memorizing pre-prepare 544 return e, false // but dropping it 545 } 546 d := msg.msg.GetCheckpoint() 547 if d != nil { 548 msg.msg = &Msg{&Msg_Preprepare{preprep.msg.GetPreprepare()}} 549 return e, true //and delivering it 550 } 551 return e, false //droping other msgs from 0 to 1 552 } 553 } 554 return e, true 555 } 556 557 connectAllForDefaultChain(sys) 558 r1 := []byte{1, 2, 3} 559 repls[0].Request(r1) 560 sys.Run() 561 for _, a := range adapters { 562 if len(a.batches[chainId]) != 1 { 563 t.Fatal("expected execution of 1 batches") 564 } 565 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 566 t.Error("wrong request executed (1)") 567 } 568 } 569 } 570 571 func TestBacklogReordering(t *testing.T) { 572 skipInShortMode(t) 573 N := lowN 574 sys := newTestSystem(N) 575 var repls []*SBFT 576 var adapters []*testSystemAdapter 577 for i := uint64(0); i < N; i++ { 578 a := sys.NewAdapter(i) 579 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 1, RequestTimeoutNsec: 20000000000}, a) 580 if err != nil { 581 t.Fatal(err) 582 } 583 repls = append(repls, s) 584 adapters = append(adapters, a) 585 } 586 587 var preprep *testMsgEvent 588 589 // forcing pre-prepare from primary 0 to reach replica 1 after some delay 590 // effectivelly delivering pre-prepare instead of checkpoint 591 sys.filterFn = func(e testElem) (testElem, bool) { 592 if msg, ok := e.ev.(*testMsgEvent); ok { 593 if msg.src == 0 && msg.dst == 1 { 594 c := msg.msg.GetPreprepare() 595 if c != nil && c.Seq.View == 0 { 596 preprep = msg //memorizing pre-prepare 597 return e, false // but dropping it 598 } 599 d := msg.msg.GetCheckpoint() 600 if d != nil { 601 msg.msg = &Msg{&Msg_Preprepare{preprep.msg.GetPreprepare()}} 602 return e, true //and delivering it 603 } 604 return e, true //letting prepare and commit from 0 to 1 pass 605 } 606 } 607 return e, true 608 } 609 610 connectAllForDefaultChain(sys) 611 r1 := []byte{1, 2, 3} 612 repls[0].Request(r1) 613 sys.Run() 614 for _, a := range adapters { 615 if len(a.batches[chainId]) != 1 { 616 t.Fatal("expected execution of 1 batches") 617 } 618 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 619 t.Error("wrong request executed (1)") 620 } 621 } 622 } 623 624 func TestViewChangeWithRetransmission(t *testing.T) { 625 skipInShortMode(t) 626 N := lowN 627 sys := newTestSystem(N) 628 var repls []*SBFT 629 var adapters []*testSystemAdapter 630 for i := uint64(0); i < N; i++ { 631 a := sys.NewAdapter(i) 632 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 1, RequestTimeoutNsec: 20000000000}, a) 633 if err != nil { 634 t.Fatal(err) 635 } 636 repls = append(repls, s) 637 adapters = append(adapters, a) 638 } 639 640 // network outage after prepares are received 641 sys.filterFn = func(e testElem) (testElem, bool) { 642 if msg, ok := e.ev.(*testMsgEvent); ok { 643 if c := msg.msg.GetPrepare(); c != nil && c.Seq.View == 0 { 644 return e, false 645 } 646 } 647 return e, true 648 } 649 650 connectAllForDefaultChain(sys) 651 r1 := []byte{1, 2, 3} 652 repls[0].Request(r1) 653 sys.Run() 654 for _, a := range adapters { 655 if len(a.batches[chainId]) != 1 { 656 t.Fatal("expected execution of 1 batches") 657 } 658 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 659 t.Error("wrong request executed (1)") 660 } 661 } 662 } 663 664 func TestViewChangeXset(t *testing.T) { 665 skipInShortMode(t) 666 N := lowN 667 sys := newTestSystem(N) 668 var repls []*SBFT 669 var adapters []*testSystemAdapter 670 for i := uint64(0); i < N; i++ { 671 a := sys.NewAdapter(i) 672 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 1, RequestTimeoutNsec: 20000000000}, a) 673 if err != nil { 674 t.Fatal(err) 675 } 676 repls = append(repls, s) 677 adapters = append(adapters, a) 678 } 679 680 phase := 1 681 682 // network outage after prepares are received 683 sys.filterFn = func(e testElem) (testElem, bool) { 684 if msg, ok := e.ev.(*testMsgEvent); ok { 685 if msg.src == msg.dst { 686 return e, true 687 } 688 689 switch phase { 690 case 1: 691 if p := msg.msg.GetPrepare(); p != nil && p.Seq.View == 0 { 692 return e, false 693 } 694 case 2: 695 if nv := msg.msg.GetNewView(); nv != nil { 696 phase = 3 697 return e, true 698 } 699 if msg.src == 3 || msg.dst == 3 { 700 return e, false 701 } 702 if c := msg.msg.GetCommit(); c != nil && c.Seq.View == 1 { 703 return e, false 704 } 705 case 3: 706 if msg.src == 3 || msg.dst == 3 { 707 return e, false 708 } 709 } 710 } 711 return e, true 712 } 713 714 connectAllForDefaultChain(sys) 715 r1 := []byte{1, 2, 3} 716 repls[0].Request(r1) 717 sys.Run() 718 phase = 2 719 720 r2 := []byte{5, 6, 7} 721 repls[1].Request(r2) 722 sys.Run() 723 724 for i, a := range adapters { 725 // 3 is disconnected 726 if i == 3 { 727 continue 728 } 729 if len(a.batches[chainId]) != 2 { 730 t.Fatalf("expected execution of 1 batches: %v", a.batches[chainId]) 731 } 732 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 733 t.Error("wrong request executed first") 734 } 735 if !reflect.DeepEqual([][]byte{r2}, a.batches[chainId][1].Payloads) { 736 t.Error("wrong request executed second") 737 } 738 } 739 } 740 741 func TestRestart(t *testing.T) { 742 skipInShortMode(t) 743 N := lowN 744 sys := newTestSystem(N) 745 var repls []*SBFT 746 var adapters []*testSystemAdapter 747 for i := uint64(0); i < N; i++ { 748 a := sys.NewAdapter(i) 749 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 750 if err != nil { 751 t.Fatal(err) 752 } 753 repls = append(repls, s) 754 adapters = append(adapters, a) 755 } 756 757 connectAllForDefaultChain(sys) 758 // move to view 1 759 for _, r := range repls { 760 r.sendViewChange() 761 } 762 sys.Run() 763 764 r1 := []byte{1, 2, 3} 765 repls[0].Request(r1) 766 sys.Run() 767 768 testLog.Notice("restarting 0") 769 repls[0], _ = New(0, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, adapters[0]) 770 for _, a := range adapters { 771 if a.id != 0 { 772 a.receivers[chainId].Connection(0) 773 adapters[0].receivers[chainId].Connection(a.id) 774 } 775 } 776 777 r2 := []byte{3, 1, 2} 778 r3 := []byte{3, 5, 2} 779 repls[1].Request(r2) 780 repls[1].Request(r3) 781 sys.Run() 782 for _, a := range adapters { 783 if len(a.batches[chainId]) != 2 { 784 t.Fatalf("expected execution of 2 batches, %d got %v", a.id, a.batches) 785 } 786 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 787 t.Error("wrong request executed (1)") 788 } 789 if !reflect.DeepEqual([][]byte{r2, r3}, a.batches[chainId][1].Payloads) { 790 t.Error("wrong request executed (2)") 791 } 792 } 793 } 794 795 func TestAbdicatingPrimary(t *testing.T) { 796 skipInShortMode(t) 797 N := lowN 798 sys := newTestSystem(N) 799 var repls []*SBFT 800 var adapters []*testSystemAdapter 801 for i := uint64(0); i < N; i++ { 802 a := sys.NewAdapter(i) 803 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 804 if err != nil { 805 t.Fatal(err) 806 } 807 repls = append(repls, s) 808 adapters = append(adapters, a) 809 } 810 811 phase := 1 812 // Dropping all phase 1 msgs except requests and viewchange to 0 813 // (preprepare to primary 0 is automatically delivered) 814 sys.filterFn = func(e testElem) (testElem, bool) { 815 if phase == 1 { 816 if msg, ok := e.ev.(*testMsgEvent); ok { 817 if c := msg.msg.GetRequest(); c != nil { 818 return e, true 819 } 820 if c := msg.msg.GetViewChange(); c != nil && msg.dst == 0 { 821 return e, true 822 } 823 return e, false 824 } 825 return e, true 826 } 827 return e, true 828 } 829 830 connectAllForDefaultChain(sys) 831 832 r1 := []byte{1, 2, 3} 833 repls[0].Request(r1) 834 sys.Run() 835 836 phase = 2 837 838 testLog.Notice("TEST: restarting connections from 0") 839 for _, a := range adapters { 840 if a.id != 0 { 841 a.receivers[chainId].Connection(0) 842 adapters[0].receivers[chainId].Connection(a.id) 843 } 844 } 845 846 sys.Run() 847 for _, a := range adapters { 848 if len(a.batches[chainId]) != 1 { 849 t.Fatalf("expected execution of 1 batches, %d got %v", a.id, a.batches[chainId]) 850 } 851 } 852 } 853 854 func TestRestartAfterPrepare(t *testing.T) { 855 skipInShortMode(t) 856 N := lowN 857 sys := newTestSystem(N) 858 var repls []*SBFT 859 var adapters []*testSystemAdapter 860 for i := uint64(0); i < N; i++ { 861 a := sys.NewAdapter(i) 862 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 863 if err != nil { 864 t.Fatal(err) 865 } 866 repls = append(repls, s) 867 adapters = append(adapters, a) 868 } 869 870 restarted := false 871 872 // network outage after prepares are received 873 sys.filterFn = func(e testElem) (testElem, bool) { 874 if msg, ok := e.ev.(*testMsgEvent); ok { 875 if msg.src == msg.dst || msg.src != 0 { 876 return e, true 877 } 878 879 if p := msg.msg.GetPrepare(); p != nil && p.Seq.Seq == 3 && !restarted { 880 restarted = true 881 testLog.Notice("restarting 0") 882 repls[0], _ = New(0, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, adapters[0]) 883 for _, a := range adapters { 884 if a.id != 0 { 885 a.receivers[chainId].Connection(0) 886 adapters[0].receivers[chainId].Connection(a.id) 887 } 888 } 889 } 890 } 891 892 return e, true 893 } 894 895 connectAllForDefaultChain(sys) 896 // move to view 1 897 for _, r := range repls { 898 r.sendViewChange() 899 } 900 sys.Run() 901 902 r1 := []byte{1, 2, 3} 903 repls[0].Request(r1) 904 sys.Run() 905 906 r2 := []byte{3, 1, 2} 907 r3 := []byte{3, 5, 2} 908 repls[1].Request(r2) 909 repls[1].Request(r3) 910 sys.Run() 911 for _, a := range adapters { 912 if len(a.batches[chainId]) != 2 { 913 t.Fatal("expected execution of 2 batches") 914 } 915 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 916 t.Error("wrong request executed (1)") 917 } 918 if !reflect.DeepEqual([][]byte{r2, r3}, a.batches[chainId][1].Payloads) { 919 t.Error("wrong request executed (2)") 920 } 921 } 922 } 923 924 func TestRestartAfterCommit(t *testing.T) { 925 skipInShortMode(t) 926 N := lowN 927 sys := newTestSystem(N) 928 var repls []*SBFT 929 var adapters []*testSystemAdapter 930 for i := uint64(0); i < N; i++ { 931 a := sys.NewAdapter(i) 932 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 933 if err != nil { 934 t.Fatal(err) 935 } 936 repls = append(repls, s) 937 adapters = append(adapters, a) 938 } 939 940 restarted := false 941 942 // network outage after prepares are received 943 sys.filterFn = func(e testElem) (testElem, bool) { 944 if msg, ok := e.ev.(*testMsgEvent); ok { 945 if msg.src == msg.dst || msg.src != 0 { 946 return e, true 947 } 948 949 if c := msg.msg.GetCommit(); c != nil && c.Seq.Seq == 3 && !restarted { 950 restarted = true 951 testLog.Notice("restarting 0") 952 repls[0], _ = New(0, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, adapters[0]) 953 for _, a := range adapters { 954 if a.id != 0 { 955 a.receivers[chainId].Connection(0) 956 adapters[0].receivers[chainId].Connection(a.id) 957 } 958 } 959 } 960 } 961 962 return e, true 963 } 964 965 connectAllForDefaultChain(sys) 966 // move to view 1 967 for _, r := range repls { 968 r.sendViewChange() 969 } 970 sys.Run() 971 972 r1 := []byte{1, 2, 3} 973 repls[0].Request(r1) 974 sys.Run() 975 976 r2 := []byte{3, 1, 2} 977 r3 := []byte{3, 5, 2} 978 repls[1].Request(r2) 979 repls[1].Request(r3) 980 sys.Run() 981 for _, a := range adapters { 982 if len(a.batches[chainId]) != 2 { 983 t.Fatal("expected execution of 2 batches") 984 } 985 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 986 t.Error("wrong request executed (1)") 987 } 988 if !reflect.DeepEqual([][]byte{r2, r3}, a.batches[chainId][1].Payloads) { 989 t.Error("wrong request executed (2)") 990 } 991 } 992 } 993 994 func TestRestartAfterCheckpoint(t *testing.T) { 995 skipInShortMode(t) 996 N := lowN 997 sys := newTestSystem(N) 998 var repls []*SBFT 999 var adapters []*testSystemAdapter 1000 for i := uint64(0); i < N; i++ { 1001 a := sys.NewAdapter(i) 1002 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 1003 if err != nil { 1004 t.Fatal(err) 1005 } 1006 repls = append(repls, s) 1007 adapters = append(adapters, a) 1008 } 1009 1010 restarted := false 1011 1012 // network outage after prepares are received 1013 sys.filterFn = func(e testElem) (testElem, bool) { 1014 if msg, ok := e.ev.(*testMsgEvent); ok { 1015 if msg.src == msg.dst || msg.src != 0 { 1016 return e, true 1017 } 1018 1019 if c := msg.msg.GetCheckpoint(); c != nil && c.Seq == 3 && !restarted { 1020 restarted = true 1021 testLog.Notice("restarting 0") 1022 repls[0], _ = New(0, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, adapters[0]) 1023 for _, a := range adapters { 1024 if a.id != 0 { 1025 a.receivers[chainId].Connection(0) 1026 adapters[0].receivers[chainId].Connection(a.id) 1027 } 1028 } 1029 } 1030 } 1031 1032 return e, true 1033 } 1034 1035 connectAllForDefaultChain(sys) 1036 // move to view 1 1037 for _, r := range repls { 1038 r.sendViewChange() 1039 } 1040 sys.Run() 1041 1042 r1 := []byte{1, 2, 3} 1043 repls[0].Request(r1) 1044 sys.Run() 1045 1046 r2 := []byte{3, 1, 2} 1047 r3 := []byte{3, 5, 2} 1048 repls[1].Request(r2) 1049 repls[1].Request(r3) 1050 sys.Run() 1051 for _, a := range adapters { 1052 if len(a.batches[chainId]) != 2 { 1053 t.Fatal("expected execution of 2 batches") 1054 } 1055 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 1056 t.Error("wrong request executed (1)") 1057 } 1058 if !reflect.DeepEqual([][]byte{r2, r3}, a.batches[chainId][1].Payloads) { 1059 t.Error("wrong request executed (2)") 1060 } 1061 } 1062 } 1063 1064 func TestErroneousViewChange(t *testing.T) { 1065 skipInShortMode(t) 1066 N := lowN 1067 sys := newTestSystem(N) 1068 var repls []*SBFT 1069 var adapters []*testSystemAdapter 1070 for i := uint64(0); i < N; i++ { 1071 a := sys.NewAdapter(i) 1072 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 1073 if err != nil { 1074 t.Fatal(err) 1075 } 1076 repls = append(repls, s) 1077 adapters = append(adapters, a) 1078 } 1079 1080 restarted := false 1081 1082 // network outage after prepares are received 1083 sys.filterFn = func(e testElem) (testElem, bool) { 1084 if msg, ok := e.ev.(*testMsgEvent); ok { 1085 if msg.src == msg.dst || msg.src != 0 { 1086 return e, true 1087 } 1088 1089 if c := msg.msg.GetCheckpoint(); c != nil && c.Seq == 3 && !restarted { 1090 restarted = true 1091 testLog.Notice("restarting 0") 1092 repls[0], _ = New(0, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, adapters[0]) 1093 for _, a := range adapters { 1094 if a.id != 0 { 1095 a.receivers[chainId].Connection(0) 1096 adapters[0].receivers[chainId].Connection(a.id) 1097 } 1098 } 1099 } 1100 } 1101 1102 return e, true 1103 } 1104 1105 // iteration order here is essential to trigger the bug 1106 outer := []uint64{2, 3, 0, 1} 1107 inner := []uint64{0, 1, 2, 3} 1108 for _, i := range outer { 1109 a, ok := sys.adapters[i] 1110 if !ok { 1111 continue 1112 } 1113 1114 for _, j := range inner { 1115 b, ok := sys.adapters[j] 1116 if !ok { 1117 continue 1118 } 1119 if a.id != b.id { 1120 a.receivers[chainId].Connection(b.id) 1121 } 1122 } 1123 } 1124 sys.Run() 1125 1126 // move to view 1 1127 for _, r := range repls { 1128 r.sendViewChange() 1129 } 1130 sys.Run() 1131 1132 r1 := []byte{1, 2, 3} 1133 repls[0].Request(r1) 1134 sys.Run() 1135 1136 r2 := []byte{3, 1, 2} 1137 r3 := []byte{3, 5, 2} 1138 repls[1].Request(r2) 1139 repls[1].Request(r3) 1140 sys.Run() 1141 for _, a := range adapters { 1142 if len(a.batches[chainId]) != 2 { 1143 t.Fatal("expected execution of 2 batches") 1144 } 1145 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 1146 t.Error("wrong request executed (1)") 1147 } 1148 if !reflect.DeepEqual([][]byte{r2, r3}, a.batches[chainId][1].Payloads) { 1149 t.Error("wrong request executed (2)") 1150 } 1151 } 1152 } 1153 1154 func TestRestartMissedViewChange(t *testing.T) { 1155 skipInShortMode(t) 1156 N := lowN 1157 sys := newTestSystem(N) 1158 var repls []*SBFT 1159 var adapters []*testSystemAdapter 1160 for i := uint64(0); i < N; i++ { 1161 a := sys.NewAdapter(i) 1162 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 1163 if err != nil { 1164 t.Fatal(err) 1165 } 1166 repls = append(repls, s) 1167 adapters = append(adapters, a) 1168 } 1169 1170 disconnect := false 1171 1172 // network outage after prepares are received 1173 sys.filterFn = func(e testElem) (testElem, bool) { 1174 if msg, ok := e.ev.(*testMsgEvent); ok { 1175 if disconnect && (msg.src == 0 || msg.dst == 0) { 1176 return e, false 1177 } 1178 } 1179 1180 return e, true 1181 } 1182 1183 connectAllForDefaultChain(sys) 1184 1185 r1 := []byte{1, 2, 3} 1186 repls[0].Request(r1) 1187 sys.Run() 1188 1189 disconnect = true 1190 // move to view 1 1191 for _, r := range repls { 1192 if r.id != 0 { 1193 r.sendViewChange() 1194 } 1195 } 1196 sys.Run() 1197 1198 r2 := []byte{3, 1, 2} 1199 repls[1].Request(r2) 1200 sys.Run() 1201 1202 disconnect = false 1203 testLog.Notice("restarting 0") 1204 repls[0], _ = New(0, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, adapters[0]) 1205 for _, a := range adapters { 1206 if a.id != 0 { 1207 a.receivers[chainId].Connection(0) 1208 adapters[0].receivers[chainId].Connection(a.id) 1209 } 1210 } 1211 1212 r3 := []byte{3, 5, 2} 1213 repls[1].Request(r3) 1214 1215 sys.Run() 1216 1217 for _, a := range adapters { 1218 if len(a.batches[chainId]) == 0 { 1219 t.Fatalf("expected execution of some batches on %d", a.id) 1220 } 1221 1222 if !reflect.DeepEqual([][]byte{r3}, a.batches[chainId][len(a.batches[chainId])-1].Payloads) { 1223 t.Errorf("wrong request executed on %d: %v", a.id, a.batches[chainId][2]) 1224 } 1225 } 1226 } 1227 1228 func TestFullBacklog(t *testing.T) { 1229 skipInShortMode(t) 1230 N := lowN 1231 BS := uint64(1) 1232 sys := newTestSystemWithBatchSize(N, BS) 1233 var repls []*SBFT 1234 var adapters []*testSystemAdapter 1235 for i := uint64(0); i < N; i++ { 1236 a := sys.NewAdapter(i) 1237 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: BS, RequestTimeoutNsec: 20000000000}, a) 1238 if err != nil { 1239 t.Fatal(err) 1240 } 1241 repls = append(repls, s) 1242 adapters = append(adapters, a) 1243 } 1244 1245 r1 := []byte{1, 2, 3} 1246 1247 connectAllForDefaultChain(sys) 1248 sys.enqueue(200*time.Millisecond, &testTimer{id: 999, tf: func() { 1249 repls[0].sys.Send(chainId, &Msg{&Msg_Prepare{&Subject{Seq: &SeqView{Seq: 100}}}}, 1) 1250 }}) 1251 for i := 0; i < 10; i++ { 1252 sys.enqueue(time.Duration(i)*100*time.Millisecond, &testTimer{id: 999, tf: func() { 1253 repls[0].Request(r1) 1254 }}) 1255 } 1256 sys.Run() 1257 if len(repls[1].replicaState[2].backLog) > 4*3 { 1258 t.Errorf("backlog too long: %d", len(repls[1].replicaState[0].backLog)) 1259 } 1260 for _, a := range adapters { 1261 if len(a.batches[chainId]) == 0 { 1262 t.Fatalf("expected execution of batches on %d", a.id) 1263 } 1264 bh := a.batches[chainId][len(a.batches[chainId])-1].DecodeHeader() 1265 if bh.Seq != 10 { 1266 t.Errorf("wrong request executed on %d: %v", a.id, bh) 1267 } 1268 } 1269 } 1270 1271 func TestHelloMsg(t *testing.T) { 1272 skipInShortMode(t) 1273 N := lowN 1274 BS := uint64(1) 1275 sys := newTestSystemWOTimersWithBatchSize(N, BS) 1276 var repls []*SBFT 1277 var adapters []*testSystemAdapter 1278 for i := uint64(0); i < N; i++ { 1279 a := sys.NewAdapter(i) 1280 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: uint64(BS), RequestTimeoutNsec: 20000000000}, a) 1281 if err != nil { 1282 t.Fatal(err) 1283 } 1284 repls = append(repls, s) 1285 adapters = append(adapters, a) 1286 } 1287 1288 phase := 1 1289 1290 // We are going to deliver only pre-prepare of the first request to replica 1 1291 // other messages pertaining to first request, destined to 1 will be dropped 1292 sys.filterFn = func(e testElem) (testElem, bool) { 1293 if msg, ok := e.ev.(*testMsgEvent); ok { 1294 if msg.dst == 1 { 1295 c := msg.msg.GetPreprepare() 1296 if c != nil && c.Seq.View == 0 && phase == 1 { 1297 return e, true // letting the first pre-prepare be delivered to 1 1298 } 1299 if phase > 1 { 1300 return e, true //letting msgs outside phase 1 through 1301 } 1302 return e, false //dropping other phase 1 msgs 1303 } 1304 } 1305 return e, true 1306 } 1307 1308 connectAllForDefaultChain(sys) 1309 r1 := []byte{1, 2, 3} 1310 repls[0].Request(r1) 1311 sys.Run() 1312 1313 phase = 2 //start delivering msgs to replica 1 1314 1315 testLog.Notice("restarting replica 1") 1316 repls[1], _ = New(1, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: BS, RequestTimeoutNsec: 20000000000}, adapters[1]) 1317 for _, a := range adapters { 1318 if a.id != 1 { 1319 a.receivers[chainId].Connection(1) 1320 adapters[1].receivers[chainId].Connection(a.id) 1321 } 1322 } 1323 1324 sys.Run() 1325 1326 phase = 3 1327 1328 r3 := []byte{3, 5, 2} 1329 repls[1].Request(r3) 1330 sys.Run() 1331 1332 for i, a := range adapters { 1333 if len(a.batches[chainId]) != 2 { 1334 t.Fatalf("expected execution of 2 batches but executed %d %d", len(a.batches[chainId]), i) 1335 } 1336 } 1337 } 1338 1339 func TestViewChangeTimer(t *testing.T) { 1340 skipInShortMode(t) 1341 N := lowN 1342 sys := newTestSystem(N) 1343 var repls []*SBFT 1344 var adapters []*testSystemAdapter 1345 for i := uint64(0); i < N; i++ { 1346 a := sys.NewAdapter(i) 1347 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 1348 if err != nil { 1349 t.Fatal(err) 1350 } 1351 repls = append(repls, s) 1352 adapters = append(adapters, a) 1353 } 1354 1355 phase := 1 1356 1357 // network outage after prepares are received 1358 sys.filterFn = func(e testElem) (testElem, bool) { 1359 if msg, ok := e.ev.(*testMsgEvent); ok { 1360 if msg.dst == msg.src { 1361 return e, true 1362 } else if msg.src == 1 && phase == 2 { 1363 return e, false 1364 } 1365 testLog.Debugf("passing msg from %d to %d, phase %d", msg.src, msg.dst, phase) 1366 } 1367 1368 return e, true 1369 } 1370 1371 connectAllForDefaultChain(sys) 1372 r1 := []byte{1, 2, 3} 1373 repls[0].Request(r1) 1374 1375 repls[3].sendViewChange() 1376 1377 sys.enqueue(10*time.Minute, &testTimer{id: 999, tf: func() { 1378 if repls[3].view != 1 { 1379 t.Fatalf("expected view not to advance past 1, we are in %d", repls[3].view) 1380 } 1381 }}) 1382 1383 sys.enqueue(11*time.Minute, &testTimer{id: 999, tf: func() { 1384 phase = 2 1385 repls[2].sendViewChange() 1386 }}) 1387 1388 sys.enqueue(12*time.Minute, &testTimer{id: 999, tf: func() { 1389 if repls[3].view != 2 { 1390 t.Fatalf("expected view not to advance past 2, 3 is in %d", repls[3].view) 1391 } 1392 }}) 1393 1394 sys.enqueue(20*time.Minute, &testTimer{id: 999, tf: func() { 1395 for _, r := range repls { 1396 if r.view > 4 { 1397 t.Fatalf("expected view not to advance too much, we are in %d", r.view) 1398 } 1399 } 1400 }}) 1401 1402 sys.Run() 1403 r2 := []byte{3, 1, 2} 1404 r3 := []byte{3, 5, 2} 1405 repls[2].Request(r2) 1406 repls[2].Request(r3) 1407 sys.Run() 1408 for _, a := range adapters { 1409 if len(a.batches[chainId]) != 2 { 1410 t.Fatalf("%d: expected execution of 2 batches: %v", a.id, a.batches[chainId]) 1411 } 1412 if a.id != 3 { 1413 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 1414 t.Errorf("%d: wrong request executed (1): %v", a.id, a.batches[chainId]) 1415 } 1416 } 1417 if !reflect.DeepEqual([][]byte{r2, r3}, a.batches[chainId][1].Payloads) { 1418 t.Errorf("%d: wrong request executed (2): %v", a.id, a.batches[chainId]) 1419 } 1420 } 1421 } 1422 1423 func TestResendViewChange(t *testing.T) { 1424 skipInShortMode(t) 1425 N := lowN 1426 sys := newTestSystem(N) 1427 var repls []*SBFT 1428 var adapters []*testSystemAdapter 1429 for i := uint64(0); i < N; i++ { 1430 a := sys.NewAdapter(i) 1431 s, err := New(i, chainId, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) 1432 if err != nil { 1433 t.Fatal(err) 1434 } 1435 repls = append(repls, s) 1436 adapters = append(adapters, a) 1437 } 1438 1439 phase := make(map[uint64]int) 1440 1441 // prevent first view change from being delivered 1442 sys.filterFn = func(e testElem) (testElem, bool) { 1443 if msg, ok := e.ev.(*testMsgEvent); ok { 1444 if msg.dst == msg.src { 1445 return e, true 1446 } else if phase[msg.src] == 0 && msg.msg.GetViewChange() != nil { 1447 return e, false 1448 } else if msg.msg.GetHello() != nil { 1449 phase[msg.src] = 1 1450 } 1451 } 1452 1453 return e, true 1454 } 1455 1456 for _, r := range repls { 1457 r.sendViewChange() 1458 } 1459 sys.Run() 1460 1461 connectAllForDefaultChain(sys) 1462 r1 := []byte{1, 2, 3} 1463 repls[0].Request(r1) 1464 sys.Run() 1465 r2 := []byte{3, 1, 2} 1466 r3 := []byte{3, 5, 2} 1467 repls[1].Request(r2) 1468 repls[1].Request(r3) 1469 sys.Run() 1470 for _, a := range adapters { 1471 if len(a.batches[chainId]) != 2 { 1472 t.Fatal("expected execution of 2 batches") 1473 } 1474 if !reflect.DeepEqual([][]byte{r1}, a.batches[chainId][0].Payloads) { 1475 t.Error("wrong request executed (1)") 1476 } 1477 if !reflect.DeepEqual([][]byte{r2, r3}, a.batches[chainId][1].Payloads) { 1478 t.Error("wrong request executed (2)") 1479 } 1480 } 1481 } 1482 1483 func TestTenReplicasBombedWithRequests(t *testing.T) { 1484 skipInShortMode(t) 1485 N := highN 1486 requestNumber := 11 1487 sys := newTestSystem(N) 1488 var repls []*SBFT 1489 var adapters []*testSystemAdapter 1490 for i := uint64(0); i < N; i++ { 1491 a := sys.NewAdapter(i) 1492 s, err := New(i, chainId, &Config{N: N, F: 3, BatchDurationNsec: 2000000000, BatchSizeBytes: 3, RequestTimeoutNsec: 20000000000}, a) 1493 if err != nil { 1494 t.Fatal(err) 1495 } 1496 repls = append(repls, s) 1497 adapters = append(adapters, a) 1498 } 1499 1500 connectAllForDefaultChain(sys) 1501 for i := 0; i < requestNumber; i++ { 1502 r := []byte{byte(i), 2, 3} 1503 repls[2].Request(r) 1504 } 1505 sys.Run() 1506 for _, a := range adapters { 1507 i := 0 1508 for _, b := range a.batches[chainId] { 1509 i = i + len(b.Payloads) 1510 } 1511 if i != requestNumber { 1512 t.Fatalf("expected execution of %d requests but: %d", requestNumber, i) 1513 } 1514 } 1515 }