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