github.com/ccm-chain/ccmchain@v1.0.0/core/blockchain_repair_test.go (about) 1 // Copyright 2020 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Tests that abnormal program termination (i.e.crash) and restart doesn't leave 18 // the database in some strange state with gaps in the chain, nor with block data 19 // dangling in the future. 20 21 package core 22 23 import ( 24 "io/ioutil" 25 "math/big" 26 "os" 27 "testing" 28 29 "github.com/ccm-chain/ccmchain/common" 30 "github.com/ccm-chain/ccmchain/consensus/ethash" 31 "github.com/ccm-chain/ccmchain/core/rawdb" 32 "github.com/ccm-chain/ccmchain/core/types" 33 "github.com/ccm-chain/ccmchain/core/vm" 34 "github.com/ccm-chain/ccmchain/params" 35 ) 36 37 // Tests a recovery for a short canonical chain where a recent block was already 38 // committed to disk and then the process crashed. In this case we expect the full 39 // chain to be rolled back to the committed block, but the chain data itself left 40 // in the database for replaying. 41 func TestShortRepair(t *testing.T) { 42 // Chain: 43 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 44 // 45 // Frozen: none 46 // Commit: G, C4 47 // Pivot : none 48 // 49 // CRASH 50 // 51 // ------------------------------ 52 // 53 // Expected in leveldb: 54 // G->C1->C2->C3->C4->C5->C6->C7->C8 55 // 56 // Expected head header : C8 57 // Expected head fast block: C8 58 // Expected head block : C4 59 testRepair(t, &rewindTest{ 60 canonicalBlocks: 8, 61 sidechainBlocks: 0, 62 freezeThreshold: 16, 63 commitBlock: 4, 64 pivotBlock: nil, 65 expCanonicalBlocks: 8, 66 expSidechainBlocks: 0, 67 expFrozen: 0, 68 expHeadHeader: 8, 69 expHeadFastBlock: 8, 70 expHeadBlock: 4, 71 }) 72 } 73 74 // Tests a recovery for a short canonical chain where the fast sync pivot point was 75 // already committed, after which the process crashed. In this case we expect the full 76 // chain to be rolled back to the committed block, but the chain data itself left in 77 // the database for replaying. 78 func TestShortFastSyncedRepair(t *testing.T) { 79 // Chain: 80 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 81 // 82 // Frozen: none 83 // Commit: G, C4 84 // Pivot : C4 85 // 86 // CRASH 87 // 88 // ------------------------------ 89 // 90 // Expected in leveldb: 91 // G->C1->C2->C3->C4->C5->C6->C7->C8 92 // 93 // Expected head header : C8 94 // Expected head fast block: C8 95 // Expected head block : C4 96 testRepair(t, &rewindTest{ 97 canonicalBlocks: 8, 98 sidechainBlocks: 0, 99 freezeThreshold: 16, 100 commitBlock: 4, 101 pivotBlock: uint64ptr(4), 102 expCanonicalBlocks: 8, 103 expSidechainBlocks: 0, 104 expFrozen: 0, 105 expHeadHeader: 8, 106 expHeadFastBlock: 8, 107 expHeadBlock: 4, 108 }) 109 } 110 111 // Tests a recovery for a short canonical chain where the fast sync pivot point was 112 // not yet committed, but the process crashed. In this case we expect the chain to 113 // detect that it was fast syncing and not delete anything, since we can just pick 114 // up directly where we left off. 115 func TestShortFastSyncingRepair(t *testing.T) { 116 // Chain: 117 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 118 // 119 // Frozen: none 120 // Commit: G 121 // Pivot : C4 122 // 123 // CRASH 124 // 125 // ------------------------------ 126 // 127 // Expected in leveldb: 128 // G->C1->C2->C3->C4->C5->C6->C7->C8 129 // 130 // Expected head header : C8 131 // Expected head fast block: C8 132 // Expected head block : G 133 testRepair(t, &rewindTest{ 134 canonicalBlocks: 8, 135 sidechainBlocks: 0, 136 freezeThreshold: 16, 137 commitBlock: 0, 138 pivotBlock: uint64ptr(4), 139 expCanonicalBlocks: 8, 140 expSidechainBlocks: 0, 141 expFrozen: 0, 142 expHeadHeader: 8, 143 expHeadFastBlock: 8, 144 expHeadBlock: 0, 145 }) 146 } 147 148 // Tests a recovery for a short canonical chain and a shorter side chain, where a 149 // recent block was already committed to disk and then the process crashed. In this 150 // test scenario the side chain is below the committed block. In this case we expect 151 // the canonical chain to be rolled back to the committed block, but the chain data 152 // itself left in the database for replaying. 153 func TestShortOldForkedRepair(t *testing.T) { 154 // Chain: 155 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 156 // └->S1->S2->S3 157 // 158 // Frozen: none 159 // Commit: G, C4 160 // Pivot : none 161 // 162 // CRASH 163 // 164 // ------------------------------ 165 // 166 // Expected in leveldb: 167 // G->C1->C2->C3->C4->C5->C6->C7->C8 168 // └->S1->S2->S3 169 // 170 // Expected head header : C8 171 // Expected head fast block: C8 172 // Expected head block : C4 173 testRepair(t, &rewindTest{ 174 canonicalBlocks: 8, 175 sidechainBlocks: 3, 176 freezeThreshold: 16, 177 commitBlock: 4, 178 pivotBlock: nil, 179 expCanonicalBlocks: 8, 180 expSidechainBlocks: 3, 181 expFrozen: 0, 182 expHeadHeader: 8, 183 expHeadFastBlock: 8, 184 expHeadBlock: 4, 185 }) 186 } 187 188 // Tests a recovery for a short canonical chain and a shorter side chain, where 189 // the fast sync pivot point was already committed to disk and then the process 190 // crashed. In this test scenario the side chain is below the committed block. In 191 // this case we expect the canonical chain to be rolled back to the committed block, 192 // but the chain data itself left in the database for replaying. 193 func TestShortOldForkedFastSyncedRepair(t *testing.T) { 194 // Chain: 195 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 196 // └->S1->S2->S3 197 // 198 // Frozen: none 199 // Commit: G, C4 200 // Pivot : C4 201 // 202 // CRASH 203 // 204 // ------------------------------ 205 // 206 // Expected in leveldb: 207 // G->C1->C2->C3->C4->C5->C6->C7->C8 208 // └->S1->S2->S3 209 // 210 // Expected head header : C8 211 // Expected head fast block: C8 212 // Expected head block : C4 213 testRepair(t, &rewindTest{ 214 canonicalBlocks: 8, 215 sidechainBlocks: 3, 216 freezeThreshold: 16, 217 commitBlock: 4, 218 pivotBlock: uint64ptr(4), 219 expCanonicalBlocks: 8, 220 expSidechainBlocks: 3, 221 expFrozen: 0, 222 expHeadHeader: 8, 223 expHeadFastBlock: 8, 224 expHeadBlock: 4, 225 }) 226 } 227 228 // Tests a recovery for a short canonical chain and a shorter side chain, where 229 // the fast sync pivot point was not yet committed, but the process crashed. In this 230 // test scenario the side chain is below the committed block. In this case we expect 231 // the chain to detect that it was fast syncing and not delete anything, since we 232 // can just pick up directly where we left off. 233 func TestShortOldForkedFastSyncingRepair(t *testing.T) { 234 // Chain: 235 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 236 // └->S1->S2->S3 237 // 238 // Frozen: none 239 // Commit: G 240 // Pivot : C4 241 // 242 // CRASH 243 // 244 // ------------------------------ 245 // 246 // Expected in leveldb: 247 // G->C1->C2->C3->C4->C5->C6->C7->C8 248 // └->S1->S2->S3 249 // 250 // Expected head header : C8 251 // Expected head fast block: C8 252 // Expected head block : G 253 testRepair(t, &rewindTest{ 254 canonicalBlocks: 8, 255 sidechainBlocks: 3, 256 freezeThreshold: 16, 257 commitBlock: 0, 258 pivotBlock: uint64ptr(4), 259 expCanonicalBlocks: 8, 260 expSidechainBlocks: 3, 261 expFrozen: 0, 262 expHeadHeader: 8, 263 expHeadFastBlock: 8, 264 expHeadBlock: 0, 265 }) 266 } 267 268 // Tests a recovery for a short canonical chain and a shorter side chain, where a 269 // recent block was already committed to disk and then the process crashed. In this 270 // test scenario the side chain reaches above the committed block. In this case we 271 // expect the canonical chain to be rolled back to the committed block, but the 272 // chain data itself left in the database for replaying. 273 func TestShortNewlyForkedRepair(t *testing.T) { 274 // Chain: 275 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 276 // └->S1->S2->S3->S4->S5->S6 277 // 278 // Frozen: none 279 // Commit: G, C4 280 // Pivot : none 281 // 282 // CRASH 283 // 284 // ------------------------------ 285 // 286 // Expected in leveldb: 287 // G->C1->C2->C3->C4->C5->C6->C7->C8 288 // └->S1->S2->S3->S4->S5->S6 289 // 290 // Expected head header : C8 291 // Expected head fast block: C8 292 // Expected head block : C4 293 testRepair(t, &rewindTest{ 294 canonicalBlocks: 8, 295 sidechainBlocks: 6, 296 freezeThreshold: 16, 297 commitBlock: 4, 298 pivotBlock: nil, 299 expCanonicalBlocks: 8, 300 expSidechainBlocks: 6, 301 expFrozen: 0, 302 expHeadHeader: 8, 303 expHeadFastBlock: 8, 304 expHeadBlock: 4, 305 }) 306 } 307 308 // Tests a recovery for a short canonical chain and a shorter side chain, where 309 // the fast sync pivot point was already committed to disk and then the process 310 // crashed. In this test scenario the side chain reaches above the committed block. 311 // In this case we expect the canonical chain to be rolled back to the committed 312 // block, but the chain data itself left in the database for replaying. 313 func TestShortNewlyForkedFastSyncedRepair(t *testing.T) { 314 // Chain: 315 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 316 // └->S1->S2->S3->S4->S5->S6 317 // 318 // Frozen: none 319 // Commit: G, C4 320 // Pivot : C4 321 // 322 // CRASH 323 // 324 // ------------------------------ 325 // 326 // Expected in leveldb: 327 // G->C1->C2->C3->C4->C5->C6->C7->C8 328 // └->S1->S2->S3->S4->S5->S6 329 // 330 // Expected head header : C8 331 // Expected head fast block: C8 332 // Expected head block : C4 333 testRepair(t, &rewindTest{ 334 canonicalBlocks: 8, 335 sidechainBlocks: 6, 336 freezeThreshold: 16, 337 commitBlock: 4, 338 pivotBlock: uint64ptr(4), 339 expCanonicalBlocks: 8, 340 expSidechainBlocks: 6, 341 expFrozen: 0, 342 expHeadHeader: 8, 343 expHeadFastBlock: 8, 344 expHeadBlock: 4, 345 }) 346 } 347 348 // Tests a recovery for a short canonical chain and a shorter side chain, where 349 // the fast sync pivot point was not yet committed, but the process crashed. In 350 // this test scenario the side chain reaches above the committed block. In this 351 // case we expect the chain to detect that it was fast syncing and not delete 352 // anything, since we can just pick up directly where we left off. 353 func TestShortNewlyForkedFastSyncingRepair(t *testing.T) { 354 // Chain: 355 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 356 // └->S1->S2->S3->S4->S5->S6 357 // 358 // Frozen: none 359 // Commit: G 360 // Pivot : C4 361 // 362 // CRASH 363 // 364 // ------------------------------ 365 // 366 // Expected in leveldb: 367 // G->C1->C2->C3->C4->C5->C6->C7->C8 368 // └->S1->S2->S3->S4->S5->S6 369 // 370 // Expected head header : C8 371 // Expected head fast block: C8 372 // Expected head block : G 373 testRepair(t, &rewindTest{ 374 canonicalBlocks: 8, 375 sidechainBlocks: 6, 376 freezeThreshold: 16, 377 commitBlock: 0, 378 pivotBlock: uint64ptr(4), 379 expCanonicalBlocks: 8, 380 expSidechainBlocks: 6, 381 expFrozen: 0, 382 expHeadHeader: 8, 383 expHeadFastBlock: 8, 384 expHeadBlock: 0, 385 }) 386 } 387 388 // Tests a recovery for a short canonical chain and a longer side chain, where a 389 // recent block was already committed to disk and then the process crashed. In this 390 // case we expect the canonical chain to be rolled back to the committed block, but 391 // the chain data itself left in the database for replaying. 392 func TestShortReorgedRepair(t *testing.T) { 393 // Chain: 394 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 395 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 396 // 397 // Frozen: none 398 // Commit: G, C4 399 // Pivot : none 400 // 401 // CRASH 402 // 403 // ------------------------------ 404 // 405 // Expected in leveldb: 406 // G->C1->C2->C3->C4->C5->C6->C7->C8 407 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 408 // 409 // Expected head header : C8 410 // Expected head fast block: C8 411 // Expected head block : C4 412 testRepair(t, &rewindTest{ 413 canonicalBlocks: 8, 414 sidechainBlocks: 10, 415 freezeThreshold: 16, 416 commitBlock: 4, 417 pivotBlock: nil, 418 expCanonicalBlocks: 8, 419 expSidechainBlocks: 10, 420 expFrozen: 0, 421 expHeadHeader: 8, 422 expHeadFastBlock: 8, 423 expHeadBlock: 4, 424 }) 425 } 426 427 // Tests a recovery for a short canonical chain and a longer side chain, where 428 // the fast sync pivot point was already committed to disk and then the process 429 // crashed. In this case we expect the canonical chain to be rolled back to the 430 // committed block, but the chain data itself left in the database for replaying. 431 func TestShortReorgedFastSyncedRepair(t *testing.T) { 432 // Chain: 433 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 434 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 435 // 436 // Frozen: none 437 // Commit: G, C4 438 // Pivot : C4 439 // 440 // CRASH 441 // 442 // ------------------------------ 443 // 444 // Expected in leveldb: 445 // G->C1->C2->C3->C4->C5->C6->C7->C8 446 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 447 // 448 // Expected head header : C8 449 // Expected head fast block: C8 450 // Expected head block : C4 451 testRepair(t, &rewindTest{ 452 canonicalBlocks: 8, 453 sidechainBlocks: 10, 454 freezeThreshold: 16, 455 commitBlock: 4, 456 pivotBlock: uint64ptr(4), 457 expCanonicalBlocks: 8, 458 expSidechainBlocks: 10, 459 expFrozen: 0, 460 expHeadHeader: 8, 461 expHeadFastBlock: 8, 462 expHeadBlock: 4, 463 }) 464 } 465 466 // Tests a recovery for a short canonical chain and a longer side chain, where 467 // the fast sync pivot point was not yet committed, but the process crashed. In 468 // this case we expect the chain to detect that it was fast syncing and not delete 469 // anything, since we can just pick up directly where we left off. 470 func TestShortReorgedFastSyncingRepair(t *testing.T) { 471 // Chain: 472 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 473 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 474 // 475 // Frozen: none 476 // Commit: G 477 // Pivot : C4 478 // 479 // CRASH 480 // 481 // ------------------------------ 482 // 483 // Expected in leveldb: 484 // G->C1->C2->C3->C4->C5->C6->C7->C8 485 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 486 // 487 // Expected head header : C8 488 // Expected head fast block: C8 489 // Expected head block : G 490 testRepair(t, &rewindTest{ 491 canonicalBlocks: 8, 492 sidechainBlocks: 10, 493 freezeThreshold: 16, 494 commitBlock: 0, 495 pivotBlock: uint64ptr(4), 496 expCanonicalBlocks: 8, 497 expSidechainBlocks: 10, 498 expFrozen: 0, 499 expHeadHeader: 8, 500 expHeadFastBlock: 8, 501 expHeadBlock: 0, 502 }) 503 } 504 505 // Tests a recovery for a long canonical chain with frozen blocks where a recent 506 // block - newer than the ancient limit - was already committed to disk and then 507 // the process crashed. In this case we expect the chain to be rolled back to the 508 // committed block, with everything afterwads kept as fast sync data. 509 func TestLongShallowRepair(t *testing.T) { 510 // Chain: 511 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 512 // 513 // Frozen: 514 // G->C1->C2 515 // 516 // Commit: G, C4 517 // Pivot : none 518 // 519 // CRASH 520 // 521 // ------------------------------ 522 // 523 // Expected in freezer: 524 // G->C1->C2 525 // 526 // Expected in leveldb: 527 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 528 // 529 // Expected head header : C18 530 // Expected head fast block: C18 531 // Expected head block : C4 532 testRepair(t, &rewindTest{ 533 canonicalBlocks: 18, 534 sidechainBlocks: 0, 535 freezeThreshold: 16, 536 commitBlock: 4, 537 pivotBlock: nil, 538 expCanonicalBlocks: 18, 539 expSidechainBlocks: 0, 540 expFrozen: 3, 541 expHeadHeader: 18, 542 expHeadFastBlock: 18, 543 expHeadBlock: 4, 544 }) 545 } 546 547 // Tests a recovery for a long canonical chain with frozen blocks where a recent 548 // block - older than the ancient limit - was already committed to disk and then 549 // the process crashed. In this case we expect the chain to be rolled back to the 550 // committed block, with everything afterwads deleted. 551 func TestLongDeepRepair(t *testing.T) { 552 // Chain: 553 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 554 // 555 // Frozen: 556 // G->C1->C2->C3->C4->C5->C6->C7->C8 557 // 558 // Commit: G, C4 559 // Pivot : none 560 // 561 // CRASH 562 // 563 // ------------------------------ 564 // 565 // Expected in freezer: 566 // G->C1->C2->C3->C4 567 // 568 // Expected in leveldb: none 569 // 570 // Expected head header : C4 571 // Expected head fast block: C4 572 // Expected head block : C4 573 testRepair(t, &rewindTest{ 574 canonicalBlocks: 24, 575 sidechainBlocks: 0, 576 freezeThreshold: 16, 577 commitBlock: 4, 578 pivotBlock: nil, 579 expCanonicalBlocks: 4, 580 expSidechainBlocks: 0, 581 expFrozen: 5, 582 expHeadHeader: 4, 583 expHeadFastBlock: 4, 584 expHeadBlock: 4, 585 }) 586 } 587 588 // Tests a recovery for a long canonical chain with frozen blocks where the fast 589 // sync pivot point - newer than the ancient limit - was already committed, after 590 // which the process crashed. In this case we expect the chain to be rolled back 591 // to the committed block, with everything afterwads kept as fast sync data. 592 func TestLongFastSyncedShallowRepair(t *testing.T) { 593 // Chain: 594 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 595 // 596 // Frozen: 597 // G->C1->C2 598 // 599 // Commit: G, C4 600 // Pivot : C4 601 // 602 // CRASH 603 // 604 // ------------------------------ 605 // 606 // Expected in freezer: 607 // G->C1->C2 608 // 609 // Expected in leveldb: 610 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 611 // 612 // Expected head header : C18 613 // Expected head fast block: C18 614 // Expected head block : C4 615 testRepair(t, &rewindTest{ 616 canonicalBlocks: 18, 617 sidechainBlocks: 0, 618 freezeThreshold: 16, 619 commitBlock: 4, 620 pivotBlock: uint64ptr(4), 621 expCanonicalBlocks: 18, 622 expSidechainBlocks: 0, 623 expFrozen: 3, 624 expHeadHeader: 18, 625 expHeadFastBlock: 18, 626 expHeadBlock: 4, 627 }) 628 } 629 630 // Tests a recovery for a long canonical chain with frozen blocks where the fast 631 // sync pivot point - older than the ancient limit - was already committed, after 632 // which the process crashed. In this case we expect the chain to be rolled back 633 // to the committed block, with everything afterwads deleted. 634 func TestLongFastSyncedDeepRepair(t *testing.T) { 635 // Chain: 636 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 637 // 638 // Frozen: 639 // G->C1->C2->C3->C4->C5->C6->C7->C8 640 // 641 // Commit: G, C4 642 // Pivot : C4 643 // 644 // CRASH 645 // 646 // ------------------------------ 647 // 648 // Expected in freezer: 649 // G->C1->C2->C3->C4 650 // 651 // Expected in leveldb: none 652 // 653 // Expected head header : C4 654 // Expected head fast block: C4 655 // Expected head block : C4 656 testRepair(t, &rewindTest{ 657 canonicalBlocks: 24, 658 sidechainBlocks: 0, 659 freezeThreshold: 16, 660 commitBlock: 4, 661 pivotBlock: uint64ptr(4), 662 expCanonicalBlocks: 4, 663 expSidechainBlocks: 0, 664 expFrozen: 5, 665 expHeadHeader: 4, 666 expHeadFastBlock: 4, 667 expHeadBlock: 4, 668 }) 669 } 670 671 // Tests a recovery for a long canonical chain with frozen blocks where the fast 672 // sync pivot point - older than the ancient limit - was not yet committed, but the 673 // process crashed. In this case we expect the chain to detect that it was fast 674 // syncing and not delete anything, since we can just pick up directly where we 675 // left off. 676 func TestLongFastSyncingShallowRepair(t *testing.T) { 677 // Chain: 678 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 679 // 680 // Frozen: 681 // G->C1->C2 682 // 683 // Commit: G 684 // Pivot : C4 685 // 686 // CRASH 687 // 688 // ------------------------------ 689 // 690 // Expected in freezer: 691 // G->C1->C2 692 // 693 // Expected in leveldb: 694 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 695 // 696 // Expected head header : C18 697 // Expected head fast block: C18 698 // Expected head block : G 699 testRepair(t, &rewindTest{ 700 canonicalBlocks: 18, 701 sidechainBlocks: 0, 702 freezeThreshold: 16, 703 commitBlock: 0, 704 pivotBlock: uint64ptr(4), 705 expCanonicalBlocks: 18, 706 expSidechainBlocks: 0, 707 expFrozen: 3, 708 expHeadHeader: 18, 709 expHeadFastBlock: 18, 710 expHeadBlock: 0, 711 }) 712 } 713 714 // Tests a recovery for a long canonical chain with frozen blocks where the fast 715 // sync pivot point - newer than the ancient limit - was not yet committed, but the 716 // process crashed. In this case we expect the chain to detect that it was fast 717 // syncing and not delete anything, since we can just pick up directly where we 718 // left off. 719 func TestLongFastSyncingDeepRepair(t *testing.T) { 720 // Chain: 721 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 722 // 723 // Frozen: 724 // G->C1->C2->C3->C4->C5->C6->C7->C8 725 // 726 // Commit: G 727 // Pivot : C4 728 // 729 // CRASH 730 // 731 // ------------------------------ 732 // 733 // Expected in freezer: 734 // G->C1->C2->C3->C4->C5->C6->C7->C8 735 // 736 // Expected in leveldb: 737 // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 738 // 739 // Expected head header : C24 740 // Expected head fast block: C24 741 // Expected head block : G 742 testRepair(t, &rewindTest{ 743 canonicalBlocks: 24, 744 sidechainBlocks: 0, 745 freezeThreshold: 16, 746 commitBlock: 0, 747 pivotBlock: uint64ptr(4), 748 expCanonicalBlocks: 24, 749 expSidechainBlocks: 0, 750 expFrozen: 9, 751 expHeadHeader: 24, 752 expHeadFastBlock: 24, 753 expHeadBlock: 0, 754 }) 755 } 756 757 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 758 // side chain, where a recent block - newer than the ancient limit - was already 759 // committed to disk and then the process crashed. In this test scenario the side 760 // chain is below the committed block. In this case we expect the chain to be 761 // rolled back to the committed block, with everything afterwads kept as fast 762 // sync data; the side chain completely nuked by the freezer. 763 func TestLongOldForkedShallowRepair(t *testing.T) { 764 // Chain: 765 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 766 // └->S1->S2->S3 767 // 768 // Frozen: 769 // G->C1->C2 770 // 771 // Commit: G, C4 772 // Pivot : none 773 // 774 // CRASH 775 // 776 // ------------------------------ 777 // 778 // Expected in freezer: 779 // G->C1->C2 780 // 781 // Expected in leveldb: 782 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 783 // 784 // Expected head header : C18 785 // Expected head fast block: C18 786 // Expected head block : C4 787 testRepair(t, &rewindTest{ 788 canonicalBlocks: 18, 789 sidechainBlocks: 3, 790 freezeThreshold: 16, 791 commitBlock: 4, 792 pivotBlock: nil, 793 expCanonicalBlocks: 18, 794 expSidechainBlocks: 0, 795 expFrozen: 3, 796 expHeadHeader: 18, 797 expHeadFastBlock: 18, 798 expHeadBlock: 4, 799 }) 800 } 801 802 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 803 // side chain, where a recent block - older than the ancient limit - was already 804 // committed to disk and then the process crashed. In this test scenario the side 805 // chain is below the committed block. In this case we expect the canonical chain 806 // to be rolled back to the committed block, with everything afterwads deleted; 807 // the side chain completely nuked by the freezer. 808 func TestLongOldForkedDeepRepair(t *testing.T) { 809 // Chain: 810 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 811 // └->S1->S2->S3 812 // 813 // Frozen: 814 // G->C1->C2->C3->C4->C5->C6->C7->C8 815 // 816 // Commit: G, C4 817 // Pivot : none 818 // 819 // CRASH 820 // 821 // ------------------------------ 822 // 823 // Expected in freezer: 824 // G->C1->C2->C3->C4 825 // 826 // Expected in leveldb: none 827 // 828 // Expected head header : C4 829 // Expected head fast block: C4 830 // Expected head block : C4 831 testRepair(t, &rewindTest{ 832 canonicalBlocks: 24, 833 sidechainBlocks: 3, 834 freezeThreshold: 16, 835 commitBlock: 4, 836 pivotBlock: nil, 837 expCanonicalBlocks: 4, 838 expSidechainBlocks: 0, 839 expFrozen: 5, 840 expHeadHeader: 4, 841 expHeadFastBlock: 4, 842 expHeadBlock: 4, 843 }) 844 } 845 846 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 847 // side chain, where the fast sync pivot point - newer than the ancient limit - 848 // was already committed to disk and then the process crashed. In this test scenario 849 // the side chain is below the committed block. In this case we expect the chain 850 // to be rolled back to the committed block, with everything afterwads kept as 851 // fast sync data; the side chain completely nuked by the freezer. 852 func TestLongOldForkedFastSyncedShallowRepair(t *testing.T) { 853 // Chain: 854 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 855 // └->S1->S2->S3 856 // 857 // Frozen: 858 // G->C1->C2 859 // 860 // Commit: G, C4 861 // Pivot : C4 862 // 863 // CRASH 864 // 865 // ------------------------------ 866 // 867 // Expected in freezer: 868 // G->C1->C2 869 // 870 // Expected in leveldb: 871 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 872 // 873 // Expected head header : C18 874 // Expected head fast block: C18 875 // Expected head block : C4 876 testRepair(t, &rewindTest{ 877 canonicalBlocks: 18, 878 sidechainBlocks: 3, 879 freezeThreshold: 16, 880 commitBlock: 4, 881 pivotBlock: uint64ptr(4), 882 expCanonicalBlocks: 18, 883 expSidechainBlocks: 0, 884 expFrozen: 3, 885 expHeadHeader: 18, 886 expHeadFastBlock: 18, 887 expHeadBlock: 4, 888 }) 889 } 890 891 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 892 // side chain, where the fast sync pivot point - older than the ancient limit - 893 // was already committed to disk and then the process crashed. In this test scenario 894 // the side chain is below the committed block. In this case we expect the canonical 895 // chain to be rolled back to the committed block, with everything afterwads deleted; 896 // the side chain completely nuked by the freezer. 897 func TestLongOldForkedFastSyncedDeepRepair(t *testing.T) { 898 // Chain: 899 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 900 // └->S1->S2->S3 901 // 902 // Frozen: 903 // G->C1->C2->C3->C4->C5->C6->C7->C8 904 // 905 // Commit: G, C4 906 // Pivot : C4 907 // 908 // CRASH 909 // 910 // ------------------------------ 911 // 912 // Expected in freezer: 913 // G->C1->C2->C3->C4 914 // 915 // Expected in leveldb: none 916 // 917 // Expected head header : C4 918 // Expected head fast block: C4 919 // Expected head block : C4 920 testRepair(t, &rewindTest{ 921 canonicalBlocks: 24, 922 sidechainBlocks: 3, 923 freezeThreshold: 16, 924 commitBlock: 4, 925 pivotBlock: uint64ptr(4), 926 expCanonicalBlocks: 4, 927 expSidechainBlocks: 0, 928 expFrozen: 5, 929 expHeadHeader: 4, 930 expHeadFastBlock: 4, 931 expHeadBlock: 4, 932 }) 933 } 934 935 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 936 // side chain, where the fast sync pivot point - older than the ancient limit - 937 // was not yet committed, but the process crashed. In this test scenario the side 938 // chain is below the committed block. In this case we expect the chain to detect 939 // that it was fast syncing and not delete anything. The side chain is completely 940 // nuked by the freezer. 941 func TestLongOldForkedFastSyncingShallowRepair(t *testing.T) { 942 // Chain: 943 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 944 // └->S1->S2->S3 945 // 946 // Frozen: 947 // G->C1->C2 948 // 949 // Commit: G 950 // Pivot : C4 951 // 952 // CRASH 953 // 954 // ------------------------------ 955 // 956 // Expected in freezer: 957 // G->C1->C2 958 // 959 // Expected in leveldb: 960 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 961 // 962 // Expected head header : C18 963 // Expected head fast block: C18 964 // Expected head block : G 965 testRepair(t, &rewindTest{ 966 canonicalBlocks: 18, 967 sidechainBlocks: 3, 968 freezeThreshold: 16, 969 commitBlock: 0, 970 pivotBlock: uint64ptr(4), 971 expCanonicalBlocks: 18, 972 expSidechainBlocks: 0, 973 expFrozen: 3, 974 expHeadHeader: 18, 975 expHeadFastBlock: 18, 976 expHeadBlock: 0, 977 }) 978 } 979 980 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 981 // side chain, where the fast sync pivot point - older than the ancient limit - 982 // was not yet committed, but the process crashed. In this test scenario the side 983 // chain is below the committed block. In this case we expect the chain to detect 984 // that it was fast syncing and not delete anything. The side chain is completely 985 // nuked by the freezer. 986 func TestLongOldForkedFastSyncingDeepRepair(t *testing.T) { 987 // Chain: 988 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 989 // └->S1->S2->S3 990 // 991 // Frozen: 992 // G->C1->C2->C3->C4->C5->C6->C7->C8 993 // 994 // Commit: G 995 // Pivot : C4 996 // 997 // CRASH 998 // 999 // ------------------------------ 1000 // 1001 // Expected in freezer: 1002 // G->C1->C2->C3->C4->C5->C6->C7->C8 1003 // 1004 // Expected in leveldb: 1005 // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 1006 // 1007 // Expected head header : C24 1008 // Expected head fast block: C24 1009 // Expected head block : G 1010 testRepair(t, &rewindTest{ 1011 canonicalBlocks: 24, 1012 sidechainBlocks: 3, 1013 freezeThreshold: 16, 1014 commitBlock: 0, 1015 pivotBlock: uint64ptr(4), 1016 expCanonicalBlocks: 24, 1017 expSidechainBlocks: 0, 1018 expFrozen: 9, 1019 expHeadHeader: 24, 1020 expHeadFastBlock: 24, 1021 expHeadBlock: 0, 1022 }) 1023 } 1024 1025 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 1026 // side chain, where a recent block - newer than the ancient limit - was already 1027 // committed to disk and then the process crashed. In this test scenario the side 1028 // chain is above the committed block. In this case we expect the chain to be 1029 // rolled back to the committed block, with everything afterwads kept as fast 1030 // sync data; the side chain completely nuked by the freezer. 1031 func TestLongNewerForkedShallowRepair(t *testing.T) { 1032 // Chain: 1033 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1034 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1035 // 1036 // Frozen: 1037 // G->C1->C2 1038 // 1039 // Commit: G, C4 1040 // Pivot : none 1041 // 1042 // CRASH 1043 // 1044 // ------------------------------ 1045 // 1046 // Expected in freezer: 1047 // G->C1->C2 1048 // 1049 // Expected in leveldb: 1050 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1051 // 1052 // Expected head header : C18 1053 // Expected head fast block: C18 1054 // Expected head block : C4 1055 testRepair(t, &rewindTest{ 1056 canonicalBlocks: 18, 1057 sidechainBlocks: 12, 1058 freezeThreshold: 16, 1059 commitBlock: 4, 1060 pivotBlock: nil, 1061 expCanonicalBlocks: 18, 1062 expSidechainBlocks: 0, 1063 expFrozen: 3, 1064 expHeadHeader: 18, 1065 expHeadFastBlock: 18, 1066 expHeadBlock: 4, 1067 }) 1068 } 1069 1070 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 1071 // side chain, where a recent block - older than the ancient limit - was already 1072 // committed to disk and then the process crashed. In this test scenario the side 1073 // chain is above the committed block. In this case we expect the canonical chain 1074 // to be rolled back to the committed block, with everything afterwads deleted; 1075 // the side chain completely nuked by the freezer. 1076 func TestLongNewerForkedDeepRepair(t *testing.T) { 1077 // Chain: 1078 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 1079 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1080 // 1081 // Frozen: 1082 // G->C1->C2->C3->C4->C5->C6->C7->C8 1083 // 1084 // Commit: G, C4 1085 // Pivot : none 1086 // 1087 // CRASH 1088 // 1089 // ------------------------------ 1090 // 1091 // Expected in freezer: 1092 // G->C1->C2->C3->C4 1093 // 1094 // Expected in leveldb: none 1095 // 1096 // Expected head header : C4 1097 // Expected head fast block: C4 1098 // Expected head block : C4 1099 testRepair(t, &rewindTest{ 1100 canonicalBlocks: 24, 1101 sidechainBlocks: 12, 1102 freezeThreshold: 16, 1103 commitBlock: 4, 1104 pivotBlock: nil, 1105 expCanonicalBlocks: 4, 1106 expSidechainBlocks: 0, 1107 expFrozen: 5, 1108 expHeadHeader: 4, 1109 expHeadFastBlock: 4, 1110 expHeadBlock: 4, 1111 }) 1112 } 1113 1114 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 1115 // side chain, where the fast sync pivot point - newer than the ancient limit - 1116 // was already committed to disk and then the process crashed. In this test scenario 1117 // the side chain is above the committed block. In this case we expect the chain 1118 // to be rolled back to the committed block, with everything afterwads kept as fast 1119 // sync data; the side chain completely nuked by the freezer. 1120 func TestLongNewerForkedFastSyncedShallowRepair(t *testing.T) { 1121 // Chain: 1122 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1123 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1124 // 1125 // Frozen: 1126 // G->C1->C2 1127 // 1128 // Commit: G, C4 1129 // Pivot : C4 1130 // 1131 // CRASH 1132 // 1133 // ------------------------------ 1134 // 1135 // Expected in freezer: 1136 // G->C1->C2 1137 // 1138 // Expected in leveldb: 1139 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1140 // 1141 // Expected head header : C18 1142 // Expected head fast block: C18 1143 // Expected head block : C4 1144 testRepair(t, &rewindTest{ 1145 canonicalBlocks: 18, 1146 sidechainBlocks: 12, 1147 freezeThreshold: 16, 1148 commitBlock: 4, 1149 pivotBlock: uint64ptr(4), 1150 expCanonicalBlocks: 18, 1151 expSidechainBlocks: 0, 1152 expFrozen: 3, 1153 expHeadHeader: 18, 1154 expHeadFastBlock: 18, 1155 expHeadBlock: 4, 1156 }) 1157 } 1158 1159 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 1160 // side chain, where the fast sync pivot point - older than the ancient limit - 1161 // was already committed to disk and then the process crashed. In this test scenario 1162 // the side chain is above the committed block. In this case we expect the canonical 1163 // chain to be rolled back to the committed block, with everything afterwads deleted; 1164 // the side chain completely nuked by the freezer. 1165 func TestLongNewerForkedFastSyncedDeepRepair(t *testing.T) { 1166 // Chain: 1167 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 1168 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1169 // 1170 // Frozen: 1171 // G->C1->C2->C3->C4->C5->C6->C7->C8 1172 // 1173 // Commit: G, C4 1174 // Pivot : C4 1175 // 1176 // CRASH 1177 // 1178 // ------------------------------ 1179 // 1180 // Expected in freezer: 1181 // G->C1->C2->C3->C4 1182 // 1183 // Expected in leveldb: none 1184 // 1185 // Expected head header : C4 1186 // Expected head fast block: C4 1187 // Expected head block : C4 1188 testRepair(t, &rewindTest{ 1189 canonicalBlocks: 24, 1190 sidechainBlocks: 12, 1191 freezeThreshold: 16, 1192 commitBlock: 4, 1193 pivotBlock: uint64ptr(4), 1194 expCanonicalBlocks: 4, 1195 expSidechainBlocks: 0, 1196 expFrozen: 5, 1197 expHeadHeader: 4, 1198 expHeadFastBlock: 4, 1199 expHeadBlock: 4, 1200 }) 1201 } 1202 1203 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 1204 // side chain, where the fast sync pivot point - older than the ancient limit - 1205 // was not yet committed, but the process crashed. In this test scenario the side 1206 // chain is above the committed block. In this case we expect the chain to detect 1207 // that it was fast syncing and not delete anything. The side chain is completely 1208 // nuked by the freezer. 1209 func TestLongNewerForkedFastSyncingShallowRepair(t *testing.T) { 1210 // Chain: 1211 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1212 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1213 // 1214 // Frozen: 1215 // G->C1->C2 1216 // 1217 // Commit: G 1218 // Pivot : C4 1219 // 1220 // CRASH 1221 // 1222 // ------------------------------ 1223 // 1224 // Expected in freezer: 1225 // G->C1->C2 1226 // 1227 // Expected in leveldb: 1228 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1229 // 1230 // Expected head header : C18 1231 // Expected head fast block: C18 1232 // Expected head block : G 1233 testRepair(t, &rewindTest{ 1234 canonicalBlocks: 18, 1235 sidechainBlocks: 12, 1236 freezeThreshold: 16, 1237 commitBlock: 0, 1238 pivotBlock: uint64ptr(4), 1239 expCanonicalBlocks: 18, 1240 expSidechainBlocks: 0, 1241 expFrozen: 3, 1242 expHeadHeader: 18, 1243 expHeadFastBlock: 18, 1244 expHeadBlock: 0, 1245 }) 1246 } 1247 1248 // Tests a recovery for a long canonical chain with frozen blocks and a shorter 1249 // side chain, where the fast sync pivot point - older than the ancient limit - 1250 // was not yet committed, but the process crashed. In this test scenario the side 1251 // chain is above the committed block. In this case we expect the chain to detect 1252 // that it was fast syncing and not delete anything. The side chain is completely 1253 // nuked by the freezer. 1254 func TestLongNewerForkedFastSyncingDeepRepair(t *testing.T) { 1255 // Chain: 1256 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 1257 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1258 // 1259 // Frozen: 1260 // G->C1->C2->C3->C4->C5->C6->C7->C8 1261 // 1262 // Commit: G 1263 // Pivot : C4 1264 // 1265 // CRASH 1266 // 1267 // ------------------------------ 1268 // 1269 // Expected in freezer: 1270 // G->C1->C2->C3->C4->C5->C6->C7->C8 1271 // 1272 // Expected in leveldb: 1273 // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 1274 // 1275 // Expected head header : C24 1276 // Expected head fast block: C24 1277 // Expected head block : G 1278 testRepair(t, &rewindTest{ 1279 canonicalBlocks: 24, 1280 sidechainBlocks: 12, 1281 freezeThreshold: 16, 1282 commitBlock: 0, 1283 pivotBlock: uint64ptr(4), 1284 expCanonicalBlocks: 24, 1285 expSidechainBlocks: 0, 1286 expFrozen: 9, 1287 expHeadHeader: 24, 1288 expHeadFastBlock: 24, 1289 expHeadBlock: 0, 1290 }) 1291 } 1292 1293 // Tests a recovery for a long canonical chain with frozen blocks and a longer side 1294 // chain, where a recent block - newer than the ancient limit - was already committed 1295 // to disk and then the process crashed. In this case we expect the chain to be 1296 // rolled back to the committed block, with everything afterwads kept as fast sync 1297 // data. The side chain completely nuked by the freezer. 1298 func TestLongReorgedShallowRepair(t *testing.T) { 1299 // Chain: 1300 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1301 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 1302 // 1303 // Frozen: 1304 // G->C1->C2 1305 // 1306 // Commit: G, C4 1307 // Pivot : none 1308 // 1309 // CRASH 1310 // 1311 // ------------------------------ 1312 // 1313 // Expected in freezer: 1314 // G->C1->C2 1315 // 1316 // Expected in leveldb: 1317 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1318 // 1319 // Expected head header : C18 1320 // Expected head fast block: C18 1321 // Expected head block : C4 1322 testRepair(t, &rewindTest{ 1323 canonicalBlocks: 18, 1324 sidechainBlocks: 26, 1325 freezeThreshold: 16, 1326 commitBlock: 4, 1327 pivotBlock: nil, 1328 expCanonicalBlocks: 18, 1329 expSidechainBlocks: 0, 1330 expFrozen: 3, 1331 expHeadHeader: 18, 1332 expHeadFastBlock: 18, 1333 expHeadBlock: 4, 1334 }) 1335 } 1336 1337 // Tests a recovery for a long canonical chain with frozen blocks and a longer side 1338 // chain, where a recent block - older than the ancient limit - was already committed 1339 // to disk and then the process crashed. In this case we expect the canonical chains 1340 // to be rolled back to the committed block, with everything afterwads deleted. The 1341 // side chain completely nuked by the freezer. 1342 func TestLongReorgedDeepRepair(t *testing.T) { 1343 // Chain: 1344 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 1345 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 1346 // 1347 // Frozen: 1348 // G->C1->C2->C3->C4->C5->C6->C7->C8 1349 // 1350 // Commit: G, C4 1351 // Pivot : none 1352 // 1353 // CRASH 1354 // 1355 // ------------------------------ 1356 // 1357 // Expected in freezer: 1358 // G->C1->C2->C3->C4 1359 // 1360 // Expected in leveldb: none 1361 // 1362 // Expected head header : C4 1363 // Expected head fast block: C4 1364 // Expected head block : C4 1365 testRepair(t, &rewindTest{ 1366 canonicalBlocks: 24, 1367 sidechainBlocks: 26, 1368 freezeThreshold: 16, 1369 commitBlock: 4, 1370 pivotBlock: nil, 1371 expCanonicalBlocks: 4, 1372 expSidechainBlocks: 0, 1373 expFrozen: 5, 1374 expHeadHeader: 4, 1375 expHeadFastBlock: 4, 1376 expHeadBlock: 4, 1377 }) 1378 } 1379 1380 // Tests a recovery for a long canonical chain with frozen blocks and a longer 1381 // side chain, where the fast sync pivot point - newer than the ancient limit - 1382 // was already committed to disk and then the process crashed. In this case we 1383 // expect the chain to be rolled back to the committed block, with everything 1384 // afterwads kept as fast sync data. The side chain completely nuked by the 1385 // freezer. 1386 func TestLongReorgedFastSyncedShallowRepair(t *testing.T) { 1387 // Chain: 1388 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1389 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 1390 // 1391 // Frozen: 1392 // G->C1->C2 1393 // 1394 // Commit: G, C4 1395 // Pivot : C4 1396 // 1397 // CRASH 1398 // 1399 // ------------------------------ 1400 // 1401 // Expected in freezer: 1402 // G->C1->C2 1403 // 1404 // Expected in leveldb: 1405 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1406 // 1407 // Expected head header : C18 1408 // Expected head fast block: C18 1409 // Expected head block : C4 1410 testRepair(t, &rewindTest{ 1411 canonicalBlocks: 18, 1412 sidechainBlocks: 26, 1413 freezeThreshold: 16, 1414 commitBlock: 4, 1415 pivotBlock: uint64ptr(4), 1416 expCanonicalBlocks: 18, 1417 expSidechainBlocks: 0, 1418 expFrozen: 3, 1419 expHeadHeader: 18, 1420 expHeadFastBlock: 18, 1421 expHeadBlock: 4, 1422 }) 1423 } 1424 1425 // Tests a recovery for a long canonical chain with frozen blocks and a longer 1426 // side chain, where the fast sync pivot point - older than the ancient limit - 1427 // was already committed to disk and then the process crashed. In this case we 1428 // expect the canonical chains to be rolled back to the committed block, with 1429 // everything afterwads deleted. The side chain completely nuked by the freezer. 1430 func TestLongReorgedFastSyncedDeepRepair(t *testing.T) { 1431 // Chain: 1432 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 1433 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 1434 // 1435 // Frozen: 1436 // G->C1->C2->C3->C4->C5->C6->C7->C8 1437 // 1438 // Commit: G, C4 1439 // Pivot : C4 1440 // 1441 // CRASH 1442 // 1443 // ------------------------------ 1444 // 1445 // Expected in freezer: 1446 // G->C1->C2->C3->C4 1447 // 1448 // Expected in leveldb: none 1449 // 1450 // Expected head header : C4 1451 // Expected head fast block: C4 1452 // Expected head block : C4 1453 testRepair(t, &rewindTest{ 1454 canonicalBlocks: 24, 1455 sidechainBlocks: 26, 1456 freezeThreshold: 16, 1457 commitBlock: 4, 1458 pivotBlock: uint64ptr(4), 1459 expCanonicalBlocks: 4, 1460 expSidechainBlocks: 0, 1461 expFrozen: 5, 1462 expHeadHeader: 4, 1463 expHeadFastBlock: 4, 1464 expHeadBlock: 4, 1465 }) 1466 } 1467 1468 // Tests a recovery for a long canonical chain with frozen blocks and a longer 1469 // side chain, where the fast sync pivot point - newer than the ancient limit - 1470 // was not yet committed, but the process crashed. In this case we expect the 1471 // chain to detect that it was fast syncing and not delete anything, since we 1472 // can just pick up directly where we left off. 1473 func TestLongReorgedFastSyncingShallowRepair(t *testing.T) { 1474 // Chain: 1475 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1476 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 1477 // 1478 // Frozen: 1479 // G->C1->C2 1480 // 1481 // Commit: G 1482 // Pivot : C4 1483 // 1484 // CRASH 1485 // 1486 // ------------------------------ 1487 // 1488 // Expected in freezer: 1489 // G->C1->C2 1490 // 1491 // Expected in leveldb: 1492 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1493 // 1494 // Expected head header : C18 1495 // Expected head fast block: C18 1496 // Expected head block : G 1497 testRepair(t, &rewindTest{ 1498 canonicalBlocks: 18, 1499 sidechainBlocks: 26, 1500 freezeThreshold: 16, 1501 commitBlock: 0, 1502 pivotBlock: uint64ptr(4), 1503 expCanonicalBlocks: 18, 1504 expSidechainBlocks: 0, 1505 expFrozen: 3, 1506 expHeadHeader: 18, 1507 expHeadFastBlock: 18, 1508 expHeadBlock: 0, 1509 }) 1510 } 1511 1512 // Tests a recovery for a long canonical chain with frozen blocks and a longer 1513 // side chain, where the fast sync pivot point - older than the ancient limit - 1514 // was not yet committed, but the process crashed. In this case we expect the 1515 // chain to detect that it was fast syncing and not delete anything, since we 1516 // can just pick up directly where we left off. 1517 func TestLongReorgedFastSyncingDeepRepair(t *testing.T) { 1518 // Chain: 1519 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 1520 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 1521 // 1522 // Frozen: 1523 // G->C1->C2->C3->C4->C5->C6->C7->C8 1524 // 1525 // Commit: G 1526 // Pivot : C4 1527 // 1528 // CRASH 1529 // 1530 // ------------------------------ 1531 // 1532 // Expected in freezer: 1533 // G->C1->C2->C3->C4->C5->C6->C7->C8 1534 // 1535 // Expected in leveldb: 1536 // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 1537 // 1538 // Expected head header : C24 1539 // Expected head fast block: C24 1540 // Expected head block : G 1541 testRepair(t, &rewindTest{ 1542 canonicalBlocks: 24, 1543 sidechainBlocks: 26, 1544 freezeThreshold: 16, 1545 commitBlock: 0, 1546 pivotBlock: uint64ptr(4), 1547 expCanonicalBlocks: 24, 1548 expSidechainBlocks: 0, 1549 expFrozen: 9, 1550 expHeadHeader: 24, 1551 expHeadFastBlock: 24, 1552 expHeadBlock: 0, 1553 }) 1554 } 1555 1556 func testRepair(t *testing.T, tt *rewindTest) { 1557 // It's hard to follow the test case, visualize the input 1558 //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 1559 //fmt.Println(tt.dump(true)) 1560 1561 // Create a temporary persistent database 1562 datadir, err := ioutil.TempDir("", "") 1563 if err != nil { 1564 t.Fatalf("Failed to create temporary datadir: %v", err) 1565 } 1566 os.RemoveAll(datadir) 1567 1568 db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "") 1569 if err != nil { 1570 t.Fatalf("Failed to create persistent database: %v", err) 1571 } 1572 defer db.Close() // Might double close, should be fine 1573 1574 // Initialize a fresh chain 1575 var ( 1576 genesis = new(Genesis).MustCommit(db) 1577 engine = ethash.NewFullFaker() 1578 ) 1579 chain, err := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) 1580 if err != nil { 1581 t.Fatalf("Failed to create chain: %v", err) 1582 } 1583 // If sidechain blocks are needed, make a light chain and import it 1584 var sideblocks types.Blocks 1585 if tt.sidechainBlocks > 0 { 1586 sideblocks, _ = GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) { 1587 b.SetCoinbase(common.Address{0x01}) 1588 }) 1589 if _, err := chain.InsertChain(sideblocks); err != nil { 1590 t.Fatalf("Failed to import side chain: %v", err) 1591 } 1592 } 1593 canonblocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { 1594 b.SetCoinbase(common.Address{0x02}) 1595 b.SetDifficulty(big.NewInt(1000000)) 1596 }) 1597 if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { 1598 t.Fatalf("Failed to import canonical chain start: %v", err) 1599 } 1600 if tt.commitBlock > 0 { 1601 chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) 1602 } 1603 if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { 1604 t.Fatalf("Failed to import canonical chain tail: %v", err) 1605 } 1606 // Force run a freeze cycle 1607 type freezer interface { 1608 Freeze(threshold uint64) 1609 Ancients() (uint64, error) 1610 } 1611 db.(freezer).Freeze(tt.freezeThreshold) 1612 1613 // Set the simulated pivot block 1614 if tt.pivotBlock != nil { 1615 rawdb.WriteLastPivotNumber(db, *tt.pivotBlock) 1616 } 1617 // Pull the plug on the database, simulating a hard crash 1618 db.Close() 1619 1620 // Start a new blockchain back up and see where the repait leads us 1621 db, err = rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "") 1622 if err != nil { 1623 t.Fatalf("Failed to reopen persistent database: %v", err) 1624 } 1625 defer db.Close() 1626 1627 chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) 1628 if err != nil { 1629 t.Fatalf("Failed to recreate chain: %v", err) 1630 } 1631 defer chain.Stop() 1632 1633 // Iterate over all the remaining blocks and ensure there are no gaps 1634 verifyNoGaps(t, chain, true, canonblocks) 1635 verifyNoGaps(t, chain, false, sideblocks) 1636 verifyCutoff(t, chain, true, canonblocks, tt.expCanonicalBlocks) 1637 verifyCutoff(t, chain, false, sideblocks, tt.expSidechainBlocks) 1638 1639 if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { 1640 t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) 1641 } 1642 if head := chain.CurrentFastBlock(); head.NumberU64() != tt.expHeadFastBlock { 1643 t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadFastBlock) 1644 } 1645 if head := chain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock { 1646 t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock) 1647 } 1648 if frozen, err := db.(freezer).Ancients(); err != nil { 1649 t.Errorf("Failed to retrieve ancient count: %v\n", err) 1650 } else if int(frozen) != tt.expFrozen { 1651 t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen) 1652 } 1653 }