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 21package core 22 23import ( 24 "io/ioutil" 25 "math/big" 26 "os" 27 "testing" 28 "time" 29 30 "github.com/ethereum/go-ethereum/common" 31 "github.com/ethereum/go-ethereum/consensus/ethash" 32 "github.com/ethereum/go-ethereum/core/rawdb" 33 "github.com/ethereum/go-ethereum/core/types" 34 "github.com/ethereum/go-ethereum/core/vm" 35 "github.com/ethereum/go-ethereum/params" 36) 37 38// Tests a recovery for a short canonical chain where a recent block was already 39// committed to disk and then the process crashed. In this case we expect the full 40// chain to be rolled back to the committed block, but the chain data itself left 41// in the database for replaying. 42func TestShortRepair(t *testing.T) { testShortRepair(t, false) } 43func TestShortRepairWithSnapshots(t *testing.T) { testShortRepair(t, true) } 44 45func testShortRepair(t *testing.T, snapshots bool) { 46 // Chain: 47 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 48 // 49 // Frozen: none 50 // Commit: G, C4 51 // Pivot : none 52 // 53 // CRASH 54 // 55 // ------------------------------ 56 // 57 // Expected in leveldb: 58 // G->C1->C2->C3->C4->C5->C6->C7->C8 59 // 60 // Expected head header : C8 61 // Expected head fast block: C8 62 // Expected head block : C4 63 testRepair(t, &rewindTest{ 64 canonicalBlocks: 8, 65 sidechainBlocks: 0, 66 freezeThreshold: 16, 67 commitBlock: 4, 68 pivotBlock: nil, 69 expCanonicalBlocks: 8, 70 expSidechainBlocks: 0, 71 expFrozen: 0, 72 expHeadHeader: 8, 73 expHeadFastBlock: 8, 74 expHeadBlock: 4, 75 }, snapshots) 76} 77 78// Tests a recovery for a short canonical chain where the fast sync pivot point was 79// already committed, after which the process crashed. In this case we expect the full 80// chain to be rolled back to the committed block, but the chain data itself left in 81// the database for replaying. 82func TestShortSnapSyncedRepair(t *testing.T) { testShortSnapSyncedRepair(t, false) } 83func TestShortSnapSyncedRepairWithSnapshots(t *testing.T) { testShortSnapSyncedRepair(t, true) } 84 85func testShortSnapSyncedRepair(t *testing.T, snapshots bool) { 86 // Chain: 87 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 88 // 89 // Frozen: none 90 // Commit: G, C4 91 // Pivot : C4 92 // 93 // CRASH 94 // 95 // ------------------------------ 96 // 97 // Expected in leveldb: 98 // G->C1->C2->C3->C4->C5->C6->C7->C8 99 // 100 // Expected head header : C8 101 // Expected head fast block: C8 102 // Expected head block : C4 103 testRepair(t, &rewindTest{ 104 canonicalBlocks: 8, 105 sidechainBlocks: 0, 106 freezeThreshold: 16, 107 commitBlock: 4, 108 pivotBlock: uint64ptr(4), 109 expCanonicalBlocks: 8, 110 expSidechainBlocks: 0, 111 expFrozen: 0, 112 expHeadHeader: 8, 113 expHeadFastBlock: 8, 114 expHeadBlock: 4, 115 }, snapshots) 116} 117 118// Tests a recovery for a short canonical chain where the fast sync pivot point was 119// not yet committed, but the process crashed. In this case we expect the chain to 120// detect that it was fast syncing and not delete anything, since we can just pick 121// up directly where we left off. 122func TestShortSnapSyncingRepair(t *testing.T) { testShortSnapSyncingRepair(t, false) } 123func TestShortSnapSyncingRepairWithSnapshots(t *testing.T) { testShortSnapSyncingRepair(t, true) } 124 125func testShortSnapSyncingRepair(t *testing.T, snapshots bool) { 126 // Chain: 127 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 128 // 129 // Frozen: none 130 // Commit: G 131 // Pivot : C4 132 // 133 // CRASH 134 // 135 // ------------------------------ 136 // 137 // Expected in leveldb: 138 // G->C1->C2->C3->C4->C5->C6->C7->C8 139 // 140 // Expected head header : C8 141 // Expected head fast block: C8 142 // Expected head block : G 143 testRepair(t, &rewindTest{ 144 canonicalBlocks: 8, 145 sidechainBlocks: 0, 146 freezeThreshold: 16, 147 commitBlock: 0, 148 pivotBlock: uint64ptr(4), 149 expCanonicalBlocks: 8, 150 expSidechainBlocks: 0, 151 expFrozen: 0, 152 expHeadHeader: 8, 153 expHeadFastBlock: 8, 154 expHeadBlock: 0, 155 }, snapshots) 156} 157 158// Tests a recovery for a short canonical chain and a shorter side chain, where a 159// recent block was already committed to disk and then the process crashed. In this 160// test scenario the side chain is below the committed block. In this case we expect 161// the canonical chain to be rolled back to the committed block, but the chain data 162// itself left in the database for replaying. 163func TestShortOldForkedRepair(t *testing.T) { testShortOldForkedRepair(t, false) } 164func TestShortOldForkedRepairWithSnapshots(t *testing.T) { testShortOldForkedRepair(t, true) } 165 166func testShortOldForkedRepair(t *testing.T, snapshots bool) { 167 // Chain: 168 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 169 // └->S1->S2->S3 170 // 171 // Frozen: none 172 // Commit: G, C4 173 // Pivot : none 174 // 175 // CRASH 176 // 177 // ------------------------------ 178 // 179 // Expected in leveldb: 180 // G->C1->C2->C3->C4->C5->C6->C7->C8 181 // └->S1->S2->S3 182 // 183 // Expected head header : C8 184 // Expected head fast block: C8 185 // Expected head block : C4 186 testRepair(t, &rewindTest{ 187 canonicalBlocks: 8, 188 sidechainBlocks: 3, 189 freezeThreshold: 16, 190 commitBlock: 4, 191 pivotBlock: nil, 192 expCanonicalBlocks: 8, 193 expSidechainBlocks: 3, 194 expFrozen: 0, 195 expHeadHeader: 8, 196 expHeadFastBlock: 8, 197 expHeadBlock: 4, 198 }, snapshots) 199} 200 201// Tests a recovery for a short canonical chain and a shorter side chain, where 202// the fast sync pivot point was already committed to disk and then the process 203// crashed. In this test scenario the side chain is below the committed block. In 204// this case we expect the canonical chain to be rolled back to the committed block, 205// but the chain data itself left in the database for replaying. 206func TestShortOldForkedSnapSyncedRepair(t *testing.T) { 207 testShortOldForkedSnapSyncedRepair(t, false) 208} 209func TestShortOldForkedSnapSyncedRepairWithSnapshots(t *testing.T) { 210 testShortOldForkedSnapSyncedRepair(t, true) 211} 212 213func testShortOldForkedSnapSyncedRepair(t *testing.T, snapshots bool) { 214 // Chain: 215 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 216 // └->S1->S2->S3 217 // 218 // Frozen: none 219 // Commit: G, C4 220 // Pivot : C4 221 // 222 // CRASH 223 // 224 // ------------------------------ 225 // 226 // Expected in leveldb: 227 // G->C1->C2->C3->C4->C5->C6->C7->C8 228 // └->S1->S2->S3 229 // 230 // Expected head header : C8 231 // Expected head fast block: C8 232 // Expected head block : C4 233 testRepair(t, &rewindTest{ 234 canonicalBlocks: 8, 235 sidechainBlocks: 3, 236 freezeThreshold: 16, 237 commitBlock: 4, 238 pivotBlock: uint64ptr(4), 239 expCanonicalBlocks: 8, 240 expSidechainBlocks: 3, 241 expFrozen: 0, 242 expHeadHeader: 8, 243 expHeadFastBlock: 8, 244 expHeadBlock: 4, 245 }, snapshots) 246} 247 248// Tests a recovery for a short canonical chain and a shorter side chain, where 249// the fast sync pivot point was not yet committed, but the process crashed. In this 250// test scenario the side chain is below the committed block. In this case we expect 251// the chain to detect that it was fast syncing and not delete anything, since we 252// can just pick up directly where we left off. 253func TestShortOldForkedSnapSyncingRepair(t *testing.T) { 254 testShortOldForkedSnapSyncingRepair(t, false) 255} 256func TestShortOldForkedSnapSyncingRepairWithSnapshots(t *testing.T) { 257 testShortOldForkedSnapSyncingRepair(t, true) 258} 259 260func testShortOldForkedSnapSyncingRepair(t *testing.T, snapshots bool) { 261 // Chain: 262 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 263 // └->S1->S2->S3 264 // 265 // Frozen: none 266 // Commit: G 267 // Pivot : C4 268 // 269 // CRASH 270 // 271 // ------------------------------ 272 // 273 // Expected in leveldb: 274 // G->C1->C2->C3->C4->C5->C6->C7->C8 275 // └->S1->S2->S3 276 // 277 // Expected head header : C8 278 // Expected head fast block: C8 279 // Expected head block : G 280 testRepair(t, &rewindTest{ 281 canonicalBlocks: 8, 282 sidechainBlocks: 3, 283 freezeThreshold: 16, 284 commitBlock: 0, 285 pivotBlock: uint64ptr(4), 286 expCanonicalBlocks: 8, 287 expSidechainBlocks: 3, 288 expFrozen: 0, 289 expHeadHeader: 8, 290 expHeadFastBlock: 8, 291 expHeadBlock: 0, 292 }, snapshots) 293} 294 295// Tests a recovery for a short canonical chain and a shorter side chain, where a 296// recent block was already committed to disk and then the process crashed. In this 297// test scenario the side chain reaches above the committed block. In this case we 298// expect the canonical chain to be rolled back to the committed block, but the 299// chain data itself left in the database for replaying. 300func TestShortNewlyForkedRepair(t *testing.T) { testShortNewlyForkedRepair(t, false) } 301func TestShortNewlyForkedRepairWithSnapshots(t *testing.T) { testShortNewlyForkedRepair(t, true) } 302 303func testShortNewlyForkedRepair(t *testing.T, snapshots bool) { 304 // Chain: 305 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 306 // └->S1->S2->S3->S4->S5->S6 307 // 308 // Frozen: none 309 // Commit: G, C4 310 // Pivot : none 311 // 312 // CRASH 313 // 314 // ------------------------------ 315 // 316 // Expected in leveldb: 317 // G->C1->C2->C3->C4->C5->C6->C7->C8 318 // └->S1->S2->S3->S4->S5->S6 319 // 320 // Expected head header : C8 321 // Expected head fast block: C8 322 // Expected head block : C4 323 testRepair(t, &rewindTest{ 324 canonicalBlocks: 8, 325 sidechainBlocks: 6, 326 freezeThreshold: 16, 327 commitBlock: 4, 328 pivotBlock: nil, 329 expCanonicalBlocks: 8, 330 expSidechainBlocks: 6, 331 expFrozen: 0, 332 expHeadHeader: 8, 333 expHeadFastBlock: 8, 334 expHeadBlock: 4, 335 }, snapshots) 336} 337 338// Tests a recovery for a short canonical chain and a shorter side chain, where 339// the fast sync pivot point was already committed to disk and then the process 340// crashed. In this test scenario the side chain reaches above the committed block. 341// In this case we expect the canonical chain to be rolled back to the committed 342// block, but the chain data itself left in the database for replaying. 343func TestShortNewlyForkedSnapSyncedRepair(t *testing.T) { 344 testShortNewlyForkedSnapSyncedRepair(t, false) 345} 346func TestShortNewlyForkedSnapSyncedRepairWithSnapshots(t *testing.T) { 347 testShortNewlyForkedSnapSyncedRepair(t, true) 348} 349 350func testShortNewlyForkedSnapSyncedRepair(t *testing.T, snapshots bool) { 351 // Chain: 352 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 353 // └->S1->S2->S3->S4->S5->S6 354 // 355 // Frozen: none 356 // Commit: G, C4 357 // Pivot : C4 358 // 359 // CRASH 360 // 361 // ------------------------------ 362 // 363 // Expected in leveldb: 364 // G->C1->C2->C3->C4->C5->C6->C7->C8 365 // └->S1->S2->S3->S4->S5->S6 366 // 367 // Expected head header : C8 368 // Expected head fast block: C8 369 // Expected head block : C4 370 testRepair(t, &rewindTest{ 371 canonicalBlocks: 8, 372 sidechainBlocks: 6, 373 freezeThreshold: 16, 374 commitBlock: 4, 375 pivotBlock: uint64ptr(4), 376 expCanonicalBlocks: 8, 377 expSidechainBlocks: 6, 378 expFrozen: 0, 379 expHeadHeader: 8, 380 expHeadFastBlock: 8, 381 expHeadBlock: 4, 382 }, snapshots) 383} 384 385// Tests a recovery for a short canonical chain and a shorter side chain, where 386// the fast sync pivot point was not yet committed, but the process crashed. In 387// this test scenario the side chain reaches above the committed block. In this 388// case we expect the chain to detect that it was fast syncing and not delete 389// anything, since we can just pick up directly where we left off. 390func TestShortNewlyForkedSnapSyncingRepair(t *testing.T) { 391 testShortNewlyForkedSnapSyncingRepair(t, false) 392} 393func TestShortNewlyForkedSnapSyncingRepairWithSnapshots(t *testing.T) { 394 testShortNewlyForkedSnapSyncingRepair(t, true) 395} 396 397func testShortNewlyForkedSnapSyncingRepair(t *testing.T, snapshots bool) { 398 // Chain: 399 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 400 // └->S1->S2->S3->S4->S5->S6 401 // 402 // Frozen: none 403 // Commit: G 404 // Pivot : C4 405 // 406 // CRASH 407 // 408 // ------------------------------ 409 // 410 // Expected in leveldb: 411 // G->C1->C2->C3->C4->C5->C6->C7->C8 412 // └->S1->S2->S3->S4->S5->S6 413 // 414 // Expected head header : C8 415 // Expected head fast block: C8 416 // Expected head block : G 417 testRepair(t, &rewindTest{ 418 canonicalBlocks: 8, 419 sidechainBlocks: 6, 420 freezeThreshold: 16, 421 commitBlock: 0, 422 pivotBlock: uint64ptr(4), 423 expCanonicalBlocks: 8, 424 expSidechainBlocks: 6, 425 expFrozen: 0, 426 expHeadHeader: 8, 427 expHeadFastBlock: 8, 428 expHeadBlock: 0, 429 }, snapshots) 430} 431 432// Tests a recovery for a short canonical chain and a longer side chain, where a 433// recent block was already committed to disk and then the process crashed. In this 434// case we expect the canonical chain to be rolled back to the committed block, but 435// the chain data itself left in the database for replaying. 436func TestShortReorgedRepair(t *testing.T) { testShortReorgedRepair(t, false) } 437func TestShortReorgedRepairWithSnapshots(t *testing.T) { testShortReorgedRepair(t, true) } 438 439func testShortReorgedRepair(t *testing.T, snapshots bool) { 440 // Chain: 441 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 442 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 443 // 444 // Frozen: none 445 // Commit: G, C4 446 // Pivot : none 447 // 448 // CRASH 449 // 450 // ------------------------------ 451 // 452 // Expected in leveldb: 453 // G->C1->C2->C3->C4->C5->C6->C7->C8 454 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 455 // 456 // Expected head header : C8 457 // Expected head fast block: C8 458 // Expected head block : C4 459 testRepair(t, &rewindTest{ 460 canonicalBlocks: 8, 461 sidechainBlocks: 10, 462 freezeThreshold: 16, 463 commitBlock: 4, 464 pivotBlock: nil, 465 expCanonicalBlocks: 8, 466 expSidechainBlocks: 10, 467 expFrozen: 0, 468 expHeadHeader: 8, 469 expHeadFastBlock: 8, 470 expHeadBlock: 4, 471 }, snapshots) 472} 473 474// Tests a recovery for a short canonical chain and a longer side chain, where 475// the fast sync pivot point was already committed to disk and then the process 476// crashed. In this case we expect the canonical chain to be rolled back to the 477// committed block, but the chain data itself left in the database for replaying. 478func TestShortReorgedSnapSyncedRepair(t *testing.T) { 479 testShortReorgedSnapSyncedRepair(t, false) 480} 481func TestShortReorgedSnapSyncedRepairWithSnapshots(t *testing.T) { 482 testShortReorgedSnapSyncedRepair(t, true) 483} 484 485func testShortReorgedSnapSyncedRepair(t *testing.T, snapshots bool) { 486 // Chain: 487 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 488 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 489 // 490 // Frozen: none 491 // Commit: G, C4 492 // Pivot : C4 493 // 494 // CRASH 495 // 496 // ------------------------------ 497 // 498 // Expected in leveldb: 499 // G->C1->C2->C3->C4->C5->C6->C7->C8 500 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 501 // 502 // Expected head header : C8 503 // Expected head fast block: C8 504 // Expected head block : C4 505 testRepair(t, &rewindTest{ 506 canonicalBlocks: 8, 507 sidechainBlocks: 10, 508 freezeThreshold: 16, 509 commitBlock: 4, 510 pivotBlock: uint64ptr(4), 511 expCanonicalBlocks: 8, 512 expSidechainBlocks: 10, 513 expFrozen: 0, 514 expHeadHeader: 8, 515 expHeadFastBlock: 8, 516 expHeadBlock: 4, 517 }, snapshots) 518} 519 520// Tests a recovery for a short canonical chain and a longer side chain, where 521// the fast sync pivot point was not yet committed, but the process crashed. In 522// this case we expect the chain to detect that it was fast syncing and not delete 523// anything, since we can just pick up directly where we left off. 524func TestShortReorgedSnapSyncingRepair(t *testing.T) { 525 testShortReorgedSnapSyncingRepair(t, false) 526} 527func TestShortReorgedSnapSyncingRepairWithSnapshots(t *testing.T) { 528 testShortReorgedSnapSyncingRepair(t, true) 529} 530 531func testShortReorgedSnapSyncingRepair(t *testing.T, snapshots bool) { 532 // Chain: 533 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 534 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 535 // 536 // Frozen: none 537 // Commit: G 538 // Pivot : C4 539 // 540 // CRASH 541 // 542 // ------------------------------ 543 // 544 // Expected in leveldb: 545 // G->C1->C2->C3->C4->C5->C6->C7->C8 546 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 547 // 548 // Expected head header : C8 549 // Expected head fast block: C8 550 // Expected head block : G 551 testRepair(t, &rewindTest{ 552 canonicalBlocks: 8, 553 sidechainBlocks: 10, 554 freezeThreshold: 16, 555 commitBlock: 0, 556 pivotBlock: uint64ptr(4), 557 expCanonicalBlocks: 8, 558 expSidechainBlocks: 10, 559 expFrozen: 0, 560 expHeadHeader: 8, 561 expHeadFastBlock: 8, 562 expHeadBlock: 0, 563 }, snapshots) 564} 565 566// Tests a recovery for a long canonical chain with frozen blocks where a recent 567// block - newer than the ancient limit - was already committed to disk and then 568// the process crashed. In this case we expect the chain to be rolled back to the 569// committed block, with everything afterwads kept as fast sync data. 570func TestLongShallowRepair(t *testing.T) { testLongShallowRepair(t, false) } 571func TestLongShallowRepairWithSnapshots(t *testing.T) { testLongShallowRepair(t, true) } 572 573func testLongShallowRepair(t *testing.T, snapshots bool) { 574 // Chain: 575 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 576 // 577 // Frozen: 578 // G->C1->C2 579 // 580 // Commit: G, C4 581 // Pivot : none 582 // 583 // CRASH 584 // 585 // ------------------------------ 586 // 587 // Expected in freezer: 588 // G->C1->C2 589 // 590 // Expected in leveldb: 591 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 592 // 593 // Expected head header : C18 594 // Expected head fast block: C18 595 // Expected head block : C4 596 testRepair(t, &rewindTest{ 597 canonicalBlocks: 18, 598 sidechainBlocks: 0, 599 freezeThreshold: 16, 600 commitBlock: 4, 601 pivotBlock: nil, 602 expCanonicalBlocks: 18, 603 expSidechainBlocks: 0, 604 expFrozen: 3, 605 expHeadHeader: 18, 606 expHeadFastBlock: 18, 607 expHeadBlock: 4, 608 }, snapshots) 609} 610 611// Tests a recovery for a long canonical chain with frozen blocks where a recent 612// block - older than the ancient limit - was already committed to disk and then 613// the process crashed. In this case we expect the chain to be rolled back to the 614// committed block, with everything afterwads deleted. 615func TestLongDeepRepair(t *testing.T) { testLongDeepRepair(t, false) } 616func TestLongDeepRepairWithSnapshots(t *testing.T) { testLongDeepRepair(t, true) } 617 618func testLongDeepRepair(t *testing.T, snapshots bool) { 619 // Chain: 620 // 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) 621 // 622 // Frozen: 623 // G->C1->C2->C3->C4->C5->C6->C7->C8 624 // 625 // Commit: G, C4 626 // Pivot : none 627 // 628 // CRASH 629 // 630 // ------------------------------ 631 // 632 // Expected in freezer: 633 // G->C1->C2->C3->C4 634 // 635 // Expected in leveldb: none 636 // 637 // Expected head header : C4 638 // Expected head fast block: C4 639 // Expected head block : C4 640 testRepair(t, &rewindTest{ 641 canonicalBlocks: 24, 642 sidechainBlocks: 0, 643 freezeThreshold: 16, 644 commitBlock: 4, 645 pivotBlock: nil, 646 expCanonicalBlocks: 4, 647 expSidechainBlocks: 0, 648 expFrozen: 5, 649 expHeadHeader: 4, 650 expHeadFastBlock: 4, 651 expHeadBlock: 4, 652 }, snapshots) 653} 654 655// Tests a recovery for a long canonical chain with frozen blocks where the fast 656// sync pivot point - newer than the ancient limit - was already committed, after 657// which the process crashed. In this case we expect the chain to be rolled back 658// to the committed block, with everything afterwads kept as fast sync data. 659func TestLongSnapSyncedShallowRepair(t *testing.T) { 660 testLongSnapSyncedShallowRepair(t, false) 661} 662func TestLongSnapSyncedShallowRepairWithSnapshots(t *testing.T) { 663 testLongSnapSyncedShallowRepair(t, true) 664} 665 666func testLongSnapSyncedShallowRepair(t *testing.T, snapshots bool) { 667 // Chain: 668 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 669 // 670 // Frozen: 671 // G->C1->C2 672 // 673 // Commit: G, C4 674 // Pivot : C4 675 // 676 // CRASH 677 // 678 // ------------------------------ 679 // 680 // Expected in freezer: 681 // G->C1->C2 682 // 683 // Expected in leveldb: 684 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 685 // 686 // Expected head header : C18 687 // Expected head fast block: C18 688 // Expected head block : C4 689 testRepair(t, &rewindTest{ 690 canonicalBlocks: 18, 691 sidechainBlocks: 0, 692 freezeThreshold: 16, 693 commitBlock: 4, 694 pivotBlock: uint64ptr(4), 695 expCanonicalBlocks: 18, 696 expSidechainBlocks: 0, 697 expFrozen: 3, 698 expHeadHeader: 18, 699 expHeadFastBlock: 18, 700 expHeadBlock: 4, 701 }, snapshots) 702} 703 704// Tests a recovery for a long canonical chain with frozen blocks where the fast 705// sync pivot point - older than the ancient limit - was already committed, after 706// which the process crashed. In this case we expect the chain to be rolled back 707// to the committed block, with everything afterwads deleted. 708func TestLongSnapSyncedDeepRepair(t *testing.T) { testLongSnapSyncedDeepRepair(t, false) } 709func TestLongSnapSyncedDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncedDeepRepair(t, true) } 710 711func testLongSnapSyncedDeepRepair(t *testing.T, snapshots bool) { 712 // Chain: 713 // 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) 714 // 715 // Frozen: 716 // G->C1->C2->C3->C4->C5->C6->C7->C8 717 // 718 // Commit: G, C4 719 // Pivot : C4 720 // 721 // CRASH 722 // 723 // ------------------------------ 724 // 725 // Expected in freezer: 726 // G->C1->C2->C3->C4 727 // 728 // Expected in leveldb: none 729 // 730 // Expected head header : C4 731 // Expected head fast block: C4 732 // Expected head block : C4 733 testRepair(t, &rewindTest{ 734 canonicalBlocks: 24, 735 sidechainBlocks: 0, 736 freezeThreshold: 16, 737 commitBlock: 4, 738 pivotBlock: uint64ptr(4), 739 expCanonicalBlocks: 4, 740 expSidechainBlocks: 0, 741 expFrozen: 5, 742 expHeadHeader: 4, 743 expHeadFastBlock: 4, 744 expHeadBlock: 4, 745 }, snapshots) 746} 747 748// Tests a recovery for a long canonical chain with frozen blocks where the fast 749// sync pivot point - older than the ancient limit - was not yet committed, but the 750// process crashed. In this case we expect the chain to detect that it was fast 751// syncing and not delete anything, since we can just pick up directly where we 752// left off. 753func TestLongSnapSyncingShallowRepair(t *testing.T) { 754 testLongSnapSyncingShallowRepair(t, false) 755} 756func TestLongSnapSyncingShallowRepairWithSnapshots(t *testing.T) { 757 testLongSnapSyncingShallowRepair(t, true) 758} 759 760func testLongSnapSyncingShallowRepair(t *testing.T, snapshots bool) { 761 // Chain: 762 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 763 // 764 // Frozen: 765 // G->C1->C2 766 // 767 // Commit: G 768 // Pivot : C4 769 // 770 // CRASH 771 // 772 // ------------------------------ 773 // 774 // Expected in freezer: 775 // G->C1->C2 776 // 777 // Expected in leveldb: 778 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 779 // 780 // Expected head header : C18 781 // Expected head fast block: C18 782 // Expected head block : G 783 testRepair(t, &rewindTest{ 784 canonicalBlocks: 18, 785 sidechainBlocks: 0, 786 freezeThreshold: 16, 787 commitBlock: 0, 788 pivotBlock: uint64ptr(4), 789 expCanonicalBlocks: 18, 790 expSidechainBlocks: 0, 791 expFrozen: 3, 792 expHeadHeader: 18, 793 expHeadFastBlock: 18, 794 expHeadBlock: 0, 795 }, snapshots) 796} 797 798// Tests a recovery for a long canonical chain with frozen blocks where the fast 799// sync pivot point - newer than the ancient limit - was not yet committed, but the 800// process crashed. In this case we expect the chain to detect that it was fast 801// syncing and not delete anything, since we can just pick up directly where we 802// left off. 803func TestLongSnapSyncingDeepRepair(t *testing.T) { testLongSnapSyncingDeepRepair(t, false) } 804func TestLongSnapSyncingDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncingDeepRepair(t, true) } 805 806func testLongSnapSyncingDeepRepair(t *testing.T, snapshots bool) { 807 // Chain: 808 // 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) 809 // 810 // Frozen: 811 // G->C1->C2->C3->C4->C5->C6->C7->C8 812 // 813 // Commit: G 814 // Pivot : C4 815 // 816 // CRASH 817 // 818 // ------------------------------ 819 // 820 // Expected in freezer: 821 // G->C1->C2->C3->C4->C5->C6->C7->C8 822 // 823 // Expected in leveldb: 824 // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 825 // 826 // Expected head header : C24 827 // Expected head fast block: C24 828 // Expected head block : G 829 testRepair(t, &rewindTest{ 830 canonicalBlocks: 24, 831 sidechainBlocks: 0, 832 freezeThreshold: 16, 833 commitBlock: 0, 834 pivotBlock: uint64ptr(4), 835 expCanonicalBlocks: 24, 836 expSidechainBlocks: 0, 837 expFrozen: 9, 838 expHeadHeader: 24, 839 expHeadFastBlock: 24, 840 expHeadBlock: 0, 841 }, snapshots) 842} 843 844// Tests a recovery for a long canonical chain with frozen blocks and a shorter 845// side chain, where a recent block - newer than the ancient limit - was already 846// committed to disk and then the process crashed. In this test scenario the side 847// chain is below the committed block. In this case we expect the chain to be 848// rolled back to the committed block, with everything afterwads kept as fast 849// sync data; the side chain completely nuked by the freezer. 850func TestLongOldForkedShallowRepair(t *testing.T) { 851 testLongOldForkedShallowRepair(t, false) 852} 853func TestLongOldForkedShallowRepairWithSnapshots(t *testing.T) { 854 testLongOldForkedShallowRepair(t, true) 855} 856 857func testLongOldForkedShallowRepair(t *testing.T, snapshots bool) { 858 // Chain: 859 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 860 // └->S1->S2->S3 861 // 862 // Frozen: 863 // G->C1->C2 864 // 865 // Commit: G, C4 866 // Pivot : none 867 // 868 // CRASH 869 // 870 // ------------------------------ 871 // 872 // Expected in freezer: 873 // G->C1->C2 874 // 875 // Expected in leveldb: 876 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 877 // 878 // Expected head header : C18 879 // Expected head fast block: C18 880 // Expected head block : C4 881 testRepair(t, &rewindTest{ 882 canonicalBlocks: 18, 883 sidechainBlocks: 3, 884 freezeThreshold: 16, 885 commitBlock: 4, 886 pivotBlock: nil, 887 expCanonicalBlocks: 18, 888 expSidechainBlocks: 0, 889 expFrozen: 3, 890 expHeadHeader: 18, 891 expHeadFastBlock: 18, 892 expHeadBlock: 4, 893 }, snapshots) 894} 895 896// Tests a recovery for a long canonical chain with frozen blocks and a shorter 897// side chain, where a recent block - older than the ancient limit - was already 898// committed to disk and then the process crashed. In this test scenario the side 899// chain is below the committed block. In this case we expect the canonical chain 900// to be rolled back to the committed block, with everything afterwads deleted; 901// the side chain completely nuked by the freezer. 902func TestLongOldForkedDeepRepair(t *testing.T) { testLongOldForkedDeepRepair(t, false) } 903func TestLongOldForkedDeepRepairWithSnapshots(t *testing.T) { testLongOldForkedDeepRepair(t, true) } 904 905func testLongOldForkedDeepRepair(t *testing.T, snapshots bool) { 906 // Chain: 907 // 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) 908 // └->S1->S2->S3 909 // 910 // Frozen: 911 // G->C1->C2->C3->C4->C5->C6->C7->C8 912 // 913 // Commit: G, C4 914 // Pivot : none 915 // 916 // CRASH 917 // 918 // ------------------------------ 919 // 920 // Expected in freezer: 921 // G->C1->C2->C3->C4 922 // 923 // Expected in leveldb: none 924 // 925 // Expected head header : C4 926 // Expected head fast block: C4 927 // Expected head block : C4 928 testRepair(t, &rewindTest{ 929 canonicalBlocks: 24, 930 sidechainBlocks: 3, 931 freezeThreshold: 16, 932 commitBlock: 4, 933 pivotBlock: nil, 934 expCanonicalBlocks: 4, 935 expSidechainBlocks: 0, 936 expFrozen: 5, 937 expHeadHeader: 4, 938 expHeadFastBlock: 4, 939 expHeadBlock: 4, 940 }, snapshots) 941} 942 943// Tests a recovery for a long canonical chain with frozen blocks and a shorter 944// side chain, where the fast sync pivot point - newer than the ancient limit - 945// was already committed to disk and then the process crashed. In this test scenario 946// the side chain is below the committed block. In this case we expect the chain 947// to be rolled back to the committed block, with everything afterwads kept as 948// fast sync data; the side chain completely nuked by the freezer. 949func TestLongOldForkedSnapSyncedShallowRepair(t *testing.T) { 950 testLongOldForkedSnapSyncedShallowRepair(t, false) 951} 952func TestLongOldForkedSnapSyncedShallowRepairWithSnapshots(t *testing.T) { 953 testLongOldForkedSnapSyncedShallowRepair(t, true) 954} 955 956func testLongOldForkedSnapSyncedShallowRepair(t *testing.T, snapshots bool) { 957 // Chain: 958 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 959 // └->S1->S2->S3 960 // 961 // Frozen: 962 // G->C1->C2 963 // 964 // Commit: G, C4 965 // Pivot : C4 966 // 967 // CRASH 968 // 969 // ------------------------------ 970 // 971 // Expected in freezer: 972 // G->C1->C2 973 // 974 // Expected in leveldb: 975 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 976 // 977 // Expected head header : C18 978 // Expected head fast block: C18 979 // Expected head block : C4 980 testRepair(t, &rewindTest{ 981 canonicalBlocks: 18, 982 sidechainBlocks: 3, 983 freezeThreshold: 16, 984 commitBlock: 4, 985 pivotBlock: uint64ptr(4), 986 expCanonicalBlocks: 18, 987 expSidechainBlocks: 0, 988 expFrozen: 3, 989 expHeadHeader: 18, 990 expHeadFastBlock: 18, 991 expHeadBlock: 4, 992 }, snapshots) 993} 994 995// Tests a recovery for a long canonical chain with frozen blocks and a shorter 996// side chain, where the fast sync pivot point - older than the ancient limit - 997// was already committed to disk and then the process crashed. In this test scenario 998// the side chain is below the committed block. In this case we expect the canonical 999// chain to be rolled back to the committed block, with everything afterwads deleted; 1000// the side chain completely nuked by the freezer. 1001func TestLongOldForkedSnapSyncedDeepRepair(t *testing.T) { 1002 testLongOldForkedSnapSyncedDeepRepair(t, false) 1003} 1004func TestLongOldForkedSnapSyncedDeepRepairWithSnapshots(t *testing.T) { 1005 testLongOldForkedSnapSyncedDeepRepair(t, true) 1006} 1007 1008func testLongOldForkedSnapSyncedDeepRepair(t *testing.T, snapshots bool) { 1009 // Chain: 1010 // 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) 1011 // └->S1->S2->S3 1012 // 1013 // Frozen: 1014 // G->C1->C2->C3->C4->C5->C6->C7->C8 1015 // 1016 // Commit: G, C4 1017 // Pivot : C4 1018 // 1019 // CRASH 1020 // 1021 // ------------------------------ 1022 // 1023 // Expected in freezer: 1024 // G->C1->C2->C3->C4 1025 // 1026 // Expected in leveldb: none 1027 // 1028 // Expected head header : C4 1029 // Expected head fast block: C4 1030 // Expected head block : C4 1031 testRepair(t, &rewindTest{ 1032 canonicalBlocks: 24, 1033 sidechainBlocks: 3, 1034 freezeThreshold: 16, 1035 commitBlock: 4, 1036 pivotBlock: uint64ptr(4), 1037 expCanonicalBlocks: 4, 1038 expSidechainBlocks: 0, 1039 expFrozen: 5, 1040 expHeadHeader: 4, 1041 expHeadFastBlock: 4, 1042 expHeadBlock: 4, 1043 }, snapshots) 1044} 1045 1046// Tests a recovery for a long canonical chain with frozen blocks and a shorter 1047// side chain, where the fast sync pivot point - older than the ancient limit - 1048// was not yet committed, but the process crashed. In this test scenario the side 1049// chain is below the committed block. In this case we expect the chain to detect 1050// that it was fast syncing and not delete anything. The side chain is completely 1051// nuked by the freezer. 1052func TestLongOldForkedSnapSyncingShallowRepair(t *testing.T) { 1053 testLongOldForkedSnapSyncingShallowRepair(t, false) 1054} 1055func TestLongOldForkedSnapSyncingShallowRepairWithSnapshots(t *testing.T) { 1056 testLongOldForkedSnapSyncingShallowRepair(t, true) 1057} 1058 1059func testLongOldForkedSnapSyncingShallowRepair(t *testing.T, snapshots bool) { 1060 // Chain: 1061 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1062 // └->S1->S2->S3 1063 // 1064 // Frozen: 1065 // G->C1->C2 1066 // 1067 // Commit: G 1068 // Pivot : C4 1069 // 1070 // CRASH 1071 // 1072 // ------------------------------ 1073 // 1074 // Expected in freezer: 1075 // G->C1->C2 1076 // 1077 // Expected in leveldb: 1078 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1079 // 1080 // Expected head header : C18 1081 // Expected head fast block: C18 1082 // Expected head block : G 1083 testRepair(t, &rewindTest{ 1084 canonicalBlocks: 18, 1085 sidechainBlocks: 3, 1086 freezeThreshold: 16, 1087 commitBlock: 0, 1088 pivotBlock: uint64ptr(4), 1089 expCanonicalBlocks: 18, 1090 expSidechainBlocks: 0, 1091 expFrozen: 3, 1092 expHeadHeader: 18, 1093 expHeadFastBlock: 18, 1094 expHeadBlock: 0, 1095 }, snapshots) 1096} 1097 1098// Tests a recovery for a long canonical chain with frozen blocks and a shorter 1099// side chain, where the fast sync pivot point - older than the ancient limit - 1100// was not yet committed, but the process crashed. In this test scenario the side 1101// chain is below the committed block. In this case we expect the chain to detect 1102// that it was fast syncing and not delete anything. The side chain is completely 1103// nuked by the freezer. 1104func TestLongOldForkedSnapSyncingDeepRepair(t *testing.T) { 1105 testLongOldForkedSnapSyncingDeepRepair(t, false) 1106} 1107func TestLongOldForkedSnapSyncingDeepRepairWithSnapshots(t *testing.T) { 1108 testLongOldForkedSnapSyncingDeepRepair(t, true) 1109} 1110 1111func testLongOldForkedSnapSyncingDeepRepair(t *testing.T, snapshots bool) { 1112 // Chain: 1113 // 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) 1114 // └->S1->S2->S3 1115 // 1116 // Frozen: 1117 // G->C1->C2->C3->C4->C5->C6->C7->C8 1118 // 1119 // Commit: G 1120 // Pivot : C4 1121 // 1122 // CRASH 1123 // 1124 // ------------------------------ 1125 // 1126 // Expected in freezer: 1127 // G->C1->C2->C3->C4->C5->C6->C7->C8 1128 // 1129 // Expected in leveldb: 1130 // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 1131 // 1132 // Expected head header : C24 1133 // Expected head fast block: C24 1134 // Expected head block : G 1135 testRepair(t, &rewindTest{ 1136 canonicalBlocks: 24, 1137 sidechainBlocks: 3, 1138 freezeThreshold: 16, 1139 commitBlock: 0, 1140 pivotBlock: uint64ptr(4), 1141 expCanonicalBlocks: 24, 1142 expSidechainBlocks: 0, 1143 expFrozen: 9, 1144 expHeadHeader: 24, 1145 expHeadFastBlock: 24, 1146 expHeadBlock: 0, 1147 }, snapshots) 1148} 1149 1150// Tests a recovery for a long canonical chain with frozen blocks and a shorter 1151// side chain, where a recent block - newer than the ancient limit - was already 1152// committed to disk and then the process crashed. In this test scenario the side 1153// chain is above the committed block. In this case we expect the chain to be 1154// rolled back to the committed block, with everything afterwads kept as fast 1155// sync data; the side chain completely nuked by the freezer. 1156func TestLongNewerForkedShallowRepair(t *testing.T) { 1157 testLongNewerForkedShallowRepair(t, false) 1158} 1159func TestLongNewerForkedShallowRepairWithSnapshots(t *testing.T) { 1160 testLongNewerForkedShallowRepair(t, true) 1161} 1162 1163func testLongNewerForkedShallowRepair(t *testing.T, snapshots bool) { 1164 // Chain: 1165 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1166 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1167 // 1168 // Frozen: 1169 // G->C1->C2 1170 // 1171 // Commit: G, C4 1172 // Pivot : none 1173 // 1174 // CRASH 1175 // 1176 // ------------------------------ 1177 // 1178 // Expected in freezer: 1179 // G->C1->C2 1180 // 1181 // Expected in leveldb: 1182 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1183 // 1184 // Expected head header : C18 1185 // Expected head fast block: C18 1186 // Expected head block : C4 1187 testRepair(t, &rewindTest{ 1188 canonicalBlocks: 18, 1189 sidechainBlocks: 12, 1190 freezeThreshold: 16, 1191 commitBlock: 4, 1192 pivotBlock: nil, 1193 expCanonicalBlocks: 18, 1194 expSidechainBlocks: 0, 1195 expFrozen: 3, 1196 expHeadHeader: 18, 1197 expHeadFastBlock: 18, 1198 expHeadBlock: 4, 1199 }, snapshots) 1200} 1201 1202// Tests a recovery for a long canonical chain with frozen blocks and a shorter 1203// side chain, where a recent block - older than the ancient limit - was already 1204// committed to disk and then the process crashed. In this test scenario the side 1205// chain is above the committed block. In this case we expect the canonical chain 1206// to be rolled back to the committed block, with everything afterwads deleted; 1207// the side chain completely nuked by the freezer. 1208func TestLongNewerForkedDeepRepair(t *testing.T) { testLongNewerForkedDeepRepair(t, false) } 1209func TestLongNewerForkedDeepRepairWithSnapshots(t *testing.T) { testLongNewerForkedDeepRepair(t, true) } 1210 1211func testLongNewerForkedDeepRepair(t *testing.T, snapshots bool) { 1212 // Chain: 1213 // 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) 1214 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1215 // 1216 // Frozen: 1217 // G->C1->C2->C3->C4->C5->C6->C7->C8 1218 // 1219 // Commit: G, C4 1220 // Pivot : none 1221 // 1222 // CRASH 1223 // 1224 // ------------------------------ 1225 // 1226 // Expected in freezer: 1227 // G->C1->C2->C3->C4 1228 // 1229 // Expected in leveldb: none 1230 // 1231 // Expected head header : C4 1232 // Expected head fast block: C4 1233 // Expected head block : C4 1234 testRepair(t, &rewindTest{ 1235 canonicalBlocks: 24, 1236 sidechainBlocks: 12, 1237 freezeThreshold: 16, 1238 commitBlock: 4, 1239 pivotBlock: nil, 1240 expCanonicalBlocks: 4, 1241 expSidechainBlocks: 0, 1242 expFrozen: 5, 1243 expHeadHeader: 4, 1244 expHeadFastBlock: 4, 1245 expHeadBlock: 4, 1246 }, snapshots) 1247} 1248 1249// Tests a recovery for a long canonical chain with frozen blocks and a shorter 1250// side chain, where the fast sync pivot point - newer than the ancient limit - 1251// was already committed to disk and then the process crashed. In this test scenario 1252// the side chain is above the committed block. In this case we expect the chain 1253// to be rolled back to the committed block, with everything afterwads kept as fast 1254// sync data; the side chain completely nuked by the freezer. 1255func TestLongNewerForkedSnapSyncedShallowRepair(t *testing.T) { 1256 testLongNewerForkedSnapSyncedShallowRepair(t, false) 1257} 1258func TestLongNewerForkedSnapSyncedShallowRepairWithSnapshots(t *testing.T) { 1259 testLongNewerForkedSnapSyncedShallowRepair(t, true) 1260} 1261 1262func testLongNewerForkedSnapSyncedShallowRepair(t *testing.T, snapshots bool) { 1263 // Chain: 1264 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1265 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1266 // 1267 // Frozen: 1268 // G->C1->C2 1269 // 1270 // Commit: G, C4 1271 // Pivot : C4 1272 // 1273 // CRASH 1274 // 1275 // ------------------------------ 1276 // 1277 // Expected in freezer: 1278 // G->C1->C2 1279 // 1280 // Expected in leveldb: 1281 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1282 // 1283 // Expected head header : C18 1284 // Expected head fast block: C18 1285 // Expected head block : C4 1286 testRepair(t, &rewindTest{ 1287 canonicalBlocks: 18, 1288 sidechainBlocks: 12, 1289 freezeThreshold: 16, 1290 commitBlock: 4, 1291 pivotBlock: uint64ptr(4), 1292 expCanonicalBlocks: 18, 1293 expSidechainBlocks: 0, 1294 expFrozen: 3, 1295 expHeadHeader: 18, 1296 expHeadFastBlock: 18, 1297 expHeadBlock: 4, 1298 }, snapshots) 1299} 1300 1301// Tests a recovery for a long canonical chain with frozen blocks and a shorter 1302// side chain, where the fast sync pivot point - older than the ancient limit - 1303// was already committed to disk and then the process crashed. In this test scenario 1304// the side chain is above the committed block. In this case we expect the canonical 1305// chain to be rolled back to the committed block, with everything afterwads deleted; 1306// the side chain completely nuked by the freezer. 1307func TestLongNewerForkedSnapSyncedDeepRepair(t *testing.T) { 1308 testLongNewerForkedSnapSyncedDeepRepair(t, false) 1309} 1310func TestLongNewerForkedSnapSyncedDeepRepairWithSnapshots(t *testing.T) { 1311 testLongNewerForkedSnapSyncedDeepRepair(t, true) 1312} 1313 1314func testLongNewerForkedSnapSyncedDeepRepair(t *testing.T, snapshots bool) { 1315 // Chain: 1316 // 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) 1317 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1318 // 1319 // Frozen: 1320 // G->C1->C2->C3->C4->C5->C6->C7->C8 1321 // 1322 // Commit: G, C4 1323 // Pivot : C4 1324 // 1325 // CRASH 1326 // 1327 // ------------------------------ 1328 // 1329 // Expected in freezer: 1330 // G->C1->C2->C3->C4 1331 // 1332 // Expected in leveldb: none 1333 // 1334 // Expected head header : C4 1335 // Expected head fast block: C4 1336 // Expected head block : C4 1337 testRepair(t, &rewindTest{ 1338 canonicalBlocks: 24, 1339 sidechainBlocks: 12, 1340 freezeThreshold: 16, 1341 commitBlock: 4, 1342 pivotBlock: uint64ptr(4), 1343 expCanonicalBlocks: 4, 1344 expSidechainBlocks: 0, 1345 expFrozen: 5, 1346 expHeadHeader: 4, 1347 expHeadFastBlock: 4, 1348 expHeadBlock: 4, 1349 }, snapshots) 1350} 1351 1352// Tests a recovery for a long canonical chain with frozen blocks and a shorter 1353// side chain, where the fast sync pivot point - older than the ancient limit - 1354// was not yet committed, but the process crashed. In this test scenario the side 1355// chain is above the committed block. In this case we expect the chain to detect 1356// that it was fast syncing and not delete anything. The side chain is completely 1357// nuked by the freezer. 1358func TestLongNewerForkedSnapSyncingShallowRepair(t *testing.T) { 1359 testLongNewerForkedSnapSyncingShallowRepair(t, false) 1360} 1361func TestLongNewerForkedSnapSyncingShallowRepairWithSnapshots(t *testing.T) { 1362 testLongNewerForkedSnapSyncingShallowRepair(t, true) 1363} 1364 1365func testLongNewerForkedSnapSyncingShallowRepair(t *testing.T, snapshots bool) { 1366 // Chain: 1367 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1368 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1369 // 1370 // Frozen: 1371 // G->C1->C2 1372 // 1373 // Commit: G 1374 // Pivot : C4 1375 // 1376 // CRASH 1377 // 1378 // ------------------------------ 1379 // 1380 // Expected in freezer: 1381 // G->C1->C2 1382 // 1383 // Expected in leveldb: 1384 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1385 // 1386 // Expected head header : C18 1387 // Expected head fast block: C18 1388 // Expected head block : G 1389 testRepair(t, &rewindTest{ 1390 canonicalBlocks: 18, 1391 sidechainBlocks: 12, 1392 freezeThreshold: 16, 1393 commitBlock: 0, 1394 pivotBlock: uint64ptr(4), 1395 expCanonicalBlocks: 18, 1396 expSidechainBlocks: 0, 1397 expFrozen: 3, 1398 expHeadHeader: 18, 1399 expHeadFastBlock: 18, 1400 expHeadBlock: 0, 1401 }, snapshots) 1402} 1403 1404// Tests a recovery for a long canonical chain with frozen blocks and a shorter 1405// side chain, where the fast sync pivot point - older than the ancient limit - 1406// was not yet committed, but the process crashed. In this test scenario the side 1407// chain is above the committed block. In this case we expect the chain to detect 1408// that it was fast syncing and not delete anything. The side chain is completely 1409// nuked by the freezer. 1410func TestLongNewerForkedSnapSyncingDeepRepair(t *testing.T) { 1411 testLongNewerForkedSnapSyncingDeepRepair(t, false) 1412} 1413func TestLongNewerForkedSnapSyncingDeepRepairWithSnapshots(t *testing.T) { 1414 testLongNewerForkedSnapSyncingDeepRepair(t, true) 1415} 1416 1417func testLongNewerForkedSnapSyncingDeepRepair(t *testing.T, snapshots bool) { 1418 // Chain: 1419 // 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) 1420 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1421 // 1422 // Frozen: 1423 // G->C1->C2->C3->C4->C5->C6->C7->C8 1424 // 1425 // Commit: G 1426 // Pivot : C4 1427 // 1428 // CRASH 1429 // 1430 // ------------------------------ 1431 // 1432 // Expected in freezer: 1433 // G->C1->C2->C3->C4->C5->C6->C7->C8 1434 // 1435 // Expected in leveldb: 1436 // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 1437 // 1438 // Expected head header : C24 1439 // Expected head fast block: C24 1440 // Expected head block : G 1441 testRepair(t, &rewindTest{ 1442 canonicalBlocks: 24, 1443 sidechainBlocks: 12, 1444 freezeThreshold: 16, 1445 commitBlock: 0, 1446 pivotBlock: uint64ptr(4), 1447 expCanonicalBlocks: 24, 1448 expSidechainBlocks: 0, 1449 expFrozen: 9, 1450 expHeadHeader: 24, 1451 expHeadFastBlock: 24, 1452 expHeadBlock: 0, 1453 }, snapshots) 1454} 1455 1456// Tests a recovery for a long canonical chain with frozen blocks and a longer side 1457// chain, where a recent block - newer than the ancient limit - was already committed 1458// to disk and then the process crashed. In this case we expect the chain to be 1459// rolled back to the committed block, with everything afterwads kept as fast sync 1460// data. The side chain completely nuked by the freezer. 1461func TestLongReorgedShallowRepair(t *testing.T) { testLongReorgedShallowRepair(t, false) } 1462func TestLongReorgedShallowRepairWithSnapshots(t *testing.T) { testLongReorgedShallowRepair(t, true) } 1463 1464func testLongReorgedShallowRepair(t *testing.T, snapshots bool) { 1465 // Chain: 1466 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1467 // └->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 1468 // 1469 // Frozen: 1470 // G->C1->C2 1471 // 1472 // Commit: G, C4 1473 // Pivot : none 1474 // 1475 // CRASH 1476 // 1477 // ------------------------------ 1478 // 1479 // Expected in freezer: 1480 // G->C1->C2 1481 // 1482 // Expected in leveldb: 1483 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1484 // 1485 // Expected head header : C18 1486 // Expected head fast block: C18 1487 // Expected head block : C4 1488 testRepair(t, &rewindTest{ 1489 canonicalBlocks: 18, 1490 sidechainBlocks: 26, 1491 freezeThreshold: 16, 1492 commitBlock: 4, 1493 pivotBlock: nil, 1494 expCanonicalBlocks: 18, 1495 expSidechainBlocks: 0, 1496 expFrozen: 3, 1497 expHeadHeader: 18, 1498 expHeadFastBlock: 18, 1499 expHeadBlock: 4, 1500 }, snapshots) 1501} 1502 1503// Tests a recovery for a long canonical chain with frozen blocks and a longer side 1504// chain, where a recent block - older than the ancient limit - was already committed 1505// to disk and then the process crashed. In this case we expect the canonical chains 1506// to be rolled back to the committed block, with everything afterwads deleted. The 1507// side chain completely nuked by the freezer. 1508func TestLongReorgedDeepRepair(t *testing.T) { testLongReorgedDeepRepair(t, false) } 1509func TestLongReorgedDeepRepairWithSnapshots(t *testing.T) { testLongReorgedDeepRepair(t, true) } 1510 1511func testLongReorgedDeepRepair(t *testing.T, snapshots bool) { 1512 // Chain: 1513 // 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) 1514 // └->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 1515 // 1516 // Frozen: 1517 // G->C1->C2->C3->C4->C5->C6->C7->C8 1518 // 1519 // Commit: G, C4 1520 // Pivot : none 1521 // 1522 // CRASH 1523 // 1524 // ------------------------------ 1525 // 1526 // Expected in freezer: 1527 // G->C1->C2->C3->C4 1528 // 1529 // Expected in leveldb: none 1530 // 1531 // Expected head header : C4 1532 // Expected head fast block: C4 1533 // Expected head block : C4 1534 testRepair(t, &rewindTest{ 1535 canonicalBlocks: 24, 1536 sidechainBlocks: 26, 1537 freezeThreshold: 16, 1538 commitBlock: 4, 1539 pivotBlock: nil, 1540 expCanonicalBlocks: 4, 1541 expSidechainBlocks: 0, 1542 expFrozen: 5, 1543 expHeadHeader: 4, 1544 expHeadFastBlock: 4, 1545 expHeadBlock: 4, 1546 }, snapshots) 1547} 1548 1549// Tests a recovery for a long canonical chain with frozen blocks and a longer 1550// side chain, where the fast sync pivot point - newer than the ancient limit - 1551// was already committed to disk and then the process crashed. In this case we 1552// expect the chain to be rolled back to the committed block, with everything 1553// afterwads kept as fast sync data. The side chain completely nuked by the 1554// freezer. 1555func TestLongReorgedSnapSyncedShallowRepair(t *testing.T) { 1556 testLongReorgedSnapSyncedShallowRepair(t, false) 1557} 1558func TestLongReorgedSnapSyncedShallowRepairWithSnapshots(t *testing.T) { 1559 testLongReorgedSnapSyncedShallowRepair(t, true) 1560} 1561 1562func testLongReorgedSnapSyncedShallowRepair(t *testing.T, snapshots bool) { 1563 // Chain: 1564 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1565 // └->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 1566 // 1567 // Frozen: 1568 // G->C1->C2 1569 // 1570 // Commit: G, C4 1571 // Pivot : C4 1572 // 1573 // CRASH 1574 // 1575 // ------------------------------ 1576 // 1577 // Expected in freezer: 1578 // G->C1->C2 1579 // 1580 // Expected in leveldb: 1581 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1582 // 1583 // Expected head header : C18 1584 // Expected head fast block: C18 1585 // Expected head block : C4 1586 testRepair(t, &rewindTest{ 1587 canonicalBlocks: 18, 1588 sidechainBlocks: 26, 1589 freezeThreshold: 16, 1590 commitBlock: 4, 1591 pivotBlock: uint64ptr(4), 1592 expCanonicalBlocks: 18, 1593 expSidechainBlocks: 0, 1594 expFrozen: 3, 1595 expHeadHeader: 18, 1596 expHeadFastBlock: 18, 1597 expHeadBlock: 4, 1598 }, snapshots) 1599} 1600 1601// Tests a recovery for a long canonical chain with frozen blocks and a longer 1602// side chain, where the fast sync pivot point - older than the ancient limit - 1603// was already committed to disk and then the process crashed. In this case we 1604// expect the canonical chains to be rolled back to the committed block, with 1605// everything afterwads deleted. The side chain completely nuked by the freezer. 1606func TestLongReorgedSnapSyncedDeepRepair(t *testing.T) { 1607 testLongReorgedSnapSyncedDeepRepair(t, false) 1608} 1609func TestLongReorgedSnapSyncedDeepRepairWithSnapshots(t *testing.T) { 1610 testLongReorgedSnapSyncedDeepRepair(t, true) 1611} 1612 1613func testLongReorgedSnapSyncedDeepRepair(t *testing.T, snapshots bool) { 1614 // Chain: 1615 // 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) 1616 // └->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 1617 // 1618 // Frozen: 1619 // G->C1->C2->C3->C4->C5->C6->C7->C8 1620 // 1621 // Commit: G, C4 1622 // Pivot : C4 1623 // 1624 // CRASH 1625 // 1626 // ------------------------------ 1627 // 1628 // Expected in freezer: 1629 // G->C1->C2->C3->C4 1630 // 1631 // Expected in leveldb: none 1632 // 1633 // Expected head header : C4 1634 // Expected head fast block: C4 1635 // Expected head block : C4 1636 testRepair(t, &rewindTest{ 1637 canonicalBlocks: 24, 1638 sidechainBlocks: 26, 1639 freezeThreshold: 16, 1640 commitBlock: 4, 1641 pivotBlock: uint64ptr(4), 1642 expCanonicalBlocks: 4, 1643 expSidechainBlocks: 0, 1644 expFrozen: 5, 1645 expHeadHeader: 4, 1646 expHeadFastBlock: 4, 1647 expHeadBlock: 4, 1648 }, snapshots) 1649} 1650 1651// Tests a recovery for a long canonical chain with frozen blocks and a longer 1652// side chain, where the fast sync pivot point - newer than the ancient limit - 1653// was not yet committed, but the process crashed. In this case we expect the 1654// chain to detect that it was fast syncing and not delete anything, since we 1655// can just pick up directly where we left off. 1656func TestLongReorgedSnapSyncingShallowRepair(t *testing.T) { 1657 testLongReorgedSnapSyncingShallowRepair(t, false) 1658} 1659func TestLongReorgedSnapSyncingShallowRepairWithSnapshots(t *testing.T) { 1660 testLongReorgedSnapSyncingShallowRepair(t, true) 1661} 1662 1663func testLongReorgedSnapSyncingShallowRepair(t *testing.T, snapshots bool) { 1664 // Chain: 1665 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1666 // └->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 1667 // 1668 // Frozen: 1669 // G->C1->C2 1670 // 1671 // Commit: G 1672 // Pivot : C4 1673 // 1674 // CRASH 1675 // 1676 // ------------------------------ 1677 // 1678 // Expected in freezer: 1679 // G->C1->C2 1680 // 1681 // Expected in leveldb: 1682 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 1683 // 1684 // Expected head header : C18 1685 // Expected head fast block: C18 1686 // Expected head block : G 1687 testRepair(t, &rewindTest{ 1688 canonicalBlocks: 18, 1689 sidechainBlocks: 26, 1690 freezeThreshold: 16, 1691 commitBlock: 0, 1692 pivotBlock: uint64ptr(4), 1693 expCanonicalBlocks: 18, 1694 expSidechainBlocks: 0, 1695 expFrozen: 3, 1696 expHeadHeader: 18, 1697 expHeadFastBlock: 18, 1698 expHeadBlock: 0, 1699 }, snapshots) 1700} 1701 1702// Tests a recovery for a long canonical chain with frozen blocks and a longer 1703// side chain, where the fast sync pivot point - older than the ancient limit - 1704// was not yet committed, but the process crashed. In this case we expect the 1705// chain to detect that it was fast syncing and not delete anything, since we 1706// can just pick up directly where we left off. 1707func TestLongReorgedSnapSyncingDeepRepair(t *testing.T) { 1708 testLongReorgedSnapSyncingDeepRepair(t, false) 1709} 1710func TestLongReorgedSnapSyncingDeepRepairWithSnapshots(t *testing.T) { 1711 testLongReorgedSnapSyncingDeepRepair(t, true) 1712} 1713 1714func testLongReorgedSnapSyncingDeepRepair(t *testing.T, snapshots bool) { 1715 // Chain: 1716 // 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) 1717 // └->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 1718 // 1719 // Frozen: 1720 // G->C1->C2->C3->C4->C5->C6->C7->C8 1721 // 1722 // Commit: G 1723 // Pivot : C4 1724 // 1725 // CRASH 1726 // 1727 // ------------------------------ 1728 // 1729 // Expected in freezer: 1730 // G->C1->C2->C3->C4->C5->C6->C7->C8 1731 // 1732 // Expected in leveldb: 1733 // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 1734 // 1735 // Expected head header : C24 1736 // Expected head fast block: C24 1737 // Expected head block : G 1738 testRepair(t, &rewindTest{ 1739 canonicalBlocks: 24, 1740 sidechainBlocks: 26, 1741 freezeThreshold: 16, 1742 commitBlock: 0, 1743 pivotBlock: uint64ptr(4), 1744 expCanonicalBlocks: 24, 1745 expSidechainBlocks: 0, 1746 expFrozen: 9, 1747 expHeadHeader: 24, 1748 expHeadFastBlock: 24, 1749 expHeadBlock: 0, 1750 }, snapshots) 1751} 1752 1753func testRepair(t *testing.T, tt *rewindTest, snapshots bool) { 1754 // It's hard to follow the test case, visualize the input 1755 //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 1756 // fmt.Println(tt.dump(true)) 1757 1758 // Create a temporary persistent database 1759 datadir, err := ioutil.TempDir("", "") 1760 if err != nil { 1761 t.Fatalf("Failed to create temporary datadir: %v", err) 1762 } 1763 os.RemoveAll(datadir) 1764 1765 db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false) 1766 if err != nil { 1767 t.Fatalf("Failed to create persistent database: %v", err) 1768 } 1769 defer db.Close() // Might double close, should be fine 1770 1771 // Initialize a fresh chain 1772 var ( 1773 genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) 1774 engine = ethash.NewFullFaker() 1775 config = &CacheConfig{ 1776 TrieCleanLimit: 256, 1777 TrieDirtyLimit: 256, 1778 TrieTimeLimit: 5 * time.Minute, 1779 SnapshotLimit: 0, // Disable snapshot by default 1780 } 1781 ) 1782 if snapshots { 1783 config.SnapshotLimit = 256 1784 config.SnapshotWait = true 1785 } 1786 chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) 1787 if err != nil { 1788 t.Fatalf("Failed to create chain: %v", err) 1789 } 1790 // If sidechain blocks are needed, make a light chain and import it 1791 var sideblocks types.Blocks 1792 if tt.sidechainBlocks > 0 { 1793 sideblocks, _ = GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) { 1794 b.SetCoinbase(common.Address{0x01}) 1795 }) 1796 if _, err := chain.InsertChain(sideblocks); err != nil { 1797 t.Fatalf("Failed to import side chain: %v", err) 1798 } 1799 } 1800 canonblocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { 1801 b.SetCoinbase(common.Address{0x02}) 1802 b.SetDifficulty(big.NewInt(1000000)) 1803 }) 1804 if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { 1805 t.Fatalf("Failed to import canonical chain start: %v", err) 1806 } 1807 if tt.commitBlock > 0 { 1808 chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) 1809 if snapshots { 1810 if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { 1811 t.Fatalf("Failed to flatten snapshots: %v", err) 1812 } 1813 } 1814 } 1815 if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { 1816 t.Fatalf("Failed to import canonical chain tail: %v", err) 1817 } 1818 // Force run a freeze cycle 1819 type freezer interface { 1820 Freeze(threshold uint64) error 1821 Ancients() (uint64, error) 1822 } 1823 db.(freezer).Freeze(tt.freezeThreshold) 1824 1825 // Set the simulated pivot block 1826 if tt.pivotBlock != nil { 1827 rawdb.WriteLastPivotNumber(db, *tt.pivotBlock) 1828 } 1829 // Pull the plug on the database, simulating a hard crash 1830 db.Close() 1831 1832 // Start a new blockchain back up and see where the repair leads us 1833 db, err = rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false) 1834 if err != nil { 1835 t.Fatalf("Failed to reopen persistent database: %v", err) 1836 } 1837 defer db.Close() 1838 1839 chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) 1840 if err != nil { 1841 t.Fatalf("Failed to recreate chain: %v", err) 1842 } 1843 defer chain.Stop() 1844 1845 // Iterate over all the remaining blocks and ensure there are no gaps 1846 verifyNoGaps(t, chain, true, canonblocks) 1847 verifyNoGaps(t, chain, false, sideblocks) 1848 verifyCutoff(t, chain, true, canonblocks, tt.expCanonicalBlocks) 1849 verifyCutoff(t, chain, false, sideblocks, tt.expSidechainBlocks) 1850 1851 if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { 1852 t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) 1853 } 1854 if head := chain.CurrentFastBlock(); head.NumberU64() != tt.expHeadFastBlock { 1855 t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadFastBlock) 1856 } 1857 if head := chain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock { 1858 t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock) 1859 } 1860 if frozen, err := db.(freezer).Ancients(); err != nil { 1861 t.Errorf("Failed to retrieve ancient count: %v\n", err) 1862 } else if int(frozen) != tt.expFrozen { 1863 t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen) 1864 } 1865} 1866 1867// TestIssue23496 tests scenario described in https://github.com/ethereum/go-ethereum/pull/23496#issuecomment-926393893 1868// Credits to @zzyalbert for finding the issue. 1869// 1870// Local chain owns these blocks: 1871// G B1 B2 B3 B4 1872// B1: state committed 1873// B2: snapshot disk layer 1874// B3: state committed 1875// B4: head block 1876// 1877// Crash happens without fully persisting snapshot and in-memory states, 1878// chain rewinds itself to the B1 (skip B3 in order to recover snapshot) 1879// In this case the snapshot layer of B3 is not created because of existent 1880// state. 1881func TestIssue23496(t *testing.T) { 1882 // It's hard to follow the test case, visualize the input 1883 //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 1884 1885 // Create a temporary persistent database 1886 datadir, err := ioutil.TempDir("", "") 1887 if err != nil { 1888 t.Fatalf("Failed to create temporary datadir: %v", err) 1889 } 1890 os.RemoveAll(datadir) 1891 1892 db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false) 1893 if err != nil { 1894 t.Fatalf("Failed to create persistent database: %v", err) 1895 } 1896 defer db.Close() // Might double close, should be fine 1897 1898 // Initialize a fresh chain 1899 var ( 1900 genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) 1901 engine = ethash.NewFullFaker() 1902 config = &CacheConfig{ 1903 TrieCleanLimit: 256, 1904 TrieDirtyLimit: 256, 1905 TrieTimeLimit: 5 * time.Minute, 1906 SnapshotLimit: 256, 1907 SnapshotWait: true, 1908 } 1909 ) 1910 chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) 1911 if err != nil { 1912 t.Fatalf("Failed to create chain: %v", err) 1913 } 1914 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), 4, func(i int, b *BlockGen) { 1915 b.SetCoinbase(common.Address{0x02}) 1916 b.SetDifficulty(big.NewInt(1000000)) 1917 }) 1918 1919 // Insert block B1 and commit the state into disk 1920 if _, err := chain.InsertChain(blocks[:1]); err != nil { 1921 t.Fatalf("Failed to import canonical chain start: %v", err) 1922 } 1923 chain.stateCache.TrieDB().Commit(blocks[0].Root(), true, nil) 1924 1925 // Insert block B2 and commit the snapshot into disk 1926 if _, err := chain.InsertChain(blocks[1:2]); err != nil { 1927 t.Fatalf("Failed to import canonical chain start: %v", err) 1928 } 1929 if err := chain.snaps.Cap(blocks[1].Root(), 0); err != nil { 1930 t.Fatalf("Failed to flatten snapshots: %v", err) 1931 } 1932 1933 // Insert block B3 and commit the state into disk 1934 if _, err := chain.InsertChain(blocks[2:3]); err != nil { 1935 t.Fatalf("Failed to import canonical chain start: %v", err) 1936 } 1937 chain.stateCache.TrieDB().Commit(blocks[2].Root(), true, nil) 1938 1939 // Insert the remaining blocks 1940 if _, err := chain.InsertChain(blocks[3:]); err != nil { 1941 t.Fatalf("Failed to import canonical chain tail: %v", err) 1942 } 1943 1944 // Pull the plug on the database, simulating a hard crash 1945 db.Close() 1946 1947 // Start a new blockchain back up and see where the repair leads us 1948 db, err = rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false) 1949 if err != nil { 1950 t.Fatalf("Failed to reopen persistent database: %v", err) 1951 } 1952 defer db.Close() 1953 1954 chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) 1955 if err != nil { 1956 t.Fatalf("Failed to recreate chain: %v", err) 1957 } 1958 defer chain.Stop() 1959 1960 if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { 1961 t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) 1962 } 1963 if head := chain.CurrentFastBlock(); head.NumberU64() != uint64(4) { 1964 t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), uint64(4)) 1965 } 1966 if head := chain.CurrentBlock(); head.NumberU64() != uint64(1) { 1967 t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), uint64(1)) 1968 } 1969 1970 // Reinsert B2-B4 1971 if _, err := chain.InsertChain(blocks[1:]); err != nil { 1972 t.Fatalf("Failed to import canonical chain tail: %v", err) 1973 } 1974 if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { 1975 t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) 1976 } 1977 if head := chain.CurrentFastBlock(); head.NumberU64() != uint64(4) { 1978 t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), uint64(4)) 1979 } 1980 if head := chain.CurrentBlock(); head.NumberU64() != uint64(4) { 1981 t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), uint64(4)) 1982 } 1983 if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil { 1984 t.Error("Failed to regenerate the snapshot of known state") 1985 } 1986} 1987