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