github.com/theQRL/go-zond@v0.2.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 // TODO(now.youtrack.cloud/issue/TGZ-7) 24 /* 25 import ( 26 "math/big" 27 "path" 28 "testing" 29 "time" 30 31 "github.com/theQRL/go-zond/common" 32 "github.com/theQRL/go-zond/consensus/beacon" 33 "github.com/theQRL/go-zond/core/rawdb" 34 "github.com/theQRL/go-zond/core/vm" 35 "github.com/theQRL/go-zond/params" 36 ) 37 38 // Tests a recovery for a short canonical chain where a recent block was already 39 // committed to disk and then the process crashed. In this case we expect the full 40 // chain to be rolled back to the committed block, but the chain data itself left 41 // in the database for replaying. 42 // func TestShortRepair(t *testing.T) { testShortRepair(t, false) } 43 44 // func TestShortRepairWithSnapshots(t *testing.T) { testShortRepair(t, true) } 45 46 func testShortRepair(t *testing.T, snapshots bool) { 47 // Chain: 48 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 49 // 50 // Frozen: none 51 // Commit: G, C4 52 // Pivot : none 53 // 54 // CRASH 55 // 56 // ------------------------------ 57 // 58 // Expected in leveldb: 59 // G->C1->C2->C3->C4->C5->C6->C7->C8 60 // 61 // Expected head header : C8 62 // Expected head fast block: C8 63 // Expected head block : C4 64 testRepair(t, &rewindTest{ 65 canonicalBlocks: 8, 66 freezeThreshold: 16, 67 commitBlock: 4, 68 pivotBlock: nil, 69 expCanonicalBlocks: 8, 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 freezeThreshold: 16, 105 commitBlock: 4, 106 pivotBlock: uint64ptr(4), 107 expCanonicalBlocks: 8, 108 expFrozen: 0, 109 expHeadHeader: 8, 110 expHeadFastBlock: 8, 111 expHeadBlock: 4, 112 }, snapshots) 113 } 114 115 // Tests a recovery for a short canonical chain where the fast sync pivot point was 116 // not yet committed, but the process crashed. In this case we expect the chain to 117 // detect that it was fast syncing and not delete anything, since we can just pick 118 // up directly where we left off. 119 // func TestShortSnapSyncingRepair(t *testing.T) { testShortSnapSyncingRepair(t, false) } 120 // func TestShortSnapSyncingRepairWithSnapshots(t *testing.T) { testShortSnapSyncingRepair(t, true) } 121 122 func testShortSnapSyncingRepair(t *testing.T, snapshots bool) { 123 // Chain: 124 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 125 // 126 // Frozen: none 127 // Commit: G 128 // Pivot : C4 129 // 130 // CRASH 131 // 132 // ------------------------------ 133 // 134 // Expected in leveldb: 135 // G->C1->C2->C3->C4->C5->C6->C7->C8 136 // 137 // Expected head header : C8 138 // Expected head fast block: C8 139 // Expected head block : G 140 testRepair(t, &rewindTest{ 141 canonicalBlocks: 8, 142 freezeThreshold: 16, 143 commitBlock: 0, 144 pivotBlock: uint64ptr(4), 145 expCanonicalBlocks: 8, 146 expFrozen: 0, 147 expHeadHeader: 8, 148 expHeadFastBlock: 8, 149 expHeadBlock: 0, 150 }, snapshots) 151 } 152 153 // Tests a recovery for a short canonical chain and a longer side chain, where a 154 // recent block was already committed to disk and then the process crashed. In this 155 // case we expect the canonical chain to be rolled back to the committed block, but 156 // the chain data itself left in the database for replaying. 157 // func TestShortReorgedRepair(t *testing.T) { testShortReorgedRepair(t, false) } 158 // func TestShortReorgedRepairWithSnapshots(t *testing.T) { testShortReorgedRepair(t, true) } 159 160 func testShortReorgedRepair(t *testing.T, snapshots bool) { 161 // Chain: 162 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 163 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 164 // 165 // Frozen: none 166 // Commit: G, C4 167 // Pivot : none 168 // 169 // CRASH 170 // 171 // ------------------------------ 172 // 173 // Expected in leveldb: 174 // G->C1->C2->C3->C4->C5->C6->C7->C8 175 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 176 // 177 // Expected head header : C8 178 // Expected head fast block: C8 179 // Expected head block : C4 180 testRepair(t, &rewindTest{ 181 canonicalBlocks: 8, 182 sidechainBlocks: 10, 183 freezeThreshold: 16, 184 commitBlock: 4, 185 pivotBlock: nil, 186 expCanonicalBlocks: 8, 187 expSidechainBlocks: 10, 188 expFrozen: 0, 189 expHeadHeader: 8, 190 expHeadFastBlock: 8, 191 expHeadBlock: 4, 192 }, snapshots) 193 } 194 195 // Tests a recovery for a short canonical chain and a longer side chain, where 196 // the fast sync pivot point was already committed to disk and then the process 197 // crashed. In this case we expect the canonical chain to be rolled back to the 198 // committed block, but the chain data itself left in the database for replaying. 199 // func TestShortReorgedSnapSyncedRepair(t *testing.T) { 200 // testShortReorgedSnapSyncedRepair(t, false) 201 // } 202 // func TestShortReorgedSnapSyncedRepairWithSnapshots(t *testing.T) { 203 // testShortReorgedSnapSyncedRepair(t, true) 204 // } 205 206 func testShortReorgedSnapSyncedRepair(t *testing.T, snapshots bool) { 207 // Chain: 208 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 209 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 210 // 211 // Frozen: none 212 // Commit: G, C4 213 // Pivot : C4 214 // 215 // CRASH 216 // 217 // ------------------------------ 218 // 219 // Expected in leveldb: 220 // G->C1->C2->C3->C4->C5->C6->C7->C8 221 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 222 // 223 // Expected head header : C8 224 // Expected head fast block: C8 225 // Expected head block : C4 226 testRepair(t, &rewindTest{ 227 canonicalBlocks: 8, 228 sidechainBlocks: 10, 229 freezeThreshold: 16, 230 commitBlock: 4, 231 pivotBlock: uint64ptr(4), 232 expCanonicalBlocks: 8, 233 expSidechainBlocks: 10, 234 expFrozen: 0, 235 expHeadHeader: 8, 236 expHeadFastBlock: 8, 237 expHeadBlock: 4, 238 }, snapshots) 239 } 240 241 // Tests a recovery for a short canonical chain and a longer side chain, where 242 // the fast sync pivot point was not yet committed, but the process crashed. In 243 // this case we expect the chain to detect that it was fast syncing and not delete 244 // anything, since we can just pick up directly where we left off. 245 // func TestShortReorgedSnapSyncingRepair(t *testing.T) { 246 // testShortReorgedSnapSyncingRepair(t, false) 247 // } 248 // func TestShortReorgedSnapSyncingRepairWithSnapshots(t *testing.T) { 249 // testShortReorgedSnapSyncingRepair(t, true) 250 // } 251 252 func testShortReorgedSnapSyncingRepair(t *testing.T, snapshots bool) { 253 // Chain: 254 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 255 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 256 // 257 // Frozen: none 258 // Commit: G 259 // Pivot : C4 260 // 261 // CRASH 262 // 263 // ------------------------------ 264 // 265 // Expected in leveldb: 266 // G->C1->C2->C3->C4->C5->C6->C7->C8 267 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 268 // 269 // Expected head header : C8 270 // Expected head fast block: C8 271 // Expected head block : G 272 testRepair(t, &rewindTest{ 273 canonicalBlocks: 8, 274 sidechainBlocks: 10, 275 freezeThreshold: 16, 276 commitBlock: 0, 277 pivotBlock: uint64ptr(4), 278 expCanonicalBlocks: 8, 279 expSidechainBlocks: 10, 280 expFrozen: 0, 281 expHeadHeader: 8, 282 expHeadFastBlock: 8, 283 expHeadBlock: 0, 284 }, snapshots) 285 } 286 287 // Tests a recovery for a long canonical chain with frozen blocks where a recent 288 // block - newer than the ancient limit - was already committed to disk and then 289 // the process crashed. In this case we expect the chain to be rolled back to the 290 // committed block, with everything afterwards kept as fast sync data. 291 // func TestLongShallowRepair(t *testing.T) { testLongShallowRepair(t, false) } 292 // func TestLongShallowRepairWithSnapshots(t *testing.T) { testLongShallowRepair(t, true) } 293 294 func testLongShallowRepair(t *testing.T, snapshots bool) { 295 // Chain: 296 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 297 // 298 // Frozen: 299 // G->C1->C2 300 // 301 // Commit: G, C4 302 // Pivot : none 303 // 304 // CRASH 305 // 306 // ------------------------------ 307 // 308 // Expected in freezer: 309 // G->C1->C2 310 // 311 // Expected in leveldb: 312 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 313 // 314 // Expected head header : C18 315 // Expected head fast block: C18 316 // Expected head block : C4 317 testRepair(t, &rewindTest{ 318 canonicalBlocks: 18, 319 freezeThreshold: 16, 320 commitBlock: 4, 321 pivotBlock: nil, 322 expCanonicalBlocks: 18, 323 expFrozen: 3, 324 expHeadHeader: 18, 325 expHeadFastBlock: 18, 326 expHeadBlock: 4, 327 }, snapshots) 328 } 329 330 // Tests a recovery for a long canonical chain with frozen blocks where a recent 331 // block - older than the ancient limit - was already committed to disk and then 332 // the process crashed. In this case we expect the chain to be rolled back to the 333 // committed block, with everything afterwards deleted. 334 // func TestLongDeepRepair(t *testing.T) { testLongDeepRepair(t, false) } 335 // func TestLongDeepRepairWithSnapshots(t *testing.T) { testLongDeepRepair(t, true) } 336 337 func testLongDeepRepair(t *testing.T, snapshots bool) { 338 // Chain: 339 // 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) 340 // 341 // Frozen: 342 // G->C1->C2->C3->C4->C5->C6->C7->C8 343 // 344 // Commit: G, C4 345 // Pivot : none 346 // 347 // CRASH 348 // 349 // ------------------------------ 350 // 351 // Expected in freezer: 352 // G->C1->C2->C3->C4 353 // 354 // Expected in leveldb: none 355 // 356 // Expected head header : C4 357 // Expected head fast block: C4 358 // Expected head block : C4 359 testRepair(t, &rewindTest{ 360 canonicalBlocks: 24, 361 freezeThreshold: 16, 362 commitBlock: 4, 363 pivotBlock: nil, 364 expCanonicalBlocks: 4, 365 expFrozen: 5, 366 expHeadHeader: 4, 367 expHeadFastBlock: 4, 368 expHeadBlock: 4, 369 }, snapshots) 370 } 371 372 // Tests a recovery for a long canonical chain with frozen blocks where the fast 373 // sync pivot point - newer than the ancient limit - was already committed, after 374 // which the process crashed. In this case we expect the chain to be rolled back 375 // to the committed block, with everything afterwards kept as fast sync data. 376 // func TestLongSnapSyncedShallowRepair(t *testing.T) { 377 // testLongSnapSyncedShallowRepair(t, false) 378 // } 379 // func TestLongSnapSyncedShallowRepairWithSnapshots(t *testing.T) { 380 // testLongSnapSyncedShallowRepair(t, true) 381 // } 382 383 func testLongSnapSyncedShallowRepair(t *testing.T, snapshots bool) { 384 // Chain: 385 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 386 // 387 // Frozen: 388 // G->C1->C2 389 // 390 // Commit: G, C4 391 // Pivot : C4 392 // 393 // CRASH 394 // 395 // ------------------------------ 396 // 397 // Expected in freezer: 398 // G->C1->C2 399 // 400 // Expected in leveldb: 401 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 402 // 403 // Expected head header : C18 404 // Expected head fast block: C18 405 // Expected head block : C4 406 testRepair(t, &rewindTest{ 407 canonicalBlocks: 18, 408 freezeThreshold: 16, 409 commitBlock: 4, 410 pivotBlock: uint64ptr(4), 411 expCanonicalBlocks: 18, 412 expFrozen: 3, 413 expHeadHeader: 18, 414 expHeadFastBlock: 18, 415 expHeadBlock: 4, 416 }, snapshots) 417 } 418 419 // Tests a recovery for a long canonical chain with frozen blocks where the fast 420 // sync pivot point - older than the ancient limit - was already committed, after 421 // which the process crashed. In this case we expect the chain to be rolled back 422 // to the committed block, with everything afterwards deleted. 423 // func TestLongSnapSyncedDeepRepair(t *testing.T) { testLongSnapSyncedDeepRepair(t, false) } 424 // func TestLongSnapSyncedDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncedDeepRepair(t, true) } 425 426 func testLongSnapSyncedDeepRepair(t *testing.T, snapshots bool) { 427 // Chain: 428 // 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) 429 // 430 // Frozen: 431 // G->C1->C2->C3->C4->C5->C6->C7->C8 432 // 433 // Commit: G, C4 434 // Pivot : C4 435 // 436 // CRASH 437 // 438 // ------------------------------ 439 // 440 // Expected in freezer: 441 // G->C1->C2->C3->C4 442 // 443 // Expected in leveldb: none 444 // 445 // Expected head header : C4 446 // Expected head fast block: C4 447 // Expected head block : C4 448 testRepair(t, &rewindTest{ 449 canonicalBlocks: 24, 450 freezeThreshold: 16, 451 commitBlock: 4, 452 pivotBlock: uint64ptr(4), 453 expCanonicalBlocks: 4, 454 expFrozen: 5, 455 expHeadHeader: 4, 456 expHeadFastBlock: 4, 457 expHeadBlock: 4, 458 }, snapshots) 459 } 460 461 // Tests a recovery for a long canonical chain with frozen blocks where the fast 462 // sync pivot point - older than the ancient limit - was not yet committed, but the 463 // process crashed. In this case we expect the chain to detect that it was fast 464 // syncing and not delete anything, since we can just pick up directly where we 465 // left off. 466 // func TestLongSnapSyncingShallowRepair(t *testing.T) { 467 // testLongSnapSyncingShallowRepair(t, false) 468 // } 469 // func TestLongSnapSyncingShallowRepairWithSnapshots(t *testing.T) { 470 // testLongSnapSyncingShallowRepair(t, true) 471 // } 472 473 func testLongSnapSyncingShallowRepair(t *testing.T, snapshots bool) { 474 // Chain: 475 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 476 // 477 // Frozen: 478 // G->C1->C2 479 // 480 // Commit: G 481 // Pivot : C4 482 // 483 // CRASH 484 // 485 // ------------------------------ 486 // 487 // Expected in freezer: 488 // G->C1->C2 489 // 490 // Expected in leveldb: 491 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 492 // 493 // Expected head header : C18 494 // Expected head fast block: C18 495 // Expected head block : G 496 testRepair(t, &rewindTest{ 497 canonicalBlocks: 18, 498 freezeThreshold: 16, 499 commitBlock: 0, 500 pivotBlock: uint64ptr(4), 501 expCanonicalBlocks: 18, 502 expFrozen: 3, 503 expHeadHeader: 18, 504 expHeadFastBlock: 18, 505 expHeadBlock: 0, 506 }, snapshots) 507 } 508 509 // Tests a recovery for a long canonical chain with frozen blocks where the fast 510 // sync pivot point - newer than the ancient limit - was not yet committed, but the 511 // process crashed. In this case we expect the chain to detect that it was fast 512 // syncing and not delete anything, since we can just pick up directly where we 513 // left off. 514 // func TestLongSnapSyncingDeepRepair(t *testing.T) { testLongSnapSyncingDeepRepair(t, false) } 515 // func TestLongSnapSyncingDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncingDeepRepair(t, true) } 516 517 func testLongSnapSyncingDeepRepair(t *testing.T, snapshots bool) { 518 // Chain: 519 // 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) 520 // 521 // Frozen: 522 // G->C1->C2->C3->C4->C5->C6->C7->C8 523 // 524 // Commit: G 525 // Pivot : C4 526 // 527 // CRASH 528 // 529 // ------------------------------ 530 // 531 // Expected in freezer: 532 // G->C1->C2->C3->C4->C5->C6->C7->C8 533 // 534 // Expected in leveldb: 535 // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 536 // 537 // Expected head header : C24 538 // Expected head fast block: C24 539 // Expected head block : G 540 testRepair(t, &rewindTest{ 541 canonicalBlocks: 24, 542 freezeThreshold: 16, 543 commitBlock: 0, 544 pivotBlock: uint64ptr(4), 545 expCanonicalBlocks: 24, 546 expFrozen: 9, 547 expHeadHeader: 24, 548 expHeadFastBlock: 24, 549 expHeadBlock: 0, 550 }, snapshots) 551 } 552 553 // Tests a recovery for a long canonical chain with frozen blocks and a longer side 554 // chain, where a recent block - newer than the ancient limit - was already committed 555 // to disk and then the process crashed. In this case we expect the chain to be 556 // rolled back to the committed block, with everything afterwards kept as fast sync 557 // data. The side chain completely nuked by the freezer. 558 // func TestLongReorgedShallowRepair(t *testing.T) { testLongReorgedShallowRepair(t, false) } 559 // func TestLongReorgedShallowRepairWithSnapshots(t *testing.T) { testLongReorgedShallowRepair(t, true) } 560 561 func testLongReorgedShallowRepair(t *testing.T, snapshots bool) { 562 // Chain: 563 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 564 // └->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 565 // 566 // Frozen: 567 // G->C1->C2 568 // 569 // Commit: G, C4 570 // Pivot : none 571 // 572 // CRASH 573 // 574 // ------------------------------ 575 // 576 // Expected in freezer: 577 // G->C1->C2 578 // 579 // Expected in leveldb: 580 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 581 // 582 // Expected head header : C18 583 // Expected head fast block: C18 584 // Expected head block : C4 585 testRepair(t, &rewindTest{ 586 canonicalBlocks: 18, 587 sidechainBlocks: 26, 588 freezeThreshold: 16, 589 commitBlock: 4, 590 pivotBlock: nil, 591 expCanonicalBlocks: 18, 592 expSidechainBlocks: 0, 593 expFrozen: 3, 594 expHeadHeader: 18, 595 expHeadFastBlock: 18, 596 expHeadBlock: 4, 597 }, snapshots) 598 } 599 600 // Tests a recovery for a long canonical chain with frozen blocks and a longer side 601 // chain, where a recent block - older than the ancient limit - was already committed 602 // to disk and then the process crashed. In this case we expect the canonical chains 603 // to be rolled back to the committed block, with everything afterwards deleted. The 604 // side chain completely nuked by the freezer. 605 // func TestLongReorgedDeepRepair(t *testing.T) { testLongReorgedDeepRepair(t, false) } 606 // func TestLongReorgedDeepRepairWithSnapshots(t *testing.T) { testLongReorgedDeepRepair(t, true) } 607 608 func testLongReorgedDeepRepair(t *testing.T, snapshots bool) { 609 // Chain: 610 // 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) 611 // └->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 612 // 613 // Frozen: 614 // G->C1->C2->C3->C4->C5->C6->C7->C8 615 // 616 // Commit: G, C4 617 // Pivot : none 618 // 619 // CRASH 620 // 621 // ------------------------------ 622 // 623 // Expected in freezer: 624 // G->C1->C2->C3->C4 625 // 626 // Expected in leveldb: none 627 // 628 // Expected head header : C4 629 // Expected head fast block: C4 630 // Expected head block : C4 631 testRepair(t, &rewindTest{ 632 canonicalBlocks: 24, 633 sidechainBlocks: 26, 634 freezeThreshold: 16, 635 commitBlock: 4, 636 pivotBlock: nil, 637 expCanonicalBlocks: 4, 638 expSidechainBlocks: 0, 639 expFrozen: 5, 640 expHeadHeader: 4, 641 expHeadFastBlock: 4, 642 expHeadBlock: 4, 643 }, snapshots) 644 } 645 646 // Tests a recovery for a long canonical chain with frozen blocks and a longer 647 // side chain, where the fast sync pivot point - newer than the ancient limit - 648 // was already committed to disk and then the process crashed. In this case we 649 // expect the chain to be rolled back to the committed block, with everything 650 // afterwards kept as fast sync data. The side chain completely nuked by the 651 // freezer. 652 // func TestLongReorgedSnapSyncedShallowRepair(t *testing.T) { 653 // testLongReorgedSnapSyncedShallowRepair(t, false) 654 // } 655 // func TestLongReorgedSnapSyncedShallowRepairWithSnapshots(t *testing.T) { 656 // testLongReorgedSnapSyncedShallowRepair(t, true) 657 // } 658 659 func testLongReorgedSnapSyncedShallowRepair(t *testing.T, snapshots bool) { 660 // Chain: 661 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 662 // └->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 663 // 664 // Frozen: 665 // G->C1->C2 666 // 667 // Commit: G, C4 668 // Pivot : C4 669 // 670 // CRASH 671 // 672 // ------------------------------ 673 // 674 // Expected in freezer: 675 // G->C1->C2 676 // 677 // Expected in leveldb: 678 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 679 // 680 // Expected head header : C18 681 // Expected head fast block: C18 682 // Expected head block : C4 683 testRepair(t, &rewindTest{ 684 canonicalBlocks: 18, 685 sidechainBlocks: 26, 686 freezeThreshold: 16, 687 commitBlock: 4, 688 pivotBlock: uint64ptr(4), 689 expCanonicalBlocks: 18, 690 expSidechainBlocks: 0, 691 expFrozen: 3, 692 expHeadHeader: 18, 693 expHeadFastBlock: 18, 694 expHeadBlock: 4, 695 }, snapshots) 696 } 697 698 // Tests a recovery for a long canonical chain with frozen blocks and a longer 699 // side chain, where the fast sync pivot point - older than the ancient limit - 700 // was already committed to disk and then the process crashed. In this case we 701 // expect the canonical chains to be rolled back to the committed block, with 702 // everything afterwards deleted. The side chain completely nuked by the freezer. 703 // func TestLongReorgedSnapSyncedDeepRepair(t *testing.T) { 704 // testLongReorgedSnapSyncedDeepRepair(t, false) 705 // } 706 // func TestLongReorgedSnapSyncedDeepRepairWithSnapshots(t *testing.T) { 707 // testLongReorgedSnapSyncedDeepRepair(t, true) 708 // } 709 710 func testLongReorgedSnapSyncedDeepRepair(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 // └->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 714 // 715 // Frozen: 716 // G->C1->C2->C3->C4->C5->C6->C7->C8 717 // 718 // Commit: G, C4 719 // Pivot : C4 720 // 721 // CRASH 722 // 723 // ------------------------------ 724 // 725 // Expected in freezer: 726 // G->C1->C2->C3->C4 727 // 728 // Expected in leveldb: none 729 // 730 // Expected head header : C4 731 // Expected head fast block: C4 732 // Expected head block : C4 733 testRepair(t, &rewindTest{ 734 canonicalBlocks: 24, 735 sidechainBlocks: 26, 736 freezeThreshold: 16, 737 commitBlock: 4, 738 pivotBlock: uint64ptr(4), 739 expCanonicalBlocks: 4, 740 expSidechainBlocks: 0, 741 expFrozen: 5, 742 expHeadHeader: 4, 743 expHeadFastBlock: 4, 744 expHeadBlock: 4, 745 }, snapshots) 746 } 747 748 // Tests a recovery for a long canonical chain with frozen blocks and a longer 749 // side chain, where the fast sync pivot point - newer than the ancient limit - 750 // was not yet committed, but the process crashed. In this case we expect the 751 // chain to detect that it was fast syncing and not delete anything, since we 752 // can just pick up directly where we left off. 753 // func TestLongReorgedSnapSyncingShallowRepair(t *testing.T) { 754 // testLongReorgedSnapSyncingShallowRepair(t, false) 755 // } 756 // func TestLongReorgedSnapSyncingShallowRepairWithSnapshots(t *testing.T) { 757 // testLongReorgedSnapSyncingShallowRepair(t, true) 758 // } 759 760 func testLongReorgedSnapSyncingShallowRepair(t *testing.T, snapshots bool) { 761 // Chain: 762 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 763 // └->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 764 // 765 // Frozen: 766 // G->C1->C2 767 // 768 // Commit: G 769 // Pivot : C4 770 // 771 // CRASH 772 // 773 // ------------------------------ 774 // 775 // Expected in freezer: 776 // G->C1->C2 777 // 778 // Expected in leveldb: 779 // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 780 // 781 // Expected head header : C18 782 // Expected head fast block: C18 783 // Expected head block : G 784 testRepair(t, &rewindTest{ 785 canonicalBlocks: 18, 786 sidechainBlocks: 26, 787 freezeThreshold: 16, 788 commitBlock: 0, 789 pivotBlock: uint64ptr(4), 790 expCanonicalBlocks: 18, 791 expSidechainBlocks: 0, 792 expFrozen: 3, 793 expHeadHeader: 18, 794 expHeadFastBlock: 18, 795 expHeadBlock: 0, 796 }, snapshots) 797 } 798 799 // Tests a recovery for a long canonical chain with frozen blocks and a longer 800 // side chain, where the fast sync pivot point - older than the ancient limit - 801 // was not yet committed, but the process crashed. In this case we expect the 802 // chain to detect that it was fast syncing and not delete anything, since we 803 // can just pick up directly where we left off. 804 // func TestLongReorgedSnapSyncingDeepRepair(t *testing.T) { 805 // testLongReorgedSnapSyncingDeepRepair(t, false) 806 // } 807 // func TestLongReorgedSnapSyncingDeepRepairWithSnapshots(t *testing.T) { 808 // testLongReorgedSnapSyncingDeepRepair(t, true) 809 // } 810 811 func testLongReorgedSnapSyncingDeepRepair(t *testing.T, snapshots bool) { 812 // Chain: 813 // 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) 814 // └->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 815 // 816 // Frozen: 817 // G->C1->C2->C3->C4->C5->C6->C7->C8 818 // 819 // Commit: G 820 // Pivot : C4 821 // 822 // CRASH 823 // 824 // ------------------------------ 825 // 826 // Expected in freezer: 827 // G->C1->C2->C3->C4->C5->C6->C7->C8 828 // 829 // Expected in leveldb: 830 // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 831 // 832 // Expected head header : C24 833 // Expected head fast block: C24 834 // Expected head block : G 835 testRepair(t, &rewindTest{ 836 canonicalBlocks: 24, 837 sidechainBlocks: 26, 838 freezeThreshold: 16, 839 commitBlock: 0, 840 pivotBlock: uint64ptr(4), 841 expCanonicalBlocks: 24, 842 expSidechainBlocks: 0, 843 expFrozen: 9, 844 expHeadHeader: 24, 845 expHeadFastBlock: 24, 846 expHeadBlock: 0, 847 }, snapshots) 848 } 849 850 func testRepair(t *testing.T, tt *rewindTest, snapshots bool) { 851 for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { 852 testRepairWithScheme(t, tt, snapshots, scheme) 853 } 854 } 855 856 func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) { 857 // It's hard to follow the test case, visualize the input 858 //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 859 // fmt.Println(tt.dump(true)) 860 861 // Create a temporary persistent database 862 datadir := t.TempDir() 863 ancient := path.Join(datadir, "ancient") 864 865 db, err := rawdb.Open(rawdb.OpenOptions{ 866 Directory: datadir, 867 AncientsDirectory: ancient, 868 Ephemeral: true, 869 }) 870 if err != nil { 871 t.Fatalf("Failed to create persistent database: %v", err) 872 } 873 defer db.Close() // Might double close, should be fine 874 875 // Initialize a fresh chain 876 var ( 877 gspec = &Genesis{ 878 BaseFee: big.NewInt(params.InitialBaseFee), 879 Config: params.AllBeaconProtocolChanges, 880 } 881 engine = beacon.NewFullFaker() 882 config = &CacheConfig{ 883 TrieCleanLimit: 256, 884 TrieDirtyLimit: 256, 885 TrieTimeLimit: 5 * time.Minute, 886 SnapshotLimit: 0, // Disable snapshot by default 887 StateScheme: scheme, 888 } 889 ) 890 defer engine.Close() 891 if snapshots { 892 config.SnapshotLimit = 256 893 config.SnapshotWait = true 894 } 895 chain, err := NewBlockChain(db, config, gspec, engine, vm.Config{}, nil, nil) 896 if err != nil { 897 t.Fatalf("Failed to create chain: %v", err) 898 } 899 canonblocks, _ := GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { 900 b.SetCoinbase(common.Address{0x02}) 901 }) 902 if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { 903 t.Fatalf("Failed to import canonical chain start: %v", err) 904 } 905 if tt.commitBlock > 0 { 906 if err := chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false); err != nil { 907 t.Fatalf("Failed to flush trie state: %v", err) 908 } 909 if snapshots { 910 if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { 911 t.Fatalf("Failed to flatten snapshots: %v", err) 912 } 913 } 914 } 915 if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { 916 t.Fatalf("Failed to import canonical chain tail: %v", err) 917 } 918 // Force run a freeze cycle 919 type freezer interface { 920 Freeze(threshold uint64) error 921 Ancients() (uint64, error) 922 } 923 db.(freezer).Freeze(tt.freezeThreshold) 924 925 // Set the simulated pivot block 926 if tt.pivotBlock != nil { 927 rawdb.WriteLastPivotNumber(db, *tt.pivotBlock) 928 } 929 // Pull the plug on the database, simulating a hard crash 930 chain.triedb.Close() 931 db.Close() 932 chain.stopWithoutSaving() 933 934 // Start a new blockchain back up and see where the repair leads us 935 db, err = rawdb.Open(rawdb.OpenOptions{ 936 Directory: datadir, 937 AncientsDirectory: ancient, 938 Ephemeral: true, 939 }) 940 if err != nil { 941 t.Fatalf("Failed to reopen persistent database: %v", err) 942 } 943 defer db.Close() 944 945 newChain, err := NewBlockChain(db, config, gspec, engine, vm.Config{}, nil, nil) 946 if err != nil { 947 t.Fatalf("Failed to recreate chain: %v", err) 948 } 949 defer newChain.Stop() 950 951 // Iterate over all the remaining blocks and ensure there are no gaps 952 verifyNoGaps(t, newChain, true, canonblocks) 953 verifyCutoff(t, newChain, true, canonblocks, tt.expCanonicalBlocks) 954 955 if head := newChain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { 956 t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) 957 } 958 if head := newChain.CurrentSnapBlock(); head.Number.Uint64() != tt.expHeadFastBlock { 959 t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, tt.expHeadFastBlock) 960 } 961 if head := newChain.CurrentBlock(); head.Number.Uint64() != tt.expHeadBlock { 962 t.Errorf("Head block mismatch: have %d, want %d", head.Number, tt.expHeadBlock) 963 } 964 if frozen, err := db.(freezer).Ancients(); err != nil { 965 t.Errorf("Failed to retrieve ancient count: %v\n", err) 966 } else if int(frozen) != tt.expFrozen { 967 t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen) 968 } 969 } 970 971 // TestIssue23496 tests scenario described in https://github.com/theQRL/go-zond/pull/23496#issuecomment-926393893 972 // Credits to @zzyalbert for finding the issue. 973 // 974 // Local chain owns these blocks: 975 // G B1 B2 B3 B4 976 // B1: state committed 977 // B2: snapshot disk layer 978 // B3: state committed 979 // B4: head block 980 // 981 // Crash happens without fully persisting snapshot and in-memory states, 982 // chain rewinds itself to the B1 (skip B3 in order to recover snapshot) 983 // In this case the snapshot layer of B3 is not created because of existent 984 // state. 985 // func TestIssue23496(t *testing.T) { 986 // testIssue23496(t, rawdb.HashScheme) 987 // testIssue23496(t, rawdb.PathScheme) 988 // } 989 990 func testIssue23496(t *testing.T, scheme string) { 991 // It's hard to follow the test case, visualize the input 992 //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 993 994 // Create a temporary persistent database 995 datadir := t.TempDir() 996 ancient := path.Join(datadir, "ancient") 997 998 db, err := rawdb.Open(rawdb.OpenOptions{ 999 Directory: datadir, 1000 AncientsDirectory: ancient, 1001 }) 1002 if err != nil { 1003 t.Fatalf("Failed to create persistent database: %v", err) 1004 } 1005 defer db.Close() // Might double close, should be fine 1006 1007 // Initialize a fresh chain 1008 var ( 1009 gspec = &Genesis{ 1010 Config: params.TestChainConfig, 1011 BaseFee: big.NewInt(params.InitialBaseFee), 1012 } 1013 engine = beacon.NewFullFaker() 1014 ) 1015 chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, engine, vm.Config{}, nil, nil) 1016 if err != nil { 1017 t.Fatalf("Failed to create chain: %v", err) 1018 } 1019 _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 4, func(i int, b *BlockGen) { 1020 b.SetCoinbase(common.Address{0x02}) 1021 }) 1022 1023 // Insert block B1 and commit the state into disk 1024 if _, err := chain.InsertChain(blocks[:1]); err != nil { 1025 t.Fatalf("Failed to import canonical chain start: %v", err) 1026 } 1027 chain.triedb.Commit(blocks[0].Root(), false) 1028 1029 // Insert block B2 and commit the snapshot into disk 1030 if _, err := chain.InsertChain(blocks[1:2]); err != nil { 1031 t.Fatalf("Failed to import canonical chain start: %v", err) 1032 } 1033 if err := chain.snaps.Cap(blocks[1].Root(), 0); err != nil { 1034 t.Fatalf("Failed to flatten snapshots: %v", err) 1035 } 1036 1037 // Insert block B3 and commit the state into disk 1038 if _, err := chain.InsertChain(blocks[2:3]); err != nil { 1039 t.Fatalf("Failed to import canonical chain start: %v", err) 1040 } 1041 chain.triedb.Commit(blocks[2].Root(), false) 1042 1043 // Insert the remaining blocks 1044 if _, err := chain.InsertChain(blocks[3:]); err != nil { 1045 t.Fatalf("Failed to import canonical chain tail: %v", err) 1046 } 1047 1048 // Pull the plug on the database, simulating a hard crash 1049 chain.triedb.Close() 1050 db.Close() 1051 chain.stopWithoutSaving() 1052 1053 // Start a new blockchain back up and see where the repair leads us 1054 db, err = rawdb.Open(rawdb.OpenOptions{ 1055 Directory: datadir, 1056 AncientsDirectory: ancient, 1057 Ephemeral: true, 1058 }) 1059 if err != nil { 1060 t.Fatalf("Failed to reopen persistent database: %v", err) 1061 } 1062 defer db.Close() 1063 1064 chain, err = NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, engine, vm.Config{}, nil, nil) 1065 if err != nil { 1066 t.Fatalf("Failed to recreate chain: %v", err) 1067 } 1068 defer chain.Stop() 1069 1070 if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { 1071 t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) 1072 } 1073 if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) { 1074 t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4)) 1075 } 1076 expHead := uint64(1) 1077 if scheme == rawdb.PathScheme { 1078 expHead = uint64(2) 1079 } 1080 if head := chain.CurrentBlock(); head.Number.Uint64() != expHead { 1081 t.Errorf("Head block mismatch: have %d, want %d", head.Number, expHead) 1082 } 1083 1084 // Reinsert B2-B4 1085 if _, err := chain.InsertChain(blocks[1:]); err != nil { 1086 t.Fatalf("Failed to import canonical chain tail: %v", err) 1087 } 1088 if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { 1089 t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) 1090 } 1091 if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) { 1092 t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4)) 1093 } 1094 if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(4) { 1095 t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(4)) 1096 } 1097 if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil { 1098 t.Error("Failed to regenerate the snapshot of known state") 1099 } 1100 } 1101 */